Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 409570a7

History | View | Annotate | Download (8.6 kB)

1 502a5395 pbrook
/*
2 502a5395 pbrook
 * QEMU Ultrasparc APB PCI host
3 502a5395 pbrook
 *
4 502a5395 pbrook
 * Copyright (c) 2006 Fabrice Bellard
5 5fafdf24 ths
 *
6 502a5395 pbrook
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 502a5395 pbrook
 * of this software and associated documentation files (the "Software"), to deal
8 502a5395 pbrook
 * in the Software without restriction, including without limitation the rights
9 502a5395 pbrook
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 502a5395 pbrook
 * copies of the Software, and to permit persons to whom the Software is
11 502a5395 pbrook
 * furnished to do so, subject to the following conditions:
12 502a5395 pbrook
 *
13 502a5395 pbrook
 * The above copyright notice and this permission notice shall be included in
14 502a5395 pbrook
 * all copies or substantial portions of the Software.
15 502a5395 pbrook
 *
16 502a5395 pbrook
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 502a5395 pbrook
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 502a5395 pbrook
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 502a5395 pbrook
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 502a5395 pbrook
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 502a5395 pbrook
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 502a5395 pbrook
 * THE SOFTWARE.
23 502a5395 pbrook
 */
24 80b3ada7 pbrook
25 a94fd955 blueswir1
/* XXX This file and most of its contents are somewhat misnamed.  The
26 80b3ada7 pbrook
   Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
27 80b3ada7 pbrook
   the secondary PCI bridge.  */
28 80b3ada7 pbrook
29 72f44c8c Blue Swirl
#include "sysbus.h"
30 87ecb68b pbrook
#include "pci.h"
31 4f5e19e6 Isaku Yamahata
#include "pci_host.h"
32 18e08a55 Michael S. Tsirkin
#include "apb_pci.h"
33 a94fd955 blueswir1
34 a94fd955 blueswir1
/* debug APB */
35 a94fd955 blueswir1
//#define DEBUG_APB
36 a94fd955 blueswir1
37 a94fd955 blueswir1
#ifdef DEBUG_APB
38 001faf32 Blue Swirl
#define APB_DPRINTF(fmt, ...) \
39 001faf32 Blue Swirl
do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
40 a94fd955 blueswir1
#else
41 001faf32 Blue Swirl
#define APB_DPRINTF(fmt, ...)
42 a94fd955 blueswir1
#endif
43 a94fd955 blueswir1
44 930f3fe1 Blue Swirl
/*
45 930f3fe1 Blue Swirl
 * Chipset docs:
46 930f3fe1 Blue Swirl
 * PBM: "UltraSPARC IIi User's Manual",
47 930f3fe1 Blue Swirl
 * http://www.sun.com/processors/manuals/805-0087.pdf
48 930f3fe1 Blue Swirl
 *
49 930f3fe1 Blue Swirl
 * APB: "Advanced PCI Bridge (APB) User's Manual",
50 930f3fe1 Blue Swirl
 * http://www.sun.com/processors/manuals/805-1251.pdf
51 930f3fe1 Blue Swirl
 */
52 930f3fe1 Blue Swirl
53 72f44c8c Blue Swirl
typedef struct APBState {
54 72f44c8c Blue Swirl
    SysBusDevice busdev;
55 72f44c8c Blue Swirl
    PCIHostState host_state;
56 72f44c8c Blue Swirl
} APBState;
57 502a5395 pbrook
58 c227f099 Anthony Liguori
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
59 f930d07e blueswir1
                               uint32_t val)
60 502a5395 pbrook
{
61 502a5395 pbrook
    //PCIBus *s = opaque;
62 502a5395 pbrook
63 502a5395 pbrook
    switch (addr & 0x3f) {
64 502a5395 pbrook
    case 0x00: // Control/Status
65 502a5395 pbrook
    case 0x10: // AFSR
66 502a5395 pbrook
    case 0x18: // AFAR
67 502a5395 pbrook
    case 0x20: // Diagnostic
68 502a5395 pbrook
    case 0x28: // Target address space
69 f930d07e blueswir1
        // XXX
70 502a5395 pbrook
    default:
71 f930d07e blueswir1
        break;
72 502a5395 pbrook
    }
73 502a5395 pbrook
}
74 502a5395 pbrook
75 502a5395 pbrook
static uint32_t apb_config_readl (void *opaque,
76 c227f099 Anthony Liguori
                                  target_phys_addr_t addr)
77 502a5395 pbrook
{
78 502a5395 pbrook
    //PCIBus *s = opaque;
79 502a5395 pbrook
    uint32_t val;
80 502a5395 pbrook
81 502a5395 pbrook
    switch (addr & 0x3f) {
82 502a5395 pbrook
    case 0x00: // Control/Status
83 502a5395 pbrook
    case 0x10: // AFSR
84 502a5395 pbrook
    case 0x18: // AFAR
85 502a5395 pbrook
    case 0x20: // Diagnostic
86 502a5395 pbrook
    case 0x28: // Target address space
87 f930d07e blueswir1
        // XXX
88 502a5395 pbrook
    default:
89 f930d07e blueswir1
        val = 0;
90 f930d07e blueswir1
        break;
91 502a5395 pbrook
    }
92 502a5395 pbrook
    return val;
93 502a5395 pbrook
}
94 502a5395 pbrook
95 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const apb_config_write[] = {
96 502a5395 pbrook
    &apb_config_writel,
97 502a5395 pbrook
    &apb_config_writel,
98 502a5395 pbrook
    &apb_config_writel,
99 502a5395 pbrook
};
100 502a5395 pbrook
101 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const apb_config_read[] = {
102 502a5395 pbrook
    &apb_config_readl,
103 502a5395 pbrook
    &apb_config_readl,
104 502a5395 pbrook
    &apb_config_readl,
105 502a5395 pbrook
};
106 502a5395 pbrook
107 c227f099 Anthony Liguori
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
108 502a5395 pbrook
                                  uint32_t val)
109 502a5395 pbrook
{
110 afcea8cb Blue Swirl
    cpu_outb(addr & IOPORTS_MASK, val);
111 502a5395 pbrook
}
112 502a5395 pbrook
113 c227f099 Anthony Liguori
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
114 502a5395 pbrook
                                  uint32_t val)
115 502a5395 pbrook
{
116 afcea8cb Blue Swirl
    cpu_outw(addr & IOPORTS_MASK, val);
117 502a5395 pbrook
}
118 502a5395 pbrook
119 c227f099 Anthony Liguori
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
120 502a5395 pbrook
                                uint32_t val)
121 502a5395 pbrook
{
122 afcea8cb Blue Swirl
    cpu_outl(addr & IOPORTS_MASK, val);
123 502a5395 pbrook
}
124 502a5395 pbrook
125 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
126 502a5395 pbrook
{
127 502a5395 pbrook
    uint32_t val;
128 502a5395 pbrook
129 afcea8cb Blue Swirl
    val = cpu_inb(addr & IOPORTS_MASK);
130 502a5395 pbrook
    return val;
131 502a5395 pbrook
}
132 502a5395 pbrook
133 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
134 502a5395 pbrook
{
135 502a5395 pbrook
    uint32_t val;
136 502a5395 pbrook
137 afcea8cb Blue Swirl
    val = cpu_inw(addr & IOPORTS_MASK);
138 502a5395 pbrook
    return val;
139 502a5395 pbrook
}
140 502a5395 pbrook
141 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
142 502a5395 pbrook
{
143 502a5395 pbrook
    uint32_t val;
144 502a5395 pbrook
145 afcea8cb Blue Swirl
    val = cpu_inl(addr & IOPORTS_MASK);
146 502a5395 pbrook
    return val;
147 502a5395 pbrook
}
148 502a5395 pbrook
149 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
150 502a5395 pbrook
    &pci_apb_iowriteb,
151 502a5395 pbrook
    &pci_apb_iowritew,
152 502a5395 pbrook
    &pci_apb_iowritel,
153 502a5395 pbrook
};
154 502a5395 pbrook
155 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pci_apb_ioread[] = {
156 502a5395 pbrook
    &pci_apb_ioreadb,
157 502a5395 pbrook
    &pci_apb_ioreadw,
158 502a5395 pbrook
    &pci_apb_ioreadl,
159 502a5395 pbrook
};
160 502a5395 pbrook
161 80b3ada7 pbrook
/* The APB host has an IRQ line for each IRQ line of each slot.  */
162 d2b59317 pbrook
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
163 502a5395 pbrook
{
164 80b3ada7 pbrook
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
165 80b3ada7 pbrook
}
166 80b3ada7 pbrook
167 80b3ada7 pbrook
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
168 80b3ada7 pbrook
{
169 80b3ada7 pbrook
    int bus_offset;
170 80b3ada7 pbrook
    if (pci_dev->devfn & 1)
171 80b3ada7 pbrook
        bus_offset = 16;
172 80b3ada7 pbrook
    else
173 80b3ada7 pbrook
        bus_offset = 0;
174 80b3ada7 pbrook
    return bus_offset + irq_num;
175 d2b59317 pbrook
}
176 d2b59317 pbrook
177 5d4e84c8 Juan Quintela
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
178 d2b59317 pbrook
{
179 5d4e84c8 Juan Quintela
    qemu_irq *pic = opaque;
180 5d4e84c8 Juan Quintela
181 80b3ada7 pbrook
    /* PCI IRQ map onto the first 32 INO.  */
182 d537cf6c pbrook
    qemu_set_irq(pic[irq_num], level);
183 502a5395 pbrook
}
184 502a5395 pbrook
185 d6318738 Michael S. Tsirkin
static void apb_pci_bridge_init(PCIBus *b)
186 d6318738 Michael S. Tsirkin
{
187 d6318738 Michael S. Tsirkin
    PCIDevice *dev = pci_bridge_get_device(b);
188 d6318738 Michael S. Tsirkin
189 d6318738 Michael S. Tsirkin
    /*
190 d6318738 Michael S. Tsirkin
     * command register:
191 d6318738 Michael S. Tsirkin
     * According to PCI bridge spec, after reset
192 d6318738 Michael S. Tsirkin
     *   bus master bit is off
193 d6318738 Michael S. Tsirkin
     *   memory space enable bit is off
194 d6318738 Michael S. Tsirkin
     * According to manual (805-1251.pdf).
195 d6318738 Michael S. Tsirkin
     *   the reset value should be zero unless the boot pin is tied high
196 d6318738 Michael S. Tsirkin
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
197 d6318738 Michael S. Tsirkin
     */
198 d6318738 Michael S. Tsirkin
    pci_set_word(dev->config + PCI_COMMAND,
199 d6318738 Michael S. Tsirkin
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
200 d6318738 Michael S. Tsirkin
    dev->config[PCI_LATENCY_TIMER] = 0x10;
201 d6318738 Michael S. Tsirkin
    dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
202 d6318738 Michael S. Tsirkin
}
203 d6318738 Michael S. Tsirkin
204 c227f099 Anthony Liguori
PCIBus *pci_apb_init(target_phys_addr_t special_base,
205 c227f099 Anthony Liguori
                     target_phys_addr_t mem_base,
206 c190ea07 blueswir1
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
207 502a5395 pbrook
{
208 72f44c8c Blue Swirl
    DeviceState *dev;
209 72f44c8c Blue Swirl
    SysBusDevice *s;
210 72f44c8c Blue Swirl
    APBState *d;
211 502a5395 pbrook
212 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
213 72f44c8c Blue Swirl
    dev = qdev_create(NULL, "pbm");
214 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
215 72f44c8c Blue Swirl
    s = sysbus_from_qdev(dev);
216 72f44c8c Blue Swirl
    /* apb_config */
217 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 0, special_base + 0x2000ULL);
218 72f44c8c Blue Swirl
    /* pci_ioport */
219 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
220 72f44c8c Blue Swirl
    /* mem_config: XXX size should be 4G-prom */
221 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
222 72f44c8c Blue Swirl
    /* mem_data */
223 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 3, mem_base);
224 72f44c8c Blue Swirl
    d = FROM_SYSBUS(APBState, s);
225 c5ff6d54 Blue Swirl
    d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
226 72f44c8c Blue Swirl
                                         pci_apb_set_irq, pci_pbm_map_irq, pic,
227 72f44c8c Blue Swirl
                                         0, 32);
228 72f44c8c Blue Swirl
    pci_create_simple(d->host_state.bus, 0, "pbm");
229 72f44c8c Blue Swirl
    /* APB secondary busses */
230 2217dcff Isaku Yamahata
    *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
231 2217dcff Isaku Yamahata
                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
232 2217dcff Isaku Yamahata
                            pci_apb_map_irq,
233 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 1");
234 d6318738 Michael S. Tsirkin
    apb_pci_bridge_init(*bus2);
235 d6318738 Michael S. Tsirkin
236 2217dcff Isaku Yamahata
    *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
237 2217dcff Isaku Yamahata
                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
238 2217dcff Isaku Yamahata
                            pci_apb_map_irq,
239 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 2");
240 d6318738 Michael S. Tsirkin
    apb_pci_bridge_init(*bus3);
241 502a5395 pbrook
242 72f44c8c Blue Swirl
    return d->host_state.bus;
243 72f44c8c Blue Swirl
}
244 72f44c8c Blue Swirl
245 81a322d4 Gerd Hoffmann
static int pci_pbm_init_device(SysBusDevice *dev)
246 72f44c8c Blue Swirl
{
247 72f44c8c Blue Swirl
248 72f44c8c Blue Swirl
    APBState *s;
249 72f44c8c Blue Swirl
    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
250 72f44c8c Blue Swirl
251 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
252 72f44c8c Blue Swirl
    /* apb_config */
253 1eed09cb Avi Kivity
    apb_config = cpu_register_io_memory(apb_config_read,
254 f930d07e blueswir1
                                        apb_config_write, s);
255 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x40ULL, apb_config);
256 72f44c8c Blue Swirl
    /* pci_ioport */
257 1eed09cb Avi Kivity
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
258 502a5395 pbrook
                                          pci_apb_iowrite, s);
259 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
260 72f44c8c Blue Swirl
    /* mem_config  */
261 f08b32fe Isaku Yamahata
    pci_mem_config = pci_host_conf_register_mmio(&s->host_state);
262 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
263 72f44c8c Blue Swirl
    /* mem_data */
264 f08b32fe Isaku Yamahata
    pci_mem_data = pci_host_data_register_mmio(&s->host_state);
265 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
266 81a322d4 Gerd Hoffmann
    return 0;
267 72f44c8c Blue Swirl
}
268 502a5395 pbrook
269 81a322d4 Gerd Hoffmann
static int pbm_pci_host_init(PCIDevice *d)
270 72f44c8c Blue Swirl
{
271 deb54399 aliguori
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
272 deb54399 aliguori
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
273 502a5395 pbrook
    d->config[0x04] = 0x06; // command = bus master, pci mem
274 502a5395 pbrook
    d->config[0x05] = 0x00;
275 502a5395 pbrook
    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
276 502a5395 pbrook
    d->config[0x07] = 0x03; // status = medium devsel
277 502a5395 pbrook
    d->config[0x08] = 0x00; // revision
278 502a5395 pbrook
    d->config[0x09] = 0x00; // programming i/f
279 173a543b blueswir1
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
280 502a5395 pbrook
    d->config[0x0D] = 0x10; // latency_timer
281 110c50fd Blue Swirl
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
282 81a322d4 Gerd Hoffmann
    return 0;
283 72f44c8c Blue Swirl
}
284 80b3ada7 pbrook
285 72f44c8c Blue Swirl
static PCIDeviceInfo pbm_pci_host_info = {
286 72f44c8c Blue Swirl
    .qdev.name = "pbm",
287 72f44c8c Blue Swirl
    .qdev.size = sizeof(PCIDevice),
288 72f44c8c Blue Swirl
    .init      = pbm_pci_host_init,
289 72f44c8c Blue Swirl
};
290 72f44c8c Blue Swirl
291 72f44c8c Blue Swirl
static void pbm_register_devices(void)
292 72f44c8c Blue Swirl
{
293 72f44c8c Blue Swirl
    sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
294 72f44c8c Blue Swirl
    pci_qdev_register(&pbm_pci_host_info);
295 502a5395 pbrook
}
296 72f44c8c Blue Swirl
297 72f44c8c Blue Swirl
device_init(pbm_register_devices)