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 LGPLv3 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
13 #include "pci_regs.h" // PCI_VENDOR_ID
16 extern void bios32_entry(void);
17 extern void pcibios32_entry(void);
19 #define RET_FUNC_NOT_SUPPORTED 0x81
20 #define RET_BAD_VENDOR_ID 0x83
21 #define RET_DEVICE_NOT_FOUND 0x86
22 #define RET_BUFFER_TOO_SMALL 0x89
26 handle_1ab101(struct bregs *regs)
30 foreachpci(bdf, max) {
33 regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
34 regs->bx = 0x0210; // PCI version 2.10
35 regs->cl = pci_bdf_to_bus(max - 1);
36 regs->edx = 0x20494350; // "PCI "
37 regs->edi = (u32)pcibios32_entry + BUILD_BIOS_ADDR;
38 set_code_success(regs);
43 handle_1ab102(struct bregs *regs)
45 u32 id = (regs->cx << 16) | regs->dx;
48 foreachpci(bdf, max) {
49 u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
55 set_code_success(regs);
58 set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
63 handle_1ab103(struct bregs *regs)
66 u32 classprog = regs->ecx;
68 foreachpci(bdf, max) {
69 u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
70 if ((v>>8) != classprog)
75 set_code_success(regs);
78 set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
81 // read configuration byte
83 handle_1ab108(struct bregs *regs)
85 regs->cl = pci_config_readb(regs->bx, regs->di);
86 set_code_success(regs);
89 // read configuration word
91 handle_1ab109(struct bregs *regs)
93 regs->cx = pci_config_readw(regs->bx, regs->di);
94 set_code_success(regs);
97 // read configuration dword
99 handle_1ab10a(struct bregs *regs)
101 regs->ecx = pci_config_readl(regs->bx, regs->di);
102 set_code_success(regs);
105 // write configuration byte
107 handle_1ab10b(struct bregs *regs)
109 pci_config_writeb(regs->bx, regs->di, regs->cl);
110 set_code_success(regs);
113 // write configuration word
115 handle_1ab10c(struct bregs *regs)
117 pci_config_writew(regs->bx, regs->di, regs->cx);
118 set_code_success(regs);
121 // write configuration dword
123 handle_1ab10d(struct bregs *regs)
125 pci_config_writel(regs->bx, regs->di, regs->ecx);
126 set_code_success(regs);
129 // get irq routing options
131 handle_1ab10e(struct bregs *regs)
133 struct pir_header *pirtable_g = (void*)(GET_GLOBAL(PirOffset) + 0);
135 set_code_invalid(regs, RET_FUNC_NOT_SUPPORTED);
143 } *param_far = (void*)(regs->di+0);
145 // Validate and update size.
146 u16 bufsize = GET_FARVAR(regs->es, param_far->size);
147 u16 pirsize = GET_GLOBAL(pirtable_g->size) - sizeof(struct pir_header);
148 SET_FARVAR(regs->es, param_far->size, pirsize);
149 if (bufsize < pirsize) {
150 set_code_invalid(regs, RET_BUFFER_TOO_SMALL);
155 void *buf_far = (void*)(GET_FARVAR(regs->es, param_far->buf_off)+0);
156 u16 buf_seg = GET_FARVAR(regs->es, param_far->buf_seg);
158 // Memcpy pir table slots to dest buffer.
159 memcpy_far(buf_seg, buf_far
161 , (void*)(pirtable_g->slots) + get_global_offset()
164 // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
165 regs->bx = GET_GLOBAL(pirtable_g->exclusive_irqs);
166 set_code_success(regs);
170 handle_1ab1XX(struct bregs *regs)
172 set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED);
176 handle_1ab1(struct bregs *regs)
180 if (! CONFIG_PCIBIOS) {
186 case 0x01: handle_1ab101(regs); break;
187 case 0x02: handle_1ab102(regs); break;
188 case 0x03: handle_1ab103(regs); break;
189 case 0x08: handle_1ab108(regs); break;
190 case 0x09: handle_1ab109(regs); break;
191 case 0x0a: handle_1ab10a(regs); break;
192 case 0x0b: handle_1ab10b(regs); break;
193 case 0x0c: handle_1ab10c(regs); break;
194 case 0x0d: handle_1ab10d(regs); break;
195 case 0x0e: handle_1ab10e(regs); break;
196 default: handle_1ab1XX(regs); break;
201 /****************************************************************
203 ****************************************************************/
205 // Entry point for 32bit pci bios functions.
207 handle_pcibios32(struct bregs *regs)
209 debug_enter(regs, DEBUG_HDL_pcibios32);
222 struct bios32_s BIOS32HEADER __aligned(16) VAR16EXPORT = {
223 .signature = 0x5f32335f, // _32_
224 .length = sizeof(BIOS32HEADER) / 16,
230 dprintf(3, "init bios32\n");
232 BIOS32HEADER.entry = (u32)bios32_entry;
233 BIOS32HEADER.checksum -= checksum(&BIOS32HEADER, sizeof(BIOS32HEADER));