Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / seabios / src / pcibios.c
1 // PCI BIOS (int 1a/b1) calls
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
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 "biosvar.h" // GET_GLOBAL
9 #include "bregs.h" // struct bregs
10 #include "hw/pci.h" // pci_config_readl
11 #include "hw/pci_regs.h" // PCI_VENDOR_ID
12 #include "output.h" // dprintf
13 #include "std/pirtable.h" // struct pir_header
14 #include "string.h" // checksum
15 #include "util.h" // handle_1ab1
16
17 // romlayout.S
18 extern void entry_bios32(void);
19 extern void entry_pcibios32(void);
20
21 #define RET_FUNC_NOT_SUPPORTED 0x81
22 #define RET_BAD_VENDOR_ID      0x83
23 #define RET_DEVICE_NOT_FOUND   0x86
24 #define RET_BUFFER_TOO_SMALL   0x89
25
26 // installation check
27 static void
28 handle_1ab101(struct bregs *regs)
29 {
30     regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
31     regs->bx = 0x0210; // PCI version 2.10
32     regs->cl = GET_GLOBAL(MaxPCIBus);
33     regs->edx = 0x20494350; // "PCI "
34     regs->edi = (u32)entry_pcibios32 + BUILD_BIOS_ADDR;
35     set_code_success(regs);
36 }
37
38 // find pci device
39 static void
40 handle_1ab102(struct bregs *regs)
41 {
42     u32 id = (regs->cx << 16) | regs->dx;
43     int count = regs->si;
44     int bus = -1;
45     while (bus < GET_GLOBAL(MaxPCIBus)) {
46         bus++;
47         int bdf;
48         foreachbdf(bdf, bus) {
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     }
59     set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
60 }
61
62 // find class code
63 static void
64 handle_1ab103(struct bregs *regs)
65 {
66     int count = regs->si;
67     u32 classprog = regs->ecx;
68     int bus = -1;
69     while (bus < GET_GLOBAL(MaxPCIBus)) {
70         bus++;
71         int bdf;
72         foreachbdf(bdf, bus) {
73             u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
74             if ((v>>8) != classprog)
75                 continue;
76             if (count--)
77                 continue;
78             regs->bx = bdf;
79             set_code_success(regs);
80             return;
81         }
82     }
83     set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
84 }
85
86 // read configuration byte
87 static void
88 handle_1ab108(struct bregs *regs)
89 {
90     regs->cl = pci_config_readb(regs->bx, regs->di);
91     set_code_success(regs);
92 }
93
94 // read configuration word
95 static void
96 handle_1ab109(struct bregs *regs)
97 {
98     regs->cx = pci_config_readw(regs->bx, regs->di);
99     set_code_success(regs);
100 }
101
102 // read configuration dword
103 static void
104 handle_1ab10a(struct bregs *regs)
105 {
106     regs->ecx = pci_config_readl(regs->bx, regs->di);
107     set_code_success(regs);
108 }
109
110 // write configuration byte
111 static void
112 handle_1ab10b(struct bregs *regs)
113 {
114     pci_config_writeb(regs->bx, regs->di, regs->cl);
115     set_code_success(regs);
116 }
117
118 // write configuration word
119 static void
120 handle_1ab10c(struct bregs *regs)
121 {
122     pci_config_writew(regs->bx, regs->di, regs->cx);
123     set_code_success(regs);
124 }
125
126 // write configuration dword
127 static void
128 handle_1ab10d(struct bregs *regs)
129 {
130     pci_config_writel(regs->bx, regs->di, regs->ecx);
131     set_code_success(regs);
132 }
133
134 // get irq routing options
135 static void
136 handle_1ab10e(struct bregs *regs)
137 {
138     struct pir_header *pirtable_gf = GET_GLOBAL(PirAddr);
139     if (! pirtable_gf) {
140         set_code_invalid(regs, RET_FUNC_NOT_SUPPORTED);
141         return;
142     }
143     struct pir_header *pirtable_g = GLOBALFLAT2GLOBAL(pirtable_gf);
144
145     struct param_s {
146         u16 size;
147         u16 buf_off;
148         u16 buf_seg;
149     } *param_far = (void*)(regs->di+0);
150
151     // Validate and update size.
152     u16 bufsize = GET_FARVAR(regs->es, param_far->size);
153     u16 pirsize = GET_GLOBAL(pirtable_g->size) - sizeof(struct pir_header);
154     SET_FARVAR(regs->es, param_far->size, pirsize);
155     if (bufsize < pirsize) {
156         set_code_invalid(regs, RET_BUFFER_TOO_SMALL);
157         return;
158     }
159
160     // Get dest buffer.
161     void *buf_far = (void*)(GET_FARVAR(regs->es, param_far->buf_off)+0);
162     u16 buf_seg = GET_FARVAR(regs->es, param_far->buf_seg);
163
164     // Memcpy pir table slots to dest buffer.
165     memcpy_far(buf_seg, buf_far
166                , get_global_seg()
167                , (void*)(pirtable_g->slots) + get_global_offset()
168                , pirsize);
169
170     // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
171     regs->bx = GET_GLOBAL(pirtable_g->exclusive_irqs);
172     set_code_success(regs);
173 }
174
175 static void
176 handle_1ab1XX(struct bregs *regs)
177 {
178     set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED);
179 }
180
181 void
182 handle_1ab1(struct bregs *regs)
183 {
184     //debug_stub(regs);
185
186     if (! CONFIG_PCIBIOS) {
187         set_invalid(regs);
188         return;
189     }
190
191     switch (regs->al) {
192     case 0x01: handle_1ab101(regs); break;
193     case 0x02: handle_1ab102(regs); break;
194     case 0x03: handle_1ab103(regs); break;
195     case 0x08: handle_1ab108(regs); break;
196     case 0x09: handle_1ab109(regs); break;
197     case 0x0a: handle_1ab10a(regs); break;
198     case 0x0b: handle_1ab10b(regs); break;
199     case 0x0c: handle_1ab10c(regs); break;
200     case 0x0d: handle_1ab10d(regs); break;
201     case 0x0e: handle_1ab10e(regs); break;
202     default:   handle_1ab1XX(regs); break;
203     }
204 }
205
206 // Entry point for pci bios functions.
207 void VISIBLE16 VISIBLE32SEG
208 handle_pcibios(struct bregs *regs)
209 {
210     debug_enter(regs, DEBUG_HDL_pcibios);
211     handle_1ab1(regs);
212 }
213
214
215 /****************************************************************
216  * 32bit interface
217  ****************************************************************/
218
219 struct bios32_s {
220     u32 signature;
221     u32 entry;
222     u8 version;
223     u8 length;
224     u8 checksum;
225     u8 reserved[5];
226 } PACKED;
227
228 struct bios32_s BIOS32HEADER __aligned(16) VARFSEG = {
229     .signature = 0x5f32335f, // _32_
230     .length = sizeof(BIOS32HEADER) / 16,
231 };
232
233 void
234 bios32_init(void)
235 {
236     dprintf(3, "init bios32\n");
237
238     BIOS32HEADER.entry = (u32)entry_bios32;
239     BIOS32HEADER.checksum -= checksum(&BIOS32HEADER, sizeof(BIOS32HEADER));
240 }