Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 18e08a55

History | View | Annotate | Download (7.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 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 c227f099 Anthony Liguori
PCIBus *pci_apb_init(target_phys_addr_t special_base,
186 c227f099 Anthony Liguori
                     target_phys_addr_t mem_base,
187 c190ea07 blueswir1
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
188 502a5395 pbrook
{
189 72f44c8c Blue Swirl
    DeviceState *dev;
190 72f44c8c Blue Swirl
    SysBusDevice *s;
191 72f44c8c Blue Swirl
    APBState *d;
192 502a5395 pbrook
193 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
194 72f44c8c Blue Swirl
    dev = qdev_create(NULL, "pbm");
195 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
196 72f44c8c Blue Swirl
    s = sysbus_from_qdev(dev);
197 72f44c8c Blue Swirl
    /* apb_config */
198 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 0, special_base + 0x2000ULL);
199 72f44c8c Blue Swirl
    /* pci_ioport */
200 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
201 72f44c8c Blue Swirl
    /* mem_config: XXX size should be 4G-prom */
202 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
203 72f44c8c Blue Swirl
    /* mem_data */
204 72f44c8c Blue Swirl
    sysbus_mmio_map(s, 3, mem_base);
205 72f44c8c Blue Swirl
    d = FROM_SYSBUS(APBState, s);
206 c5ff6d54 Blue Swirl
    d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
207 72f44c8c Blue Swirl
                                         pci_apb_set_irq, pci_pbm_map_irq, pic,
208 72f44c8c Blue Swirl
                                         0, 32);
209 72f44c8c Blue Swirl
    pci_create_simple(d->host_state.bus, 0, "pbm");
210 72f44c8c Blue Swirl
    /* APB secondary busses */
211 2217dcff Isaku Yamahata
    *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
212 2217dcff Isaku Yamahata
                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
213 2217dcff Isaku Yamahata
                            pci_apb_map_irq,
214 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 1");
215 2217dcff Isaku Yamahata
    *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
216 2217dcff Isaku Yamahata
                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
217 2217dcff Isaku Yamahata
                            pci_apb_map_irq,
218 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 2");
219 502a5395 pbrook
220 72f44c8c Blue Swirl
    return d->host_state.bus;
221 72f44c8c Blue Swirl
}
222 72f44c8c Blue Swirl
223 81a322d4 Gerd Hoffmann
static int pci_pbm_init_device(SysBusDevice *dev)
224 72f44c8c Blue Swirl
{
225 72f44c8c Blue Swirl
226 72f44c8c Blue Swirl
    APBState *s;
227 72f44c8c Blue Swirl
    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
228 72f44c8c Blue Swirl
229 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
230 72f44c8c Blue Swirl
    /* apb_config */
231 1eed09cb Avi Kivity
    apb_config = cpu_register_io_memory(apb_config_read,
232 f930d07e blueswir1
                                        apb_config_write, s);
233 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x40ULL, apb_config);
234 72f44c8c Blue Swirl
    /* pci_ioport */
235 1eed09cb Avi Kivity
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
236 502a5395 pbrook
                                          pci_apb_iowrite, s);
237 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
238 72f44c8c Blue Swirl
    /* mem_config  */
239 a455783b Isaku Yamahata
    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
240 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
241 72f44c8c Blue Swirl
    /* mem_data */
242 4f5e19e6 Isaku Yamahata
    pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
243 72f44c8c Blue Swirl
    sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
244 81a322d4 Gerd Hoffmann
    return 0;
245 72f44c8c Blue Swirl
}
246 502a5395 pbrook
247 81a322d4 Gerd Hoffmann
static int pbm_pci_host_init(PCIDevice *d)
248 72f44c8c Blue Swirl
{
249 deb54399 aliguori
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
250 deb54399 aliguori
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
251 502a5395 pbrook
    d->config[0x04] = 0x06; // command = bus master, pci mem
252 502a5395 pbrook
    d->config[0x05] = 0x00;
253 502a5395 pbrook
    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
254 502a5395 pbrook
    d->config[0x07] = 0x03; // status = medium devsel
255 502a5395 pbrook
    d->config[0x08] = 0x00; // revision
256 502a5395 pbrook
    d->config[0x09] = 0x00; // programming i/f
257 173a543b blueswir1
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
258 502a5395 pbrook
    d->config[0x0D] = 0x10; // latency_timer
259 110c50fd Blue Swirl
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
260 81a322d4 Gerd Hoffmann
    return 0;
261 72f44c8c Blue Swirl
}
262 80b3ada7 pbrook
263 72f44c8c Blue Swirl
static PCIDeviceInfo pbm_pci_host_info = {
264 72f44c8c Blue Swirl
    .qdev.name = "pbm",
265 72f44c8c Blue Swirl
    .qdev.size = sizeof(PCIDevice),
266 72f44c8c Blue Swirl
    .init      = pbm_pci_host_init,
267 72f44c8c Blue Swirl
};
268 72f44c8c Blue Swirl
269 72f44c8c Blue Swirl
static void pbm_register_devices(void)
270 72f44c8c Blue Swirl
{
271 72f44c8c Blue Swirl
    sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
272 72f44c8c Blue Swirl
    pci_qdev_register(&pbm_pci_host_info);
273 502a5395 pbrook
}
274 72f44c8c Blue Swirl
275 72f44c8c Blue Swirl
device_init(pbm_register_devices)