Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 7375c86f

History | View | Annotate | Download (13.3 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 63e6f31d Michael S. Tsirkin
#include "rwhandler.h"
33 18e08a55 Michael S. Tsirkin
#include "apb_pci.h"
34 a94fd955 blueswir1
35 a94fd955 blueswir1
/* debug APB */
36 a94fd955 blueswir1
//#define DEBUG_APB
37 a94fd955 blueswir1
38 a94fd955 blueswir1
#ifdef DEBUG_APB
39 001faf32 Blue Swirl
#define APB_DPRINTF(fmt, ...) \
40 001faf32 Blue Swirl
do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
41 a94fd955 blueswir1
#else
42 001faf32 Blue Swirl
#define APB_DPRINTF(fmt, ...)
43 a94fd955 blueswir1
#endif
44 a94fd955 blueswir1
45 930f3fe1 Blue Swirl
/*
46 930f3fe1 Blue Swirl
 * Chipset docs:
47 930f3fe1 Blue Swirl
 * PBM: "UltraSPARC IIi User's Manual",
48 930f3fe1 Blue Swirl
 * http://www.sun.com/processors/manuals/805-0087.pdf
49 930f3fe1 Blue Swirl
 *
50 930f3fe1 Blue Swirl
 * APB: "Advanced PCI Bridge (APB) User's Manual",
51 930f3fe1 Blue Swirl
 * http://www.sun.com/processors/manuals/805-1251.pdf
52 930f3fe1 Blue Swirl
 */
53 930f3fe1 Blue Swirl
54 95819af0 Blue Swirl
#define PBM_PCI_IMR_MASK    0x7fffffff
55 95819af0 Blue Swirl
#define PBM_PCI_IMR_ENABLED 0x80000000
56 95819af0 Blue Swirl
57 95819af0 Blue Swirl
#define POR          (1 << 31)
58 95819af0 Blue Swirl
#define SOFT_POR     (1 << 30)
59 95819af0 Blue Swirl
#define SOFT_XIR     (1 << 29)
60 95819af0 Blue Swirl
#define BTN_POR      (1 << 28)
61 95819af0 Blue Swirl
#define BTN_XIR      (1 << 27)
62 95819af0 Blue Swirl
#define RESET_MASK   0xf8000000
63 95819af0 Blue Swirl
#define RESET_WCMASK 0x98000000
64 95819af0 Blue Swirl
#define RESET_WMASK  0x60000000
65 95819af0 Blue Swirl
66 72f44c8c Blue Swirl
typedef struct APBState {
67 72f44c8c Blue Swirl
    SysBusDevice busdev;
68 d63baf92 Igor V. Kovalenko
    PCIBus      *bus;
69 63e6f31d Michael S. Tsirkin
    ReadWriteHandler pci_config_handler;
70 95819af0 Blue Swirl
    uint32_t iommu[4];
71 95819af0 Blue Swirl
    uint32_t pci_control[16];
72 95819af0 Blue Swirl
    uint32_t pci_irq_map[8];
73 95819af0 Blue Swirl
    uint32_t obio_irq_map[32];
74 95819af0 Blue Swirl
    qemu_irq pci_irqs[32];
75 95819af0 Blue Swirl
    uint32_t reset_control;
76 9c0afd0e Blue Swirl
    unsigned int nr_resets;
77 72f44c8c Blue Swirl
} APBState;
78 502a5395 pbrook
79 c227f099 Anthony Liguori
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
80 f930d07e blueswir1
                               uint32_t val)
81 502a5395 pbrook
{
82 95819af0 Blue Swirl
    APBState *s = opaque;
83 95819af0 Blue Swirl
84 95819af0 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
85 95819af0 Blue Swirl
86 95819af0 Blue Swirl
    switch (addr & 0xffff) {
87 95819af0 Blue Swirl
    case 0x30 ... 0x4f: /* DMA error registers */
88 95819af0 Blue Swirl
        /* XXX: not implemented yet */
89 95819af0 Blue Swirl
        break;
90 95819af0 Blue Swirl
    case 0x200 ... 0x20b: /* IOMMU */
91 95819af0 Blue Swirl
        s->iommu[(addr & 0xf) >> 2] = val;
92 95819af0 Blue Swirl
        break;
93 95819af0 Blue Swirl
    case 0x20c ... 0x3ff: /* IOMMU flush */
94 95819af0 Blue Swirl
        break;
95 95819af0 Blue Swirl
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
96 95819af0 Blue Swirl
        if (addr & 4) {
97 95819af0 Blue Swirl
            s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
98 95819af0 Blue Swirl
            s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
99 95819af0 Blue Swirl
        }
100 95819af0 Blue Swirl
        break;
101 95819af0 Blue Swirl
    case 0x2000 ... 0x202f: /* PCI control */
102 95819af0 Blue Swirl
        s->pci_control[(addr & 0x3f) >> 2] = val;
103 95819af0 Blue Swirl
        break;
104 95819af0 Blue Swirl
    case 0xf020 ... 0xf027: /* Reset control */
105 95819af0 Blue Swirl
        if (addr & 4) {
106 95819af0 Blue Swirl
            val &= RESET_MASK;
107 95819af0 Blue Swirl
            s->reset_control &= ~(val & RESET_WCMASK);
108 95819af0 Blue Swirl
            s->reset_control |= val & RESET_WMASK;
109 95819af0 Blue Swirl
            if (val & SOFT_POR) {
110 9c0afd0e Blue Swirl
                s->nr_resets = 0;
111 95819af0 Blue Swirl
                qemu_system_reset_request();
112 95819af0 Blue Swirl
            } else if (val & SOFT_XIR) {
113 95819af0 Blue Swirl
                qemu_system_reset_request();
114 95819af0 Blue Swirl
            }
115 95819af0 Blue Swirl
        }
116 95819af0 Blue Swirl
        break;
117 95819af0 Blue Swirl
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
118 95819af0 Blue Swirl
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
119 95819af0 Blue Swirl
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
120 95819af0 Blue Swirl
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
121 95819af0 Blue Swirl
        /* we don't care */
122 502a5395 pbrook
    default:
123 f930d07e blueswir1
        break;
124 502a5395 pbrook
    }
125 502a5395 pbrook
}
126 502a5395 pbrook
127 502a5395 pbrook
static uint32_t apb_config_readl (void *opaque,
128 c227f099 Anthony Liguori
                                  target_phys_addr_t addr)
129 502a5395 pbrook
{
130 95819af0 Blue Swirl
    APBState *s = opaque;
131 502a5395 pbrook
    uint32_t val;
132 502a5395 pbrook
133 95819af0 Blue Swirl
    switch (addr & 0xffff) {
134 95819af0 Blue Swirl
    case 0x30 ... 0x4f: /* DMA error registers */
135 95819af0 Blue Swirl
        val = 0;
136 95819af0 Blue Swirl
        /* XXX: not implemented yet */
137 95819af0 Blue Swirl
        break;
138 95819af0 Blue Swirl
    case 0x200 ... 0x20b: /* IOMMU */
139 95819af0 Blue Swirl
        val = s->iommu[(addr & 0xf) >> 2];
140 95819af0 Blue Swirl
        break;
141 95819af0 Blue Swirl
    case 0x20c ... 0x3ff: /* IOMMU flush */
142 95819af0 Blue Swirl
        val = 0;
143 95819af0 Blue Swirl
        break;
144 95819af0 Blue Swirl
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
145 95819af0 Blue Swirl
        if (addr & 4) {
146 95819af0 Blue Swirl
            val = s->pci_irq_map[(addr & 0x3f) >> 3];
147 95819af0 Blue Swirl
        } else {
148 95819af0 Blue Swirl
            val = 0;
149 95819af0 Blue Swirl
        }
150 95819af0 Blue Swirl
        break;
151 95819af0 Blue Swirl
    case 0x2000 ... 0x202f: /* PCI control */
152 95819af0 Blue Swirl
        val = s->pci_control[(addr & 0x3f) >> 2];
153 95819af0 Blue Swirl
        break;
154 95819af0 Blue Swirl
    case 0xf020 ... 0xf027: /* Reset control */
155 95819af0 Blue Swirl
        if (addr & 4) {
156 95819af0 Blue Swirl
            val = s->reset_control;
157 95819af0 Blue Swirl
        } else {
158 95819af0 Blue Swirl
            val = 0;
159 95819af0 Blue Swirl
        }
160 95819af0 Blue Swirl
        break;
161 95819af0 Blue Swirl
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
162 95819af0 Blue Swirl
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
163 95819af0 Blue Swirl
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
164 95819af0 Blue Swirl
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
165 95819af0 Blue Swirl
        /* we don't care */
166 502a5395 pbrook
    default:
167 f930d07e blueswir1
        val = 0;
168 f930d07e blueswir1
        break;
169 502a5395 pbrook
    }
170 95819af0 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
171 95819af0 Blue Swirl
172 502a5395 pbrook
    return val;
173 502a5395 pbrook
}
174 502a5395 pbrook
175 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const apb_config_write[] = {
176 502a5395 pbrook
    &apb_config_writel,
177 502a5395 pbrook
    &apb_config_writel,
178 502a5395 pbrook
    &apb_config_writel,
179 502a5395 pbrook
};
180 502a5395 pbrook
181 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const apb_config_read[] = {
182 502a5395 pbrook
    &apb_config_readl,
183 502a5395 pbrook
    &apb_config_readl,
184 502a5395 pbrook
    &apb_config_readl,
185 502a5395 pbrook
};
186 502a5395 pbrook
187 63e6f31d Michael S. Tsirkin
static void apb_pci_config_write(ReadWriteHandler *h, pcibus_t addr,
188 5a5d4a76 Blue Swirl
                                 uint32_t val, int size)
189 5a5d4a76 Blue Swirl
{
190 63e6f31d Michael S. Tsirkin
    APBState *s = container_of(h, APBState, pci_config_handler);
191 63e6f31d Michael S. Tsirkin
192 63e6f31d Michael S. Tsirkin
    val = qemu_bswap_len(val, size);
193 5a5d4a76 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
194 d63baf92 Igor V. Kovalenko
    pci_data_write(s->bus, addr, val, size);
195 5a5d4a76 Blue Swirl
}
196 5a5d4a76 Blue Swirl
197 63e6f31d Michael S. Tsirkin
static uint32_t apb_pci_config_read(ReadWriteHandler *h, pcibus_t addr,
198 5a5d4a76 Blue Swirl
                                    int size)
199 5a5d4a76 Blue Swirl
{
200 5a5d4a76 Blue Swirl
    uint32_t ret;
201 63e6f31d Michael S. Tsirkin
    APBState *s = container_of(h, APBState, pci_config_handler);
202 5a5d4a76 Blue Swirl
203 d63baf92 Igor V. Kovalenko
    ret = pci_data_read(s->bus, addr, size);
204 63e6f31d Michael S. Tsirkin
    ret = qemu_bswap_len(ret, size);
205 5a5d4a76 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
206 5a5d4a76 Blue Swirl
    return ret;
207 5a5d4a76 Blue Swirl
}
208 5a5d4a76 Blue Swirl
209 c227f099 Anthony Liguori
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
210 502a5395 pbrook
                                  uint32_t val)
211 502a5395 pbrook
{
212 afcea8cb Blue Swirl
    cpu_outb(addr & IOPORTS_MASK, val);
213 502a5395 pbrook
}
214 502a5395 pbrook
215 c227f099 Anthony Liguori
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
216 502a5395 pbrook
                                  uint32_t val)
217 502a5395 pbrook
{
218 a4d5f62c Blue Swirl
    cpu_outw(addr & IOPORTS_MASK, bswap16(val));
219 502a5395 pbrook
}
220 502a5395 pbrook
221 c227f099 Anthony Liguori
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
222 502a5395 pbrook
                                uint32_t val)
223 502a5395 pbrook
{
224 a4d5f62c Blue Swirl
    cpu_outl(addr & IOPORTS_MASK, bswap32(val));
225 502a5395 pbrook
}
226 502a5395 pbrook
227 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
228 502a5395 pbrook
{
229 502a5395 pbrook
    uint32_t val;
230 502a5395 pbrook
231 afcea8cb Blue Swirl
    val = cpu_inb(addr & IOPORTS_MASK);
232 502a5395 pbrook
    return val;
233 502a5395 pbrook
}
234 502a5395 pbrook
235 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
236 502a5395 pbrook
{
237 502a5395 pbrook
    uint32_t val;
238 502a5395 pbrook
239 a4d5f62c Blue Swirl
    val = bswap16(cpu_inw(addr & IOPORTS_MASK));
240 502a5395 pbrook
    return val;
241 502a5395 pbrook
}
242 502a5395 pbrook
243 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
244 502a5395 pbrook
{
245 502a5395 pbrook
    uint32_t val;
246 502a5395 pbrook
247 a4d5f62c Blue Swirl
    val = bswap32(cpu_inl(addr & IOPORTS_MASK));
248 502a5395 pbrook
    return val;
249 502a5395 pbrook
}
250 502a5395 pbrook
251 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
252 502a5395 pbrook
    &pci_apb_iowriteb,
253 502a5395 pbrook
    &pci_apb_iowritew,
254 502a5395 pbrook
    &pci_apb_iowritel,
255 502a5395 pbrook
};
256 502a5395 pbrook
257 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pci_apb_ioread[] = {
258 502a5395 pbrook
    &pci_apb_ioreadb,
259 502a5395 pbrook
    &pci_apb_ioreadw,
260 502a5395 pbrook
    &pci_apb_ioreadl,
261 502a5395 pbrook
};
262 502a5395 pbrook
263 80b3ada7 pbrook
/* The APB host has an IRQ line for each IRQ line of each slot.  */
264 d2b59317 pbrook
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
265 502a5395 pbrook
{
266 80b3ada7 pbrook
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
267 80b3ada7 pbrook
}
268 80b3ada7 pbrook
269 80b3ada7 pbrook
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
270 80b3ada7 pbrook
{
271 80b3ada7 pbrook
    int bus_offset;
272 80b3ada7 pbrook
    if (pci_dev->devfn & 1)
273 80b3ada7 pbrook
        bus_offset = 16;
274 80b3ada7 pbrook
    else
275 80b3ada7 pbrook
        bus_offset = 0;
276 80b3ada7 pbrook
    return bus_offset + irq_num;
277 d2b59317 pbrook
}
278 d2b59317 pbrook
279 5d4e84c8 Juan Quintela
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
280 d2b59317 pbrook
{
281 95819af0 Blue Swirl
    APBState *s = opaque;
282 5d4e84c8 Juan Quintela
283 80b3ada7 pbrook
    /* PCI IRQ map onto the first 32 INO.  */
284 95819af0 Blue Swirl
    if (irq_num < 32) {
285 95819af0 Blue Swirl
        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
286 95819af0 Blue Swirl
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
287 95819af0 Blue Swirl
            qemu_set_irq(s->pci_irqs[irq_num], level);
288 95819af0 Blue Swirl
        } else {
289 95819af0 Blue Swirl
            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
290 95819af0 Blue Swirl
            qemu_irq_lower(s->pci_irqs[irq_num]);
291 95819af0 Blue Swirl
        }
292 95819af0 Blue Swirl
    }
293 502a5395 pbrook
}
294 502a5395 pbrook
295 d6318738 Michael S. Tsirkin
static void apb_pci_bridge_init(PCIBus *b)
296 d6318738 Michael S. Tsirkin
{
297 d6318738 Michael S. Tsirkin
    PCIDevice *dev = pci_bridge_get_device(b);
298 d6318738 Michael S. Tsirkin
299 d6318738 Michael S. Tsirkin
    /*
300 d6318738 Michael S. Tsirkin
     * command register:
301 d6318738 Michael S. Tsirkin
     * According to PCI bridge spec, after reset
302 d6318738 Michael S. Tsirkin
     *   bus master bit is off
303 d6318738 Michael S. Tsirkin
     *   memory space enable bit is off
304 d6318738 Michael S. Tsirkin
     * According to manual (805-1251.pdf).
305 d6318738 Michael S. Tsirkin
     *   the reset value should be zero unless the boot pin is tied high
306 d6318738 Michael S. Tsirkin
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
307 d6318738 Michael S. Tsirkin
     */
308 d6318738 Michael S. Tsirkin
    pci_set_word(dev->config + PCI_COMMAND,
309 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY);
310 9fe52c7f Blue Swirl
    pci_set_word(dev->config + PCI_STATUS,
311 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
312 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
313 9fe52c7f Blue Swirl
    pci_set_byte(dev->config + PCI_REVISION_ID, 0x11);
314 9fe52c7f Blue Swirl
    pci_set_byte(dev->config + PCI_HEADER_TYPE,
315 9fe52c7f Blue Swirl
                 pci_get_byte(dev->config + PCI_HEADER_TYPE) |
316 9fe52c7f Blue Swirl
                 PCI_HEADER_TYPE_MULTI_FUNCTION);
317 d6318738 Michael S. Tsirkin
}
318 d6318738 Michael S. Tsirkin
319 c227f099 Anthony Liguori
PCIBus *pci_apb_init(target_phys_addr_t special_base,
320 c227f099 Anthony Liguori
                     target_phys_addr_t mem_base,
321 c190ea07 blueswir1
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
322 502a5395 pbrook
{
323 72f44c8c Blue Swirl
    DeviceState *dev;
324 72f44c8c Blue Swirl
    SysBusDevice *s;
325 72f44c8c Blue Swirl
    APBState *d;
326 95819af0 Blue Swirl
    unsigned int i;
327 502a5395 pbrook
328 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
329 72f44c8c Blue Swirl
    dev = qdev_create(NULL, "pbm");
330 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
331 72f44c8c Blue Swirl
    s = sysbus_from_qdev(dev);
332 72f44c8c Blue Swirl
    /* apb_config */
333 bae7b517 Blue Swirl
    sysbus_mmio_map(s, 0, special_base);
334 d63baf92 Igor V. Kovalenko
    /* PCI configuration space */
335 d63baf92 Igor V. Kovalenko
    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
336 72f44c8c Blue Swirl
    /* pci_ioport */
337 d63baf92 Igor V. Kovalenko
    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
338 72f44c8c Blue Swirl
    d = FROM_SYSBUS(APBState, s);
339 d63baf92 Igor V. Kovalenko
340 d63baf92 Igor V. Kovalenko
    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
341 95819af0 Blue Swirl
                                         pci_apb_set_irq, pci_pbm_map_irq, d,
342 72f44c8c Blue Swirl
                                         0, 32);
343 d63baf92 Igor V. Kovalenko
    pci_bus_set_mem_base(d->bus, mem_base);
344 f6b6f1bc Blue Swirl
345 95819af0 Blue Swirl
    for (i = 0; i < 32; i++) {
346 95819af0 Blue Swirl
        sysbus_connect_irq(s, i, pic[i]);
347 95819af0 Blue Swirl
    }
348 95819af0 Blue Swirl
349 d63baf92 Igor V. Kovalenko
    pci_create_simple(d->bus, 0, "pbm");
350 d63baf92 Igor V. Kovalenko
351 72f44c8c Blue Swirl
    /* APB secondary busses */
352 d63baf92 Igor V. Kovalenko
    *bus2 = pci_bridge_init(d->bus, PCI_DEVFN(1, 0),
353 2217dcff Isaku Yamahata
                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
354 2217dcff Isaku Yamahata
                            pci_apb_map_irq,
355 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 1");
356 d6318738 Michael S. Tsirkin
    apb_pci_bridge_init(*bus2);
357 d6318738 Michael S. Tsirkin
358 d63baf92 Igor V. Kovalenko
    *bus3 = pci_bridge_init(d->bus, PCI_DEVFN(1, 1),
359 2217dcff Isaku Yamahata
                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
360 2217dcff Isaku Yamahata
                            pci_apb_map_irq,
361 72f44c8c Blue Swirl
                            "Advanced PCI Bus secondary bridge 2");
362 d6318738 Michael S. Tsirkin
    apb_pci_bridge_init(*bus3);
363 502a5395 pbrook
364 d63baf92 Igor V. Kovalenko
    return d->bus;
365 72f44c8c Blue Swirl
}
366 72f44c8c Blue Swirl
367 95819af0 Blue Swirl
static void pci_pbm_reset(DeviceState *d)
368 72f44c8c Blue Swirl
{
369 95819af0 Blue Swirl
    unsigned int i;
370 95819af0 Blue Swirl
    APBState *s = container_of(d, APBState, busdev.qdev);
371 72f44c8c Blue Swirl
372 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
373 95819af0 Blue Swirl
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
374 95819af0 Blue Swirl
    }
375 95819af0 Blue Swirl
376 9c0afd0e Blue Swirl
    if (s->nr_resets++ == 0) {
377 95819af0 Blue Swirl
        /* Power on reset */
378 95819af0 Blue Swirl
        s->reset_control = POR;
379 95819af0 Blue Swirl
    }
380 95819af0 Blue Swirl
}
381 95819af0 Blue Swirl
382 95819af0 Blue Swirl
static int pci_pbm_init_device(SysBusDevice *dev)
383 95819af0 Blue Swirl
{
384 72f44c8c Blue Swirl
    APBState *s;
385 d63baf92 Igor V. Kovalenko
    int pci_config, apb_config, pci_ioport;
386 95819af0 Blue Swirl
    unsigned int i;
387 72f44c8c Blue Swirl
388 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
389 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
390 95819af0 Blue Swirl
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
391 95819af0 Blue Swirl
    }
392 95819af0 Blue Swirl
    for (i = 0; i < 32; i++) {
393 95819af0 Blue Swirl
        sysbus_init_irq(dev, &s->pci_irqs[i]);
394 95819af0 Blue Swirl
    }
395 95819af0 Blue Swirl
396 72f44c8c Blue Swirl
    /* apb_config */
397 1eed09cb Avi Kivity
    apb_config = cpu_register_io_memory(apb_config_read,
398 f930d07e blueswir1
                                        apb_config_write, s);
399 d63baf92 Igor V. Kovalenko
    /* at region 0 */
400 bae7b517 Blue Swirl
    sysbus_init_mmio(dev, 0x10000ULL, apb_config);
401 d63baf92 Igor V. Kovalenko
402 d63baf92 Igor V. Kovalenko
    /* PCI configuration space */
403 63e6f31d Michael S. Tsirkin
    s->pci_config_handler.read = apb_pci_config_read;
404 63e6f31d Michael S. Tsirkin
    s->pci_config_handler.write = apb_pci_config_write;
405 63e6f31d Michael S. Tsirkin
    pci_config = cpu_register_io_memory_simple(&s->pci_config_handler);
406 63e6f31d Michael S. Tsirkin
    assert(pci_config >= 0);
407 d63baf92 Igor V. Kovalenko
    /* at region 1 */
408 5a5d4a76 Blue Swirl
    sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
409 d63baf92 Igor V. Kovalenko
410 d63baf92 Igor V. Kovalenko
    /* pci_ioport */
411 d63baf92 Igor V. Kovalenko
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
412 d63baf92 Igor V. Kovalenko
                                        pci_apb_iowrite, s);
413 d63baf92 Igor V. Kovalenko
    /* at region 2 */
414 d63baf92 Igor V. Kovalenko
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
415 d63baf92 Igor V. Kovalenko
416 81a322d4 Gerd Hoffmann
    return 0;
417 72f44c8c Blue Swirl
}
418 502a5395 pbrook
419 81a322d4 Gerd Hoffmann
static int pbm_pci_host_init(PCIDevice *d)
420 72f44c8c Blue Swirl
{
421 deb54399 aliguori
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
422 deb54399 aliguori
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
423 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_COMMAND,
424 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
425 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_STATUS,
426 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
427 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
428 173a543b blueswir1
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
429 9fe52c7f Blue Swirl
    pci_set_byte(d->config + PCI_HEADER_TYPE,
430 9fe52c7f Blue Swirl
                 PCI_HEADER_TYPE_NORMAL);
431 81a322d4 Gerd Hoffmann
    return 0;
432 72f44c8c Blue Swirl
}
433 80b3ada7 pbrook
434 72f44c8c Blue Swirl
static PCIDeviceInfo pbm_pci_host_info = {
435 72f44c8c Blue Swirl
    .qdev.name = "pbm",
436 72f44c8c Blue Swirl
    .qdev.size = sizeof(PCIDevice),
437 72f44c8c Blue Swirl
    .init      = pbm_pci_host_init,
438 776e1bbb Blue Swirl
    .header_type  = PCI_HEADER_TYPE_BRIDGE,
439 72f44c8c Blue Swirl
};
440 72f44c8c Blue Swirl
441 95819af0 Blue Swirl
static SysBusDeviceInfo pbm_host_info = {
442 95819af0 Blue Swirl
    .qdev.name = "pbm",
443 95819af0 Blue Swirl
    .qdev.size = sizeof(APBState),
444 95819af0 Blue Swirl
    .qdev.reset = pci_pbm_reset,
445 95819af0 Blue Swirl
    .init = pci_pbm_init_device,
446 95819af0 Blue Swirl
};
447 72f44c8c Blue Swirl
static void pbm_register_devices(void)
448 72f44c8c Blue Swirl
{
449 95819af0 Blue Swirl
    sysbus_register_withprop(&pbm_host_info);
450 72f44c8c Blue Swirl
    pci_qdev_register(&pbm_pci_host_info);
451 502a5395 pbrook
}
452 72f44c8c Blue Swirl
453 72f44c8c Blue Swirl
device_init(pbm_register_devices)