|
|
1.1 root 1: // PCI BIOS (int 1a/b1) calls
2: //
3: // Copyright (C) 2008 Kevin O'Connor <[email protected]>
4: // Copyright (C) 2002 MandrakeSoft S.A.
5: //
6: // This file may be distributed under the terms of the GNU LGPLv3 license.
7:
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
14:
1.1.1.2 ! root 15: // romlayout.S
! 16: extern void bios32_entry(void);
! 17: extern void pcibios32_entry(void);
! 18:
1.1 root 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
23:
24: // installation check
25: static void
26: handle_1ab101(struct bregs *regs)
27: {
28: // Find max bus.
29: int bdf, max;
30: foreachpci(bdf, max) {
31: }
32:
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 "
1.1.1.2 ! root 37: regs->edi = (u32)pcibios32_entry + BUILD_BIOS_ADDR;
1.1 root 38: set_code_success(regs);
39: }
40:
41: // find pci device
42: static void
43: handle_1ab102(struct bregs *regs)
44: {
45: u32 id = (regs->cx << 16) | regs->dx;
46: int count = regs->si;
47: int bdf, max;
48: foreachpci(bdf, max) {
49: u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
50: if (v != id)
51: continue;
52: if (count--)
53: continue;
54: regs->bx = bdf;
55: set_code_success(regs);
56: return;
57: }
58: set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
59: }
60:
61: // find class code
62: static void
63: handle_1ab103(struct bregs *regs)
64: {
65: int count = regs->si;
66: u32 classprog = regs->ecx;
67: int bdf, max;
68: foreachpci(bdf, max) {
69: u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
70: if ((v>>8) != classprog)
71: continue;
72: if (count--)
73: continue;
74: regs->bx = bdf;
75: set_code_success(regs);
76: return;
77: }
78: set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
79: }
80:
81: // read configuration byte
82: static void
83: handle_1ab108(struct bregs *regs)
84: {
85: regs->cl = pci_config_readb(regs->bx, regs->di);
86: set_code_success(regs);
87: }
88:
89: // read configuration word
90: static void
91: handle_1ab109(struct bregs *regs)
92: {
93: regs->cx = pci_config_readw(regs->bx, regs->di);
94: set_code_success(regs);
95: }
96:
97: // read configuration dword
98: static void
99: handle_1ab10a(struct bregs *regs)
100: {
101: regs->ecx = pci_config_readl(regs->bx, regs->di);
102: set_code_success(regs);
103: }
104:
105: // write configuration byte
106: static void
107: handle_1ab10b(struct bregs *regs)
108: {
109: pci_config_writeb(regs->bx, regs->di, regs->cl);
110: set_code_success(regs);
111: }
112:
113: // write configuration word
114: static void
115: handle_1ab10c(struct bregs *regs)
116: {
117: pci_config_writew(regs->bx, regs->di, regs->cx);
118: set_code_success(regs);
119: }
120:
121: // write configuration dword
122: static void
123: handle_1ab10d(struct bregs *regs)
124: {
125: pci_config_writel(regs->bx, regs->di, regs->ecx);
126: set_code_success(regs);
127: }
128:
129: // get irq routing options
130: static void
131: handle_1ab10e(struct bregs *regs)
132: {
133: struct pir_header *pirtable_g = (void*)(GET_GLOBAL(PirOffset) + 0);
134: if (! pirtable_g) {
135: set_code_invalid(regs, RET_FUNC_NOT_SUPPORTED);
136: return;
137: }
138:
139: struct param_s {
140: u16 size;
141: u16 buf_off;
142: u16 buf_seg;
143: } *param_far = (void*)(regs->di+0);
144:
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);
151: return;
152: }
153:
154: // Get dest buffer.
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);
157:
158: // Memcpy pir table slots to dest buffer.
159: memcpy_far(buf_seg, buf_far
1.1.1.2 ! root 160: , get_global_seg()
! 161: , (void*)(pirtable_g->slots) + get_global_offset()
1.1 root 162: , pirsize);
163:
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);
167: }
168:
169: static void
170: handle_1ab1XX(struct bregs *regs)
171: {
172: set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED);
173: }
174:
175: void
176: handle_1ab1(struct bregs *regs)
177: {
178: //debug_stub(regs);
179:
180: if (! CONFIG_PCIBIOS) {
181: set_invalid(regs);
182: return;
183: }
184:
185: switch (regs->al) {
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;
197: }
198: }
1.1.1.2 ! root 199:
! 200:
! 201: /****************************************************************
! 202: * 32bit interface
! 203: ****************************************************************/
! 204:
! 205: // Entry point for 32bit pci bios functions.
! 206: void VISIBLE32SEG
! 207: handle_pcibios32(struct bregs *regs)
! 208: {
! 209: debug_enter(regs, DEBUG_HDL_pcibios32);
! 210: handle_1ab1(regs);
! 211: }
! 212:
! 213: struct bios32_s {
! 214: u32 signature;
! 215: u32 entry;
! 216: u8 version;
! 217: u8 length;
! 218: u8 checksum;
! 219: u8 reserved[5];
! 220: } PACKED;
! 221:
! 222: struct bios32_s BIOS32HEADER __aligned(16) VAR16EXPORT = {
! 223: .signature = 0x5f32335f, // _32_
! 224: .length = sizeof(BIOS32HEADER) / 16,
! 225: };
! 226:
! 227: void
! 228: bios32_setup(void)
! 229: {
! 230: dprintf(3, "init bios32\n");
! 231:
! 232: BIOS32HEADER.entry = (u32)bios32_entry;
! 233: BIOS32HEADER.checksum -= checksum(&BIOS32HEADER, sizeof(BIOS32HEADER));
! 234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.