]> Git Repo - qemu.git/blob - hw/apb_pci.c
pci_bridge: introduce pci bridge library.
[qemu.git] / hw / apb_pci.c
1 /*
2  * QEMU Ultrasparc APB PCI host
3  *
4  * Copyright (c) 2006 Fabrice Bellard
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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.
23  */
24
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.  */
28
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 "rwhandler.h"
35 #include "apb_pci.h"
36 #include "sysemu.h"
37
38 /* debug APB */
39 //#define DEBUG_APB
40
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
47
48 /*
49  * Chipset docs:
50  * PBM: "UltraSPARC IIi User's Manual",
51  * http://www.sun.com/processors/manuals/805-0087.pdf
52  *
53  * APB: "Advanced PCI Bridge (APB) User's Manual",
54  * http://www.sun.com/processors/manuals/805-1251.pdf
55  */
56
57 #define PBM_PCI_IMR_MASK    0x7fffffff
58 #define PBM_PCI_IMR_ENABLED 0x80000000
59
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
68
69 typedef struct APBState {
70     SysBusDevice busdev;
71     PCIBus      *bus;
72     ReadWriteHandler pci_config_handler;
73     uint32_t iommu[4];
74     uint32_t pci_control[16];
75     uint32_t pci_irq_map[8];
76     uint32_t obio_irq_map[32];
77     qemu_irq pci_irqs[32];
78     uint32_t reset_control;
79     unsigned int nr_resets;
80 } APBState;
81
82 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
83                                uint32_t val)
84 {
85     APBState *s = opaque;
86
87     APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
88
89     switch (addr & 0xffff) {
90     case 0x30 ... 0x4f: /* DMA error registers */
91         /* XXX: not implemented yet */
92         break;
93     case 0x200 ... 0x20b: /* IOMMU */
94         s->iommu[(addr & 0xf) >> 2] = val;
95         break;
96     case 0x20c ... 0x3ff: /* IOMMU flush */
97         break;
98     case 0xc00 ... 0xc3f: /* PCI interrupt control */
99         if (addr & 4) {
100             s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
101             s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
102         }
103         break;
104     case 0x2000 ... 0x202f: /* PCI control */
105         s->pci_control[(addr & 0x3f) >> 2] = val;
106         break;
107     case 0xf020 ... 0xf027: /* Reset control */
108         if (addr & 4) {
109             val &= RESET_MASK;
110             s->reset_control &= ~(val & RESET_WCMASK);
111             s->reset_control |= val & RESET_WMASK;
112             if (val & SOFT_POR) {
113                 s->nr_resets = 0;
114                 qemu_system_reset_request();
115             } else if (val & SOFT_XIR) {
116                 qemu_system_reset_request();
117             }
118         }
119         break;
120     case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
121     case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
122     case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
123     case 0xf000 ... 0xf01f: /* FFB config, memory control */
124         /* we don't care */
125     default:
126         break;
127     }
128 }
129
130 static uint32_t apb_config_readl (void *opaque,
131                                   target_phys_addr_t addr)
132 {
133     APBState *s = opaque;
134     uint32_t val;
135
136     switch (addr & 0xffff) {
137     case 0x30 ... 0x4f: /* DMA error registers */
138         val = 0;
139         /* XXX: not implemented yet */
140         break;
141     case 0x200 ... 0x20b: /* IOMMU */
142         val = s->iommu[(addr & 0xf) >> 2];
143         break;
144     case 0x20c ... 0x3ff: /* IOMMU flush */
145         val = 0;
146         break;
147     case 0xc00 ... 0xc3f: /* PCI interrupt control */
148         if (addr & 4) {
149             val = s->pci_irq_map[(addr & 0x3f) >> 3];
150         } else {
151             val = 0;
152         }
153         break;
154     case 0x2000 ... 0x202f: /* PCI control */
155         val = s->pci_control[(addr & 0x3f) >> 2];
156         break;
157     case 0xf020 ... 0xf027: /* Reset control */
158         if (addr & 4) {
159             val = s->reset_control;
160         } else {
161             val = 0;
162         }
163         break;
164     case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
165     case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
166     case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
167     case 0xf000 ... 0xf01f: /* FFB config, memory control */
168         /* we don't care */
169     default:
170         val = 0;
171         break;
172     }
173     APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
174
175     return val;
176 }
177
178 static CPUWriteMemoryFunc * const apb_config_write[] = {
179     &apb_config_writel,
180     &apb_config_writel,
181     &apb_config_writel,
182 };
183
184 static CPUReadMemoryFunc * const apb_config_read[] = {
185     &apb_config_readl,
186     &apb_config_readl,
187     &apb_config_readl,
188 };
189
190 static void apb_pci_config_write(ReadWriteHandler *h, pcibus_t addr,
191                                  uint32_t val, int size)
192 {
193     APBState *s = container_of(h, APBState, pci_config_handler);
194
195     val = qemu_bswap_len(val, size);
196     APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
197     pci_data_write(s->bus, addr, val, size);
198 }
199
200 static uint32_t apb_pci_config_read(ReadWriteHandler *h, pcibus_t addr,
201                                     int size)
202 {
203     uint32_t ret;
204     APBState *s = container_of(h, APBState, pci_config_handler);
205
206     ret = pci_data_read(s->bus, addr, size);
207     ret = qemu_bswap_len(ret, size);
208     APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
209     return ret;
210 }
211
212 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
213                                   uint32_t val)
214 {
215     cpu_outb(addr & IOPORTS_MASK, val);
216 }
217
218 static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
219                                   uint32_t val)
220 {
221     cpu_outw(addr & IOPORTS_MASK, bswap16(val));
222 }
223
224 static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
225                                 uint32_t val)
226 {
227     cpu_outl(addr & IOPORTS_MASK, bswap32(val));
228 }
229
230 static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
231 {
232     uint32_t val;
233
234     val = cpu_inb(addr & IOPORTS_MASK);
235     return val;
236 }
237
238 static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
239 {
240     uint32_t val;
241
242     val = bswap16(cpu_inw(addr & IOPORTS_MASK));
243     return val;
244 }
245
246 static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
247 {
248     uint32_t val;
249
250     val = bswap32(cpu_inl(addr & IOPORTS_MASK));
251     return val;
252 }
253
254 static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
255     &pci_apb_iowriteb,
256     &pci_apb_iowritew,
257     &pci_apb_iowritel,
258 };
259
260 static CPUReadMemoryFunc * const pci_apb_ioread[] = {
261     &pci_apb_ioreadb,
262     &pci_apb_ioreadw,
263     &pci_apb_ioreadl,
264 };
265
266 /* The APB host has an IRQ line for each IRQ line of each slot.  */
267 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
268 {
269     return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
270 }
271
272 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
273 {
274     int bus_offset;
275     if (pci_dev->devfn & 1)
276         bus_offset = 16;
277     else
278         bus_offset = 0;
279     return bus_offset + irq_num;
280 }
281
282 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
283 {
284     APBState *s = opaque;
285
286     /* PCI IRQ map onto the first 32 INO.  */
287     if (irq_num < 32) {
288         if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
289             APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
290             qemu_set_irq(s->pci_irqs[irq_num], level);
291         } else {
292             APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
293             qemu_irq_lower(s->pci_irqs[irq_num]);
294         }
295     }
296 }
297
298 static int apb_pci_bridge_initfn(PCIDevice *dev)
299 {
300     int rc;
301
302     rc = pci_bridge_initfn(dev);
303     if (rc < 0) {
304         return rc;
305     }
306
307     pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_SUN);
308     pci_config_set_device_id(dev->config, PCI_DEVICE_ID_SUN_SIMBA);
309
310     /*
311      * command register:
312      * According to PCI bridge spec, after reset
313      *   bus master bit is off
314      *   memory space enable bit is off
315      * According to manual (805-1251.pdf).
316      *   the reset value should be zero unless the boot pin is tied high
317      *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
318      */
319     pci_set_word(dev->config + PCI_COMMAND,
320                  PCI_COMMAND_MEMORY);
321     pci_set_word(dev->config + PCI_STATUS,
322                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
323                  PCI_STATUS_DEVSEL_MEDIUM);
324     pci_set_byte(dev->config + PCI_REVISION_ID, 0x11);
325     return 0;
326 }
327
328 PCIBus *pci_apb_init(target_phys_addr_t special_base,
329                      target_phys_addr_t mem_base,
330                      qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
331 {
332     DeviceState *dev;
333     SysBusDevice *s;
334     APBState *d;
335     unsigned int i;
336     PCIDevice *pci_dev;
337     PCIBridge *br;
338
339     /* Ultrasparc PBM main bus */
340     dev = qdev_create(NULL, "pbm");
341     qdev_init_nofail(dev);
342     s = sysbus_from_qdev(dev);
343     /* apb_config */
344     sysbus_mmio_map(s, 0, special_base);
345     /* PCI configuration space */
346     sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
347     /* pci_ioport */
348     sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
349     d = FROM_SYSBUS(APBState, s);
350
351     d->bus = pci_register_bus(&d->busdev.qdev, "pci",
352                                          pci_apb_set_irq, pci_pbm_map_irq, d,
353                                          0, 32);
354     pci_bus_set_mem_base(d->bus, mem_base);
355
356     for (i = 0; i < 32; i++) {
357         sysbus_connect_irq(s, i, pic[i]);
358     }
359
360     pci_create_simple(d->bus, 0, "pbm");
361
362     /* APB secondary busses */
363     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
364                                    "pbm-bridge");
365     br = DO_UPCAST(PCIBridge, dev, pci_dev);
366     pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
367                        pci_apb_map_irq);
368     qdev_init_nofail(&pci_dev->qdev);
369     *bus2 = pci_bridge_get_sec_bus(br);
370
371     pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
372                                    "pbm-bridge");
373     br = DO_UPCAST(PCIBridge, dev, pci_dev);
374     pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
375                        pci_apb_map_irq);
376     qdev_init_nofail(&pci_dev->qdev);
377     *bus3 = pci_bridge_get_sec_bus(br);
378
379     return d->bus;
380 }
381
382 static void pci_pbm_reset(DeviceState *d)
383 {
384     unsigned int i;
385     APBState *s = container_of(d, APBState, busdev.qdev);
386
387     for (i = 0; i < 8; i++) {
388         s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
389     }
390
391     if (s->nr_resets++ == 0) {
392         /* Power on reset */
393         s->reset_control = POR;
394     }
395 }
396
397 static int pci_pbm_init_device(SysBusDevice *dev)
398 {
399     APBState *s;
400     int pci_config, apb_config, pci_ioport;
401     unsigned int i;
402
403     s = FROM_SYSBUS(APBState, dev);
404     for (i = 0; i < 8; i++) {
405         s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
406     }
407     for (i = 0; i < 32; i++) {
408         sysbus_init_irq(dev, &s->pci_irqs[i]);
409     }
410
411     /* apb_config */
412     apb_config = cpu_register_io_memory(apb_config_read,
413                                         apb_config_write, s);
414     /* at region 0 */
415     sysbus_init_mmio(dev, 0x10000ULL, apb_config);
416
417     /* PCI configuration space */
418     s->pci_config_handler.read = apb_pci_config_read;
419     s->pci_config_handler.write = apb_pci_config_write;
420     pci_config = cpu_register_io_memory_simple(&s->pci_config_handler);
421     assert(pci_config >= 0);
422     /* at region 1 */
423     sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
424
425     /* pci_ioport */
426     pci_ioport = cpu_register_io_memory(pci_apb_ioread,
427                                         pci_apb_iowrite, s);
428     /* at region 2 */
429     sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
430
431     return 0;
432 }
433
434 static int pbm_pci_host_init(PCIDevice *d)
435 {
436     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
437     pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
438     pci_set_word(d->config + PCI_COMMAND,
439                  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
440     pci_set_word(d->config + PCI_STATUS,
441                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
442                  PCI_STATUS_DEVSEL_MEDIUM);
443     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
444     return 0;
445 }
446
447 static PCIDeviceInfo pbm_pci_host_info = {
448     .qdev.name = "pbm",
449     .qdev.size = sizeof(PCIDevice),
450     .init      = pbm_pci_host_init,
451     .is_bridge = 1,
452 };
453
454 static SysBusDeviceInfo pbm_host_info = {
455     .qdev.name = "pbm",
456     .qdev.size = sizeof(APBState),
457     .qdev.reset = pci_pbm_reset,
458     .init = pci_pbm_init_device,
459 };
460
461 static PCIDeviceInfo pbm_pci_bridge_info = {
462     .qdev.name = "pbm-bridge",
463     .qdev.size = sizeof(PCIBridge),
464     .qdev.vmsd = &vmstate_pci_device,
465     .qdev.reset = pci_bridge_reset,
466     .init = apb_pci_bridge_initfn,
467     .exit = pci_bridge_exitfn,
468     .config_write = pci_bridge_write_config,
469     .is_bridge = 1,
470 };
471
472 static void pbm_register_devices(void)
473 {
474     sysbus_register_withprop(&pbm_host_info);
475     pci_qdev_register(&pbm_pci_host_info);
476     pci_qdev_register(&pbm_pci_bridge_info);
477 }
478
479 device_init(pbm_register_devices)
This page took 0.052745 seconds and 4 git commands to generate.