1 // Low level ATA disk access
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
13 /****************************************************************
15 ****************************************************************/
38 struct link_info links[4];
45 struct pir_slot slots[6];
46 } PACKED PIR_TABLE VISIBLE16 __attribute__((aligned(16))) = {
49 .signature = 0x52495024, // "$PIR"
51 .size = sizeof(struct pir_table),
52 .router_devfunc = 0x08,
53 .compatible_devid = 0x70008086,
54 .checksum = 0x07, // XXX - should auto calculate
58 // first slot entry PCI-to-ISA (embedded)
61 {.link = 0x60, .bitmap = 0xdef8}, // INTA#
62 {.link = 0x61, .bitmap = 0xdef8}, // INTB#
63 {.link = 0x62, .bitmap = 0xdef8}, // INTC#
64 {.link = 0x63, .bitmap = 0xdef8}, // INTD#
66 .slot_nr = 0, // embedded
68 // second slot entry: 1st PCI slot
71 {.link = 0x61, .bitmap = 0xdef8}, // INTA#
72 {.link = 0x62, .bitmap = 0xdef8}, // INTB#
73 {.link = 0x63, .bitmap = 0xdef8}, // INTC#
74 {.link = 0x60, .bitmap = 0xdef8}, // INTD#
78 // third slot entry: 2nd PCI slot
81 {.link = 0x62, .bitmap = 0xdef8}, // INTA#
82 {.link = 0x63, .bitmap = 0xdef8}, // INTB#
83 {.link = 0x60, .bitmap = 0xdef8}, // INTC#
84 {.link = 0x61, .bitmap = 0xdef8}, // INTD#
88 // 4th slot entry: 3rd PCI slot
91 {.link = 0x63, .bitmap = 0xdef8}, // INTA#
92 {.link = 0x60, .bitmap = 0xdef8}, // INTB#
93 {.link = 0x61, .bitmap = 0xdef8}, // INTC#
94 {.link = 0x62, .bitmap = 0xdef8}, // INTD#
98 // 5th slot entry: 4rd PCI slot
101 {.link = 0x60, .bitmap = 0xdef8}, // INTA#
102 {.link = 0x61, .bitmap = 0xdef8}, // INTB#
103 {.link = 0x62, .bitmap = 0xdef8}, // INTC#
104 {.link = 0x63, .bitmap = 0xdef8}, // INTD#
108 // 6th slot entry: 5rd PCI slot
111 {.link = 0x61, .bitmap = 0xdef8}, // INTA#
112 {.link = 0x62, .bitmap = 0xdef8}, // INTB#
113 {.link = 0x63, .bitmap = 0xdef8}, // INTC#
114 {.link = 0x60, .bitmap = 0xdef8}, // INTD#
119 #endif // CONFIG_PCIBIOS
123 /****************************************************************
125 ****************************************************************/
127 #define RET_FUNC_NOT_SUPPORTED 0x81
128 #define RET_BAD_VENDOR_ID 0x83
129 #define RET_DEVICE_NOT_FOUND 0x86
130 #define RET_BUFFER_TOO_SMALL 0x89
132 // installation check
134 handle_1ab101(struct bregs *regs)
139 regs->edx = 0x20494350; // "PCI "
140 // XXX - bochs bios code sets edi to point to 32bit code - but no
141 // reference to this in spec.
147 handle_1ab102(struct bregs *regs)
149 u32 dev = (regs->cx << 16) | regs->dx;
150 u16 index = regs->si;
152 for (i=0; i<0x100; i++) {
153 PCIDevice d = {0, i};
154 u32 v = pci_config_readl(&d, 0);
163 set_code_success(regs);
166 set_code_fail(regs, RET_DEVICE_NOT_FOUND);
171 handle_1ab103(struct bregs *regs)
173 u32 code = regs->ecx << 8;
174 u16 index = regs->si;
176 for (i=0; i<0x100; i++) {
177 PCIDevice d = {0, i};
178 u32 v = pci_config_readl(&d, 0x08);
187 set_code_success(regs);
190 set_code_fail(regs, RET_DEVICE_NOT_FOUND);
193 // read configuration byte
195 handle_1ab108(struct bregs *regs)
197 PCIDevice d = {regs->bh, regs->bl};
198 regs->cl = pci_config_readb(&d, regs->di);
199 set_code_success(regs);
202 // read configuration word
204 handle_1ab109(struct bregs *regs)
206 PCIDevice d = {regs->bh, regs->bl};
207 regs->cx = pci_config_readw(&d, regs->di);
208 set_code_success(regs);
211 // read configuration dword
213 handle_1ab10a(struct bregs *regs)
215 PCIDevice d = {regs->bh, regs->bl};
216 regs->ecx = pci_config_readl(&d, regs->di);
217 set_code_success(regs);
220 // write configuration byte
222 handle_1ab10b(struct bregs *regs)
224 PCIDevice d = {regs->bh, regs->bl};
225 pci_config_writeb(&d, regs->di, regs->cl);
226 set_code_success(regs);
229 // write configuration word
231 handle_1ab10c(struct bregs *regs)
233 PCIDevice d = {regs->bh, regs->bl};
234 pci_config_writew(&d, regs->di, regs->cx);
235 set_code_success(regs);
238 // write configuration dword
240 handle_1ab10d(struct bregs *regs)
242 PCIDevice d = {regs->bh, regs->bl};
243 pci_config_writel(&d, regs->di, regs->ecx);
244 set_code_success(regs);
247 // get irq routing options
249 handle_1ab10e(struct bregs *regs)
251 // Validate and update size.
252 u16 size = GET_FARVAR(regs->es, *(u16*)(regs->di+0));
253 u32 pirsize = sizeof(PIR_TABLE.slots);
254 SET_FARVAR(regs->es, *(u16*)(regs->di+0), pirsize);
255 if (size < pirsize) {
256 set_code_fail(regs, RET_BUFFER_TOO_SMALL);
261 u8 *d = (u8*)(GET_FARVAR(regs->es, *(u16*)(regs->di+2)) + 0);
262 u16 destseg = GET_FARVAR(regs->es, *(u16*)(regs->di+4));
264 // Memcpy pir table slots to dest buffer.
265 u8 *p = (u8*)PIR_TABLE.slots;
266 u8 *end = p + pirsize;
267 for (; p<end; p++, d++) {
268 u8 c = GET_VAR(CS, *p);
269 SET_FARVAR(destseg, *d, c);
272 // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
273 regs->bx = GET_VAR(CS, PIR_TABLE.pir.exclusive_irqs);
274 set_code_success(regs);
278 handle_1ab1XX(struct bregs *regs)
280 set_code_fail(regs, RET_FUNC_NOT_SUPPORTED);
283 #define PCI_FIXED_HOST_BRIDGE 0x12378086 // i440FX PCI bridge
286 handle_1ab1(struct bregs *regs)
290 if (! CONFIG_PCIBIOS) {
295 outl(0x80000000, 0x0cf8);
298 #ifdef PCI_FIXED_HOST_BRIDGE
299 v != PCI_FIXED_HOST_BRIDGE
304 // Device not present
305 set_code_fail(regs, 0xff);
310 case 0x01: handle_1ab101(regs); break;
311 case 0x02: handle_1ab102(regs); break;
312 case 0x03: handle_1ab103(regs); break;
313 case 0x08: handle_1ab108(regs); break;
314 case 0x09: handle_1ab109(regs); break;
315 case 0x0a: handle_1ab10a(regs); break;
316 case 0x0b: handle_1ab10b(regs); break;
317 case 0x0c: handle_1ab10c(regs); break;
318 case 0x0d: handle_1ab10d(regs); break;
319 case 0x0e: handle_1ab10e(regs); break;
320 default: handle_1ab1XX(regs); break;