Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 28366c3a

History | View | Annotate | Download (9.2 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 a94fd955 blueswir1
32 a94fd955 blueswir1
/* debug APB */
33 a94fd955 blueswir1
//#define DEBUG_APB
34 a94fd955 blueswir1
35 a94fd955 blueswir1
#ifdef DEBUG_APB
36 001faf32 Blue Swirl
#define APB_DPRINTF(fmt, ...) \
37 001faf32 Blue Swirl
do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
38 a94fd955 blueswir1
#else
39 001faf32 Blue Swirl
#define APB_DPRINTF(fmt, ...)
40 a94fd955 blueswir1
#endif
41 a94fd955 blueswir1
42 930f3fe1 Blue Swirl
/*
43 930f3fe1 Blue Swirl
 * Chipset docs:
44 930f3fe1 Blue Swirl
 * PBM: "UltraSPARC IIi User's Manual",
45 930f3fe1 Blue Swirl
 * http://www.sun.com/processors/manuals/805-0087.pdf
46 930f3fe1 Blue Swirl
 *
47 930f3fe1 Blue Swirl
 * APB: "Advanced PCI Bridge (APB) User's Manual",
48 930f3fe1 Blue Swirl
 * http://www.sun.com/processors/manuals/805-1251.pdf
49 930f3fe1 Blue Swirl
 */
50 930f3fe1 Blue Swirl
51 c227f099 Anthony Liguori
typedef target_phys_addr_t pci_addr_t;
52 502a5395 pbrook
#include "pci_host.h"
53 502a5395 pbrook
54 72f44c8c Blue Swirl
typedef struct APBState {
55 72f44c8c Blue Swirl
    SysBusDevice busdev;
56 72f44c8c Blue Swirl
    PCIHostState host_state;
57 72f44c8c Blue Swirl
} APBState;
58 502a5395 pbrook
59 c227f099 Anthony Liguori
static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
60 502a5395 pbrook
                                         uint32_t val)
61 502a5395 pbrook
{
62 502a5395 pbrook
    APBState *s = opaque;
63 502a5395 pbrook
64 a94fd955 blueswir1
#ifdef TARGET_WORDS_BIGENDIAN
65 a94fd955 blueswir1
    val = bswap32(val);
66 a94fd955 blueswir1
#endif
67 a94fd955 blueswir1
    APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
68 a94fd955 blueswir1
                val);
69 72f44c8c Blue Swirl
    s->host_state.config_reg = val;
70 502a5395 pbrook
}
71 502a5395 pbrook
72 502a5395 pbrook
static uint32_t pci_apb_config_readl (void *opaque,
73 c227f099 Anthony Liguori
                                            target_phys_addr_t addr)
74 502a5395 pbrook
{
75 502a5395 pbrook
    APBState *s = opaque;
76 502a5395 pbrook
    uint32_t val;
77 502a5395 pbrook
78 72f44c8c Blue Swirl
    val = s->host_state.config_reg;
79 a94fd955 blueswir1
#ifdef TARGET_WORDS_BIGENDIAN
80 a94fd955 blueswir1
    val = bswap32(val);
81 a94fd955 blueswir1
#endif
82 a94fd955 blueswir1
    APB_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
83 a94fd955 blueswir1
                val);
84 502a5395 pbrook
    return val;
85 502a5395 pbrook
}
86 502a5395 pbrook
87 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pci_apb_config_write[] = {
88 502a5395 pbrook
    &pci_apb_config_writel,
89 502a5395 pbrook
    &pci_apb_config_writel,
90 502a5395 pbrook
    &pci_apb_config_writel,
91 502a5395 pbrook
};
92 502a5395 pbrook
93 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pci_apb_config_read[] = {
94 502a5395 pbrook
    &pci_apb_config_readl,
95 502a5395 pbrook
    &pci_apb_config_readl,
96 502a5395 pbrook
    &pci_apb_config_readl,
97 502a5395 pbrook
};
98 502a5395 pbrook
99 c227f099 Anthony Liguori
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
100 f930d07e blueswir1
                               uint32_t val)
101 502a5395 pbrook
{
102 502a5395 pbrook
    //PCIBus *s = opaque;
103 502a5395 pbrook
104 502a5395 pbrook
    switch (addr & 0x3f) {
105 502a5395 pbrook
    case 0x00: // Control/Status
106 502a5395 pbrook
    case 0x10: // AFSR
107 502a5395 pbrook
    case 0x18: // AFAR
108 502a5395 pbrook
    case 0x20: // Diagnostic
109 502a5395 pbrook
    case 0x28: // Target address space
110 f930d07e blueswir1
        // XXX
111 502a5395 pbrook
    default:
112 f930d07e blueswir1
        break;
113 502a5395 pbrook
    }
114 502a5395 pbrook
}
115 502a5395 pbrook
116 502a5395 pbrook
static uint32_t apb_config_readl (void *opaque,
117 c227f099 Anthony Liguori
                                  target_phys_addr_t addr)
118 502a5395 pbrook
{
119 502a5395 pbrook
    //PCIBus *s = opaque;
120 502a5395 pbrook
    uint32_t val;
121 502a5395 pbrook
122 502a5395 pbrook
    switch (addr & 0x3f) {
123 502a5395 pbrook
    case 0x00: // Control/Status
124 502a5395 pbrook
    case 0x10: // AFSR
125 502a5395 pbrook
    case 0x18: // AFAR
126 502a5395 pbrook
    case 0x20: // Diagnostic
127 502a5395 pbrook
    case 0x28: // Target address space
128 f930d07e blueswir1
        // XXX
129 502a5395 pbrook
    default:
130 f930d07e blueswir1
        val = 0;
131 f930d07e blueswir1
        break;
132 502a5395 pbrook
    }
133 502a5395 pbrook
    return val;
134 502a5395 pbrook
}
135 502a5395 pbrook
136 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const apb_config_write[] = {
137 502a5395 pbrook
    &apb_config_writel,
138 502a5395 pbrook
    &apb_config_writel,
139 502a5395 pbrook
    &apb_config_writel,
140 502a5395 pbrook
};
141 502a5395 pbrook
142 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const apb_config_read[] = {
143 502a5395 pbrook
    &apb_config_readl,
144 502a5395 pbrook
    &apb_config_readl,
145 502a5395 pbrook
    &apb_config_readl,
146 502a5395 pbrook
};
147 502a5395 pbrook
148 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pci_apb_write[] = {
149 502a5395 pbrook
    &pci_host_data_writeb,
150 502a5395 pbrook
    &pci_host_data_writew,
151 502a5395 pbrook
    &pci_host_data_writel,
152 502a5395 pbrook
};
153 502a5395 pbrook
154 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pci_apb_read[] = {
155 502a5395 pbrook
    &pci_host_data_readb,
156 502a5395 pbrook
    &pci_host_data_readw,
157 502a5395 pbrook
    &pci_host_data_readl,
158 502a5395 pbrook
};
159 502a5395 pbrook
160 c227f099 Anthony Liguori
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
161 502a5395 pbrook
                                  uint32_t val)
162 502a5395 pbrook
{
163 afcea8cb Blue Swirl
    cpu_outb(addr & IOPORTS_MASK, val);
164 502a5395 pbrook
}
165 502a5395 pbrook
166 c227f099 Anthony Liguori
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
167 502a5395 pbrook
                                  uint32_t val)
168 502a5395 pbrook
{
169 afcea8cb Blue Swirl
    cpu_outw(addr & IOPORTS_MASK, val);
170 502a5395 pbrook
}
171 502a5395 pbrook
172 c227f099 Anthony Liguori
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
173 502a5395 pbrook
                                uint32_t val)
174 502a5395 pbrook
{
175 afcea8cb Blue Swirl
    cpu_outl(addr & IOPORTS_MASK, val);
176 502a5395 pbrook
}
177 502a5395 pbrook
178 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
179 502a5395 pbrook
{
180 502a5395 pbrook
    uint32_t val;
181 502a5395 pbrook
182 afcea8cb Blue Swirl
    val = cpu_inb(addr & IOPORTS_MASK);
183 502a5395 pbrook
    return val;
184 502a5395 pbrook
}
185 502a5395 pbrook
186 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
187 502a5395 pbrook
{
188 502a5395 pbrook
    uint32_t val;
189 502a5395 pbrook
190 afcea8cb Blue Swirl
    val = cpu_inw(addr & IOPORTS_MASK);
191 502a5395 pbrook
    return val;
192 502a5395 pbrook
}
193 502a5395 pbrook
194 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
195 502a5395 pbrook
{
196 502a5395 pbrook
    uint32_t val;
197 502a5395 pbrook
198 afcea8cb Blue Swirl
    val = cpu_inl(addr & IOPORTS_MASK);
199 502a5395 pbrook
    return val;
200 502a5395 pbrook
}
201 502a5395 pbrook
202 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
203 502a5395 pbrook
    &pci_apb_iowriteb,
204 502a5395 pbrook
    &pci_apb_iowritew,
205 502a5395 pbrook
    &pci_apb_iowritel,
206 502a5395 pbrook
};
207 502a5395 pbrook
208 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pci_apb_ioread[] = {
209 502a5395 pbrook
    &pci_apb_ioreadb,
210 502a5395 pbrook
    &pci_apb_ioreadw,
211 502a5395 pbrook
    &pci_apb_ioreadl,
212 502a5395 pbrook
};
213 502a5395 pbrook
214 80b3ada7 pbrook
/* The APB host has an IRQ line for each IRQ line of each slot.  */
215 d2b59317 pbrook
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
216 502a5395 pbrook
{
217 80b3ada7 pbrook
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
218 80b3ada7 pbrook
}
219 80b3ada7 pbrook
220 80b3ada7 pbrook
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
221 80b3ada7 pbrook
{
222 80b3ada7 pbrook
    int bus_offset;
223 80b3ada7 pbrook
    if (pci_dev->devfn & 1)
224 80b3ada7 pbrook
        bus_offset = 16;
225 80b3ada7 pbrook
    else
226 80b3ada7 pbrook
        bus_offset = 0;
227 80b3ada7 pbrook
    return bus_offset + irq_num;
228 d2b59317 pbrook
}
229 d2b59317 pbrook
230 5d4e84c8 Juan Quintela
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
231 d2b59317 pbrook
{
232 5d4e84c8 Juan Quintela
    qemu_irq *pic = opaque;
233 5d4e84c8 Juan Quintela
234 80b3ada7 pbrook
    /* PCI IRQ map onto the first 32 INO.  */
235 d537cf6c pbrook
    qemu_set_irq(pic[irq_num], level);
236 502a5395 pbrook
}
237 502a5395 pbrook
238 c227f099 Anthony Liguori
PCIBus *pci_apb_init(target_phys_addr_t special_base,
239 c227f099 Anthony Liguori
                     target_phys_addr_t mem_base,
240 c190ea07 blueswir1
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
241 502a5395 pbrook
{
242 72f44c8c Blue Swirl
    DeviceState *dev;
243 72f44c8c Blue Swirl
    SysBusDevice *s;
244 72f44c8c Blue Swirl
    APBState *d;
245 502a5395 pbrook
246 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
247 72f44c8c Blue Swirl
    dev = qdev_create(NULL, "pbm");
248 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
249 72f44c8c Blue Swirl
    s = sysbus_from_qdev(dev);
250 72f44c8c Blue Swirl
    /* apb_config */
251 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 0, special_base + 0x2000ULL);
252 72f44c8c Blue Swirl
    /* pci_ioport */
253 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
254 72f44c8c Blue Swirl
    /* mem_config: XXX size should be 4G-prom */
255 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
256 72f44c8c Blue Swirl
    /* mem_data */
257 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 3, mem_base);
258 72f44c8c Blue Swirl
    d = FROM_SYSBUS(APBState, s);
259 c5ff6d54 Blue Swirl
    d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
260 72f44c8c Blue Swirl
                                         pci_apb_set_irq, pci_pbm_map_irq, pic,
261 72f44c8c Blue Swirl
                                         0, 32);
262 72f44c8c Blue Swirl
    pci_create_simple(d->host_state.bus, 0, "pbm");
263 72f44c8c Blue Swirl
    /* APB secondary busses */
264 72f44c8c Blue Swirl
    *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
265 72f44c8c Blue Swirl
                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
266 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 1");
267 72f44c8c Blue Swirl
    *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
268 72f44c8c Blue Swirl
                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
269 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 2");
270 502a5395 pbrook
271 72f44c8c Blue Swirl
    return d->host_state.bus;
272 72f44c8c Blue Swirl
}
273 72f44c8c Blue Swirl
274 81a322d4 Gerd Hoffmann
static int pci_pbm_init_device(SysBusDevice *dev)
275 72f44c8c Blue Swirl
{
276 72f44c8c Blue Swirl
277 72f44c8c Blue Swirl
    APBState *s;
278 72f44c8c Blue Swirl
    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
279 72f44c8c Blue Swirl
280 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
281 72f44c8c Blue Swirl
    /* apb_config */
282 1eed09cb Avi Kivity
    apb_config = cpu_register_io_memory(apb_config_read,
283 f930d07e blueswir1
                                        apb_config_write, s);
284 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x40ULL, apb_config);
285 72f44c8c Blue Swirl
    /* pci_ioport */
286 1eed09cb Avi Kivity
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
287 502a5395 pbrook
                                          pci_apb_iowrite, s);
288 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
289 72f44c8c Blue Swirl
    /* mem_config  */
290 72f44c8c Blue Swirl
    pci_mem_config = cpu_register_io_memory(pci_apb_config_read,
291 72f44c8c Blue Swirl
                                            pci_apb_config_write, s);
292 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
293 72f44c8c Blue Swirl
    /* mem_data */
294 72f44c8c Blue Swirl
    pci_mem_data = cpu_register_io_memory(pci_apb_read,
295 72f44c8c Blue Swirl
                                          pci_apb_write, &s->host_state);
296 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
297 81a322d4 Gerd Hoffmann
    return 0;
298 72f44c8c Blue Swirl
}
299 502a5395 pbrook
300 81a322d4 Gerd Hoffmann
static int pbm_pci_host_init(PCIDevice *d)
301 72f44c8c Blue Swirl
{
302 deb54399 aliguori
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
303 deb54399 aliguori
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
304 502a5395 pbrook
    d->config[0x04] = 0x06; // command = bus master, pci mem
305 502a5395 pbrook
    d->config[0x05] = 0x00;
306 502a5395 pbrook
    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
307 502a5395 pbrook
    d->config[0x07] = 0x03; // status = medium devsel
308 502a5395 pbrook
    d->config[0x08] = 0x00; // revision
309 502a5395 pbrook
    d->config[0x09] = 0x00; // programming i/f
310 173a543b blueswir1
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
311 502a5395 pbrook
    d->config[0x0D] = 0x10; // latency_timer
312 110c50fd Blue Swirl
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
313 81a322d4 Gerd Hoffmann
    return 0;
314 72f44c8c Blue Swirl
}
315 80b3ada7 pbrook
316 72f44c8c Blue Swirl
static PCIDeviceInfo pbm_pci_host_info = {
317 72f44c8c Blue Swirl
    .qdev.name = "pbm",
318 72f44c8c Blue Swirl
    .qdev.size = sizeof(PCIDevice),
319 72f44c8c Blue Swirl
    .init      = pbm_pci_host_init,
320 72f44c8c Blue Swirl
};
321 72f44c8c Blue Swirl
322 72f44c8c Blue Swirl
static void pbm_register_devices(void)
323 72f44c8c Blue Swirl
{
324 72f44c8c Blue Swirl
    sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
325 72f44c8c Blue Swirl
    pci_qdev_register(&pbm_pci_host_info);
326 502a5395 pbrook
}
327 72f44c8c Blue Swirl
328 72f44c8c Blue Swirl
device_init(pbm_register_devices)