Fix -device help and documentation
[qemu/aliguori-queue.git] / hw / apb_pci.c
blob65d8ba610f34420a4f0d0432af99e035af898ba5
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 "rwhandler.h"
33 #include "apb_pci.h"
35 /* debug APB */
36 //#define DEBUG_APB
38 #ifdef DEBUG_APB
39 #define APB_DPRINTF(fmt, ...) \
40 do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
41 #else
42 #define APB_DPRINTF(fmt, ...)
43 #endif
46 * Chipset docs:
47 * PBM: "UltraSPARC IIi User's Manual",
48 * http://www.sun.com/processors/manuals/805-0087.pdf
50 * APB: "Advanced PCI Bridge (APB) User's Manual",
51 * http://www.sun.com/processors/manuals/805-1251.pdf
54 #define PBM_PCI_IMR_MASK 0x7fffffff
55 #define PBM_PCI_IMR_ENABLED 0x80000000
57 #define POR (1 << 31)
58 #define SOFT_POR (1 << 30)
59 #define SOFT_XIR (1 << 29)
60 #define BTN_POR (1 << 28)
61 #define BTN_XIR (1 << 27)
62 #define RESET_MASK 0xf8000000
63 #define RESET_WCMASK 0x98000000
64 #define RESET_WMASK 0x60000000
66 typedef struct APBState {
67 SysBusDevice busdev;
68 PCIHostState host_state;
69 ReadWriteHandler pci_config_handler;
70 uint32_t iommu[4];
71 uint32_t pci_control[16];
72 uint32_t pci_irq_map[8];
73 uint32_t obio_irq_map[32];
74 qemu_irq pci_irqs[32];
75 uint32_t reset_control;
76 unsigned int nr_resets;
77 } APBState;
79 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
80 uint32_t val)
82 APBState *s = opaque;
84 APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
86 switch (addr & 0xffff) {
87 case 0x30 ... 0x4f: /* DMA error registers */
88 /* XXX: not implemented yet */
89 break;
90 case 0x200 ... 0x20b: /* IOMMU */
91 s->iommu[(addr & 0xf) >> 2] = val;
92 break;
93 case 0x20c ... 0x3ff: /* IOMMU flush */
94 break;
95 case 0xc00 ... 0xc3f: /* PCI interrupt control */
96 if (addr & 4) {
97 s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
98 s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
100 break;
101 case 0x2000 ... 0x202f: /* PCI control */
102 s->pci_control[(addr & 0x3f) >> 2] = val;
103 break;
104 case 0xf020 ... 0xf027: /* Reset control */
105 if (addr & 4) {
106 val &= RESET_MASK;
107 s->reset_control &= ~(val & RESET_WCMASK);
108 s->reset_control |= val & RESET_WMASK;
109 if (val & SOFT_POR) {
110 s->nr_resets = 0;
111 qemu_system_reset_request();
112 } else if (val & SOFT_XIR) {
113 qemu_system_reset_request();
116 break;
117 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
118 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
119 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
120 case 0xf000 ... 0xf01f: /* FFB config, memory control */
121 /* we don't care */
122 default:
123 break;
127 static uint32_t apb_config_readl (void *opaque,
128 target_phys_addr_t addr)
130 APBState *s = opaque;
131 uint32_t val;
133 switch (addr & 0xffff) {
134 case 0x30 ... 0x4f: /* DMA error registers */
135 val = 0;
136 /* XXX: not implemented yet */
137 break;
138 case 0x200 ... 0x20b: /* IOMMU */
139 val = s->iommu[(addr & 0xf) >> 2];
140 break;
141 case 0x20c ... 0x3ff: /* IOMMU flush */
142 val = 0;
143 break;
144 case 0xc00 ... 0xc3f: /* PCI interrupt control */
145 if (addr & 4) {
146 val = s->pci_irq_map[(addr & 0x3f) >> 3];
147 } else {
148 val = 0;
150 break;
151 case 0x2000 ... 0x202f: /* PCI control */
152 val = s->pci_control[(addr & 0x3f) >> 2];
153 break;
154 case 0xf020 ... 0xf027: /* Reset control */
155 if (addr & 4) {
156 val = s->reset_control;
157 } else {
158 val = 0;
160 break;
161 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
162 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
163 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
164 case 0xf000 ... 0xf01f: /* FFB config, memory control */
165 /* we don't care */
166 default:
167 val = 0;
168 break;
170 APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
172 return val;
175 static CPUWriteMemoryFunc * const apb_config_write[] = {
176 &apb_config_writel,
177 &apb_config_writel,
178 &apb_config_writel,
181 static CPUReadMemoryFunc * const apb_config_read[] = {
182 &apb_config_readl,
183 &apb_config_readl,
184 &apb_config_readl,
187 static void apb_pci_config_write(ReadWriteHandler *h, pcibus_t addr,
188 uint32_t val, int size)
190 APBState *s = container_of(h, APBState, pci_config_handler);
192 val = qemu_bswap_len(val, size);
193 APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
194 pci_data_write(s->host_state.bus, addr, val, size);
197 static uint32_t apb_pci_config_read(ReadWriteHandler *h, pcibus_t addr,
198 int size)
200 uint32_t ret;
201 APBState *s = container_of(h, APBState, pci_config_handler);
203 ret = pci_data_read(s->host_state.bus, addr, size);
204 ret = qemu_bswap_len(ret, size);
205 APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
206 return ret;
209 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
210 uint32_t val)
212 cpu_outb(addr & IOPORTS_MASK, val);
215 static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
216 uint32_t val)
218 cpu_outw(addr & IOPORTS_MASK, bswap16(val));
221 static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
222 uint32_t val)
224 cpu_outl(addr & IOPORTS_MASK, bswap32(val));
227 static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
229 uint32_t val;
231 val = cpu_inb(addr & IOPORTS_MASK);
232 return val;
235 static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
237 uint32_t val;
239 val = bswap16(cpu_inw(addr & IOPORTS_MASK));
240 return val;
243 static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
245 uint32_t val;
247 val = bswap32(cpu_inl(addr & IOPORTS_MASK));
248 return val;
251 static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
252 &pci_apb_iowriteb,
253 &pci_apb_iowritew,
254 &pci_apb_iowritel,
257 static CPUReadMemoryFunc * const pci_apb_ioread[] = {
258 &pci_apb_ioreadb,
259 &pci_apb_ioreadw,
260 &pci_apb_ioreadl,
263 /* The APB host has an IRQ line for each IRQ line of each slot. */
264 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
266 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
269 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
271 int bus_offset;
272 if (pci_dev->devfn & 1)
273 bus_offset = 16;
274 else
275 bus_offset = 0;
276 return bus_offset + irq_num;
279 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
281 APBState *s = opaque;
283 /* PCI IRQ map onto the first 32 INO. */
284 if (irq_num < 32) {
285 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
286 APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
287 qemu_set_irq(s->pci_irqs[irq_num], level);
288 } else {
289 APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
290 qemu_irq_lower(s->pci_irqs[irq_num]);
295 static void apb_pci_bridge_init(PCIBus *b)
297 PCIDevice *dev = pci_bridge_get_device(b);
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 pci_set_byte(dev->config + PCI_REVISION_ID, 0x11);
314 pci_set_byte(dev->config + PCI_HEADER_TYPE,
315 pci_get_byte(dev->config + PCI_HEADER_TYPE) |
316 PCI_HEADER_TYPE_MULTI_FUNCTION);
319 PCIBus *pci_apb_init(target_phys_addr_t special_base,
320 target_phys_addr_t mem_base,
321 qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
323 DeviceState *dev;
324 SysBusDevice *s;
325 APBState *d;
326 unsigned int i;
328 /* Ultrasparc PBM main bus */
329 dev = qdev_create(NULL, "pbm");
330 qdev_init_nofail(dev);
331 s = sysbus_from_qdev(dev);
332 /* apb_config */
333 sysbus_mmio_map(s, 0, special_base);
334 /* pci_ioport */
335 sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
336 /* pci_config */
337 sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
338 /* mem_data */
339 sysbus_mmio_map(s, 3, mem_base);
340 d = FROM_SYSBUS(APBState, s);
341 d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
342 pci_apb_set_irq, pci_pbm_map_irq, d,
343 0, 32);
344 pci_bus_set_mem_base(d->host_state.bus, mem_base);
346 for (i = 0; i < 32; i++) {
347 sysbus_connect_irq(s, i, pic[i]);
350 pci_create_simple(d->host_state.bus, 0, "pbm");
351 /* APB secondary busses */
352 *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
353 PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
354 pci_apb_map_irq,
355 "Advanced PCI Bus secondary bridge 1");
356 apb_pci_bridge_init(*bus2);
358 *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
359 PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
360 pci_apb_map_irq,
361 "Advanced PCI Bus secondary bridge 2");
362 apb_pci_bridge_init(*bus3);
364 return d->host_state.bus;
367 static void pci_pbm_reset(DeviceState *d)
369 unsigned int i;
370 APBState *s = container_of(d, APBState, busdev.qdev);
372 for (i = 0; i < 8; i++) {
373 s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
376 if (s->nr_resets++ == 0) {
377 /* Power on reset */
378 s->reset_control = POR;
382 static int pci_pbm_init_device(SysBusDevice *dev)
384 APBState *s;
385 int pci_mem_data, apb_config, pci_ioport, pci_config;
386 unsigned int i;
388 s = FROM_SYSBUS(APBState, dev);
389 for (i = 0; i < 8; i++) {
390 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
392 for (i = 0; i < 32; i++) {
393 sysbus_init_irq(dev, &s->pci_irqs[i]);
396 /* apb_config */
397 apb_config = cpu_register_io_memory(apb_config_read,
398 apb_config_write, s);
399 sysbus_init_mmio(dev, 0x10000ULL, apb_config);
400 /* pci_ioport */
401 pci_ioport = cpu_register_io_memory(pci_apb_ioread,
402 pci_apb_iowrite, s);
403 sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
404 /* pci_config */
405 s->pci_config_handler.read = apb_pci_config_read;
406 s->pci_config_handler.write = apb_pci_config_write;
407 pci_config = cpu_register_io_memory_simple(&s->pci_config_handler);
408 assert(pci_config >= 0);
409 sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
410 /* mem_data */
411 pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
412 sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
413 return 0;
416 static int pbm_pci_host_init(PCIDevice *d)
418 pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
419 pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
420 pci_set_word(d->config + PCI_COMMAND,
421 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
422 pci_set_word(d->config + PCI_STATUS,
423 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
424 PCI_STATUS_DEVSEL_MEDIUM);
425 pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
426 pci_set_byte(d->config + PCI_HEADER_TYPE,
427 PCI_HEADER_TYPE_NORMAL);
428 return 0;
431 static PCIDeviceInfo pbm_pci_host_info = {
432 .qdev.name = "pbm",
433 .qdev.size = sizeof(PCIDevice),
434 .init = pbm_pci_host_init,
435 .header_type = PCI_HEADER_TYPE_BRIDGE,
438 static SysBusDeviceInfo pbm_host_info = {
439 .qdev.name = "pbm",
440 .qdev.size = sizeof(APBState),
441 .qdev.reset = pci_pbm_reset,
442 .init = pci_pbm_init_device,
444 static void pbm_register_devices(void)
446 sysbus_register_withprop(&pbm_host_info);
447 pci_qdev_register(&pbm_pci_host_info);
450 device_init(pbm_register_devices)