-
Notifications
You must be signed in to change notification settings - Fork 118
/
code32seg.c
75 lines (65 loc) · 1.69 KB
/
code32seg.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <stddef.h>
#include "bios.h"
#include "pci.h"
#include "processor-flags.h"
#define PCI_FUNC_NOT_SUPPORTED 0x81
#define PCI_BAD_VENDOR_ID 0x83
#define PCI_DEVICE_NOT_FOUND 0x86
#define PCI_BUFFER_TOO_SMALL 0x89
/*
* The PCIBIOS handler must be position independent. To read a flat pointer,
* we use the instruction pointer to retrieve the address corresponding to
* physical address 0 (i.e., what Linux calls PAGE_OFFSET).
*/
static inline void *from_flat_ptr(void *p)
{
return p + pic_base();
}
#define FLAT_VAR(x) (*(typeof(&(x))) from_flat_ptr(&(x)))
#pragma GCC optimize("no-jump-tables")
bioscall void pcibios_handler(struct bios32regs *args)
{
switch (args->eax) {
/* discovery */
case 0xb101:
args->eax = 0x01;
args->ebx = 0x210;
args->ecx = FLAT_VAR(max_bus);
args->edx = 0x20494350;
goto success;
/* config space access */
case 0xb108:
args->ecx = pci_config_readb(args->ebx, args->edi);
goto success;
case 0xb109:
args->ecx = pci_config_readw(args->ebx, args->edi);
goto success;
case 0xb10a:
args->ecx = pci_config_readl(args->ebx, args->edi);
goto success;
case 0xb10b:
pci_config_writeb(args->ebx, args->edi, args->ecx);
goto success;
case 0xb10c:
pci_config_writew(args->ebx, args->edi, args->ecx);
goto success;
case 0xb10d:
pci_config_writel(args->ebx, args->edi, args->ecx);
goto success;
/* find device id, find class code */
case 0xb102:
case 0xb103:
args->eax &= ~0xff00;
args->eax |= PCI_DEVICE_NOT_FOUND << 8;
break;
default:
args->eax &= ~0xff00;
args->eax |= PCI_FUNC_NOT_SUPPORTED << 8;
break;
}
args->eflags |= X86_EFLAGS_CF;
return;
success:
/* On entry, CF=0 */
args->eax &= ~0xff00; /* clear ah */
}