Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ abd0c6bd

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