Commit 80b3ada7dd56088613a446934d144a747e740fa1

Authored by pbrook
1 parent d2b59317

Implement sun4u PCI IRQ routing.

Allow multiple PCI busses and PCI-PCI bridges.
Fix bugs in Versatile PCI implementation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2166 c046a42c-6fe2-441c-8c8c-71466251a162
hw/apb_pci.c
... ... @@ -21,6 +21,11 @@
21 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 22 * THE SOFTWARE.
23 23 */
  24 +
  25 +/* XXX This file and most of its contests are somewhat misnamed. The
  26 + Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
  27 + the secondary PCI bridge. */
  28 +
24 29 #include "vl.h"
25 30 typedef target_phys_addr_t pci_addr_t;
26 31 #include "pci_host.h"
... ... @@ -179,17 +184,25 @@ static CPUReadMemoryFunc *pci_apb_ioread[] = {
179 184 &pci_apb_ioreadl,
180 185 };
181 186  
  187 +/* The APB host has an IRQ line for each IRQ line of each slot. */
182 188 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
183 189 {
184   - /* ??? As mentioned below this is probably wrong. */
185   - return irq_num;
  190 + return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
  191 +}
  192 +
  193 +static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
  194 +{
  195 + int bus_offset;
  196 + if (pci_dev->devfn & 1)
  197 + bus_offset = 16;
  198 + else
  199 + bus_offset = 0;
  200 + return bus_offset + irq_num;
186 201 }
187 202  
188 203 static void pci_apb_set_irq(void *pic, int irq_num, int level)
189 204 {
190   - /* ??? This is almost certainly wrong. However the rest of the sun4u
191   - IRQ handling is missing, as is OpenBIOS support, so it wouldn't work
192   - anyway. */
  205 + /* PCI IRQ map onto the first 32 INO. */
193 206 pic_set_irq_new(pic, irq_num, level);
194 207 }
195 208  
... ... @@ -199,10 +212,12 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
199 212 APBState *s;
200 213 PCIDevice *d;
201 214 int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
  215 + PCIDevice *apb;
  216 + PCIBus *secondary;
202 217  
203 218 s = qemu_mallocz(sizeof(APBState));
204   - /* Ultrasparc APB main bus */
205   - s->bus = pci_register_bus(pci_apb_set_irq, pci_apb_map_irq, pic, 0);
  219 + /* Ultrasparc PBM main bus */
  220 + s->bus = pci_register_bus(pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32);
206 221  
207 222 pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
208 223 pci_apb_config_write, s);
... ... @@ -219,7 +234,7 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
219 234 cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
220 235  
221 236 d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
222   - -1, NULL, NULL);
  237 + 0, NULL, NULL);
223 238 d->config[0x00] = 0x8e; // vendor_id : Sun
224 239 d->config[0x01] = 0x10;
225 240 d->config[0x02] = 0x00; // device_id
... ... @@ -234,7 +249,11 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
234 249 d->config[0x0B] = 0x06; // class_base = PCI_bridge
235 250 d->config[0x0D] = 0x10; // latency_timer
236 251 d->config[0x0E] = 0x00; // header_type
237   - return s->bus;
  252 +
  253 + /* APB secondary busses */
  254 + secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq);
  255 + pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq);
  256 + return secondary;
238 257 }
239 258  
240 259  
... ...
hw/grackle_pci.c
... ... @@ -92,7 +92,8 @@ PCIBus *pci_grackle_init(uint32_t base, void *pic)
92 92 int pci_mem_config, pci_mem_data;
93 93  
94 94 s = qemu_mallocz(sizeof(GrackleState));
95   - s->bus = pci_register_bus(pci_grackle_set_irq, pci_grackle_map_irq, pic, 0);
  95 + s->bus = pci_register_bus(pci_grackle_set_irq, pci_grackle_map_irq,
  96 + pic, 0, 0);
96 97  
97 98 pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read,
98 99 pci_grackle_config_write, s);
... ...
hw/pci.c
... ... @@ -35,9 +35,11 @@ struct PCIBus {
35 35 SetIRQFunc *low_set_irq;
36 36 void *irq_opaque;
37 37 PCIDevice *devices[256];
  38 + PCIDevice *parent_dev;
  39 + PCIBus *next;
38 40 /* The bus IRQ state is the logical OR of the connected devices.
39 41 Keep a count of the number of devices with raised IRQs. */
40   - int irq_count[4];
  42 + int irq_count[];
41 43 };
42 44  
43 45 static void pci_update_mappings(PCIDevice *d);
... ... @@ -47,19 +49,29 @@ static int pci_irq_index;
47 49 static PCIBus *first_bus;
48 50  
49 51 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
50   - void *pic, int devfn_min)
  52 + void *pic, int devfn_min, int nirq)
51 53 {
52 54 PCIBus *bus;
53   - bus = qemu_mallocz(sizeof(PCIBus));
  55 + bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
54 56 bus->set_irq = set_irq;
55 57 bus->map_irq = map_irq;
56 58 bus->irq_opaque = pic;
57 59 bus->devfn_min = devfn_min;
58   - memset(bus->irq_count, 0, sizeof(bus->irq_count));
59 60 first_bus = bus;
60 61 return bus;
61 62 }
62 63  
  64 +PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
  65 +{
  66 + PCIBus *bus;
  67 + bus = qemu_mallocz(sizeof(PCIBus));
  68 + bus->map_irq = map_irq;
  69 + bus->parent_dev = dev;
  70 + bus->next = dev->bus->next;
  71 + dev->bus->next = bus;
  72 + return bus;
  73 +}
  74 +
63 75 int pci_bus_num(PCIBus *s)
64 76 {
65 77 return s->bus_num;
... ... @@ -351,7 +363,9 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
351 363 addr, val, len);
352 364 #endif
353 365 bus_num = (addr >> 16) & 0xff;
354   - if (bus_num != 0)
  366 + while (s && s->bus_num != bus_num)
  367 + s = s->next;
  368 + if (!s)
355 369 return;
356 370 pci_dev = s->devices[(addr >> 8) & 0xff];
357 371 if (!pci_dev)
... ... @@ -372,7 +386,9 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
372 386 uint32_t val;
373 387  
374 388 bus_num = (addr >> 16) & 0xff;
375   - if (bus_num != 0)
  389 + while (s && s->bus_num != bus_num)
  390 + s= s->next;
  391 + if (!s)
376 392 goto fail;
377 393 pci_dev = s->devices[(addr >> 8) & 0xff];
378 394 if (!pci_dev) {
... ... @@ -411,11 +427,21 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
411 427 /* 0 <= irq_num <= 3. level must be 0 or 1 */
412 428 void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
413 429 {
414   - PCIBus *bus = pci_dev->bus;
  430 + PCIBus *bus;
  431 + int change;
  432 +
  433 + change = level - pci_dev->irq_state[irq_num];
  434 + if (!change)
  435 + return;
415 436  
416   - irq_num = bus->map_irq(pci_dev, irq_num);
417   - bus->irq_count[irq_num] += level - pci_dev->irq_state[irq_num];
418 437 pci_dev->irq_state[irq_num] = level;
  438 + bus = pci_dev->bus;
  439 + while (!bus->set_irq) {
  440 + irq_num = bus->map_irq(pci_dev, irq_num);
  441 + pci_dev = bus->parent_dev;
  442 + bus = pci_dev->bus;
  443 + }
  444 + bus->irq_count[irq_num] += change;
419 445 bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
420 446 }
421 447  
... ... @@ -465,6 +491,9 @@ static void pci_info_device(PCIDevice *d)
465 491 if (d->config[PCI_INTERRUPT_PIN] != 0) {
466 492 term_printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
467 493 }
  494 + if (class == 0x0604) {
  495 + term_printf(" BUS %d.\n", d->config[0x19]);
  496 + }
468 497 for(i = 0;i < PCI_NUM_REGIONS; i++) {
469 498 r = &d->io_regions[i];
470 499 if (r->size != 0) {
... ... @@ -478,14 +507,19 @@ static void pci_info_device(PCIDevice *d)
478 507 }
479 508 }
480 509 }
  510 + if (class == 0x0604 && d->config[0x19] != 0) {
  511 + pci_for_each_device(d->config[0x19], pci_info_device);
  512 + }
481 513 }
482 514  
483   -void pci_for_each_device(void (*fn)(PCIDevice *d))
  515 +void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
484 516 {
485 517 PCIBus *bus = first_bus;
486 518 PCIDevice *d;
487 519 int devfn;
488 520  
  521 + while (bus && bus->bus_num != bus_num)
  522 + bus = bus->next;
489 523 if (bus) {
490 524 for(devfn = 0; devfn < 256; devfn++) {
491 525 d = bus->devices[devfn];
... ... @@ -497,7 +531,7 @@ void pci_for_each_device(void (*fn)(PCIDevice *d))
497 531  
498 532 void pci_info(void)
499 533 {
500   - pci_for_each_device(pci_info_device);
  534 + pci_for_each_device(0, pci_info_device);
501 535 }
502 536  
503 537 /* Initialize a PCI NIC. */
... ... @@ -515,3 +549,50 @@ void pci_nic_init(PCIBus *bus, NICInfo *nd)
515 549 }
516 550 }
517 551  
  552 +typedef struct {
  553 + PCIDevice dev;
  554 + PCIBus *bus;
  555 +} PCIBridge;
  556 +
  557 +void pci_bridge_write_config(PCIDevice *d,
  558 + uint32_t address, uint32_t val, int len)
  559 +{
  560 + PCIBridge *s = (PCIBridge *)d;
  561 +
  562 + if (address == 0x19 || (address == 0x18 && len > 1)) {
  563 + if (address == 0x19)
  564 + s->bus->bus_num = val & 0xff;
  565 + else
  566 + s->bus->bus_num = (val >> 8) & 0xff;
  567 +#if defined(DEBUG_PCI)
  568 + printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
  569 +#endif
  570 + }
  571 + pci_default_write_config(d, address, val, len);
  572 +}
  573 +
  574 +PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
  575 + pci_map_irq_fn map_irq, const char *name)
  576 +{
  577 + PCIBridge *s;
  578 + s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
  579 + devfn, NULL, pci_bridge_write_config);
  580 + s->dev.config[0x00] = id >> 16;
  581 + s->dev.config[0x01] = id > 24;
  582 + s->dev.config[0x02] = id; // device_id
  583 + s->dev.config[0x03] = id >> 8;
  584 + s->dev.config[0x04] = 0x06; // command = bus master, pci mem
  585 + s->dev.config[0x05] = 0x00;
  586 + s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
  587 + s->dev.config[0x07] = 0x00; // status = fast devsel
  588 + s->dev.config[0x08] = 0x00; // revision
  589 + s->dev.config[0x09] = 0x00; // programming i/f
  590 + s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge
  591 + s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge
  592 + s->dev.config[0x0D] = 0x10; // latency_timer
  593 + s->dev.config[0x0E] = 0x81; // header_type
  594 + s->dev.config[0x1E] = 0xa0; // secondary status
  595 +
  596 + s->bus = pci_register_secondary_bus(&s->dev, map_irq);
  597 + return s->bus;
  598 +}
... ...
hw/piix_pci.c
... ... @@ -59,7 +59,7 @@ PCIBus *i440fx_init(void)
59 59 I440FXState *s;
60 60  
61 61 s = qemu_mallocz(sizeof(I440FXState));
62   - b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, NULL, 0);
  62 + b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, NULL, 0, 4);
63 63 s->bus = b;
64 64  
65 65 register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
... ... @@ -226,6 +226,7 @@ static uint32_t pci_bios_io_addr;
226 226 static uint32_t pci_bios_mem_addr;
227 227 /* host irqs corresponding to PCI irqs A-D */
228 228 static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
  229 +static int pci_bios_next_bus;
229 230  
230 231 static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
231 232 {
... ... @@ -320,6 +321,14 @@ static void pci_bios_init_device(PCIDevice *d)
320 321 pci_set_io_region_addr(d, 3, 0x374);
321 322 }
322 323 break;
  324 + case 0x0604:
  325 + /* PCI to PCI bridge. Assign bus ID and recurse to configure
  326 + devices on the secondary bus. */
  327 + i = pci_bios_next_bus++;
  328 + pci_config_writeb(d, 0x18, pci_bus_num(d->bus));
  329 + pci_config_writeb(d, 0x19, i);
  330 + pci_for_each_device(i, pci_bios_init_device);
  331 + break;
323 332 case 0x0300:
324 333 if (vendor_id != 0x1234)
325 334 goto default_map;
... ... @@ -398,6 +407,7 @@ void pci_bios_init(void)
398 407 isa_outb(elcr[0], 0x4d0);
399 408 isa_outb(elcr[1], 0x4d1);
400 409  
401   - pci_for_each_device(pci_bios_init_device);
  410 + pci_bios_next_bus = 1;
  411 + pci_for_each_device(0, pci_bios_init_device);
402 412 }
403 413  
... ...
hw/prep_pci.c
... ... @@ -120,18 +120,12 @@ static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
120 120 /* Don't know if this matches real hardware, but it agrees with OHW. */
121 121 static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
122 122 {
123   - return (irq_num + (pci_dev->devfn >> 3)) & 3;
  123 + return (irq_num + (pci_dev->devfn >> 3)) & 1;
124 124 }
125 125  
126   -static int prep_irq_levels[4];
127   -
128 126 static void prep_set_irq(void *pic, int irq_num, int level)
129 127 {
130   - int pic_irq_num;
131   - prep_irq_levels[irq_num] = level;
132   - level |= prep_irq_levels[irq_num ^ 2];
133   - pic_irq_num = (irq_num == 0 || irq_num == 2) ? 9 : 11;
134   - pic_set_irq(pic_irq_num, level);
  128 + pic_set_irq(irq_num ? 11 : 9, level);
135 129 }
136 130  
137 131 PCIBus *pci_prep_init(void)
... ... @@ -141,7 +135,7 @@ PCIBus *pci_prep_init(void)
141 135 int PPC_io_memory;
142 136  
143 137 s = qemu_mallocz(sizeof(PREPPCIState));
144   - s->bus = pci_register_bus(prep_set_irq, prep_map_irq, NULL, 0);
  138 + s->bus = pci_register_bus(prep_set_irq, prep_map_irq, NULL, 0, 2);
145 139  
146 140 register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
147 141 register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
... ...
hw/unin_pci.c
... ... @@ -161,7 +161,7 @@ PCIBus *pci_pmac_init(void *pic)
161 161 /* Uninorth main bus */
162 162 s = qemu_mallocz(sizeof(UNINState));
163 163 s->bus = pci_register_bus(pci_unin_set_irq, pci_unin_map_irq,
164   - pic, 11 << 3);
  164 + pic, 11 << 3, 4);
165 165  
166 166 pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read,
167 167 pci_unin_main_config_write, s);
... ...
hw/versatile_pci.c
... ... @@ -11,7 +11,7 @@
11 11  
12 12 static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr)
13 13 {
14   - return addr & 0xf8ff;
  14 + return addr & 0xffffff;
15 15 }
16 16  
17 17 static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr,
... ... @@ -105,15 +105,15 @@ PCIBus *pci_vpb_init(void *pic, int irq, int realview)
105 105 base = 0x40000000;
106 106 name = "Versatile/PB PCI Controller";
107 107 }
108   - s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, pic, 11 << 3);
  108 + s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, pic, 11 << 3, 4);
109 109 /* ??? Register memory space. */
110 110  
111 111 mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
112 112 pci_vpb_config_write, s);
113 113 /* Selfconfig area. */
114   - cpu_register_physical_memory(base + 0x01000000, 0x10000, mem_config);
  114 + cpu_register_physical_memory(base + 0x01000000, 0x1000000, mem_config);
115 115 /* Normal config area. */
116   - cpu_register_physical_memory(base + 0x02000000, 0x10000, mem_config);
  116 + cpu_register_physical_memory(base + 0x02000000, 0x1000000, mem_config);
117 117  
118 118 d = pci_register_device(s, name, sizeof(PCIDevice), -1, NULL, NULL);
119 119  
... ...
... ... @@ -759,15 +759,17 @@ int pci_device_load(PCIDevice *s, QEMUFile *f);
759 759 typedef void (*pci_set_irq_fn)(void *pic, int irq_num, int level);
760 760 typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
761 761 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
762   - void *pic, int devfn_min);
  762 + void *pic, int devfn_min, int nirq);
763 763  
764 764 void pci_nic_init(PCIBus *bus, NICInfo *nd);
765 765 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
766 766 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
767 767 int pci_bus_num(PCIBus *s);
768   -void pci_for_each_device(void (*fn)(PCIDevice *d));
  768 +void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
769 769  
770 770 void pci_info(void);
  771 +PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
  772 + pci_map_irq_fn map_irq, const char *name);
771 773  
772 774 /* prep_pci.c */
773 775 PCIBus *pci_prep_init(void);
... ...