Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ e72d5c9d

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