1 // PCI BIOS (int 1a/b1) calls
3 // Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002 MandrakeSoft S.A.
6 // This file may be distributed under the terms of the GNU GPLv3 license.
8 #include "types.h" // u32
9 #include "util.h" // handle_1ab1
10 #include "pci.h" // pci_config_readl
11 #include "bregs.h" // struct bregs
12 #include "biosvar.h" // GET_EBDA
14 #define RET_FUNC_NOT_SUPPORTED 0x81
15 #define RET_BAD_VENDOR_ID 0x83
16 #define RET_DEVICE_NOT_FOUND 0x86
17 #define RET_BUFFER_TOO_SMALL 0x89
21 handle_1ab101(struct bregs *regs)
23 regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
24 regs->bx = 0x0210; // PCI version 2.10
25 regs->cl = CONFIG_PCI_BUS_COUNT - 1;
26 regs->edx = 0x20494350; // "PCI "
27 // XXX - bochs bios code sets edi to point to 32bit code - but no
28 // reference to this in spec.
29 set_code_success(regs);
34 handle_1ab102(struct bregs *regs)
37 int ret = pci_find_device(regs->dx, regs->cx, regs->si, &d);
39 set_code_fail(regs, RET_DEVICE_NOT_FOUND);
44 set_code_success(regs);
49 handle_1ab103(struct bregs *regs)
52 int ret = pci_find_classprog(regs->ecx, regs->si, &d);
54 set_code_fail(regs, RET_DEVICE_NOT_FOUND);
59 set_code_success(regs);
62 // read configuration byte
64 handle_1ab108(struct bregs *regs)
66 regs->cl = pci_config_readb(pci_bd(regs->bh, regs->bl), regs->di);
67 set_code_success(regs);
70 // read configuration word
72 handle_1ab109(struct bregs *regs)
74 regs->cx = pci_config_readw(pci_bd(regs->bh, regs->bl), regs->di);
75 set_code_success(regs);
78 // read configuration dword
80 handle_1ab10a(struct bregs *regs)
82 regs->ecx = pci_config_readl(pci_bd(regs->bh, regs->bl), regs->di);
83 set_code_success(regs);
86 // write configuration byte
88 handle_1ab10b(struct bregs *regs)
90 pci_config_writeb(pci_bd(regs->bh, regs->bl), regs->di, regs->cl);
91 set_code_success(regs);
94 // write configuration word
96 handle_1ab10c(struct bregs *regs)
98 pci_config_writew(pci_bd(regs->bh, regs->bl), regs->di, regs->cx);
99 set_code_success(regs);
102 // write configuration dword
104 handle_1ab10d(struct bregs *regs)
106 pci_config_writel(pci_bd(regs->bh, regs->bl), regs->di, regs->ecx);
107 set_code_success(regs);
110 // get irq routing options
112 handle_1ab10e(struct bregs *regs)
114 struct pir_header *pirtable_far = (struct pir_header*)GET_EBDA(pir_loc);
115 if (! pirtable_far) {
116 set_code_fail(regs, RET_FUNC_NOT_SUPPORTED);
120 // Validate and update size.
121 u16 size = GET_FARVAR(regs->es, *(u16*)(regs->di+0));
122 u16 pirsize = (GET_FARPTR(pirtable_far->size)
123 - sizeof(struct pir_header));
124 SET_FARVAR(regs->es, *(u16*)(regs->di+0), pirsize);
125 if (size < pirsize) {
126 set_code_fail(regs, RET_BUFFER_TOO_SMALL);
131 u16 d = (GET_FARVAR(regs->es, *(u16*)(regs->di+2)) + 0);
132 u16 destseg = GET_FARVAR(regs->es, *(u16*)(regs->di+4));
134 // Memcpy pir table slots to dest buffer.
135 memcpy_far(MAKE_FARPTR(destseg, d), pirtable_far, pirsize);
137 // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
138 regs->bx = GET_FARPTR(pirtable_far->exclusive_irqs);
139 set_code_success(regs);
143 handle_1ab1XX(struct bregs *regs)
145 set_code_fail(regs, RET_FUNC_NOT_SUPPORTED);
149 handle_1ab1(struct bregs *regs)
153 if (! CONFIG_PCIBIOS) {
159 case 0x01: handle_1ab101(regs); break;
160 case 0x02: handle_1ab102(regs); break;
161 case 0x03: handle_1ab103(regs); break;
162 case 0x08: handle_1ab108(regs); break;
163 case 0x09: handle_1ab109(regs); break;
164 case 0x0a: handle_1ab10a(regs); break;
165 case 0x0b: handle_1ab10b(regs); break;
166 case 0x0c: handle_1ab10c(regs); break;
167 case 0x0d: handle_1ab10d(regs); break;
168 case 0x0e: handle_1ab10e(regs); break;
169 default: handle_1ab1XX(regs); break;