From e7fc653f44247f1008509a68bf9b666e33fea0e5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Jul 2019 19:45:15 +0200 Subject: implement PCIBIOS specification Signed-off-by: Paolo Bonzini --- code32seg.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 code32seg.c (limited to 'code32seg.c') diff --git a/code32seg.c b/code32seg.c new file mode 100644 index 0000000..213bf44 --- /dev/null +++ b/code32seg.c @@ -0,0 +1,73 @@ +#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))) + +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 */ +} -- cgit v1.1