]>
Commit | Line | Data |
---|---|---|
69b91039 FB |
1 | /* |
2 | * QEMU PCI bus manager | |
3 | * | |
4 | * Copyright (c) 2004 Fabrice Bellard | |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | * of this software and associated documentation files (the "Software"), to deal | |
8 | * in the Software without restriction, including without limitation the rights | |
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | * copies of the Software, and to permit persons to whom the Software is | |
11 | * furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in | |
14 | * all copies or substantial portions of the Software. | |
15 | * | |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | * THE SOFTWARE. | |
23 | */ | |
24 | #include "vl.h" | |
25 | ||
26 | //#define DEBUG_PCI | |
27 | ||
0ac32c83 FB |
28 | #define PCI_VENDOR_ID 0x00 /* 16 bits */ |
29 | #define PCI_DEVICE_ID 0x02 /* 16 bits */ | |
30 | #define PCI_COMMAND 0x04 /* 16 bits */ | |
31 | #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ | |
32 | #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ | |
33 | #define PCI_CLASS_DEVICE 0x0a /* Device class */ | |
34 | #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ | |
35 | #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ | |
36 | #define PCI_MIN_GNT 0x3e /* 8 bits */ | |
37 | #define PCI_MAX_LAT 0x3f /* 8 bits */ | |
38 | ||
39 | /* just used for simpler irq handling. */ | |
40 | #define PCI_DEVICES_MAX 64 | |
41 | #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32) | |
42 | ||
69b91039 FB |
43 | typedef struct PCIBridge { |
44 | uint32_t config_reg; | |
45 | PCIDevice **pci_bus[256]; | |
46 | } PCIBridge; | |
47 | ||
48 | static PCIBridge pci_bridge; | |
49 | target_phys_addr_t pci_mem_base; | |
0ac32c83 FB |
50 | static int pci_irq_index; |
51 | static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS]; | |
69b91039 FB |
52 | |
53 | /* -1 for devfn means auto assign */ | |
54 | PCIDevice *pci_register_device(const char *name, int instance_size, | |
55 | int bus_num, int devfn, | |
56 | PCIConfigReadFunc *config_read, | |
57 | PCIConfigWriteFunc *config_write) | |
58 | { | |
59 | PCIBridge *s = &pci_bridge; | |
60 | PCIDevice *pci_dev, **bus; | |
61 | ||
0ac32c83 FB |
62 | if (pci_irq_index >= PCI_DEVICES_MAX) |
63 | return NULL; | |
64 | ||
69b91039 FB |
65 | if (!s->pci_bus[bus_num]) { |
66 | s->pci_bus[bus_num] = qemu_mallocz(256 * sizeof(PCIDevice *)); | |
67 | if (!s->pci_bus[bus_num]) | |
68 | return NULL; | |
69 | } | |
70 | bus = s->pci_bus[bus_num]; | |
71 | if (devfn < 0) { | |
72 | for(devfn = 0 ; devfn < 256; devfn += 8) { | |
73 | if (!bus[devfn]) | |
74 | goto found; | |
75 | } | |
76 | return NULL; | |
77 | found: ; | |
78 | } | |
79 | pci_dev = qemu_mallocz(instance_size); | |
80 | if (!pci_dev) | |
81 | return NULL; | |
82 | pci_dev->bus_num = bus_num; | |
83 | pci_dev->devfn = devfn; | |
84 | pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); | |
0ac32c83 FB |
85 | |
86 | if (!config_read) | |
87 | config_read = pci_default_read_config; | |
88 | if (!config_write) | |
89 | config_write = pci_default_write_config; | |
69b91039 FB |
90 | pci_dev->config_read = config_read; |
91 | pci_dev->config_write = config_write; | |
0ac32c83 | 92 | pci_dev->irq_index = pci_irq_index++; |
69b91039 FB |
93 | bus[devfn] = pci_dev; |
94 | return pci_dev; | |
95 | } | |
96 | ||
97 | void pci_register_io_region(PCIDevice *pci_dev, int region_num, | |
98 | uint32_t size, int type, | |
99 | PCIMapIORegionFunc *map_func) | |
100 | { | |
101 | PCIIORegion *r; | |
102 | ||
8a8696a3 | 103 | if ((unsigned int)region_num >= PCI_NUM_REGIONS) |
69b91039 FB |
104 | return; |
105 | r = &pci_dev->io_regions[region_num]; | |
106 | r->addr = -1; | |
107 | r->size = size; | |
108 | r->type = type; | |
109 | r->map_func = map_func; | |
110 | } | |
111 | ||
0ac32c83 | 112 | static void pci_addr_writel(void* opaque, uint32_t addr, uint32_t val) |
69b91039 FB |
113 | { |
114 | PCIBridge *s = opaque; | |
115 | s->config_reg = val; | |
116 | } | |
117 | ||
0ac32c83 | 118 | static uint32_t pci_addr_readl(void* opaque, uint32_t addr) |
69b91039 FB |
119 | { |
120 | PCIBridge *s = opaque; | |
121 | return s->config_reg; | |
122 | } | |
123 | ||
0ac32c83 FB |
124 | static void pci_update_mappings(PCIDevice *d) |
125 | { | |
126 | PCIIORegion *r; | |
127 | int cmd, i; | |
8a8696a3 | 128 | uint32_t last_addr, new_addr, config_ofs; |
0ac32c83 FB |
129 | |
130 | cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND)); | |
8a8696a3 | 131 | for(i = 0; i < PCI_NUM_REGIONS; i++) { |
0ac32c83 | 132 | r = &d->io_regions[i]; |
8a8696a3 FB |
133 | if (i == PCI_ROM_SLOT) { |
134 | config_ofs = 0x30; | |
135 | } else { | |
136 | config_ofs = 0x10 + i * 4; | |
137 | } | |
0ac32c83 FB |
138 | if (r->size != 0) { |
139 | if (r->type & PCI_ADDRESS_SPACE_IO) { | |
140 | if (cmd & PCI_COMMAND_IO) { | |
141 | new_addr = le32_to_cpu(*(uint32_t *)(d->config + | |
8a8696a3 | 142 | config_ofs)); |
0ac32c83 FB |
143 | new_addr = new_addr & ~(r->size - 1); |
144 | last_addr = new_addr + r->size - 1; | |
145 | /* NOTE: we have only 64K ioports on PC */ | |
146 | if (last_addr <= new_addr || new_addr == 0 || | |
147 | last_addr >= 0x10000) { | |
148 | new_addr = -1; | |
149 | } | |
150 | } else { | |
151 | new_addr = -1; | |
152 | } | |
153 | } else { | |
154 | if (cmd & PCI_COMMAND_MEMORY) { | |
155 | new_addr = le32_to_cpu(*(uint32_t *)(d->config + | |
8a8696a3 FB |
156 | config_ofs)); |
157 | /* the ROM slot has a specific enable bit */ | |
158 | if (i == PCI_ROM_SLOT && !(new_addr & 1)) | |
159 | goto no_mem_map; | |
0ac32c83 FB |
160 | new_addr = new_addr & ~(r->size - 1); |
161 | last_addr = new_addr + r->size - 1; | |
162 | /* NOTE: we do not support wrapping */ | |
163 | /* XXX: as we cannot support really dynamic | |
164 | mappings, we handle specific values as invalid | |
165 | mappings. */ | |
166 | if (last_addr <= new_addr || new_addr == 0 || | |
167 | last_addr == -1) { | |
168 | new_addr = -1; | |
169 | } | |
170 | } else { | |
8a8696a3 | 171 | no_mem_map: |
0ac32c83 FB |
172 | new_addr = -1; |
173 | } | |
174 | } | |
175 | /* now do the real mapping */ | |
176 | if (new_addr != r->addr) { | |
177 | if (r->addr != -1) { | |
178 | if (r->type & PCI_ADDRESS_SPACE_IO) { | |
179 | int class; | |
180 | /* NOTE: specific hack for IDE in PC case: | |
181 | only one byte must be mapped. */ | |
182 | class = d->config[0x0a] | (d->config[0x0b] << 8); | |
183 | if (class == 0x0101 && r->size == 4) { | |
184 | isa_unassign_ioport(r->addr + 2, 1); | |
185 | } else { | |
186 | isa_unassign_ioport(r->addr, r->size); | |
187 | } | |
188 | } else { | |
189 | cpu_register_physical_memory(r->addr + pci_mem_base, | |
190 | r->size, | |
191 | IO_MEM_UNASSIGNED); | |
192 | } | |
193 | } | |
194 | r->addr = new_addr; | |
195 | if (r->addr != -1) { | |
196 | r->map_func(d, i, r->addr, r->size, r->type); | |
197 | } | |
198 | } | |
199 | } | |
200 | } | |
201 | } | |
202 | ||
203 | uint32_t pci_default_read_config(PCIDevice *d, | |
204 | uint32_t address, int len) | |
69b91039 | 205 | { |
0ac32c83 FB |
206 | uint32_t val; |
207 | switch(len) { | |
208 | case 1: | |
209 | val = d->config[address]; | |
210 | break; | |
211 | case 2: | |
212 | val = le16_to_cpu(*(uint16_t *)(d->config + address)); | |
213 | break; | |
214 | default: | |
215 | case 4: | |
216 | val = le32_to_cpu(*(uint32_t *)(d->config + address)); | |
217 | break; | |
218 | } | |
219 | return val; | |
220 | } | |
221 | ||
222 | void pci_default_write_config(PCIDevice *d, | |
223 | uint32_t address, uint32_t val, int len) | |
224 | { | |
225 | int can_write, i; | |
7bf5be70 | 226 | uint32_t end, addr; |
0ac32c83 | 227 | |
8a8696a3 FB |
228 | if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || |
229 | (address >= 0x30 && address < 0x34))) { | |
0ac32c83 FB |
230 | PCIIORegion *r; |
231 | int reg; | |
232 | ||
8a8696a3 FB |
233 | if ( address >= 0x30 ) { |
234 | reg = PCI_ROM_SLOT; | |
235 | }else{ | |
236 | reg = (address - 0x10) >> 2; | |
237 | } | |
0ac32c83 FB |
238 | r = &d->io_regions[reg]; |
239 | if (r->size == 0) | |
240 | goto default_config; | |
241 | /* compute the stored value */ | |
8a8696a3 FB |
242 | if (reg == PCI_ROM_SLOT) { |
243 | /* keep ROM enable bit */ | |
244 | val &= (~(r->size - 1)) | 1; | |
245 | } else { | |
246 | val &= ~(r->size - 1); | |
247 | val |= r->type; | |
248 | } | |
249 | *(uint32_t *)(d->config + address) = cpu_to_le32(val); | |
0ac32c83 | 250 | pci_update_mappings(d); |
69b91039 | 251 | return; |
0ac32c83 FB |
252 | } |
253 | default_config: | |
254 | /* not efficient, but simple */ | |
7bf5be70 | 255 | addr = address; |
0ac32c83 FB |
256 | for(i = 0; i < len; i++) { |
257 | /* default read/write accesses */ | |
1f62d938 | 258 | switch(d->config[0x0e]) { |
0ac32c83 | 259 | case 0x00: |
1f62d938 FB |
260 | case 0x80: |
261 | switch(addr) { | |
262 | case 0x00: | |
263 | case 0x01: | |
264 | case 0x02: | |
265 | case 0x03: | |
266 | case 0x08: | |
267 | case 0x09: | |
268 | case 0x0a: | |
269 | case 0x0b: | |
270 | case 0x0e: | |
271 | case 0x10 ... 0x27: /* base */ | |
272 | case 0x30 ... 0x33: /* rom */ | |
273 | case 0x3d: | |
274 | can_write = 0; | |
275 | break; | |
276 | default: | |
277 | can_write = 1; | |
278 | break; | |
279 | } | |
0ac32c83 FB |
280 | break; |
281 | default: | |
1f62d938 FB |
282 | case 0x01: |
283 | switch(addr) { | |
284 | case 0x00: | |
285 | case 0x01: | |
286 | case 0x02: | |
287 | case 0x03: | |
288 | case 0x08: | |
289 | case 0x09: | |
290 | case 0x0a: | |
291 | case 0x0b: | |
292 | case 0x0e: | |
293 | case 0x38 ... 0x3b: /* rom */ | |
294 | case 0x3d: | |
295 | can_write = 0; | |
296 | break; | |
297 | default: | |
298 | can_write = 1; | |
299 | break; | |
300 | } | |
0ac32c83 FB |
301 | break; |
302 | } | |
303 | if (can_write) { | |
7bf5be70 | 304 | d->config[addr] = val; |
0ac32c83 | 305 | } |
7bf5be70 | 306 | addr++; |
0ac32c83 FB |
307 | val >>= 8; |
308 | } | |
309 | ||
310 | end = address + len; | |
311 | if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) { | |
312 | /* if the command register is modified, we must modify the mappings */ | |
313 | pci_update_mappings(d); | |
69b91039 FB |
314 | } |
315 | } | |
316 | ||
317 | static void pci_data_write(void *opaque, uint32_t addr, | |
318 | uint32_t val, int len) | |
319 | { | |
320 | PCIBridge *s = opaque; | |
321 | PCIDevice **bus, *pci_dev; | |
0ac32c83 | 322 | int config_addr; |
69b91039 FB |
323 | |
324 | #if defined(DEBUG_PCI) && 0 | |
325 | printf("pci_data_write: addr=%08x val=%08x len=%d\n", | |
326 | s->config_reg, val, len); | |
327 | #endif | |
328 | if (!(s->config_reg & (1 << 31))) { | |
329 | return; | |
330 | } | |
331 | if ((s->config_reg & 0x3) != 0) { | |
332 | return; | |
333 | } | |
334 | bus = s->pci_bus[(s->config_reg >> 16) & 0xff]; | |
335 | if (!bus) | |
336 | return; | |
337 | pci_dev = bus[(s->config_reg >> 8) & 0xff]; | |
338 | if (!pci_dev) | |
339 | return; | |
340 | config_addr = (s->config_reg & 0xfc) | (addr & 3); | |
69b91039 FB |
341 | #if defined(DEBUG_PCI) |
342 | printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n", | |
343 | pci_dev->name, config_addr, val, len); | |
344 | #endif | |
0ac32c83 | 345 | pci_dev->config_write(pci_dev, config_addr, val, len); |
69b91039 FB |
346 | } |
347 | ||
348 | static uint32_t pci_data_read(void *opaque, uint32_t addr, | |
349 | int len) | |
350 | { | |
351 | PCIBridge *s = opaque; | |
352 | PCIDevice **bus, *pci_dev; | |
353 | int config_addr; | |
354 | uint32_t val; | |
355 | ||
356 | if (!(s->config_reg & (1 << 31))) | |
357 | goto fail; | |
358 | if ((s->config_reg & 0x3) != 0) | |
359 | goto fail; | |
360 | bus = s->pci_bus[(s->config_reg >> 16) & 0xff]; | |
361 | if (!bus) | |
362 | goto fail; | |
363 | pci_dev = bus[(s->config_reg >> 8) & 0xff]; | |
364 | if (!pci_dev) { | |
365 | fail: | |
63ce9e0a FB |
366 | switch(len) { |
367 | case 1: | |
368 | val = 0xff; | |
369 | break; | |
370 | case 2: | |
371 | val = 0xffff; | |
372 | break; | |
373 | default: | |
374 | case 4: | |
375 | val = 0xffffffff; | |
376 | break; | |
377 | } | |
69b91039 FB |
378 | goto the_end; |
379 | } | |
380 | config_addr = (s->config_reg & 0xfc) | (addr & 3); | |
381 | val = pci_dev->config_read(pci_dev, config_addr, len); | |
382 | #if defined(DEBUG_PCI) | |
383 | printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", | |
384 | pci_dev->name, config_addr, val, len); | |
385 | #endif | |
386 | the_end: | |
387 | #if defined(DEBUG_PCI) && 0 | |
388 | printf("pci_data_read: addr=%08x val=%08x len=%d\n", | |
389 | s->config_reg, val, len); | |
390 | #endif | |
391 | return val; | |
392 | } | |
393 | ||
394 | static void pci_data_writeb(void* opaque, uint32_t addr, uint32_t val) | |
395 | { | |
396 | pci_data_write(opaque, addr, val, 1); | |
397 | } | |
398 | ||
399 | static void pci_data_writew(void* opaque, uint32_t addr, uint32_t val) | |
400 | { | |
401 | pci_data_write(opaque, addr, val, 2); | |
402 | } | |
403 | ||
404 | static void pci_data_writel(void* opaque, uint32_t addr, uint32_t val) | |
405 | { | |
406 | pci_data_write(opaque, addr, val, 4); | |
407 | } | |
408 | ||
409 | static uint32_t pci_data_readb(void* opaque, uint32_t addr) | |
410 | { | |
411 | return pci_data_read(opaque, addr, 1); | |
412 | } | |
413 | ||
414 | static uint32_t pci_data_readw(void* opaque, uint32_t addr) | |
415 | { | |
416 | return pci_data_read(opaque, addr, 2); | |
417 | } | |
418 | ||
419 | static uint32_t pci_data_readl(void* opaque, uint32_t addr) | |
420 | { | |
421 | return pci_data_read(opaque, addr, 4); | |
422 | } | |
423 | ||
424 | /* i440FX PCI bridge */ | |
425 | ||
69b91039 FB |
426 | void i440fx_init(void) |
427 | { | |
428 | PCIBridge *s = &pci_bridge; | |
429 | PCIDevice *d; | |
430 | ||
0ac32c83 FB |
431 | register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s); |
432 | register_ioport_read(0xcf8, 4, 4, pci_addr_readl, s); | |
69b91039 FB |
433 | |
434 | register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s); | |
435 | register_ioport_write(0xcfc, 4, 2, pci_data_writew, s); | |
436 | register_ioport_write(0xcfc, 4, 4, pci_data_writel, s); | |
437 | register_ioport_read(0xcfc, 4, 1, pci_data_readb, s); | |
438 | register_ioport_read(0xcfc, 4, 2, pci_data_readw, s); | |
439 | register_ioport_read(0xcfc, 4, 4, pci_data_readl, s); | |
440 | ||
441 | d = pci_register_device("i440FX", sizeof(PCIDevice), 0, 0, | |
0ac32c83 | 442 | NULL, NULL); |
69b91039 FB |
443 | |
444 | d->config[0x00] = 0x86; // vendor_id | |
445 | d->config[0x01] = 0x80; | |
446 | d->config[0x02] = 0x37; // device_id | |
447 | d->config[0x03] = 0x12; | |
448 | d->config[0x08] = 0x02; // revision | |
449 | d->config[0x0a] = 0x04; // class_sub = pci2pci | |
450 | d->config[0x0b] = 0x06; // class_base = PCI_bridge | |
451 | d->config[0x0c] = 0x01; // line_size in 32 bit words | |
452 | d->config[0x0e] = 0x01; // header_type | |
453 | } | |
454 | ||
0ac32c83 FB |
455 | /* PIIX3 PCI to ISA bridge */ |
456 | ||
457 | typedef struct PIIX3State { | |
458 | PCIDevice dev; | |
459 | } PIIX3State; | |
460 | ||
461 | PIIX3State *piix3_state; | |
462 | ||
463 | static void piix3_reset(PIIX3State *d) | |
464 | { | |
465 | uint8_t *pci_conf = d->dev.config; | |
466 | ||
467 | pci_conf[0x04] = 0x07; // master, memory and I/O | |
468 | pci_conf[0x05] = 0x00; | |
469 | pci_conf[0x06] = 0x00; | |
470 | pci_conf[0x07] = 0x02; // PCI_status_devsel_medium | |
471 | pci_conf[0x4c] = 0x4d; | |
472 | pci_conf[0x4e] = 0x03; | |
473 | pci_conf[0x4f] = 0x00; | |
474 | pci_conf[0x60] = 0x80; | |
475 | pci_conf[0x69] = 0x02; | |
476 | pci_conf[0x70] = 0x80; | |
477 | pci_conf[0x76] = 0x0c; | |
478 | pci_conf[0x77] = 0x0c; | |
479 | pci_conf[0x78] = 0x02; | |
480 | pci_conf[0x79] = 0x00; | |
481 | pci_conf[0x80] = 0x00; | |
482 | pci_conf[0x82] = 0x00; | |
483 | pci_conf[0xa0] = 0x08; | |
484 | pci_conf[0xa0] = 0x08; | |
485 | pci_conf[0xa2] = 0x00; | |
486 | pci_conf[0xa3] = 0x00; | |
487 | pci_conf[0xa4] = 0x00; | |
488 | pci_conf[0xa5] = 0x00; | |
489 | pci_conf[0xa6] = 0x00; | |
490 | pci_conf[0xa7] = 0x00; | |
491 | pci_conf[0xa8] = 0x0f; | |
492 | pci_conf[0xaa] = 0x00; | |
493 | pci_conf[0xab] = 0x00; | |
494 | pci_conf[0xac] = 0x00; | |
495 | pci_conf[0xae] = 0x00; | |
496 | } | |
497 | ||
498 | void piix3_init(void) | |
499 | { | |
500 | PIIX3State *d; | |
501 | uint8_t *pci_conf; | |
502 | ||
503 | d = (PIIX3State *)pci_register_device("PIIX3", sizeof(PIIX3State), | |
504 | 0, -1, | |
505 | NULL, NULL); | |
506 | piix3_state = d; | |
507 | pci_conf = d->dev.config; | |
508 | ||
509 | pci_conf[0x00] = 0x86; // Intel | |
510 | pci_conf[0x01] = 0x80; | |
511 | pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1) | |
512 | pci_conf[0x03] = 0x70; | |
513 | pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA | |
514 | pci_conf[0x0b] = 0x06; // class_base = PCI_bridge | |
515 | pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic | |
516 | ||
517 | piix3_reset(d); | |
518 | } | |
519 | ||
77d4bc34 FB |
520 | /* PREP pci init */ |
521 | ||
522 | static inline void set_config(PCIBridge *s, target_phys_addr_t addr) | |
523 | { | |
524 | int devfn, i; | |
525 | ||
526 | for(i = 0; i < 11; i++) { | |
527 | if ((addr & (1 << (11 + i))) != 0) | |
528 | break; | |
529 | } | |
530 | devfn = ((addr >> 8) & 7) | (i << 3); | |
531 | s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8); | |
532 | } | |
533 | ||
8a8696a3 | 534 | static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 535 | { |
8a8696a3 | 536 | PCIBridge *s = opaque; |
77d4bc34 FB |
537 | set_config(s, addr); |
538 | pci_data_write(s, addr, val, 1); | |
539 | } | |
540 | ||
8a8696a3 | 541 | static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 542 | { |
8a8696a3 | 543 | PCIBridge *s = opaque; |
77d4bc34 FB |
544 | set_config(s, addr); |
545 | #ifdef TARGET_WORDS_BIGENDIAN | |
546 | val = bswap16(val); | |
547 | #endif | |
548 | pci_data_write(s, addr, val, 2); | |
549 | } | |
550 | ||
8a8696a3 | 551 | static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 552 | { |
8a8696a3 | 553 | PCIBridge *s = opaque; |
77d4bc34 FB |
554 | set_config(s, addr); |
555 | #ifdef TARGET_WORDS_BIGENDIAN | |
556 | val = bswap32(val); | |
557 | #endif | |
558 | pci_data_write(s, addr, val, 4); | |
559 | } | |
560 | ||
8a8696a3 | 561 | static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 562 | { |
8a8696a3 | 563 | PCIBridge *s = opaque; |
77d4bc34 FB |
564 | uint32_t val; |
565 | set_config(s, addr); | |
566 | val = pci_data_read(s, addr, 1); | |
567 | return val; | |
568 | } | |
569 | ||
8a8696a3 | 570 | static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 571 | { |
8a8696a3 | 572 | PCIBridge *s = opaque; |
77d4bc34 FB |
573 | uint32_t val; |
574 | set_config(s, addr); | |
575 | val = pci_data_read(s, addr, 2); | |
576 | #ifdef TARGET_WORDS_BIGENDIAN | |
577 | val = bswap16(val); | |
578 | #endif | |
579 | return val; | |
580 | } | |
581 | ||
8a8696a3 | 582 | static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 583 | { |
8a8696a3 | 584 | PCIBridge *s = opaque; |
77d4bc34 FB |
585 | uint32_t val; |
586 | set_config(s, addr); | |
587 | val = pci_data_read(s, addr, 4); | |
588 | #ifdef TARGET_WORDS_BIGENDIAN | |
589 | val = bswap32(val); | |
590 | #endif | |
591 | return val; | |
592 | } | |
593 | ||
594 | static CPUWriteMemoryFunc *PPC_PCIIO_write[] = { | |
595 | &PPC_PCIIO_writeb, | |
596 | &PPC_PCIIO_writew, | |
597 | &PPC_PCIIO_writel, | |
598 | }; | |
599 | ||
600 | static CPUReadMemoryFunc *PPC_PCIIO_read[] = { | |
601 | &PPC_PCIIO_readb, | |
602 | &PPC_PCIIO_readw, | |
603 | &PPC_PCIIO_readl, | |
604 | }; | |
605 | ||
606 | void pci_prep_init(void) | |
607 | { | |
8a8696a3 | 608 | PCIBridge *s = &pci_bridge; |
77d4bc34 FB |
609 | PCIDevice *d; |
610 | int PPC_io_memory; | |
611 | ||
8a8696a3 FB |
612 | PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, |
613 | PPC_PCIIO_write, s); | |
77d4bc34 FB |
614 | cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory); |
615 | ||
616 | d = pci_register_device("PREP PCI Bridge", sizeof(PCIDevice), 0, 0, | |
617 | NULL, NULL); | |
618 | ||
619 | /* XXX: put correct IDs */ | |
620 | d->config[0x00] = 0x11; // vendor_id | |
621 | d->config[0x01] = 0x10; | |
622 | d->config[0x02] = 0x26; // device_id | |
623 | d->config[0x03] = 0x00; | |
624 | d->config[0x08] = 0x02; // revision | |
625 | d->config[0x0a] = 0x04; // class_sub = pci2pci | |
626 | d->config[0x0b] = 0x06; // class_base = PCI_bridge | |
627 | d->config[0x0e] = 0x01; // header_type | |
628 | } | |
629 | ||
630 | ||
631 | /* pmac pci init */ | |
632 | ||
8a8696a3 | 633 | static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 634 | { |
8a8696a3 | 635 | PCIBridge *s = opaque; |
77d4bc34 FB |
636 | #ifdef TARGET_WORDS_BIGENDIAN |
637 | val = bswap32(val); | |
638 | #endif | |
639 | s->config_reg = val; | |
640 | } | |
641 | ||
8a8696a3 | 642 | static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 643 | { |
8a8696a3 | 644 | PCIBridge *s = opaque; |
77d4bc34 FB |
645 | uint32_t val; |
646 | ||
647 | val = s->config_reg; | |
648 | #ifdef TARGET_WORDS_BIGENDIAN | |
649 | val = bswap32(val); | |
650 | #endif | |
651 | return val; | |
652 | } | |
653 | ||
654 | static CPUWriteMemoryFunc *pci_pmac_config_write[] = { | |
655 | &pci_pmac_config_writel, | |
656 | &pci_pmac_config_writel, | |
657 | &pci_pmac_config_writel, | |
658 | }; | |
659 | ||
660 | static CPUReadMemoryFunc *pci_pmac_config_read[] = { | |
661 | &pci_pmac_config_readl, | |
662 | &pci_pmac_config_readl, | |
663 | &pci_pmac_config_readl, | |
664 | }; | |
665 | ||
8a8696a3 | 666 | static void pci_pmac_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 667 | { |
8a8696a3 | 668 | PCIBridge *s = opaque; |
77d4bc34 FB |
669 | pci_data_write(s, addr, val, 1); |
670 | } | |
671 | ||
8a8696a3 | 672 | static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 673 | { |
8a8696a3 | 674 | PCIBridge *s = opaque; |
77d4bc34 FB |
675 | #ifdef TARGET_WORDS_BIGENDIAN |
676 | val = bswap16(val); | |
677 | #endif | |
678 | pci_data_write(s, addr, val, 2); | |
679 | } | |
680 | ||
8a8696a3 | 681 | static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 682 | { |
8a8696a3 | 683 | PCIBridge *s = opaque; |
77d4bc34 FB |
684 | #ifdef TARGET_WORDS_BIGENDIAN |
685 | val = bswap32(val); | |
686 | #endif | |
687 | pci_data_write(s, addr, val, 4); | |
688 | } | |
689 | ||
8a8696a3 | 690 | static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 691 | { |
8a8696a3 | 692 | PCIBridge *s = opaque; |
77d4bc34 FB |
693 | uint32_t val; |
694 | val = pci_data_read(s, addr, 1); | |
695 | return val; | |
696 | } | |
697 | ||
8a8696a3 | 698 | static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 699 | { |
8a8696a3 | 700 | PCIBridge *s = opaque; |
77d4bc34 FB |
701 | uint32_t val; |
702 | val = pci_data_read(s, addr, 2); | |
703 | #ifdef TARGET_WORDS_BIGENDIAN | |
704 | val = bswap16(val); | |
705 | #endif | |
706 | return val; | |
707 | } | |
708 | ||
8a8696a3 | 709 | static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 710 | { |
8a8696a3 | 711 | PCIBridge *s = opaque; |
77d4bc34 FB |
712 | uint32_t val; |
713 | ||
714 | val = pci_data_read(s, addr, 4); | |
715 | #ifdef TARGET_WORDS_BIGENDIAN | |
716 | val = bswap32(val); | |
717 | #endif | |
718 | return val; | |
719 | } | |
720 | ||
721 | static CPUWriteMemoryFunc *pci_pmac_write[] = { | |
722 | &pci_pmac_writeb, | |
723 | &pci_pmac_writew, | |
724 | &pci_pmac_writel, | |
725 | }; | |
726 | ||
727 | static CPUReadMemoryFunc *pci_pmac_read[] = { | |
728 | &pci_pmac_readb, | |
729 | &pci_pmac_readw, | |
730 | &pci_pmac_readl, | |
731 | }; | |
732 | ||
733 | void pci_pmac_init(void) | |
734 | { | |
8a8696a3 | 735 | PCIBridge *s = &pci_bridge; |
77d4bc34 FB |
736 | PCIDevice *d; |
737 | int pci_mem_config, pci_mem_data; | |
738 | ||
739 | pci_mem_config = cpu_register_io_memory(0, pci_pmac_config_read, | |
8a8696a3 FB |
740 | pci_pmac_config_write, s); |
741 | pci_mem_data = cpu_register_io_memory(0, pci_pmac_read, pci_pmac_write, s); | |
77d4bc34 FB |
742 | |
743 | cpu_register_physical_memory(0xfec00000, 0x1000, pci_mem_config); | |
744 | cpu_register_physical_memory(0xfee00000, 0x1000, pci_mem_data); | |
745 | ||
746 | d = pci_register_device("MPC106", sizeof(PCIDevice), 0, 0, | |
747 | NULL, NULL); | |
748 | ||
749 | /* same values as PearPC - check this */ | |
750 | d->config[0x00] = 0x11; // vendor_id | |
751 | d->config[0x01] = 0x10; | |
752 | d->config[0x02] = 0x26; // device_id | |
753 | d->config[0x03] = 0x00; | |
754 | d->config[0x08] = 0x02; // revision | |
755 | d->config[0x0a] = 0x04; // class_sub = pci2pci | |
756 | d->config[0x0b] = 0x06; // class_base = PCI_bridge | |
757 | d->config[0x0e] = 0x01; // header_type | |
758 | ||
759 | d->config[0x18] = 0x0; // primary_bus | |
760 | d->config[0x19] = 0x1; // secondary_bus | |
761 | d->config[0x1a] = 0x1; // subordinate_bus | |
762 | d->config[0x1c] = 0x10; // io_base | |
763 | d->config[0x1d] = 0x20; // io_limit | |
764 | ||
765 | d->config[0x20] = 0x80; // memory_base | |
766 | d->config[0x21] = 0x80; | |
767 | d->config[0x22] = 0x90; // memory_limit | |
768 | d->config[0x23] = 0x80; | |
769 | ||
770 | d->config[0x24] = 0x00; // prefetchable_memory_base | |
771 | d->config[0x25] = 0x84; | |
772 | d->config[0x26] = 0x00; // prefetchable_memory_limit | |
773 | d->config[0x27] = 0x85; | |
774 | } | |
775 | ||
0ac32c83 FB |
776 | /***********************************************************/ |
777 | /* generic PCI irq support */ | |
778 | ||
779 | /* return the global irq number corresponding to a given device irq | |
780 | pin. We could also use the bus number to have a more precise | |
781 | mapping. */ | |
782 | static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) | |
783 | { | |
784 | int slot_addend; | |
785 | slot_addend = (pci_dev->devfn >> 3); | |
786 | return (irq_num + slot_addend) & 3; | |
787 | } | |
788 | ||
789 | /* 0 <= irq_num <= 3. level must be 0 or 1 */ | |
77d4bc34 FB |
790 | #ifdef TARGET_PPC |
791 | void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level) | |
792 | { | |
793 | } | |
794 | #else | |
0ac32c83 FB |
795 | void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level) |
796 | { | |
797 | int irq_index, shift, pic_irq, pic_level; | |
798 | uint32_t *p; | |
799 | ||
800 | irq_num = pci_slot_get_pirq(pci_dev, irq_num); | |
801 | irq_index = pci_dev->irq_index; | |
802 | p = &pci_irq_levels[irq_num][irq_index >> 5]; | |
803 | shift = (irq_index & 0x1f); | |
804 | *p = (*p & ~(1 << shift)) | (level << shift); | |
805 | ||
806 | /* now we change the pic irq level according to the piix irq mappings */ | |
807 | pic_irq = piix3_state->dev.config[0x60 + irq_num]; | |
808 | if (pic_irq < 16) { | |
809 | /* the pic level is the logical OR of all the PCI irqs mapped | |
810 | to it */ | |
811 | pic_level = 0; | |
812 | #if (PCI_IRQ_WORDS == 2) | |
813 | pic_level = ((pci_irq_levels[irq_num][0] | | |
814 | pci_irq_levels[irq_num][1]) != 0); | |
815 | #else | |
816 | { | |
817 | int i; | |
818 | pic_level = 0; | |
819 | for(i = 0; i < PCI_IRQ_WORDS; i++) { | |
820 | if (pci_irq_levels[irq_num][i]) { | |
821 | pic_level = 1; | |
822 | break; | |
823 | } | |
824 | } | |
825 | } | |
826 | #endif | |
827 | pic_set_irq(pic_irq, pic_level); | |
828 | } | |
829 | } | |
77d4bc34 | 830 | #endif |
0ac32c83 FB |
831 | |
832 | /***********************************************************/ | |
833 | /* monitor info on PCI */ | |
834 | ||
835 | static void pci_info_device(PCIDevice *d) | |
836 | { | |
837 | int i, class; | |
838 | PCIIORegion *r; | |
839 | ||
840 | printf(" Bus %2d, device %3d, function %d:\n", | |
841 | d->bus_num, d->devfn >> 3, d->devfn & 7); | |
842 | class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE))); | |
843 | printf(" "); | |
844 | switch(class) { | |
845 | case 0x0101: | |
846 | printf("IDE controller"); | |
847 | break; | |
848 | case 0x0200: | |
849 | printf("Ethernet controller"); | |
850 | break; | |
851 | case 0x0300: | |
852 | printf("VGA controller"); | |
853 | break; | |
854 | default: | |
855 | printf("Class %04x", class); | |
856 | break; | |
857 | } | |
858 | printf(": PCI device %04x:%04x\n", | |
859 | le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))), | |
860 | le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID)))); | |
861 | ||
862 | if (d->config[PCI_INTERRUPT_PIN] != 0) { | |
863 | printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]); | |
864 | } | |
8a8696a3 | 865 | for(i = 0;i < PCI_NUM_REGIONS; i++) { |
0ac32c83 FB |
866 | r = &d->io_regions[i]; |
867 | if (r->size != 0) { | |
868 | printf(" BAR%d: ", i); | |
869 | if (r->type & PCI_ADDRESS_SPACE_IO) { | |
870 | printf("I/O at 0x%04x [0x%04x].\n", | |
871 | r->addr, r->addr + r->size - 1); | |
872 | } else { | |
873 | printf("32 bit memory at 0x%08x [0x%08x].\n", | |
874 | r->addr, r->addr + r->size - 1); | |
875 | } | |
876 | } | |
877 | } | |
878 | } | |
879 | ||
880 | void pci_info(void) | |
881 | { | |
882 | PCIBridge *s = &pci_bridge; | |
883 | PCIDevice **bus; | |
884 | int bus_num, devfn; | |
885 | ||
886 | for(bus_num = 0; bus_num < 256; bus_num++) { | |
887 | bus = s->pci_bus[bus_num]; | |
888 | if (bus) { | |
889 | for(devfn = 0; devfn < 256; devfn++) { | |
890 | if (bus[devfn]) | |
891 | pci_info_device(bus[devfn]); | |
892 | } | |
893 | } | |
894 | } | |
895 | } | |
896 | ||
897 | /***********************************************************/ | |
898 | /* XXX: the following should be moved to the PC BIOS */ | |
899 | ||
900 | static uint32_t isa_inb(uint32_t addr) | |
901 | { | |
902 | return cpu_inb(cpu_single_env, addr); | |
903 | } | |
904 | ||
905 | static void isa_outb(uint32_t val, uint32_t addr) | |
906 | { | |
907 | cpu_outb(cpu_single_env, addr, val); | |
908 | } | |
909 | ||
910 | static uint32_t isa_inw(uint32_t addr) | |
911 | { | |
912 | return cpu_inw(cpu_single_env, addr); | |
913 | } | |
914 | ||
915 | static void isa_outw(uint32_t val, uint32_t addr) | |
916 | { | |
917 | cpu_outw(cpu_single_env, addr, val); | |
918 | } | |
919 | ||
920 | static uint32_t isa_inl(uint32_t addr) | |
921 | { | |
922 | return cpu_inl(cpu_single_env, addr); | |
923 | } | |
924 | ||
925 | static void isa_outl(uint32_t val, uint32_t addr) | |
926 | { | |
927 | cpu_outl(cpu_single_env, addr, val); | |
928 | } | |
929 | ||
930 | static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) | |
931 | { | |
932 | PCIBridge *s = &pci_bridge; | |
933 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
934 | (d->devfn << 8) | addr; | |
935 | pci_data_write(s, 0, val, 4); | |
936 | } | |
937 | ||
938 | static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) | |
939 | { | |
940 | PCIBridge *s = &pci_bridge; | |
941 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
942 | (d->devfn << 8) | (addr & ~3); | |
943 | pci_data_write(s, addr & 3, val, 2); | |
944 | } | |
945 | ||
946 | static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) | |
947 | { | |
948 | PCIBridge *s = &pci_bridge; | |
949 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
950 | (d->devfn << 8) | (addr & ~3); | |
951 | pci_data_write(s, addr & 3, val, 1); | |
952 | } | |
953 | ||
954 | static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) | |
955 | { | |
956 | PCIBridge *s = &pci_bridge; | |
957 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
958 | (d->devfn << 8) | addr; | |
959 | return pci_data_read(s, 0, 4); | |
960 | } | |
961 | ||
962 | static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) | |
963 | { | |
964 | PCIBridge *s = &pci_bridge; | |
965 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
966 | (d->devfn << 8) | (addr & ~3); | |
967 | return pci_data_read(s, addr & 3, 2); | |
968 | } | |
969 | ||
970 | static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) | |
971 | { | |
972 | PCIBridge *s = &pci_bridge; | |
973 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
974 | (d->devfn << 8) | (addr & ~3); | |
975 | return pci_data_read(s, addr & 3, 1); | |
976 | } | |
69b91039 FB |
977 | |
978 | static uint32_t pci_bios_io_addr; | |
979 | static uint32_t pci_bios_mem_addr; | |
0ac32c83 FB |
980 | /* host irqs corresponding to PCI irqs A-D */ |
981 | static uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; | |
69b91039 FB |
982 | |
983 | static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) | |
984 | { | |
69b91039 | 985 | PCIIORegion *r; |
0ac32c83 | 986 | uint16_t cmd; |
8a8696a3 FB |
987 | uint32_t ofs; |
988 | ||
989 | if ( region_num == PCI_ROM_SLOT ) { | |
990 | ofs = 0x30; | |
991 | }else{ | |
992 | ofs = 0x10 + region_num * 4; | |
993 | } | |
69b91039 | 994 | |
8a8696a3 | 995 | pci_config_writel(d, ofs, addr); |
69b91039 FB |
996 | r = &d->io_regions[region_num]; |
997 | ||
998 | /* enable memory mappings */ | |
0ac32c83 | 999 | cmd = pci_config_readw(d, PCI_COMMAND); |
8a8696a3 FB |
1000 | if ( region_num == PCI_ROM_SLOT ) |
1001 | cmd |= 2; | |
1002 | else if (r->type & PCI_ADDRESS_SPACE_IO) | |
0ac32c83 | 1003 | cmd |= 1; |
69b91039 | 1004 | else |
0ac32c83 FB |
1005 | cmd |= 2; |
1006 | pci_config_writew(d, PCI_COMMAND, cmd); | |
69b91039 FB |
1007 | } |
1008 | ||
69b91039 FB |
1009 | static void pci_bios_init_device(PCIDevice *d) |
1010 | { | |
1011 | int class; | |
1012 | PCIIORegion *r; | |
1013 | uint32_t *paddr; | |
63ce9e0a | 1014 | int i, pin, pic_irq, vendor_id, device_id; |
69b91039 | 1015 | |
63ce9e0a | 1016 | class = pci_config_readw(d, PCI_CLASS_DEVICE); |
1f62d938 FB |
1017 | vendor_id = pci_config_readw(d, PCI_VENDOR_ID); |
1018 | device_id = pci_config_readw(d, PCI_DEVICE_ID); | |
69b91039 FB |
1019 | switch(class) { |
1020 | case 0x0101: | |
63ce9e0a FB |
1021 | if (vendor_id == 0x8086 && device_id == 0x7010) { |
1022 | /* PIIX3 IDE */ | |
1023 | pci_config_writew(d, PCI_COMMAND, PCI_COMMAND_IO); | |
1024 | pci_config_writew(d, 0x40, 0x8000); // enable IDE0 | |
1025 | } else { | |
1026 | /* IDE: we map it as in ISA mode */ | |
1027 | pci_set_io_region_addr(d, 0, 0x1f0); | |
1028 | pci_set_io_region_addr(d, 1, 0x3f4); | |
1029 | pci_set_io_region_addr(d, 2, 0x170); | |
1030 | pci_set_io_region_addr(d, 3, 0x374); | |
1031 | } | |
69b91039 | 1032 | break; |
0ac32c83 FB |
1033 | case 0x0300: |
1034 | /* VGA: map frame buffer to default Bochs VBE address */ | |
1035 | pci_set_io_region_addr(d, 0, 0xE0000000); | |
1036 | break; | |
1f62d938 FB |
1037 | case 0xff00: |
1038 | if (vendor_id == 0x0106b && device_id == 0x0017) { | |
1039 | /* macio bridge */ | |
1040 | pci_set_io_region_addr(d, 0, 0x80800000); | |
1041 | } | |
1042 | break; | |
69b91039 FB |
1043 | default: |
1044 | /* default memory mappings */ | |
8a8696a3 | 1045 | for(i = 0; i < PCI_NUM_REGIONS; i++) { |
69b91039 FB |
1046 | r = &d->io_regions[i]; |
1047 | if (r->size) { | |
1048 | if (r->type & PCI_ADDRESS_SPACE_IO) | |
1049 | paddr = &pci_bios_io_addr; | |
1050 | else | |
1051 | paddr = &pci_bios_mem_addr; | |
1052 | *paddr = (*paddr + r->size - 1) & ~(r->size - 1); | |
1053 | pci_set_io_region_addr(d, i, *paddr); | |
1054 | *paddr += r->size; | |
1055 | } | |
1056 | } | |
1057 | break; | |
1058 | } | |
0ac32c83 FB |
1059 | |
1060 | /* map the interrupt */ | |
1061 | pin = pci_config_readb(d, PCI_INTERRUPT_PIN); | |
1062 | if (pin != 0) { | |
1063 | pin = pci_slot_get_pirq(d, pin - 1); | |
1064 | pic_irq = pci_irqs[pin]; | |
1065 | pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq); | |
1066 | } | |
69b91039 FB |
1067 | } |
1068 | ||
1069 | /* | |
1070 | * This function initializes the PCI devices as a normal PCI BIOS | |
1071 | * would do. It is provided just in case the BIOS has no support for | |
1072 | * PCI. | |
1073 | */ | |
1074 | void pci_bios_init(void) | |
1075 | { | |
1076 | PCIBridge *s = &pci_bridge; | |
1077 | PCIDevice **bus; | |
0ac32c83 FB |
1078 | int bus_num, devfn, i, irq; |
1079 | uint8_t elcr[2]; | |
69b91039 FB |
1080 | |
1081 | pci_bios_io_addr = 0xc000; | |
1082 | pci_bios_mem_addr = 0xf0000000; | |
1083 | ||
0ac32c83 FB |
1084 | /* activate IRQ mappings */ |
1085 | elcr[0] = 0x00; | |
1086 | elcr[1] = 0x00; | |
1087 | for(i = 0; i < 4; i++) { | |
1088 | irq = pci_irqs[i]; | |
1089 | /* set to trigger level */ | |
1090 | elcr[irq >> 3] |= (1 << (irq & 7)); | |
1091 | /* activate irq remapping in PIIX */ | |
1092 | pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq); | |
1093 | } | |
1094 | isa_outb(elcr[0], 0x4d0); | |
1095 | isa_outb(elcr[1], 0x4d1); | |
1096 | ||
69b91039 FB |
1097 | for(bus_num = 0; bus_num < 256; bus_num++) { |
1098 | bus = s->pci_bus[bus_num]; | |
1099 | if (bus) { | |
1100 | for(devfn = 0; devfn < 256; devfn++) { | |
1101 | if (bus[devfn]) | |
1102 | pci_bios_init_device(bus[devfn]); | |
1103 | } | |
1104 | } | |
1105 | } | |
1106 | } | |
77d4bc34 FB |
1107 | |
1108 | /* | |
1109 | * This function initializes the PCI devices as a normal PCI BIOS | |
1110 | * would do. It is provided just in case the BIOS has no support for | |
1111 | * PCI. | |
1112 | */ | |
1113 | void pci_ppc_bios_init(void) | |
1114 | { | |
1115 | PCIBridge *s = &pci_bridge; | |
1116 | PCIDevice **bus; | |
1117 | int bus_num, devfn, i, irq; | |
1118 | uint8_t elcr[2]; | |
1119 | ||
1120 | pci_bios_io_addr = 0xc000; | |
1121 | pci_bios_mem_addr = 0xc0000000; | |
1122 | ||
1123 | #if 0 | |
1124 | /* activate IRQ mappings */ | |
1125 | elcr[0] = 0x00; | |
1126 | elcr[1] = 0x00; | |
1127 | for(i = 0; i < 4; i++) { | |
1128 | irq = pci_irqs[i]; | |
1129 | /* set to trigger level */ | |
1130 | elcr[irq >> 3] |= (1 << (irq & 7)); | |
1131 | /* activate irq remapping in PIIX */ | |
1132 | pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq); | |
1133 | } | |
1134 | isa_outb(elcr[0], 0x4d0); | |
1135 | isa_outb(elcr[1], 0x4d1); | |
1136 | #endif | |
1137 | ||
1138 | for(bus_num = 0; bus_num < 256; bus_num++) { | |
1139 | bus = s->pci_bus[bus_num]; | |
1140 | if (bus) { | |
1141 | for(devfn = 0; devfn < 256; devfn++) { | |
1142 | if (bus[devfn]) | |
1143 | pci_bios_init_device(bus[devfn]); | |
1144 | } | |
1145 | } | |
1146 | } | |
1147 | } |