Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ c4470b25

History | View | Annotate | Download (8.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 502a5395 pbrook
static CPUWriteMemoryFunc *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 502a5395 pbrook
static CPUReadMemoryFunc *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 502a5395 pbrook
static CPUWriteMemoryFunc *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 502a5395 pbrook
static CPUReadMemoryFunc *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 502a5395 pbrook
static CPUWriteMemoryFunc *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 502a5395 pbrook
static CPUReadMemoryFunc *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 502a5395 pbrook
static CPUWriteMemoryFunc *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 502a5395 pbrook
static CPUReadMemoryFunc *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 d537cf6c pbrook
static void pci_apb_set_irq(qemu_irq *pic, int irq_num, int level)
222 d2b59317 pbrook
{
223 80b3ada7 pbrook
    /* PCI IRQ map onto the first 32 INO.  */
224 d537cf6c pbrook
    qemu_set_irq(pic[irq_num], level);
225 502a5395 pbrook
}
226 502a5395 pbrook
227 fdf41d22 blueswir1
PCIBus *pci_apb_init(target_phys_addr_t special_base,
228 fdf41d22 blueswir1
                     target_phys_addr_t mem_base,
229 c190ea07 blueswir1
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
230 502a5395 pbrook
{
231 72f44c8c Blue Swirl
    DeviceState *dev;
232 72f44c8c Blue Swirl
    SysBusDevice *s;
233 72f44c8c Blue Swirl
    APBState *d;
234 502a5395 pbrook
235 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
236 72f44c8c Blue Swirl
    dev = qdev_create(NULL, "pbm");
237 72f44c8c Blue Swirl
    qdev_init(dev);
238 72f44c8c Blue Swirl
    s = sysbus_from_qdev(dev);
239 72f44c8c Blue Swirl
    /* apb_config */
240 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 0, special_base + 0x2000ULL);
241 72f44c8c Blue Swirl
    /* pci_ioport */
242 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
243 72f44c8c Blue Swirl
    /* mem_config: XXX size should be 4G-prom */
244 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
245 72f44c8c Blue Swirl
    /* mem_data */
246 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 3, mem_base);
247 72f44c8c Blue Swirl
    d = FROM_SYSBUS(APBState, s);
248 72f44c8c Blue Swirl
    d->host_state.bus = pci_register_bus(NULL, "pci",
249 72f44c8c Blue Swirl
                                         pci_apb_set_irq, pci_pbm_map_irq, pic,
250 72f44c8c Blue Swirl
                                         0, 32);
251 72f44c8c Blue Swirl
    pci_create_simple(d->host_state.bus, 0, "pbm");
252 72f44c8c Blue Swirl
    /* APB secondary busses */
253 72f44c8c Blue Swirl
    *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
254 72f44c8c Blue Swirl
                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
255 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 1");
256 72f44c8c Blue Swirl
    *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
257 72f44c8c Blue Swirl
                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
258 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 2");
259 502a5395 pbrook
260 72f44c8c Blue Swirl
    return d->host_state.bus;
261 72f44c8c Blue Swirl
}
262 72f44c8c Blue Swirl
263 72f44c8c Blue Swirl
static void pci_pbm_init_device(SysBusDevice *dev)
264 72f44c8c Blue Swirl
{
265 72f44c8c Blue Swirl
266 72f44c8c Blue Swirl
    APBState *s;
267 72f44c8c Blue Swirl
    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
268 72f44c8c Blue Swirl
269 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
270 72f44c8c Blue Swirl
    /* apb_config */
271 1eed09cb Avi Kivity
    apb_config = cpu_register_io_memory(apb_config_read,
272 f930d07e blueswir1
                                        apb_config_write, s);
273 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x40ULL, apb_config);
274 72f44c8c Blue Swirl
    /* pci_ioport */
275 1eed09cb Avi Kivity
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
276 502a5395 pbrook
                                          pci_apb_iowrite, s);
277 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
278 72f44c8c Blue Swirl
    /* mem_config  */
279 72f44c8c Blue Swirl
    pci_mem_config = cpu_register_io_memory(pci_apb_config_read,
280 72f44c8c Blue Swirl
                                            pci_apb_config_write, s);
281 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
282 72f44c8c Blue Swirl
    /* mem_data */
283 72f44c8c Blue Swirl
    pci_mem_data = cpu_register_io_memory(pci_apb_read,
284 72f44c8c Blue Swirl
                                          pci_apb_write, &s->host_state);
285 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
286 72f44c8c Blue Swirl
}
287 502a5395 pbrook
288 72f44c8c Blue Swirl
static void pbm_pci_host_init(PCIDevice *d)
289 72f44c8c Blue Swirl
{
290 deb54399 aliguori
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
291 deb54399 aliguori
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
292 502a5395 pbrook
    d->config[0x04] = 0x06; // command = bus master, pci mem
293 502a5395 pbrook
    d->config[0x05] = 0x00;
294 502a5395 pbrook
    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
295 502a5395 pbrook
    d->config[0x07] = 0x03; // status = medium devsel
296 502a5395 pbrook
    d->config[0x08] = 0x00; // revision
297 502a5395 pbrook
    d->config[0x09] = 0x00; // programming i/f
298 173a543b blueswir1
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
299 502a5395 pbrook
    d->config[0x0D] = 0x10; // latency_timer
300 110c50fd Blue Swirl
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
301 72f44c8c Blue Swirl
}
302 80b3ada7 pbrook
303 72f44c8c Blue Swirl
static PCIDeviceInfo pbm_pci_host_info = {
304 72f44c8c Blue Swirl
    .qdev.name = "pbm",
305 72f44c8c Blue Swirl
    .qdev.size = sizeof(PCIDevice),
306 72f44c8c Blue Swirl
    .init      = pbm_pci_host_init,
307 72f44c8c Blue Swirl
};
308 72f44c8c Blue Swirl
309 72f44c8c Blue Swirl
static void pbm_register_devices(void)
310 72f44c8c Blue Swirl
{
311 72f44c8c Blue Swirl
    sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
312 72f44c8c Blue Swirl
    pci_qdev_register(&pbm_pci_host_info);
313 502a5395 pbrook
}
314 72f44c8c Blue Swirl
315 72f44c8c Blue Swirl
device_init(pbm_register_devices)