]> Git Repo - qemu.git/blob - hw/apb_pci.c
QMP: Fix asynchronous events delivery
[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 "apb_pci.h"
33
34 /* debug APB */
35 //#define DEBUG_APB
36
37 #ifdef DEBUG_APB
38 #define APB_DPRINTF(fmt, ...) \
39 do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
40 #else
41 #define APB_DPRINTF(fmt, ...)
42 #endif
43
44 /*
45  * Chipset docs:
46  * PBM: "UltraSPARC IIi User's Manual",
47  * http://www.sun.com/processors/manuals/805-0087.pdf
48  *
49  * APB: "Advanced PCI Bridge (APB) User's Manual",
50  * http://www.sun.com/processors/manuals/805-1251.pdf
51  */
52
53 typedef struct APBState {
54     SysBusDevice busdev;
55     PCIHostState host_state;
56 } APBState;
57
58 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
59                                uint32_t val)
60 {
61     //PCIBus *s = opaque;
62
63     switch (addr & 0x3f) {
64     case 0x00: // Control/Status
65     case 0x10: // AFSR
66     case 0x18: // AFAR
67     case 0x20: // Diagnostic
68     case 0x28: // Target address space
69         // XXX
70     default:
71         break;
72     }
73 }
74
75 static uint32_t apb_config_readl (void *opaque,
76                                   target_phys_addr_t addr)
77 {
78     //PCIBus *s = opaque;
79     uint32_t val;
80
81     switch (addr & 0x3f) {
82     case 0x00: // Control/Status
83     case 0x10: // AFSR
84     case 0x18: // AFAR
85     case 0x20: // Diagnostic
86     case 0x28: // Target address space
87         // XXX
88     default:
89         val = 0;
90         break;
91     }
92     return val;
93 }
94
95 static CPUWriteMemoryFunc * const apb_config_write[] = {
96     &apb_config_writel,
97     &apb_config_writel,
98     &apb_config_writel,
99 };
100
101 static CPUReadMemoryFunc * const apb_config_read[] = {
102     &apb_config_readl,
103     &apb_config_readl,
104     &apb_config_readl,
105 };
106
107 static void apb_pci_config_write(APBState *s, target_phys_addr_t addr,
108                                  uint32_t val, int size)
109 {
110     APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
111     pci_data_write(s->host_state.bus, (addr & 0x00ffffff) | (1u << 31), val,
112                    size);
113 }
114
115 static uint32_t apb_pci_config_read(APBState *s, target_phys_addr_t addr,
116                                     int size)
117 {
118     uint32_t ret;
119
120     ret = pci_data_read(s->host_state.bus, (addr & 0x00ffffff) | (1u << 31),
121                         size);
122     APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
123     return ret;
124 }
125
126 static void apb_pci_config_writel(void *opaque, target_phys_addr_t addr,
127                                   uint32_t val)
128 {
129     APBState *s = opaque;
130
131     apb_pci_config_write(s, addr, val, 4);
132 }
133
134 static void apb_pci_config_writew(void *opaque, target_phys_addr_t addr,
135                                   uint32_t val)
136 {
137     APBState *s = opaque;
138
139     apb_pci_config_write(s, addr, val, 2);
140 }
141
142 static void apb_pci_config_writeb(void *opaque, target_phys_addr_t addr,
143                                   uint32_t val)
144 {
145     APBState *s = opaque;
146
147     apb_pci_config_write(s, addr, val, 1);
148 }
149
150 static uint32_t apb_pci_config_readl(void *opaque, target_phys_addr_t addr)
151 {
152     APBState *s = opaque;
153
154     return apb_pci_config_read(s, addr, 4);
155 }
156
157 static uint32_t apb_pci_config_readw(void *opaque, target_phys_addr_t addr)
158 {
159     APBState *s = opaque;
160
161     return apb_pci_config_read(s, addr, 2);
162 }
163
164 static uint32_t apb_pci_config_readb(void *opaque, target_phys_addr_t addr)
165 {
166     APBState *s = opaque;
167
168     return apb_pci_config_read(s, addr, 1);
169 }
170
171 static CPUWriteMemoryFunc * const apb_pci_config_writes[] = {
172     &apb_pci_config_writeb,
173     &apb_pci_config_writew,
174     &apb_pci_config_writel,
175 };
176
177 static CPUReadMemoryFunc * const apb_pci_config_reads[] = {
178     &apb_pci_config_readb,
179     &apb_pci_config_readw,
180     &apb_pci_config_readl,
181 };
182
183 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
184                                   uint32_t val)
185 {
186     cpu_outb(addr & IOPORTS_MASK, val);
187 }
188
189 static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
190                                   uint32_t val)
191 {
192     cpu_outw(addr & IOPORTS_MASK, val);
193 }
194
195 static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
196                                 uint32_t val)
197 {
198     cpu_outl(addr & IOPORTS_MASK, val);
199 }
200
201 static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
202 {
203     uint32_t val;
204
205     val = cpu_inb(addr & IOPORTS_MASK);
206     return val;
207 }
208
209 static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
210 {
211     uint32_t val;
212
213     val = cpu_inw(addr & IOPORTS_MASK);
214     return val;
215 }
216
217 static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
218 {
219     uint32_t val;
220
221     val = cpu_inl(addr & IOPORTS_MASK);
222     return val;
223 }
224
225 static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
226     &pci_apb_iowriteb,
227     &pci_apb_iowritew,
228     &pci_apb_iowritel,
229 };
230
231 static CPUReadMemoryFunc * const pci_apb_ioread[] = {
232     &pci_apb_ioreadb,
233     &pci_apb_ioreadw,
234     &pci_apb_ioreadl,
235 };
236
237 /* The APB host has an IRQ line for each IRQ line of each slot.  */
238 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
239 {
240     return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
241 }
242
243 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
244 {
245     int bus_offset;
246     if (pci_dev->devfn & 1)
247         bus_offset = 16;
248     else
249         bus_offset = 0;
250     return bus_offset + irq_num;
251 }
252
253 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
254 {
255     qemu_irq *pic = opaque;
256
257     /* PCI IRQ map onto the first 32 INO.  */
258     qemu_set_irq(pic[irq_num], level);
259 }
260
261 static void apb_pci_bridge_init(PCIBus *b)
262 {
263     PCIDevice *dev = pci_bridge_get_device(b);
264
265     /*
266      * command register:
267      * According to PCI bridge spec, after reset
268      *   bus master bit is off
269      *   memory space enable bit is off
270      * According to manual (805-1251.pdf).
271      *   the reset value should be zero unless the boot pin is tied high
272      *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
273      */
274     pci_set_word(dev->config + PCI_COMMAND,
275                  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
276     dev->config[PCI_LATENCY_TIMER] = 0x10;
277     dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
278 }
279
280 PCIBus *pci_apb_init(target_phys_addr_t special_base,
281                      target_phys_addr_t mem_base,
282                      qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
283 {
284     DeviceState *dev;
285     SysBusDevice *s;
286     APBState *d;
287
288     /* Ultrasparc PBM main bus */
289     dev = qdev_create(NULL, "pbm");
290     qdev_init_nofail(dev);
291     s = sysbus_from_qdev(dev);
292     /* apb_config */
293     sysbus_mmio_map(s, 0, special_base);
294     /* pci_ioport */
295     sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
296     /* mem_config: XXX should not exist */
297     sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
298     /* mem_config: XXX size should be 4G-prom */
299     sysbus_mmio_map(s, 3, special_base + 0x1000010ULL);
300     /* mem_data */
301     sysbus_mmio_map(s, 4, mem_base);
302     d = FROM_SYSBUS(APBState, s);
303     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
304                                          pci_apb_set_irq, pci_pbm_map_irq, pic,
305                                          0, 32);
306     pci_bus_set_mem_base(d->host_state.bus, mem_base);
307
308     pci_create_simple(d->host_state.bus, 0, "pbm");
309     /* APB secondary busses */
310     *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
311                             PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
312                             pci_apb_map_irq,
313                             "Advanced PCI Bus secondary bridge 1");
314     apb_pci_bridge_init(*bus2);
315
316     *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
317                             PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
318                             pci_apb_map_irq,
319                             "Advanced PCI Bus secondary bridge 2");
320     apb_pci_bridge_init(*bus3);
321
322     return d->host_state.bus;
323 }
324
325 static int pci_pbm_init_device(SysBusDevice *dev)
326 {
327
328     APBState *s;
329     int pci_mem_config, pci_mem_data, apb_config, pci_ioport, pci_config;
330
331     s = FROM_SYSBUS(APBState, dev);
332     /* apb_config */
333     apb_config = cpu_register_io_memory(apb_config_read,
334                                         apb_config_write, s);
335     sysbus_init_mmio(dev, 0x10000ULL, apb_config);
336     /* pci_ioport */
337     pci_ioport = cpu_register_io_memory(pci_apb_ioread,
338                                           pci_apb_iowrite, s);
339     sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
340     /* mem_config  */
341     pci_mem_config = pci_host_conf_register_mmio(&s->host_state);
342     sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
343     /* pci_config */
344     pci_config = cpu_register_io_memory(apb_pci_config_reads,
345                                         apb_pci_config_writes, s);
346     sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
347     /* mem_data */
348     pci_mem_data = pci_host_data_register_mmio(&s->host_state);
349     sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
350     return 0;
351 }
352
353 static int pbm_pci_host_init(PCIDevice *d)
354 {
355     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
356     pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
357     d->config[0x04] = 0x06; // command = bus master, pci mem
358     d->config[0x05] = 0x00;
359     d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
360     d->config[0x07] = 0x03; // status = medium devsel
361     d->config[0x08] = 0x00; // revision
362     d->config[0x09] = 0x00; // programming i/f
363     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
364     d->config[0x0D] = 0x10; // latency_timer
365     d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
366     return 0;
367 }
368
369 static PCIDeviceInfo pbm_pci_host_info = {
370     .qdev.name = "pbm",
371     .qdev.size = sizeof(PCIDevice),
372     .init      = pbm_pci_host_init,
373 };
374
375 static void pbm_register_devices(void)
376 {
377     sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
378     pci_qdev_register(&pbm_pci_host_info);
379 }
380
381 device_init(pbm_register_devices)
This page took 0.04673 seconds and 4 git commands to generate.