Merge remote-tracking branch 'qemu-kvm/memory/core' into staging
[qemu.git] / hw / apb_pci.c
blob6ee2068128c082329af9f4cb71dbf20e11def95e
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"
31 #include "pci_host.h"
32 #include "pci_bridge.h"
33 #include "pci_internals.h"
34 #include "apb_pci.h"
35 #include "sysemu.h"
36 #include "exec-memory.h"
38 /* debug APB */
39 //#define DEBUG_APB
41 #ifdef DEBUG_APB
42 #define APB_DPRINTF(fmt, ...) \
43 do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
44 #else
45 #define APB_DPRINTF(fmt, ...)
46 #endif
49 * Chipset docs:
50 * PBM: "UltraSPARC IIi User's Manual",
51 * http://www.sun.com/processors/manuals/805-0087.pdf
53 * APB: "Advanced PCI Bridge (APB) User's Manual",
54 * http://www.sun.com/processors/manuals/805-1251.pdf
57 #define PBM_PCI_IMR_MASK 0x7fffffff
58 #define PBM_PCI_IMR_ENABLED 0x80000000
60 #define POR (1 << 31)
61 #define SOFT_POR (1 << 30)
62 #define SOFT_XIR (1 << 29)
63 #define BTN_POR (1 << 28)
64 #define BTN_XIR (1 << 27)
65 #define RESET_MASK 0xf8000000
66 #define RESET_WCMASK 0x98000000
67 #define RESET_WMASK 0x60000000
69 typedef struct APBState {
70 SysBusDevice busdev;
71 PCIBus *bus;
72 MemoryRegion apb_config;
73 MemoryRegion pci_config;
74 MemoryRegion pci_ioport;
75 uint32_t iommu[4];
76 uint32_t pci_control[16];
77 uint32_t pci_irq_map[8];
78 uint32_t obio_irq_map[32];
79 qemu_irq pci_irqs[32];
80 uint32_t reset_control;
81 unsigned int nr_resets;
82 } APBState;
84 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
85 uint64_t val, unsigned size)
87 APBState *s = opaque;
89 APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
91 switch (addr & 0xffff) {
92 case 0x30 ... 0x4f: /* DMA error registers */
93 /* XXX: not implemented yet */
94 break;
95 case 0x200 ... 0x20b: /* IOMMU */
96 s->iommu[(addr & 0xf) >> 2] = val;
97 break;
98 case 0x20c ... 0x3ff: /* IOMMU flush */
99 break;
100 case 0xc00 ... 0xc3f: /* PCI interrupt control */
101 if (addr & 4) {
102 s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
103 s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
105 break;
106 case 0x2000 ... 0x202f: /* PCI control */
107 s->pci_control[(addr & 0x3f) >> 2] = val;
108 break;
109 case 0xf020 ... 0xf027: /* Reset control */
110 if (addr & 4) {
111 val &= RESET_MASK;
112 s->reset_control &= ~(val & RESET_WCMASK);
113 s->reset_control |= val & RESET_WMASK;
114 if (val & SOFT_POR) {
115 s->nr_resets = 0;
116 qemu_system_reset_request();
117 } else if (val & SOFT_XIR) {
118 qemu_system_reset_request();
121 break;
122 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
123 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
124 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
125 case 0xf000 ... 0xf01f: /* FFB config, memory control */
126 /* we don't care */
127 default:
128 break;
132 static uint64_t apb_config_readl (void *opaque,
133 target_phys_addr_t addr, unsigned size)
135 APBState *s = opaque;
136 uint32_t val;
138 switch (addr & 0xffff) {
139 case 0x30 ... 0x4f: /* DMA error registers */
140 val = 0;
141 /* XXX: not implemented yet */
142 break;
143 case 0x200 ... 0x20b: /* IOMMU */
144 val = s->iommu[(addr & 0xf) >> 2];
145 break;
146 case 0x20c ... 0x3ff: /* IOMMU flush */
147 val = 0;
148 break;
149 case 0xc00 ... 0xc3f: /* PCI interrupt control */
150 if (addr & 4) {
151 val = s->pci_irq_map[(addr & 0x3f) >> 3];
152 } else {
153 val = 0;
155 break;
156 case 0x2000 ... 0x202f: /* PCI control */
157 val = s->pci_control[(addr & 0x3f) >> 2];
158 break;
159 case 0xf020 ... 0xf027: /* Reset control */
160 if (addr & 4) {
161 val = s->reset_control;
162 } else {
163 val = 0;
165 break;
166 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
167 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
168 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
169 case 0xf000 ... 0xf01f: /* FFB config, memory control */
170 /* we don't care */
171 default:
172 val = 0;
173 break;
175 APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
177 return val;
180 static const MemoryRegionOps apb_config_ops = {
181 .read = apb_config_readl,
182 .write = apb_config_writel,
183 .endianness = DEVICE_NATIVE_ENDIAN,
186 static void apb_pci_config_write(void *opaque, target_phys_addr_t addr,
187 uint64_t val, unsigned size)
189 APBState *s = opaque;
191 val = qemu_bswap_len(val, size);
192 APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
193 pci_data_write(s->bus, addr, val, size);
196 static uint64_t apb_pci_config_read(void *opaque, target_phys_addr_t addr,
197 unsigned size)
199 uint32_t ret;
200 APBState *s = opaque;
202 ret = pci_data_read(s->bus, addr, size);
203 ret = qemu_bswap_len(ret, size);
204 APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
205 return ret;
208 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
209 uint32_t val)
211 cpu_outb(addr & IOPORTS_MASK, val);
214 static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
215 uint32_t val)
217 cpu_outw(addr & IOPORTS_MASK, bswap16(val));
220 static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
221 uint32_t val)
223 cpu_outl(addr & IOPORTS_MASK, bswap32(val));
226 static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
228 uint32_t val;
230 val = cpu_inb(addr & IOPORTS_MASK);
231 return val;
234 static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
236 uint32_t val;
238 val = bswap16(cpu_inw(addr & IOPORTS_MASK));
239 return val;
242 static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
244 uint32_t val;
246 val = bswap32(cpu_inl(addr & IOPORTS_MASK));
247 return val;
250 static const MemoryRegionOps pci_ioport_ops = {
251 .old_mmio = {
252 .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
253 .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
255 .endianness = DEVICE_NATIVE_ENDIAN,
258 /* The APB host has an IRQ line for each IRQ line of each slot. */
259 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
261 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
264 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
266 int bus_offset;
267 if (pci_dev->devfn & 1)
268 bus_offset = 16;
269 else
270 bus_offset = 0;
271 return bus_offset + irq_num;
274 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
276 APBState *s = opaque;
278 /* PCI IRQ map onto the first 32 INO. */
279 if (irq_num < 32) {
280 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
281 APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
282 qemu_set_irq(s->pci_irqs[irq_num], level);
283 } else {
284 APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
285 qemu_irq_lower(s->pci_irqs[irq_num]);
290 static int apb_pci_bridge_initfn(PCIDevice *dev)
292 int rc;
294 rc = pci_bridge_initfn(dev);
295 if (rc < 0) {
296 return rc;
300 * command register:
301 * According to PCI bridge spec, after reset
302 * bus master bit is off
303 * memory space enable bit is off
304 * According to manual (805-1251.pdf).
305 * the reset value should be zero unless the boot pin is tied high
306 * (which is true) and thus it should be PCI_COMMAND_MEMORY.
308 pci_set_word(dev->config + PCI_COMMAND,
309 PCI_COMMAND_MEMORY);
310 pci_set_word(dev->config + PCI_STATUS,
311 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
312 PCI_STATUS_DEVSEL_MEDIUM);
313 return 0;
316 PCIBus *pci_apb_init(target_phys_addr_t special_base,
317 target_phys_addr_t mem_base,
318 qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
320 DeviceState *dev;
321 SysBusDevice *s;
322 APBState *d;
323 unsigned int i;
324 PCIDevice *pci_dev;
325 PCIBridge *br;
327 /* Ultrasparc PBM main bus */
328 dev = qdev_create(NULL, "pbm");
329 qdev_init_nofail(dev);
330 s = sysbus_from_qdev(dev);
331 /* apb_config */
332 sysbus_mmio_map(s, 0, special_base);
333 /* PCI configuration space */
334 sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
335 /* pci_ioport */
336 sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
337 d = FROM_SYSBUS(APBState, s);
339 d->bus = pci_register_bus(&d->busdev.qdev, "pci",
340 pci_apb_set_irq, pci_pbm_map_irq, d,
341 get_system_memory(),
342 get_system_io(),
343 0, 32);
344 pci_bus_set_mem_base(d->bus, mem_base);
346 for (i = 0; i < 32; i++) {
347 sysbus_connect_irq(s, i, pic[i]);
350 pci_create_simple(d->bus, 0, "pbm");
352 /* APB secondary busses */
353 pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
354 "pbm-bridge");
355 br = DO_UPCAST(PCIBridge, dev, pci_dev);
356 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
357 pci_apb_map_irq);
358 qdev_init_nofail(&pci_dev->qdev);
359 *bus2 = pci_bridge_get_sec_bus(br);
361 pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
362 "pbm-bridge");
363 br = DO_UPCAST(PCIBridge, dev, pci_dev);
364 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
365 pci_apb_map_irq);
366 qdev_init_nofail(&pci_dev->qdev);
367 *bus3 = pci_bridge_get_sec_bus(br);
369 return d->bus;
372 static void pci_pbm_reset(DeviceState *d)
374 unsigned int i;
375 APBState *s = container_of(d, APBState, busdev.qdev);
377 for (i = 0; i < 8; i++) {
378 s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
381 if (s->nr_resets++ == 0) {
382 /* Power on reset */
383 s->reset_control = POR;
387 static const MemoryRegionOps pci_config_ops = {
388 .read = apb_pci_config_read,
389 .write = apb_pci_config_write,
390 .endianness = DEVICE_NATIVE_ENDIAN,
393 static int pci_pbm_init_device(SysBusDevice *dev)
395 APBState *s;
396 unsigned int i;
398 s = FROM_SYSBUS(APBState, dev);
399 for (i = 0; i < 8; i++) {
400 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
402 for (i = 0; i < 32; i++) {
403 sysbus_init_irq(dev, &s->pci_irqs[i]);
406 /* apb_config */
407 memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
408 0x10000);
409 /* at region 0 */
410 sysbus_init_mmio_region(dev, &s->apb_config);
412 memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
413 0x1000000);
414 /* at region 1 */
415 sysbus_init_mmio_region(dev, &s->pci_config);
417 /* pci_ioport */
418 memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
419 "apb-pci-ioport", 0x10000);
420 /* at region 2 */
421 sysbus_init_mmio_region(dev, &s->pci_ioport);
423 return 0;
426 static int pbm_pci_host_init(PCIDevice *d)
428 pci_set_word(d->config + PCI_COMMAND,
429 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
430 pci_set_word(d->config + PCI_STATUS,
431 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
432 PCI_STATUS_DEVSEL_MEDIUM);
433 return 0;
436 static PCIDeviceInfo pbm_pci_host_info = {
437 .qdev.name = "pbm",
438 .qdev.size = sizeof(PCIDevice),
439 .init = pbm_pci_host_init,
440 .vendor_id = PCI_VENDOR_ID_SUN,
441 .device_id = PCI_DEVICE_ID_SUN_SABRE,
442 .class_id = PCI_CLASS_BRIDGE_HOST,
443 .is_bridge = 1,
446 static SysBusDeviceInfo pbm_host_info = {
447 .qdev.name = "pbm",
448 .qdev.size = sizeof(APBState),
449 .qdev.reset = pci_pbm_reset,
450 .init = pci_pbm_init_device,
453 static PCIDeviceInfo pbm_pci_bridge_info = {
454 .qdev.name = "pbm-bridge",
455 .qdev.size = sizeof(PCIBridge),
456 .qdev.vmsd = &vmstate_pci_device,
457 .qdev.reset = pci_bridge_reset,
458 .init = apb_pci_bridge_initfn,
459 .exit = pci_bridge_exitfn,
460 .vendor_id = PCI_VENDOR_ID_SUN,
461 .device_id = PCI_DEVICE_ID_SUN_SIMBA,
462 .revision = 0x11,
463 .config_write = pci_bridge_write_config,
464 .is_bridge = 1,
467 static void pbm_register_devices(void)
469 sysbus_register_withprop(&pbm_host_info);
470 pci_qdev_register(&pbm_pci_host_info);
471 pci_qdev_register(&pbm_pci_bridge_info);
474 device_init(pbm_register_devices)