Get rid of _t suffix
[qemu/kraxel.git] / hw / apb_pci.c
blob6bb032472844bc00f46f3dce34003cc8ec4307ed
1 /*
2 * QEMU Ultrasparc APB PCI host
4 * Copyright (c) 2006 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
25 /* XXX This file and most of its contents are somewhat misnamed. The
26 Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
27 the secondary PCI bridge. */
29 #include "sysbus.h"
30 #include "pci.h"
32 /* debug APB */
33 //#define DEBUG_APB
35 #ifdef DEBUG_APB
36 #define APB_DPRINTF(fmt, ...) \
37 do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
38 #else
39 #define APB_DPRINTF(fmt, ...)
40 #endif
42 typedef a_target_phys_addr a_pci_addr;
43 #include "pci_host.h"
45 typedef struct APBState {
46 SysBusDevice busdev;
47 PCIHostState host_state;
48 } APBState;
50 static void pci_apb_config_writel (void *opaque, a_target_phys_addr addr,
51 uint32_t val)
53 APBState *s = opaque;
55 #ifdef TARGET_WORDS_BIGENDIAN
56 val = bswap32(val);
57 #endif
58 APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
59 val);
60 s->host_state.config_reg = val;
63 static uint32_t pci_apb_config_readl (void *opaque,
64 a_target_phys_addr addr)
66 APBState *s = opaque;
67 uint32_t val;
69 val = s->host_state.config_reg;
70 #ifdef TARGET_WORDS_BIGENDIAN
71 val = bswap32(val);
72 #endif
73 APB_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
74 val);
75 return val;
78 static CPUWriteMemoryFunc * const pci_apb_config_write[] = {
79 &pci_apb_config_writel,
80 &pci_apb_config_writel,
81 &pci_apb_config_writel,
84 static CPUReadMemoryFunc * const pci_apb_config_read[] = {
85 &pci_apb_config_readl,
86 &pci_apb_config_readl,
87 &pci_apb_config_readl,
90 static void apb_config_writel (void *opaque, a_target_phys_addr addr,
91 uint32_t val)
93 //PCIBus *s = opaque;
95 switch (addr & 0x3f) {
96 case 0x00: // Control/Status
97 case 0x10: // AFSR
98 case 0x18: // AFAR
99 case 0x20: // Diagnostic
100 case 0x28: // Target address space
101 // XXX
102 default:
103 break;
107 static uint32_t apb_config_readl (void *opaque,
108 a_target_phys_addr addr)
110 //PCIBus *s = opaque;
111 uint32_t val;
113 switch (addr & 0x3f) {
114 case 0x00: // Control/Status
115 case 0x10: // AFSR
116 case 0x18: // AFAR
117 case 0x20: // Diagnostic
118 case 0x28: // Target address space
119 // XXX
120 default:
121 val = 0;
122 break;
124 return val;
127 static CPUWriteMemoryFunc * const apb_config_write[] = {
128 &apb_config_writel,
129 &apb_config_writel,
130 &apb_config_writel,
133 static CPUReadMemoryFunc * const apb_config_read[] = {
134 &apb_config_readl,
135 &apb_config_readl,
136 &apb_config_readl,
139 static CPUWriteMemoryFunc * const pci_apb_write[] = {
140 &pci_host_data_writeb,
141 &pci_host_data_writew,
142 &pci_host_data_writel,
145 static CPUReadMemoryFunc * const pci_apb_read[] = {
146 &pci_host_data_readb,
147 &pci_host_data_readw,
148 &pci_host_data_readl,
151 static void pci_apb_iowriteb (void *opaque, a_target_phys_addr addr,
152 uint32_t val)
154 cpu_outb(addr & IOPORTS_MASK, val);
157 static void pci_apb_iowritew (void *opaque, a_target_phys_addr addr,
158 uint32_t val)
160 cpu_outw(addr & IOPORTS_MASK, val);
163 static void pci_apb_iowritel (void *opaque, a_target_phys_addr addr,
164 uint32_t val)
166 cpu_outl(addr & IOPORTS_MASK, val);
169 static uint32_t pci_apb_ioreadb (void *opaque, a_target_phys_addr addr)
171 uint32_t val;
173 val = cpu_inb(addr & IOPORTS_MASK);
174 return val;
177 static uint32_t pci_apb_ioreadw (void *opaque, a_target_phys_addr addr)
179 uint32_t val;
181 val = cpu_inw(addr & IOPORTS_MASK);
182 return val;
185 static uint32_t pci_apb_ioreadl (void *opaque, a_target_phys_addr addr)
187 uint32_t val;
189 val = cpu_inl(addr & IOPORTS_MASK);
190 return val;
193 static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
194 &pci_apb_iowriteb,
195 &pci_apb_iowritew,
196 &pci_apb_iowritel,
199 static CPUReadMemoryFunc * const pci_apb_ioread[] = {
200 &pci_apb_ioreadb,
201 &pci_apb_ioreadw,
202 &pci_apb_ioreadl,
205 /* The APB host has an IRQ line for each IRQ line of each slot. */
206 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
208 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
211 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
213 int bus_offset;
214 if (pci_dev->devfn & 1)
215 bus_offset = 16;
216 else
217 bus_offset = 0;
218 return bus_offset + irq_num;
221 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
223 qemu_irq *pic = opaque;
225 /* PCI IRQ map onto the first 32 INO. */
226 qemu_set_irq(pic[irq_num], level);
229 PCIBus *pci_apb_init(a_target_phys_addr special_base,
230 a_target_phys_addr mem_base,
231 qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
233 DeviceState *dev;
234 SysBusDevice *s;
235 APBState *d;
237 /* Ultrasparc PBM main bus */
238 dev = qdev_create(NULL, "pbm");
239 qdev_init(dev);
240 s = sysbus_from_qdev(dev);
241 /* apb_config */
242 sysbus_mmio_map(s, 0, special_base + 0x2000ULL);
243 /* pci_ioport */
244 sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
245 /* mem_config: XXX size should be 4G-prom */
246 sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
247 /* mem_data */
248 sysbus_mmio_map(s, 3, mem_base);
249 d = FROM_SYSBUS(APBState, s);
250 d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
251 pci_apb_set_irq, pci_pbm_map_irq, pic,
252 0, 32);
253 pci_create_simple(d->host_state.bus, 0, "pbm");
254 /* APB secondary busses */
255 *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
256 PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
257 "Advanced PCI Bus secondary bridge 1");
258 *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
259 PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
260 "Advanced PCI Bus secondary bridge 2");
262 return d->host_state.bus;
265 static int pci_pbm_init_device(SysBusDevice *dev)
268 APBState *s;
269 int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
271 s = FROM_SYSBUS(APBState, dev);
272 /* apb_config */
273 apb_config = cpu_register_io_memory(apb_config_read,
274 apb_config_write, s);
275 sysbus_init_mmio(dev, 0x40ULL, apb_config);
276 /* pci_ioport */
277 pci_ioport = cpu_register_io_memory(pci_apb_ioread,
278 pci_apb_iowrite, s);
279 sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
280 /* mem_config */
281 pci_mem_config = cpu_register_io_memory(pci_apb_config_read,
282 pci_apb_config_write, s);
283 sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
284 /* mem_data */
285 pci_mem_data = cpu_register_io_memory(pci_apb_read,
286 pci_apb_write, &s->host_state);
287 sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
288 return 0;
291 static int pbm_pci_host_init(PCIDevice *d)
293 pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
294 pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
295 d->config[0x04] = 0x06; // command = bus master, pci mem
296 d->config[0x05] = 0x00;
297 d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
298 d->config[0x07] = 0x03; // status = medium devsel
299 d->config[0x08] = 0x00; // revision
300 d->config[0x09] = 0x00; // programming i/f
301 pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
302 d->config[0x0D] = 0x10; // latency_timer
303 d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
304 return 0;
307 static PCIDeviceInfo pbm_pci_host_info = {
308 .qdev.name = "pbm",
309 .qdev.size = sizeof(PCIDevice),
310 .init = pbm_pci_host_init,
313 static void pbm_register_devices(void)
315 sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
316 pci_qdev_register(&pbm_pci_host_info);
319 device_init(pbm_register_devices)