diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-09-24 17:01:44 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-09-24 17:01:44 +0000 |
commit | 80b3ada7dd56088613a446934d144a747e740fa1 (patch) | |
tree | 3dc8bf29b3bee0c06772b56e5add4a7d5df2de23 /hw/apb_pci.c | |
parent | d2b5931756fdb9f839180e33898cd1e3e4fbdc90 (diff) |
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
Diffstat (limited to 'hw/apb_pci.c')
-rw-r--r-- | hw/apb_pci.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 6fa885e9ea..3ebe3207fe 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -21,6 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + +/* XXX This file and most of its contests are somewhat misnamed. The + Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is + the secondary PCI bridge. */ + #include "vl.h" typedef target_phys_addr_t pci_addr_t; #include "pci_host.h" @@ -179,17 +184,25 @@ static CPUReadMemoryFunc *pci_apb_ioread[] = { &pci_apb_ioreadl, }; +/* The APB host has an IRQ line for each IRQ line of each slot. */ static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num) { - /* ??? As mentioned below this is probably wrong. */ - return irq_num; + return ((pci_dev->devfn & 0x18) >> 1) + irq_num; +} + +static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num) +{ + int bus_offset; + if (pci_dev->devfn & 1) + bus_offset = 16; + else + bus_offset = 0; + return bus_offset + irq_num; } static void pci_apb_set_irq(void *pic, int irq_num, int level) { - /* ??? This is almost certainly wrong. However the rest of the sun4u - IRQ handling is missing, as is OpenBIOS support, so it wouldn't work - anyway. */ + /* PCI IRQ map onto the first 32 INO. */ pic_set_irq_new(pic, irq_num, level); } @@ -199,10 +212,12 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base, APBState *s; PCIDevice *d; int pci_mem_config, pci_mem_data, apb_config, pci_ioport; + PCIDevice *apb; + PCIBus *secondary; s = qemu_mallocz(sizeof(APBState)); - /* Ultrasparc APB main bus */ - s->bus = pci_register_bus(pci_apb_set_irq, pci_apb_map_irq, pic, 0); + /* Ultrasparc PBM main bus */ + s->bus = pci_register_bus(pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32); pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read, pci_apb_config_write, s); @@ -219,7 +234,7 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base, cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice), - -1, NULL, NULL); + 0, NULL, NULL); d->config[0x00] = 0x8e; // vendor_id : Sun d->config[0x01] = 0x10; d->config[0x02] = 0x00; // device_id @@ -234,7 +249,11 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base, d->config[0x0B] = 0x06; // class_base = PCI_bridge d->config[0x0D] = 0x10; // latency_timer d->config[0x0E] = 0x00; // header_type - return s->bus; + + /* APB secondary busses */ + secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq); + pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq); + return secondary; } |