| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QEMU Ultrasparc APB PCI host | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2006 Fabrice Bellard | 
					
						
							| 
									
										
										
										
											2007-09-16 21:08:06 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | 
					
						
							|  |  |  |  * of this software and associated documentation files (the "Software"), to deal | 
					
						
							|  |  |  |  * in the Software without restriction, including without limitation the rights | 
					
						
							|  |  |  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
					
						
							|  |  |  |  * copies of the Software, and to permit persons to whom the Software is | 
					
						
							|  |  |  |  * furnished to do so, subject to the following conditions: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The above copyright notice and this permission notice shall be included in | 
					
						
							|  |  |  |  * all copies or substantial portions of the Software. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
					
						
							|  |  |  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | 
					
						
							|  |  |  |  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
					
						
							|  |  |  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
					
						
							|  |  |  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
					
						
							|  |  |  |  * THE SOFTWARE. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-09-24 17:01:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-09 20:53:30 +00:00
										 |  |  | /* XXX This file and most of its contents are somewhat misnamed.  The
 | 
					
						
							| 
									
										
										
										
											2006-09-24 17:01:44 +00:00
										 |  |  |    Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is | 
					
						
							|  |  |  |    the secondary PCI bridge.  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | #include "sysbus.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-12 14:24:50 +02:00
										 |  |  | #include "pci/pci.h"
 | 
					
						
							|  |  |  | #include "pci/pci_host.h"
 | 
					
						
							|  |  |  | #include "pci/pci_bridge.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-12 15:00:45 +02:00
										 |  |  | #include "pci/pci_bus.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-11 14:59:56 +02:00
										 |  |  | #include "apb_pci.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-17 18:20:04 +01:00
										 |  |  | #include "sysemu/sysemu.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-17 18:19:49 +01:00
										 |  |  | #include "exec/address-spaces.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-09 20:53:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* debug APB */ | 
					
						
							|  |  |  | //#define DEBUG_APB
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG_APB
 | 
					
						
							| 
									
										
										
										
											2009-05-13 17:53:17 +00:00
										 |  |  | #define APB_DPRINTF(fmt, ...) \
 | 
					
						
							|  |  |  | do { printf("APB: " fmt , ## __VA_ARGS__); } while (0) | 
					
						
							| 
									
										
										
										
											2009-01-09 20:53:30 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-05-13 17:53:17 +00:00
										 |  |  | #define APB_DPRINTF(fmt, ...)
 | 
					
						
							| 
									
										
										
										
											2009-01-09 20:53:30 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-13 18:56:27 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Chipset docs: | 
					
						
							|  |  |  |  * PBM: "UltraSPARC IIi User's Manual", | 
					
						
							|  |  |  |  * http://www.sun.com/processors/manuals/805-0087.pdf
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * APB: "Advanced PCI Bridge (APB) User's Manual", | 
					
						
							|  |  |  |  * http://www.sun.com/processors/manuals/805-1251.pdf
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | #define PBM_PCI_IMR_MASK    0x7fffffff
 | 
					
						
							|  |  |  | #define PBM_PCI_IMR_ENABLED 0x80000000
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define POR          (1 << 31)
 | 
					
						
							|  |  |  | #define SOFT_POR     (1 << 30)
 | 
					
						
							|  |  |  | #define SOFT_XIR     (1 << 29)
 | 
					
						
							|  |  |  | #define BTN_POR      (1 << 28)
 | 
					
						
							|  |  |  | #define BTN_XIR      (1 << 27)
 | 
					
						
							|  |  |  | #define RESET_MASK   0xf8000000
 | 
					
						
							|  |  |  | #define RESET_WCMASK 0x98000000
 | 
					
						
							|  |  |  | #define RESET_WMASK  0x60000000
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  | #define MAX_IVEC 0x30
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | typedef struct APBState { | 
					
						
							|  |  |  |     SysBusDevice busdev; | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     PCIBus      *bus; | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |     MemoryRegion apb_config; | 
					
						
							|  |  |  |     MemoryRegion pci_config; | 
					
						
							| 
									
										
										
										
											2011-09-03 16:38:02 +00:00
										 |  |  |     MemoryRegion pci_mmio; | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |     MemoryRegion pci_ioport; | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     uint32_t iommu[4]; | 
					
						
							|  |  |  |     uint32_t pci_control[16]; | 
					
						
							|  |  |  |     uint32_t pci_irq_map[8]; | 
					
						
							|  |  |  |     uint32_t obio_irq_map[32]; | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |     qemu_irq *pbm_irqs; | 
					
						
							|  |  |  |     qemu_irq *ivec_irqs; | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     uint32_t reset_control; | 
					
						
							| 
									
										
										
										
											2010-05-12 19:27:23 +00:00
										 |  |  |     unsigned int nr_resets; | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | } APBState; | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 11:15:23 +02:00
										 |  |  | static void pci_apb_set_irq(void *opaque, int irq_num, int level); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static void apb_config_writel (void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |                                uint64_t val, unsigned size) | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     APBState *s = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |     APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val); | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (addr & 0xffff) { | 
					
						
							|  |  |  |     case 0x30 ... 0x4f: /* DMA error registers */ | 
					
						
							|  |  |  |         /* XXX: not implemented yet */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0x200 ... 0x20b: /* IOMMU */ | 
					
						
							|  |  |  |         s->iommu[(addr & 0xf) >> 2] = val; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0x20c ... 0x3ff: /* IOMMU flush */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0xc00 ... 0xc3f: /* PCI interrupt control */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK; | 
					
						
							|  |  |  |             s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |     case 0x1000 ... 0x1080: /* OBIO interrupt control */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK; | 
					
						
							|  |  |  |             s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-05-12 11:15:23 +02:00
										 |  |  |     case 0x1400 ... 0x143f: /* PCI interrupt clear */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             pci_apb_set_irq(s, (addr & 0x3f) >> 3, 0); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0x1800 ... 0x1860: /* OBIO interrupt clear */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             pci_apb_set_irq(s, 0x20 | ((addr & 0xff) >> 3), 0); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     case 0x2000 ... 0x202f: /* PCI control */ | 
					
						
							|  |  |  |         s->pci_control[(addr & 0x3f) >> 2] = val; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0xf020 ... 0xf027: /* Reset control */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             val &= RESET_MASK; | 
					
						
							|  |  |  |             s->reset_control &= ~(val & RESET_WCMASK); | 
					
						
							|  |  |  |             s->reset_control |= val & RESET_WMASK; | 
					
						
							|  |  |  |             if (val & SOFT_POR) { | 
					
						
							| 
									
										
										
										
											2010-05-12 19:27:23 +00:00
										 |  |  |                 s->nr_resets = 0; | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |                 qemu_system_reset_request(); | 
					
						
							|  |  |  |             } else if (val & SOFT_XIR) { | 
					
						
							|  |  |  |                 qemu_system_reset_request(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */ | 
					
						
							|  |  |  |     case 0xa400 ... 0xa67f: /* IOMMU diagnostics */ | 
					
						
							|  |  |  |     case 0xa800 ... 0xa80f: /* Interrupt diagnostics */ | 
					
						
							|  |  |  |     case 0xf000 ... 0xf01f: /* FFB config, memory control */ | 
					
						
							|  |  |  |         /* we don't care */ | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2007-10-06 11:28:21 +00:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  | static uint64_t apb_config_readl (void *opaque, | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  |                                   hwaddr addr, unsigned size) | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     APBState *s = opaque; | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     uint32_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     switch (addr & 0xffff) { | 
					
						
							|  |  |  |     case 0x30 ... 0x4f: /* DMA error registers */ | 
					
						
							|  |  |  |         val = 0; | 
					
						
							|  |  |  |         /* XXX: not implemented yet */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0x200 ... 0x20b: /* IOMMU */ | 
					
						
							|  |  |  |         val = s->iommu[(addr & 0xf) >> 2]; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0x20c ... 0x3ff: /* IOMMU flush */ | 
					
						
							|  |  |  |         val = 0; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0xc00 ... 0xc3f: /* PCI interrupt control */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             val = s->pci_irq_map[(addr & 0x3f) >> 3]; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             val = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |     case 0x1000 ... 0x1080: /* OBIO interrupt control */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             val = s->obio_irq_map[(addr & 0xff) >> 3]; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             val = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     case 0x2000 ... 0x202f: /* PCI control */ | 
					
						
							|  |  |  |         val = s->pci_control[(addr & 0x3f) >> 2]; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0xf020 ... 0xf027: /* Reset control */ | 
					
						
							|  |  |  |         if (addr & 4) { | 
					
						
							|  |  |  |             val = s->reset_control; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             val = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */ | 
					
						
							|  |  |  |     case 0xa400 ... 0xa67f: /* IOMMU diagnostics */ | 
					
						
							|  |  |  |     case 0xa800 ... 0xa80f: /* Interrupt diagnostics */ | 
					
						
							|  |  |  |     case 0xf000 ... 0xf01f: /* FFB config, memory control */ | 
					
						
							|  |  |  |         /* we don't care */ | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2007-10-06 11:28:21 +00:00
										 |  |  |         val = 0; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  | static const MemoryRegionOps apb_config_ops = { | 
					
						
							|  |  |  |     .read = apb_config_readl, | 
					
						
							|  |  |  |     .write = apb_config_writel, | 
					
						
							|  |  |  |     .endianness = DEVICE_NATIVE_ENDIAN, | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static void apb_pci_config_write(void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |                                  uint64_t val, unsigned size) | 
					
						
							| 
									
										
										
										
											2010-01-11 21:20:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |     APBState *s = opaque; | 
					
						
							| 
									
										
										
										
											2010-02-22 12:38:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     val = qemu_bswap_len(val, size); | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |     APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     pci_data_write(s->bus, addr, val, size); | 
					
						
							| 
									
										
										
										
											2010-01-11 21:20:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static uint64_t apb_pci_config_read(void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |                                     unsigned size) | 
					
						
							| 
									
										
										
										
											2010-01-11 21:20:53 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     uint32_t ret; | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |     APBState *s = opaque; | 
					
						
							| 
									
										
										
										
											2010-01-11 21:20:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     ret = pci_data_read(s->bus, addr, size); | 
					
						
							| 
									
										
										
										
											2010-02-22 12:38:25 +02:00
										 |  |  |     ret = qemu_bswap_len(ret, size); | 
					
						
							| 
									
										
										
										
											2010-01-11 21:20:53 +00:00
										 |  |  |     APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static void pci_apb_iowriteb (void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |                                   uint32_t val) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-20 16:05:47 +00:00
										 |  |  |     cpu_outb(addr & IOPORTS_MASK, val); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static void pci_apb_iowritew (void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |                                   uint32_t val) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-29 18:15:21 +00:00
										 |  |  |     cpu_outw(addr & IOPORTS_MASK, bswap16(val)); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static void pci_apb_iowritel (void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |                                 uint32_t val) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-29 18:15:21 +00:00
										 |  |  |     cpu_outl(addr & IOPORTS_MASK, bswap32(val)); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr) | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     uint32_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-20 16:05:47 +00:00
										 |  |  |     val = cpu_inb(addr & IOPORTS_MASK); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr) | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     uint32_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-29 18:15:21 +00:00
										 |  |  |     val = bswap16(cpu_inw(addr & IOPORTS_MASK)); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr) | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     uint32_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-29 18:15:21 +00:00
										 |  |  |     val = bswap32(cpu_inl(addr & IOPORTS_MASK)); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  | static const MemoryRegionOps pci_ioport_ops = { | 
					
						
							|  |  |  |     .old_mmio = { | 
					
						
							|  |  |  |         .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl }, | 
					
						
							|  |  |  |         .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, }, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     .endianness = DEVICE_NATIVE_ENDIAN, | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-24 17:01:44 +00:00
										 |  |  | /* The APB host has an IRQ line for each IRQ line of each slot.  */ | 
					
						
							| 
									
										
										
										
											2006-09-24 00:16:34 +00:00
										 |  |  | static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num) | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-24 17:01:44 +00:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2006-09-24 00:16:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-28 15:28:17 +02:00
										 |  |  | static void pci_apb_set_irq(void *opaque, int irq_num, int level) | 
					
						
							| 
									
										
										
										
											2006-09-24 00:16:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     APBState *s = opaque; | 
					
						
							| 
									
										
										
										
											2009-08-28 15:28:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-24 17:01:44 +00:00
										 |  |  |     /* PCI IRQ map onto the first 32 INO.  */ | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     if (irq_num < 32) { | 
					
						
							|  |  |  |         if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) { | 
					
						
							|  |  |  |             APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level); | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |             qemu_set_irq(s->ivec_irqs[irq_num], level); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num); | 
					
						
							|  |  |  |             qemu_irq_lower(s->ivec_irqs[irq_num]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         /* OBIO IRQ map onto the next 16 INO.  */ | 
					
						
							|  |  |  |         if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) { | 
					
						
							|  |  |  |             APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level); | 
					
						
							|  |  |  |             qemu_set_irq(s->ivec_irqs[irq_num], level); | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num); | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |             qemu_irq_lower(s->ivec_irqs[irq_num]); | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-13 13:01:42 +09:00
										 |  |  | static int apb_pci_bridge_initfn(PCIDevice *dev) | 
					
						
							| 
									
										
										
										
											2009-11-11 14:33:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-13 13:01:42 +09:00
										 |  |  |     int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rc = pci_bridge_initfn(dev); | 
					
						
							|  |  |  |     if (rc < 0) { | 
					
						
							|  |  |  |         return rc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-11 14:33:54 +02:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * command register: | 
					
						
							|  |  |  |      * According to PCI bridge spec, after reset | 
					
						
							|  |  |  |      *   bus master bit is off | 
					
						
							|  |  |  |      *   memory space enable bit is off | 
					
						
							|  |  |  |      * According to manual (805-1251.pdf). | 
					
						
							|  |  |  |      *   the reset value should be zero unless the boot pin is tied high | 
					
						
							|  |  |  |      *   (which is true) and thus it should be PCI_COMMAND_MEMORY. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     pci_set_word(dev->config + PCI_COMMAND, | 
					
						
							| 
									
										
										
										
											2010-02-14 08:27:19 +00:00
										 |  |  |                  PCI_COMMAND_MEMORY); | 
					
						
							|  |  |  |     pci_set_word(dev->config + PCI_STATUS, | 
					
						
							|  |  |  |                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | | 
					
						
							|  |  |  |                  PCI_STATUS_DEVSEL_MEDIUM); | 
					
						
							| 
									
										
										
										
											2010-07-13 13:01:42 +09:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2009-11-11 14:33:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | PCIBus *pci_apb_init(hwaddr special_base, | 
					
						
							|  |  |  |                      hwaddr mem_base, | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |                      qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3, | 
					
						
							|  |  |  |                      qemu_irq **pbm_irqs) | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     DeviceState *dev; | 
					
						
							|  |  |  |     SysBusDevice *s; | 
					
						
							|  |  |  |     APBState *d; | 
					
						
							| 
									
										
										
										
											2010-07-13 13:01:42 +09:00
										 |  |  |     PCIDevice *pci_dev; | 
					
						
							|  |  |  |     PCIBridge *br; | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-24 17:01:44 +00:00
										 |  |  |     /* Ultrasparc PBM main bus */ | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     dev = qdev_create(NULL, "pbm"); | 
					
						
							| 
									
										
										
										
											2009-10-07 01:15:58 +02:00
										 |  |  |     qdev_init_nofail(dev); | 
					
						
							| 
									
										
										
										
											2013-01-20 02:47:33 +01:00
										 |  |  |     s = SYS_BUS_DEVICE(dev); | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     /* apb_config */ | 
					
						
							| 
									
										
										
										
											2010-01-10 18:25:48 +00:00
										 |  |  |     sysbus_mmio_map(s, 0, special_base); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     /* PCI configuration space */ | 
					
						
							|  |  |  |     sysbus_mmio_map(s, 1, special_base + 0x1000000ULL); | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     /* pci_ioport */ | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     sysbus_mmio_map(s, 2, special_base + 0x2000000ULL); | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     d = FROM_SYSBUS(APBState, s); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-03 16:38:02 +00:00
										 |  |  |     memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); | 
					
						
							|  |  |  |     memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     d->bus = pci_register_bus(&d->busdev.qdev, "pci", | 
					
						
							| 
									
										
										
										
											2011-09-03 16:38:02 +00:00
										 |  |  |                               pci_apb_set_irq, pci_pbm_map_irq, d, | 
					
						
							|  |  |  |                               &d->pci_mmio, | 
					
						
							|  |  |  |                               get_system_io(), | 
					
						
							|  |  |  |                               0, 32); | 
					
						
							| 
									
										
										
										
											2009-12-27 20:52:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |     *pbm_irqs = d->pbm_irqs; | 
					
						
							|  |  |  |     d->ivec_irqs = ivec_irqs; | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-25 13:37:36 -06:00
										 |  |  |     pci_create_simple(d->bus, 0, "pbm-pci"); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     /* APB secondary busses */ | 
					
						
							| 
									
										
										
										
											2010-07-13 13:01:42 +09:00
										 |  |  |     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true, | 
					
						
							|  |  |  |                                    "pbm-bridge"); | 
					
						
							|  |  |  |     br = DO_UPCAST(PCIBridge, dev, pci_dev); | 
					
						
							|  |  |  |     pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1", | 
					
						
							|  |  |  |                        pci_apb_map_irq); | 
					
						
							|  |  |  |     qdev_init_nofail(&pci_dev->qdev); | 
					
						
							|  |  |  |     *bus2 = pci_bridge_get_sec_bus(br); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true, | 
					
						
							|  |  |  |                                    "pbm-bridge"); | 
					
						
							|  |  |  |     br = DO_UPCAST(PCIBridge, dev, pci_dev); | 
					
						
							|  |  |  |     pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2", | 
					
						
							|  |  |  |                        pci_apb_map_irq); | 
					
						
							|  |  |  |     qdev_init_nofail(&pci_dev->qdev); | 
					
						
							|  |  |  |     *bus3 = pci_bridge_get_sec_bus(br); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     return d->bus; | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | static void pci_pbm_reset(DeviceState *d) | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     unsigned int i; | 
					
						
							|  |  |  |     APBState *s = container_of(d, APBState, busdev.qdev); | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     for (i = 0; i < 8; i++) { | 
					
						
							|  |  |  |         s->pci_irq_map[i] &= PBM_PCI_IMR_MASK; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-05-12 11:15:22 +02:00
										 |  |  |     for (i = 0; i < 32; i++) { | 
					
						
							|  |  |  |         s->obio_irq_map[i] &= PBM_PCI_IMR_MASK; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 19:27:23 +00:00
										 |  |  |     if (s->nr_resets++ == 0) { | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |         /* Power on reset */ | 
					
						
							|  |  |  |         s->reset_control = POR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  | static const MemoryRegionOps pci_config_ops = { | 
					
						
							|  |  |  |     .read = apb_pci_config_read, | 
					
						
							|  |  |  |     .write = apb_pci_config_write, | 
					
						
							|  |  |  |     .endianness = DEVICE_NATIVE_ENDIAN, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | static int pci_pbm_init_device(SysBusDevice *dev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     APBState *s; | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     unsigned int i; | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     s = FROM_SYSBUS(APBState, dev); | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  |     for (i = 0; i < 8; i++) { | 
					
						
							|  |  |  |         s->pci_irq_map[i] = (0x1f << 6) | (i << 2); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-05-12 11:15:22 +02:00
										 |  |  |     for (i = 0; i < 32; i++) { | 
					
						
							|  |  |  |         s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-03-10 20:37:00 +00:00
										 |  |  |     s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC); | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  |     /* apb_config */ | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |     memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config", | 
					
						
							|  |  |  |                           0x10000); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     /* at region 0 */ | 
					
						
							| 
									
										
										
										
											2011-11-27 11:38:10 +02:00
										 |  |  |     sysbus_init_mmio(dev, &s->apb_config); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |     memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config", | 
					
						
							|  |  |  |                           0x1000000); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     /* at region 1 */ | 
					
						
							| 
									
										
										
										
											2011-11-27 11:38:10 +02:00
										 |  |  |     sysbus_init_mmio(dev, &s->pci_config); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* pci_ioport */ | 
					
						
							| 
									
										
										
										
											2011-08-15 17:17:15 +03:00
										 |  |  |     memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s, | 
					
						
							|  |  |  |                           "apb-pci-ioport", 0x10000); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  |     /* at region 2 */ | 
					
						
							| 
									
										
										
										
											2011-11-27 11:38:10 +02:00
										 |  |  |     sysbus_init_mmio(dev, &s->pci_ioport); | 
					
						
							| 
									
										
										
										
											2010-05-25 16:09:03 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-14 10:36:05 +02:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-14 10:36:05 +02:00
										 |  |  | static int pbm_pci_host_init(PCIDevice *d) | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-14 08:27:19 +00:00
										 |  |  |     pci_set_word(d->config + PCI_COMMAND, | 
					
						
							|  |  |  |                  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | 
					
						
							|  |  |  |     pci_set_word(d->config + PCI_STATUS, | 
					
						
							|  |  |  |                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | | 
					
						
							|  |  |  |                  PCI_STATUS_DEVSEL_MEDIUM); | 
					
						
							| 
									
										
										
										
											2009-08-14 10:36:05 +02:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-09-24 17:01:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-04 12:22:06 -06:00
										 |  |  | static void pbm_pci_host_class_init(ObjectClass *klass, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     k->init = pbm_pci_host_init; | 
					
						
							|  |  |  |     k->vendor_id = PCI_VENDOR_ID_SUN; | 
					
						
							|  |  |  |     k->device_id = PCI_DEVICE_ID_SUN_SABRE; | 
					
						
							|  |  |  |     k->class_id = PCI_CLASS_BRIDGE_HOST; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-10 16:19:07 +01:00
										 |  |  | static const TypeInfo pbm_pci_host_info = { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     .name          = "pbm-pci", | 
					
						
							|  |  |  |     .parent        = TYPE_PCI_DEVICE, | 
					
						
							|  |  |  |     .instance_size = sizeof(PCIDevice), | 
					
						
							|  |  |  |     .class_init    = pbm_pci_host_class_init, | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 13:12:29 -06:00
										 |  |  | static void pbm_host_class_init(ObjectClass *klass, void *data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     DeviceClass *dc = DEVICE_CLASS(klass); | 
					
						
							| 
									
										
										
										
											2012-01-24 13:12:29 -06:00
										 |  |  |     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     k->init = pci_pbm_init_device; | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     dc->reset = pci_pbm_reset; | 
					
						
							| 
									
										
										
										
											2012-01-24 13:12:29 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-10 16:19:07 +01:00
										 |  |  | static const TypeInfo pbm_host_info = { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     .name          = "pbm", | 
					
						
							|  |  |  |     .parent        = TYPE_SYS_BUS_DEVICE, | 
					
						
							|  |  |  |     .instance_size = sizeof(APBState), | 
					
						
							|  |  |  |     .class_init    = pbm_host_class_init, | 
					
						
							| 
									
										
										
										
											2010-01-30 19:48:12 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2010-07-13 13:01:42 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-04 12:22:06 -06:00
										 |  |  | static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     DeviceClass *dc = DEVICE_CLASS(klass); | 
					
						
							| 
									
										
										
										
											2011-12-04 12:22:06 -06:00
										 |  |  |     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     k->init = apb_pci_bridge_initfn; | 
					
						
							|  |  |  |     k->exit = pci_bridge_exitfn; | 
					
						
							|  |  |  |     k->vendor_id = PCI_VENDOR_ID_SUN; | 
					
						
							|  |  |  |     k->device_id = PCI_DEVICE_ID_SUN_SIMBA; | 
					
						
							|  |  |  |     k->revision = 0x11; | 
					
						
							|  |  |  |     k->config_write = pci_bridge_write_config; | 
					
						
							|  |  |  |     k->is_bridge = 1; | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     dc->reset = pci_bridge_reset; | 
					
						
							|  |  |  |     dc->vmsd = &vmstate_pci_device; | 
					
						
							| 
									
										
										
										
											2011-12-04 12:22:06 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-10 16:19:07 +01:00
										 |  |  | static const TypeInfo pbm_pci_bridge_info = { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     .name          = "pbm-bridge", | 
					
						
							|  |  |  |     .parent        = TYPE_PCI_DEVICE, | 
					
						
							|  |  |  |     .instance_size = sizeof(PCIBridge), | 
					
						
							|  |  |  |     .class_init    = pbm_pci_bridge_class_init, | 
					
						
							| 
									
										
										
										
											2010-07-13 13:01:42 +09:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-09 15:20:55 +01:00
										 |  |  | static void pbm_register_types(void) | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     type_register_static(&pbm_host_info); | 
					
						
							|  |  |  |     type_register_static(&pbm_pci_host_info); | 
					
						
							|  |  |  |     type_register_static(&pbm_pci_bridge_info); | 
					
						
							| 
									
										
										
										
											2006-05-13 16:11:23 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-07-21 08:36:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-09 15:20:55 +01:00
										 |  |  | type_init(pbm_register_types) |