Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 4f4cc0ef

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