]>
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 | |
358c6407 | 449 | d->config[0x0a] = 0x00; // class_sub = host2pci |
69b91039 | 450 | d->config[0x0b] = 0x06; // class_base = PCI_bridge |
358c6407 | 451 | d->config[0x0e] = 0x00; // header_type |
69b91039 FB |
452 | } |
453 | ||
0ac32c83 FB |
454 | /* PIIX3 PCI to ISA bridge */ |
455 | ||
456 | typedef struct PIIX3State { | |
457 | PCIDevice dev; | |
458 | } PIIX3State; | |
459 | ||
460 | PIIX3State *piix3_state; | |
461 | ||
462 | static void piix3_reset(PIIX3State *d) | |
463 | { | |
464 | uint8_t *pci_conf = d->dev.config; | |
465 | ||
466 | pci_conf[0x04] = 0x07; // master, memory and I/O | |
467 | pci_conf[0x05] = 0x00; | |
468 | pci_conf[0x06] = 0x00; | |
469 | pci_conf[0x07] = 0x02; // PCI_status_devsel_medium | |
470 | pci_conf[0x4c] = 0x4d; | |
471 | pci_conf[0x4e] = 0x03; | |
472 | pci_conf[0x4f] = 0x00; | |
473 | pci_conf[0x60] = 0x80; | |
474 | pci_conf[0x69] = 0x02; | |
475 | pci_conf[0x70] = 0x80; | |
476 | pci_conf[0x76] = 0x0c; | |
477 | pci_conf[0x77] = 0x0c; | |
478 | pci_conf[0x78] = 0x02; | |
479 | pci_conf[0x79] = 0x00; | |
480 | pci_conf[0x80] = 0x00; | |
481 | pci_conf[0x82] = 0x00; | |
482 | pci_conf[0xa0] = 0x08; | |
483 | pci_conf[0xa0] = 0x08; | |
484 | pci_conf[0xa2] = 0x00; | |
485 | pci_conf[0xa3] = 0x00; | |
486 | pci_conf[0xa4] = 0x00; | |
487 | pci_conf[0xa5] = 0x00; | |
488 | pci_conf[0xa6] = 0x00; | |
489 | pci_conf[0xa7] = 0x00; | |
490 | pci_conf[0xa8] = 0x0f; | |
491 | pci_conf[0xaa] = 0x00; | |
492 | pci_conf[0xab] = 0x00; | |
493 | pci_conf[0xac] = 0x00; | |
494 | pci_conf[0xae] = 0x00; | |
495 | } | |
496 | ||
497 | void piix3_init(void) | |
498 | { | |
499 | PIIX3State *d; | |
500 | uint8_t *pci_conf; | |
501 | ||
502 | d = (PIIX3State *)pci_register_device("PIIX3", sizeof(PIIX3State), | |
503 | 0, -1, | |
504 | NULL, NULL); | |
505 | piix3_state = d; | |
506 | pci_conf = d->dev.config; | |
507 | ||
508 | pci_conf[0x00] = 0x86; // Intel | |
509 | pci_conf[0x01] = 0x80; | |
510 | pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1) | |
511 | pci_conf[0x03] = 0x70; | |
512 | pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA | |
513 | pci_conf[0x0b] = 0x06; // class_base = PCI_bridge | |
514 | pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic | |
515 | ||
516 | piix3_reset(d); | |
517 | } | |
518 | ||
77d4bc34 FB |
519 | /* PREP pci init */ |
520 | ||
521 | static inline void set_config(PCIBridge *s, target_phys_addr_t addr) | |
522 | { | |
523 | int devfn, i; | |
524 | ||
525 | for(i = 0; i < 11; i++) { | |
526 | if ((addr & (1 << (11 + i))) != 0) | |
527 | break; | |
528 | } | |
529 | devfn = ((addr >> 8) & 7) | (i << 3); | |
530 | s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8); | |
531 | } | |
532 | ||
8a8696a3 | 533 | static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 534 | { |
8a8696a3 | 535 | PCIBridge *s = opaque; |
77d4bc34 FB |
536 | set_config(s, addr); |
537 | pci_data_write(s, addr, val, 1); | |
538 | } | |
539 | ||
8a8696a3 | 540 | static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 541 | { |
8a8696a3 | 542 | PCIBridge *s = opaque; |
77d4bc34 FB |
543 | set_config(s, addr); |
544 | #ifdef TARGET_WORDS_BIGENDIAN | |
545 | val = bswap16(val); | |
546 | #endif | |
547 | pci_data_write(s, addr, val, 2); | |
548 | } | |
549 | ||
8a8696a3 | 550 | static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 551 | { |
8a8696a3 | 552 | PCIBridge *s = opaque; |
77d4bc34 FB |
553 | set_config(s, addr); |
554 | #ifdef TARGET_WORDS_BIGENDIAN | |
555 | val = bswap32(val); | |
556 | #endif | |
557 | pci_data_write(s, addr, val, 4); | |
558 | } | |
559 | ||
8a8696a3 | 560 | static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 561 | { |
8a8696a3 | 562 | PCIBridge *s = opaque; |
77d4bc34 FB |
563 | uint32_t val; |
564 | set_config(s, addr); | |
565 | val = pci_data_read(s, addr, 1); | |
566 | return val; | |
567 | } | |
568 | ||
8a8696a3 | 569 | static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 570 | { |
8a8696a3 | 571 | PCIBridge *s = opaque; |
77d4bc34 FB |
572 | uint32_t val; |
573 | set_config(s, addr); | |
574 | val = pci_data_read(s, addr, 2); | |
575 | #ifdef TARGET_WORDS_BIGENDIAN | |
576 | val = bswap16(val); | |
577 | #endif | |
578 | return val; | |
579 | } | |
580 | ||
8a8696a3 | 581 | static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 582 | { |
8a8696a3 | 583 | PCIBridge *s = opaque; |
77d4bc34 FB |
584 | uint32_t val; |
585 | set_config(s, addr); | |
586 | val = pci_data_read(s, addr, 4); | |
587 | #ifdef TARGET_WORDS_BIGENDIAN | |
588 | val = bswap32(val); | |
589 | #endif | |
590 | return val; | |
591 | } | |
592 | ||
593 | static CPUWriteMemoryFunc *PPC_PCIIO_write[] = { | |
594 | &PPC_PCIIO_writeb, | |
595 | &PPC_PCIIO_writew, | |
596 | &PPC_PCIIO_writel, | |
597 | }; | |
598 | ||
599 | static CPUReadMemoryFunc *PPC_PCIIO_read[] = { | |
600 | &PPC_PCIIO_readb, | |
601 | &PPC_PCIIO_readw, | |
602 | &PPC_PCIIO_readl, | |
603 | }; | |
604 | ||
605 | void pci_prep_init(void) | |
606 | { | |
8a8696a3 | 607 | PCIBridge *s = &pci_bridge; |
77d4bc34 FB |
608 | PCIDevice *d; |
609 | int PPC_io_memory; | |
610 | ||
8a8696a3 FB |
611 | PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, |
612 | PPC_PCIIO_write, s); | |
77d4bc34 FB |
613 | cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory); |
614 | ||
615 | d = pci_register_device("PREP PCI Bridge", sizeof(PCIDevice), 0, 0, | |
616 | NULL, NULL); | |
617 | ||
618 | /* XXX: put correct IDs */ | |
619 | d->config[0x00] = 0x11; // vendor_id | |
620 | d->config[0x01] = 0x10; | |
621 | d->config[0x02] = 0x26; // device_id | |
622 | d->config[0x03] = 0x00; | |
623 | d->config[0x08] = 0x02; // revision | |
624 | d->config[0x0a] = 0x04; // class_sub = pci2pci | |
625 | d->config[0x0b] = 0x06; // class_base = PCI_bridge | |
626 | d->config[0x0e] = 0x01; // header_type | |
627 | } | |
628 | ||
629 | ||
630 | /* pmac pci init */ | |
631 | ||
8a8696a3 | 632 | static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 633 | { |
8a8696a3 | 634 | PCIBridge *s = opaque; |
77d4bc34 FB |
635 | #ifdef TARGET_WORDS_BIGENDIAN |
636 | val = bswap32(val); | |
637 | #endif | |
638 | s->config_reg = val; | |
639 | } | |
640 | ||
8a8696a3 | 641 | static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 642 | { |
8a8696a3 | 643 | PCIBridge *s = opaque; |
77d4bc34 FB |
644 | uint32_t val; |
645 | ||
646 | val = s->config_reg; | |
647 | #ifdef TARGET_WORDS_BIGENDIAN | |
648 | val = bswap32(val); | |
649 | #endif | |
650 | return val; | |
651 | } | |
652 | ||
653 | static CPUWriteMemoryFunc *pci_pmac_config_write[] = { | |
654 | &pci_pmac_config_writel, | |
655 | &pci_pmac_config_writel, | |
656 | &pci_pmac_config_writel, | |
657 | }; | |
658 | ||
659 | static CPUReadMemoryFunc *pci_pmac_config_read[] = { | |
660 | &pci_pmac_config_readl, | |
661 | &pci_pmac_config_readl, | |
662 | &pci_pmac_config_readl, | |
663 | }; | |
664 | ||
8a8696a3 | 665 | static void pci_pmac_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 666 | { |
8a8696a3 | 667 | PCIBridge *s = opaque; |
77d4bc34 FB |
668 | pci_data_write(s, addr, val, 1); |
669 | } | |
670 | ||
8a8696a3 | 671 | static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 672 | { |
8a8696a3 | 673 | PCIBridge *s = opaque; |
77d4bc34 FB |
674 | #ifdef TARGET_WORDS_BIGENDIAN |
675 | val = bswap16(val); | |
676 | #endif | |
677 | pci_data_write(s, addr, val, 2); | |
678 | } | |
679 | ||
8a8696a3 | 680 | static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val) |
77d4bc34 | 681 | { |
8a8696a3 | 682 | PCIBridge *s = opaque; |
77d4bc34 FB |
683 | #ifdef TARGET_WORDS_BIGENDIAN |
684 | val = bswap32(val); | |
685 | #endif | |
686 | pci_data_write(s, addr, val, 4); | |
687 | } | |
688 | ||
8a8696a3 | 689 | static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 690 | { |
8a8696a3 | 691 | PCIBridge *s = opaque; |
77d4bc34 FB |
692 | uint32_t val; |
693 | val = pci_data_read(s, addr, 1); | |
694 | return val; | |
695 | } | |
696 | ||
8a8696a3 | 697 | static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 698 | { |
8a8696a3 | 699 | PCIBridge *s = opaque; |
77d4bc34 FB |
700 | uint32_t val; |
701 | val = pci_data_read(s, addr, 2); | |
702 | #ifdef TARGET_WORDS_BIGENDIAN | |
703 | val = bswap16(val); | |
704 | #endif | |
705 | return val; | |
706 | } | |
707 | ||
8a8696a3 | 708 | static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr) |
77d4bc34 | 709 | { |
8a8696a3 | 710 | PCIBridge *s = opaque; |
77d4bc34 FB |
711 | uint32_t val; |
712 | ||
713 | val = pci_data_read(s, addr, 4); | |
714 | #ifdef TARGET_WORDS_BIGENDIAN | |
715 | val = bswap32(val); | |
716 | #endif | |
717 | return val; | |
718 | } | |
719 | ||
720 | static CPUWriteMemoryFunc *pci_pmac_write[] = { | |
721 | &pci_pmac_writeb, | |
722 | &pci_pmac_writew, | |
723 | &pci_pmac_writel, | |
724 | }; | |
725 | ||
726 | static CPUReadMemoryFunc *pci_pmac_read[] = { | |
727 | &pci_pmac_readb, | |
728 | &pci_pmac_readw, | |
729 | &pci_pmac_readl, | |
730 | }; | |
731 | ||
732 | void pci_pmac_init(void) | |
733 | { | |
8a8696a3 | 734 | PCIBridge *s = &pci_bridge; |
77d4bc34 FB |
735 | PCIDevice *d; |
736 | int pci_mem_config, pci_mem_data; | |
737 | ||
738 | pci_mem_config = cpu_register_io_memory(0, pci_pmac_config_read, | |
8a8696a3 FB |
739 | pci_pmac_config_write, s); |
740 | pci_mem_data = cpu_register_io_memory(0, pci_pmac_read, pci_pmac_write, s); | |
77d4bc34 FB |
741 | |
742 | cpu_register_physical_memory(0xfec00000, 0x1000, pci_mem_config); | |
743 | cpu_register_physical_memory(0xfee00000, 0x1000, pci_mem_data); | |
744 | ||
745 | d = pci_register_device("MPC106", sizeof(PCIDevice), 0, 0, | |
746 | NULL, NULL); | |
747 | ||
748 | /* same values as PearPC - check this */ | |
749 | d->config[0x00] = 0x11; // vendor_id | |
750 | d->config[0x01] = 0x10; | |
751 | d->config[0x02] = 0x26; // device_id | |
752 | d->config[0x03] = 0x00; | |
753 | d->config[0x08] = 0x02; // revision | |
754 | d->config[0x0a] = 0x04; // class_sub = pci2pci | |
755 | d->config[0x0b] = 0x06; // class_base = PCI_bridge | |
756 | d->config[0x0e] = 0x01; // header_type | |
757 | ||
758 | d->config[0x18] = 0x0; // primary_bus | |
759 | d->config[0x19] = 0x1; // secondary_bus | |
760 | d->config[0x1a] = 0x1; // subordinate_bus | |
761 | d->config[0x1c] = 0x10; // io_base | |
762 | d->config[0x1d] = 0x20; // io_limit | |
763 | ||
764 | d->config[0x20] = 0x80; // memory_base | |
765 | d->config[0x21] = 0x80; | |
766 | d->config[0x22] = 0x90; // memory_limit | |
767 | d->config[0x23] = 0x80; | |
768 | ||
769 | d->config[0x24] = 0x00; // prefetchable_memory_base | |
770 | d->config[0x25] = 0x84; | |
771 | d->config[0x26] = 0x00; // prefetchable_memory_limit | |
772 | d->config[0x27] = 0x85; | |
773 | } | |
774 | ||
0ac32c83 FB |
775 | /***********************************************************/ |
776 | /* generic PCI irq support */ | |
777 | ||
778 | /* return the global irq number corresponding to a given device irq | |
779 | pin. We could also use the bus number to have a more precise | |
780 | mapping. */ | |
781 | static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) | |
782 | { | |
783 | int slot_addend; | |
784 | slot_addend = (pci_dev->devfn >> 3); | |
785 | return (irq_num + slot_addend) & 3; | |
786 | } | |
787 | ||
788 | /* 0 <= irq_num <= 3. level must be 0 or 1 */ | |
77d4bc34 FB |
789 | #ifdef TARGET_PPC |
790 | void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level) | |
791 | { | |
792 | } | |
793 | #else | |
0ac32c83 FB |
794 | void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level) |
795 | { | |
796 | int irq_index, shift, pic_irq, pic_level; | |
797 | uint32_t *p; | |
798 | ||
799 | irq_num = pci_slot_get_pirq(pci_dev, irq_num); | |
800 | irq_index = pci_dev->irq_index; | |
801 | p = &pci_irq_levels[irq_num][irq_index >> 5]; | |
802 | shift = (irq_index & 0x1f); | |
803 | *p = (*p & ~(1 << shift)) | (level << shift); | |
804 | ||
805 | /* now we change the pic irq level according to the piix irq mappings */ | |
806 | pic_irq = piix3_state->dev.config[0x60 + irq_num]; | |
807 | if (pic_irq < 16) { | |
808 | /* the pic level is the logical OR of all the PCI irqs mapped | |
809 | to it */ | |
810 | pic_level = 0; | |
811 | #if (PCI_IRQ_WORDS == 2) | |
812 | pic_level = ((pci_irq_levels[irq_num][0] | | |
813 | pci_irq_levels[irq_num][1]) != 0); | |
814 | #else | |
815 | { | |
816 | int i; | |
817 | pic_level = 0; | |
818 | for(i = 0; i < PCI_IRQ_WORDS; i++) { | |
819 | if (pci_irq_levels[irq_num][i]) { | |
820 | pic_level = 1; | |
821 | break; | |
822 | } | |
823 | } | |
824 | } | |
825 | #endif | |
826 | pic_set_irq(pic_irq, pic_level); | |
827 | } | |
828 | } | |
77d4bc34 | 829 | #endif |
0ac32c83 FB |
830 | |
831 | /***********************************************************/ | |
832 | /* monitor info on PCI */ | |
833 | ||
834 | static void pci_info_device(PCIDevice *d) | |
835 | { | |
836 | int i, class; | |
837 | PCIIORegion *r; | |
838 | ||
839 | printf(" Bus %2d, device %3d, function %d:\n", | |
840 | d->bus_num, d->devfn >> 3, d->devfn & 7); | |
841 | class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE))); | |
842 | printf(" "); | |
843 | switch(class) { | |
844 | case 0x0101: | |
845 | printf("IDE controller"); | |
846 | break; | |
847 | case 0x0200: | |
848 | printf("Ethernet controller"); | |
849 | break; | |
850 | case 0x0300: | |
851 | printf("VGA controller"); | |
852 | break; | |
853 | default: | |
854 | printf("Class %04x", class); | |
855 | break; | |
856 | } | |
857 | printf(": PCI device %04x:%04x\n", | |
858 | le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))), | |
859 | le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID)))); | |
860 | ||
861 | if (d->config[PCI_INTERRUPT_PIN] != 0) { | |
862 | printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]); | |
863 | } | |
8a8696a3 | 864 | for(i = 0;i < PCI_NUM_REGIONS; i++) { |
0ac32c83 FB |
865 | r = &d->io_regions[i]; |
866 | if (r->size != 0) { | |
867 | printf(" BAR%d: ", i); | |
868 | if (r->type & PCI_ADDRESS_SPACE_IO) { | |
869 | printf("I/O at 0x%04x [0x%04x].\n", | |
870 | r->addr, r->addr + r->size - 1); | |
871 | } else { | |
872 | printf("32 bit memory at 0x%08x [0x%08x].\n", | |
873 | r->addr, r->addr + r->size - 1); | |
874 | } | |
875 | } | |
876 | } | |
877 | } | |
878 | ||
879 | void pci_info(void) | |
880 | { | |
881 | PCIBridge *s = &pci_bridge; | |
882 | PCIDevice **bus; | |
883 | int bus_num, devfn; | |
884 | ||
885 | for(bus_num = 0; bus_num < 256; bus_num++) { | |
886 | bus = s->pci_bus[bus_num]; | |
887 | if (bus) { | |
888 | for(devfn = 0; devfn < 256; devfn++) { | |
889 | if (bus[devfn]) | |
890 | pci_info_device(bus[devfn]); | |
891 | } | |
892 | } | |
893 | } | |
894 | } | |
895 | ||
896 | /***********************************************************/ | |
897 | /* XXX: the following should be moved to the PC BIOS */ | |
898 | ||
899 | static uint32_t isa_inb(uint32_t addr) | |
900 | { | |
901 | return cpu_inb(cpu_single_env, addr); | |
902 | } | |
903 | ||
904 | static void isa_outb(uint32_t val, uint32_t addr) | |
905 | { | |
906 | cpu_outb(cpu_single_env, addr, val); | |
907 | } | |
908 | ||
909 | static uint32_t isa_inw(uint32_t addr) | |
910 | { | |
911 | return cpu_inw(cpu_single_env, addr); | |
912 | } | |
913 | ||
914 | static void isa_outw(uint32_t val, uint32_t addr) | |
915 | { | |
916 | cpu_outw(cpu_single_env, addr, val); | |
917 | } | |
918 | ||
919 | static uint32_t isa_inl(uint32_t addr) | |
920 | { | |
921 | return cpu_inl(cpu_single_env, addr); | |
922 | } | |
923 | ||
924 | static void isa_outl(uint32_t val, uint32_t addr) | |
925 | { | |
926 | cpu_outl(cpu_single_env, addr, val); | |
927 | } | |
928 | ||
929 | static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) | |
930 | { | |
931 | PCIBridge *s = &pci_bridge; | |
932 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
933 | (d->devfn << 8) | addr; | |
934 | pci_data_write(s, 0, val, 4); | |
935 | } | |
936 | ||
937 | static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) | |
938 | { | |
939 | PCIBridge *s = &pci_bridge; | |
940 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
941 | (d->devfn << 8) | (addr & ~3); | |
942 | pci_data_write(s, addr & 3, val, 2); | |
943 | } | |
944 | ||
945 | static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) | |
946 | { | |
947 | PCIBridge *s = &pci_bridge; | |
948 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
949 | (d->devfn << 8) | (addr & ~3); | |
950 | pci_data_write(s, addr & 3, val, 1); | |
951 | } | |
952 | ||
953 | static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) | |
954 | { | |
955 | PCIBridge *s = &pci_bridge; | |
956 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
957 | (d->devfn << 8) | addr; | |
958 | return pci_data_read(s, 0, 4); | |
959 | } | |
960 | ||
961 | static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) | |
962 | { | |
963 | PCIBridge *s = &pci_bridge; | |
964 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
965 | (d->devfn << 8) | (addr & ~3); | |
966 | return pci_data_read(s, addr & 3, 2); | |
967 | } | |
968 | ||
969 | static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) | |
970 | { | |
971 | PCIBridge *s = &pci_bridge; | |
972 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
973 | (d->devfn << 8) | (addr & ~3); | |
974 | return pci_data_read(s, addr & 3, 1); | |
975 | } | |
69b91039 FB |
976 | |
977 | static uint32_t pci_bios_io_addr; | |
978 | static uint32_t pci_bios_mem_addr; | |
0ac32c83 FB |
979 | /* host irqs corresponding to PCI irqs A-D */ |
980 | static uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; | |
69b91039 FB |
981 | |
982 | static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) | |
983 | { | |
69b91039 | 984 | PCIIORegion *r; |
0ac32c83 | 985 | uint16_t cmd; |
8a8696a3 FB |
986 | uint32_t ofs; |
987 | ||
988 | if ( region_num == PCI_ROM_SLOT ) { | |
989 | ofs = 0x30; | |
990 | }else{ | |
991 | ofs = 0x10 + region_num * 4; | |
992 | } | |
69b91039 | 993 | |
8a8696a3 | 994 | pci_config_writel(d, ofs, addr); |
69b91039 FB |
995 | r = &d->io_regions[region_num]; |
996 | ||
997 | /* enable memory mappings */ | |
0ac32c83 | 998 | cmd = pci_config_readw(d, PCI_COMMAND); |
8a8696a3 FB |
999 | if ( region_num == PCI_ROM_SLOT ) |
1000 | cmd |= 2; | |
1001 | else if (r->type & PCI_ADDRESS_SPACE_IO) | |
0ac32c83 | 1002 | cmd |= 1; |
69b91039 | 1003 | else |
0ac32c83 FB |
1004 | cmd |= 2; |
1005 | pci_config_writew(d, PCI_COMMAND, cmd); | |
69b91039 FB |
1006 | } |
1007 | ||
69b91039 FB |
1008 | static void pci_bios_init_device(PCIDevice *d) |
1009 | { | |
1010 | int class; | |
1011 | PCIIORegion *r; | |
1012 | uint32_t *paddr; | |
63ce9e0a | 1013 | int i, pin, pic_irq, vendor_id, device_id; |
69b91039 | 1014 | |
63ce9e0a | 1015 | class = pci_config_readw(d, PCI_CLASS_DEVICE); |
1f62d938 FB |
1016 | vendor_id = pci_config_readw(d, PCI_VENDOR_ID); |
1017 | device_id = pci_config_readw(d, PCI_DEVICE_ID); | |
69b91039 FB |
1018 | switch(class) { |
1019 | case 0x0101: | |
63ce9e0a FB |
1020 | if (vendor_id == 0x8086 && device_id == 0x7010) { |
1021 | /* PIIX3 IDE */ | |
1022 | pci_config_writew(d, PCI_COMMAND, PCI_COMMAND_IO); | |
1023 | pci_config_writew(d, 0x40, 0x8000); // enable IDE0 | |
1024 | } else { | |
1025 | /* IDE: we map it as in ISA mode */ | |
1026 | pci_set_io_region_addr(d, 0, 0x1f0); | |
1027 | pci_set_io_region_addr(d, 1, 0x3f4); | |
1028 | pci_set_io_region_addr(d, 2, 0x170); | |
1029 | pci_set_io_region_addr(d, 3, 0x374); | |
1030 | } | |
69b91039 | 1031 | break; |
0ac32c83 | 1032 | case 0x0300: |
4c7634bc FB |
1033 | if (vendor_id != 0x1234) |
1034 | goto default_map; | |
0ac32c83 FB |
1035 | /* VGA: map frame buffer to default Bochs VBE address */ |
1036 | pci_set_io_region_addr(d, 0, 0xE0000000); | |
1037 | break; | |
1f62d938 FB |
1038 | case 0xff00: |
1039 | if (vendor_id == 0x0106b && device_id == 0x0017) { | |
1040 | /* macio bridge */ | |
1041 | pci_set_io_region_addr(d, 0, 0x80800000); | |
1042 | } | |
1043 | break; | |
69b91039 | 1044 | default: |
4c7634bc | 1045 | default_map: |
69b91039 | 1046 | /* default memory mappings */ |
8a8696a3 | 1047 | for(i = 0; i < PCI_NUM_REGIONS; i++) { |
69b91039 FB |
1048 | r = &d->io_regions[i]; |
1049 | if (r->size) { | |
1050 | if (r->type & PCI_ADDRESS_SPACE_IO) | |
1051 | paddr = &pci_bios_io_addr; | |
1052 | else | |
1053 | paddr = &pci_bios_mem_addr; | |
1054 | *paddr = (*paddr + r->size - 1) & ~(r->size - 1); | |
1055 | pci_set_io_region_addr(d, i, *paddr); | |
1056 | *paddr += r->size; | |
1057 | } | |
1058 | } | |
1059 | break; | |
1060 | } | |
0ac32c83 FB |
1061 | |
1062 | /* map the interrupt */ | |
1063 | pin = pci_config_readb(d, PCI_INTERRUPT_PIN); | |
1064 | if (pin != 0) { | |
1065 | pin = pci_slot_get_pirq(d, pin - 1); | |
1066 | pic_irq = pci_irqs[pin]; | |
1067 | pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq); | |
1068 | } | |
69b91039 FB |
1069 | } |
1070 | ||
1071 | /* | |
1072 | * This function initializes the PCI devices as a normal PCI BIOS | |
1073 | * would do. It is provided just in case the BIOS has no support for | |
1074 | * PCI. | |
1075 | */ | |
1076 | void pci_bios_init(void) | |
1077 | { | |
1078 | PCIBridge *s = &pci_bridge; | |
1079 | PCIDevice **bus; | |
0ac32c83 FB |
1080 | int bus_num, devfn, i, irq; |
1081 | uint8_t elcr[2]; | |
69b91039 FB |
1082 | |
1083 | pci_bios_io_addr = 0xc000; | |
1084 | pci_bios_mem_addr = 0xf0000000; | |
1085 | ||
0ac32c83 FB |
1086 | /* activate IRQ mappings */ |
1087 | elcr[0] = 0x00; | |
1088 | elcr[1] = 0x00; | |
1089 | for(i = 0; i < 4; i++) { | |
1090 | irq = pci_irqs[i]; | |
1091 | /* set to trigger level */ | |
1092 | elcr[irq >> 3] |= (1 << (irq & 7)); | |
1093 | /* activate irq remapping in PIIX */ | |
1094 | pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq); | |
1095 | } | |
1096 | isa_outb(elcr[0], 0x4d0); | |
1097 | isa_outb(elcr[1], 0x4d1); | |
1098 | ||
69b91039 FB |
1099 | for(bus_num = 0; bus_num < 256; bus_num++) { |
1100 | bus = s->pci_bus[bus_num]; | |
1101 | if (bus) { | |
1102 | for(devfn = 0; devfn < 256; devfn++) { | |
1103 | if (bus[devfn]) | |
1104 | pci_bios_init_device(bus[devfn]); | |
1105 | } | |
1106 | } | |
1107 | } | |
1108 | } | |
77d4bc34 FB |
1109 | |
1110 | /* | |
1111 | * This function initializes the PCI devices as a normal PCI BIOS | |
1112 | * would do. It is provided just in case the BIOS has no support for | |
1113 | * PCI. | |
1114 | */ | |
1115 | void pci_ppc_bios_init(void) | |
1116 | { | |
1117 | PCIBridge *s = &pci_bridge; | |
1118 | PCIDevice **bus; | |
1119 | int bus_num, devfn, i, irq; | |
1120 | uint8_t elcr[2]; | |
1121 | ||
1122 | pci_bios_io_addr = 0xc000; | |
1123 | pci_bios_mem_addr = 0xc0000000; | |
1124 | ||
1125 | #if 0 | |
1126 | /* activate IRQ mappings */ | |
1127 | elcr[0] = 0x00; | |
1128 | elcr[1] = 0x00; | |
1129 | for(i = 0; i < 4; i++) { | |
1130 | irq = pci_irqs[i]; | |
1131 | /* set to trigger level */ | |
1132 | elcr[irq >> 3] |= (1 << (irq & 7)); | |
1133 | /* activate irq remapping in PIIX */ | |
1134 | pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq); | |
1135 | } | |
1136 | isa_outb(elcr[0], 0x4d0); | |
1137 | isa_outb(elcr[1], 0x4d1); | |
1138 | #endif | |
1139 | ||
1140 | for(bus_num = 0; bus_num < 256; bus_num++) { | |
1141 | bus = s->pci_bus[bus_num]; | |
1142 | if (bus) { | |
1143 | for(devfn = 0; devfn < 256; devfn++) { | |
1144 | if (bus[devfn]) | |
1145 | pci_bios_init_device(bus[devfn]); | |
1146 | } | |
1147 | } | |
1148 | } | |
1149 | } |