#include #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 */ }