Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ b0eb8449

History | View | Annotate | Download (13.8 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 18e08a55 Michael S. Tsirkin
#include "apb_pci.h"
35 666daa68 Markus Armbruster
#include "sysemu.h"
36 1e39101c Avi Kivity
#include "exec-memory.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 3812ed0b Avi Kivity
    MemoryRegion apb_config;
73 3812ed0b Avi Kivity
    MemoryRegion pci_config;
74 f69539b1 Blue Swirl
    MemoryRegion pci_mmio;
75 3812ed0b Avi Kivity
    MemoryRegion pci_ioport;
76 95819af0 Blue Swirl
    uint32_t iommu[4];
77 95819af0 Blue Swirl
    uint32_t pci_control[16];
78 95819af0 Blue Swirl
    uint32_t pci_irq_map[8];
79 95819af0 Blue Swirl
    uint32_t obio_irq_map[32];
80 95819af0 Blue Swirl
    qemu_irq pci_irqs[32];
81 95819af0 Blue Swirl
    uint32_t reset_control;
82 9c0afd0e Blue Swirl
    unsigned int nr_resets;
83 72f44c8c Blue Swirl
} APBState;
84 502a5395 pbrook
85 c227f099 Anthony Liguori
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
86 3812ed0b Avi Kivity
                               uint64_t val, unsigned size)
87 502a5395 pbrook
{
88 95819af0 Blue Swirl
    APBState *s = opaque;
89 95819af0 Blue Swirl
90 95819af0 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
91 95819af0 Blue Swirl
92 95819af0 Blue Swirl
    switch (addr & 0xffff) {
93 95819af0 Blue Swirl
    case 0x30 ... 0x4f: /* DMA error registers */
94 95819af0 Blue Swirl
        /* XXX: not implemented yet */
95 95819af0 Blue Swirl
        break;
96 95819af0 Blue Swirl
    case 0x200 ... 0x20b: /* IOMMU */
97 95819af0 Blue Swirl
        s->iommu[(addr & 0xf) >> 2] = val;
98 95819af0 Blue Swirl
        break;
99 95819af0 Blue Swirl
    case 0x20c ... 0x3ff: /* IOMMU flush */
100 95819af0 Blue Swirl
        break;
101 95819af0 Blue Swirl
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
102 95819af0 Blue Swirl
        if (addr & 4) {
103 95819af0 Blue Swirl
            s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
104 95819af0 Blue Swirl
            s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
105 95819af0 Blue Swirl
        }
106 95819af0 Blue Swirl
        break;
107 95819af0 Blue Swirl
    case 0x2000 ... 0x202f: /* PCI control */
108 95819af0 Blue Swirl
        s->pci_control[(addr & 0x3f) >> 2] = val;
109 95819af0 Blue Swirl
        break;
110 95819af0 Blue Swirl
    case 0xf020 ... 0xf027: /* Reset control */
111 95819af0 Blue Swirl
        if (addr & 4) {
112 95819af0 Blue Swirl
            val &= RESET_MASK;
113 95819af0 Blue Swirl
            s->reset_control &= ~(val & RESET_WCMASK);
114 95819af0 Blue Swirl
            s->reset_control |= val & RESET_WMASK;
115 95819af0 Blue Swirl
            if (val & SOFT_POR) {
116 9c0afd0e Blue Swirl
                s->nr_resets = 0;
117 95819af0 Blue Swirl
                qemu_system_reset_request();
118 95819af0 Blue Swirl
            } else if (val & SOFT_XIR) {
119 95819af0 Blue Swirl
                qemu_system_reset_request();
120 95819af0 Blue Swirl
            }
121 95819af0 Blue Swirl
        }
122 95819af0 Blue Swirl
        break;
123 95819af0 Blue Swirl
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
124 95819af0 Blue Swirl
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
125 95819af0 Blue Swirl
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
126 95819af0 Blue Swirl
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
127 95819af0 Blue Swirl
        /* we don't care */
128 502a5395 pbrook
    default:
129 f930d07e blueswir1
        break;
130 502a5395 pbrook
    }
131 502a5395 pbrook
}
132 502a5395 pbrook
133 3812ed0b Avi Kivity
static uint64_t apb_config_readl (void *opaque,
134 3812ed0b Avi Kivity
                                  target_phys_addr_t addr, unsigned size)
135 502a5395 pbrook
{
136 95819af0 Blue Swirl
    APBState *s = opaque;
137 502a5395 pbrook
    uint32_t val;
138 502a5395 pbrook
139 95819af0 Blue Swirl
    switch (addr & 0xffff) {
140 95819af0 Blue Swirl
    case 0x30 ... 0x4f: /* DMA error registers */
141 95819af0 Blue Swirl
        val = 0;
142 95819af0 Blue Swirl
        /* XXX: not implemented yet */
143 95819af0 Blue Swirl
        break;
144 95819af0 Blue Swirl
    case 0x200 ... 0x20b: /* IOMMU */
145 95819af0 Blue Swirl
        val = s->iommu[(addr & 0xf) >> 2];
146 95819af0 Blue Swirl
        break;
147 95819af0 Blue Swirl
    case 0x20c ... 0x3ff: /* IOMMU flush */
148 95819af0 Blue Swirl
        val = 0;
149 95819af0 Blue Swirl
        break;
150 95819af0 Blue Swirl
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
151 95819af0 Blue Swirl
        if (addr & 4) {
152 95819af0 Blue Swirl
            val = s->pci_irq_map[(addr & 0x3f) >> 3];
153 95819af0 Blue Swirl
        } else {
154 95819af0 Blue Swirl
            val = 0;
155 95819af0 Blue Swirl
        }
156 95819af0 Blue Swirl
        break;
157 95819af0 Blue Swirl
    case 0x2000 ... 0x202f: /* PCI control */
158 95819af0 Blue Swirl
        val = s->pci_control[(addr & 0x3f) >> 2];
159 95819af0 Blue Swirl
        break;
160 95819af0 Blue Swirl
    case 0xf020 ... 0xf027: /* Reset control */
161 95819af0 Blue Swirl
        if (addr & 4) {
162 95819af0 Blue Swirl
            val = s->reset_control;
163 95819af0 Blue Swirl
        } else {
164 95819af0 Blue Swirl
            val = 0;
165 95819af0 Blue Swirl
        }
166 95819af0 Blue Swirl
        break;
167 95819af0 Blue Swirl
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
168 95819af0 Blue Swirl
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
169 95819af0 Blue Swirl
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
170 95819af0 Blue Swirl
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
171 95819af0 Blue Swirl
        /* we don't care */
172 502a5395 pbrook
    default:
173 f930d07e blueswir1
        val = 0;
174 f930d07e blueswir1
        break;
175 502a5395 pbrook
    }
176 95819af0 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
177 95819af0 Blue Swirl
178 502a5395 pbrook
    return val;
179 502a5395 pbrook
}
180 502a5395 pbrook
181 3812ed0b Avi Kivity
static const MemoryRegionOps apb_config_ops = {
182 3812ed0b Avi Kivity
    .read = apb_config_readl,
183 3812ed0b Avi Kivity
    .write = apb_config_writel,
184 3812ed0b Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
185 502a5395 pbrook
};
186 502a5395 pbrook
187 3812ed0b Avi Kivity
static void apb_pci_config_write(void *opaque, target_phys_addr_t addr,
188 3812ed0b Avi Kivity
                                 uint64_t val, unsigned size)
189 5a5d4a76 Blue Swirl
{
190 3812ed0b Avi Kivity
    APBState *s = opaque;
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 3812ed0b Avi Kivity
static uint64_t apb_pci_config_read(void *opaque, target_phys_addr_t addr,
198 3812ed0b Avi Kivity
                                    unsigned size)
199 5a5d4a76 Blue Swirl
{
200 5a5d4a76 Blue Swirl
    uint32_t ret;
201 3812ed0b Avi Kivity
    APBState *s = opaque;
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 3812ed0b Avi Kivity
static const MemoryRegionOps pci_ioport_ops = {
252 3812ed0b Avi Kivity
    .old_mmio = {
253 3812ed0b Avi Kivity
        .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
254 3812ed0b Avi Kivity
        .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
255 3812ed0b Avi Kivity
    },
256 3812ed0b Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
257 502a5395 pbrook
};
258 502a5395 pbrook
259 80b3ada7 pbrook
/* The APB host has an IRQ line for each IRQ line of each slot.  */
260 d2b59317 pbrook
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
261 502a5395 pbrook
{
262 80b3ada7 pbrook
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
263 80b3ada7 pbrook
}
264 80b3ada7 pbrook
265 80b3ada7 pbrook
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
266 80b3ada7 pbrook
{
267 80b3ada7 pbrook
    int bus_offset;
268 80b3ada7 pbrook
    if (pci_dev->devfn & 1)
269 80b3ada7 pbrook
        bus_offset = 16;
270 80b3ada7 pbrook
    else
271 80b3ada7 pbrook
        bus_offset = 0;
272 80b3ada7 pbrook
    return bus_offset + irq_num;
273 d2b59317 pbrook
}
274 d2b59317 pbrook
275 5d4e84c8 Juan Quintela
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
276 d2b59317 pbrook
{
277 95819af0 Blue Swirl
    APBState *s = opaque;
278 5d4e84c8 Juan Quintela
279 80b3ada7 pbrook
    /* PCI IRQ map onto the first 32 INO.  */
280 95819af0 Blue Swirl
    if (irq_num < 32) {
281 95819af0 Blue Swirl
        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
282 95819af0 Blue Swirl
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
283 95819af0 Blue Swirl
            qemu_set_irq(s->pci_irqs[irq_num], level);
284 95819af0 Blue Swirl
        } else {
285 95819af0 Blue Swirl
            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
286 95819af0 Blue Swirl
            qemu_irq_lower(s->pci_irqs[irq_num]);
287 95819af0 Blue Swirl
        }
288 95819af0 Blue Swirl
    }
289 502a5395 pbrook
}
290 502a5395 pbrook
291 68f79994 Isaku Yamahata
static int apb_pci_bridge_initfn(PCIDevice *dev)
292 d6318738 Michael S. Tsirkin
{
293 68f79994 Isaku Yamahata
    int rc;
294 68f79994 Isaku Yamahata
295 68f79994 Isaku Yamahata
    rc = pci_bridge_initfn(dev);
296 68f79994 Isaku Yamahata
    if (rc < 0) {
297 68f79994 Isaku Yamahata
        return rc;
298 68f79994 Isaku Yamahata
    }
299 68f79994 Isaku Yamahata
300 d6318738 Michael S. Tsirkin
    /*
301 d6318738 Michael S. Tsirkin
     * command register:
302 d6318738 Michael S. Tsirkin
     * According to PCI bridge spec, after reset
303 d6318738 Michael S. Tsirkin
     *   bus master bit is off
304 d6318738 Michael S. Tsirkin
     *   memory space enable bit is off
305 d6318738 Michael S. Tsirkin
     * According to manual (805-1251.pdf).
306 d6318738 Michael S. Tsirkin
     *   the reset value should be zero unless the boot pin is tied high
307 d6318738 Michael S. Tsirkin
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
308 d6318738 Michael S. Tsirkin
     */
309 d6318738 Michael S. Tsirkin
    pci_set_word(dev->config + PCI_COMMAND,
310 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY);
311 9fe52c7f Blue Swirl
    pci_set_word(dev->config + PCI_STATUS,
312 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
313 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
314 68f79994 Isaku Yamahata
    return 0;
315 d6318738 Michael S. Tsirkin
}
316 d6318738 Michael S. Tsirkin
317 c227f099 Anthony Liguori
PCIBus *pci_apb_init(target_phys_addr_t special_base,
318 c227f099 Anthony Liguori
                     target_phys_addr_t mem_base,
319 c190ea07 blueswir1
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
320 502a5395 pbrook
{
321 72f44c8c Blue Swirl
    DeviceState *dev;
322 72f44c8c Blue Swirl
    SysBusDevice *s;
323 72f44c8c Blue Swirl
    APBState *d;
324 95819af0 Blue Swirl
    unsigned int i;
325 68f79994 Isaku Yamahata
    PCIDevice *pci_dev;
326 68f79994 Isaku Yamahata
    PCIBridge *br;
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 f69539b1 Blue Swirl
    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
341 f69539b1 Blue Swirl
    memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
342 f69539b1 Blue Swirl
343 d63baf92 Igor V. Kovalenko
    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
344 f69539b1 Blue Swirl
                              pci_apb_set_irq, pci_pbm_map_irq, d,
345 f69539b1 Blue Swirl
                              &d->pci_mmio,
346 f69539b1 Blue Swirl
                              get_system_io(),
347 f69539b1 Blue Swirl
                              0, 32);
348 f6b6f1bc Blue Swirl
349 95819af0 Blue Swirl
    for (i = 0; i < 32; i++) {
350 95819af0 Blue Swirl
        sysbus_connect_irq(s, i, pic[i]);
351 95819af0 Blue Swirl
    }
352 95819af0 Blue Swirl
353 d63baf92 Igor V. Kovalenko
    pci_create_simple(d->bus, 0, "pbm");
354 d63baf92 Igor V. Kovalenko
355 72f44c8c Blue Swirl
    /* APB secondary busses */
356 68f79994 Isaku Yamahata
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
357 68f79994 Isaku Yamahata
                                   "pbm-bridge");
358 68f79994 Isaku Yamahata
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
359 68f79994 Isaku Yamahata
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
360 68f79994 Isaku Yamahata
                       pci_apb_map_irq);
361 68f79994 Isaku Yamahata
    qdev_init_nofail(&pci_dev->qdev);
362 68f79994 Isaku Yamahata
    *bus2 = pci_bridge_get_sec_bus(br);
363 68f79994 Isaku Yamahata
364 68f79994 Isaku Yamahata
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
365 68f79994 Isaku Yamahata
                                   "pbm-bridge");
366 68f79994 Isaku Yamahata
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
367 68f79994 Isaku Yamahata
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
368 68f79994 Isaku Yamahata
                       pci_apb_map_irq);
369 68f79994 Isaku Yamahata
    qdev_init_nofail(&pci_dev->qdev);
370 68f79994 Isaku Yamahata
    *bus3 = pci_bridge_get_sec_bus(br);
371 502a5395 pbrook
372 d63baf92 Igor V. Kovalenko
    return d->bus;
373 72f44c8c Blue Swirl
}
374 72f44c8c Blue Swirl
375 95819af0 Blue Swirl
static void pci_pbm_reset(DeviceState *d)
376 72f44c8c Blue Swirl
{
377 95819af0 Blue Swirl
    unsigned int i;
378 95819af0 Blue Swirl
    APBState *s = container_of(d, APBState, busdev.qdev);
379 72f44c8c Blue Swirl
380 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
381 95819af0 Blue Swirl
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
382 95819af0 Blue Swirl
    }
383 95819af0 Blue Swirl
384 9c0afd0e Blue Swirl
    if (s->nr_resets++ == 0) {
385 95819af0 Blue Swirl
        /* Power on reset */
386 95819af0 Blue Swirl
        s->reset_control = POR;
387 95819af0 Blue Swirl
    }
388 95819af0 Blue Swirl
}
389 95819af0 Blue Swirl
390 3812ed0b Avi Kivity
static const MemoryRegionOps pci_config_ops = {
391 3812ed0b Avi Kivity
    .read = apb_pci_config_read,
392 3812ed0b Avi Kivity
    .write = apb_pci_config_write,
393 3812ed0b Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
394 3812ed0b Avi Kivity
};
395 3812ed0b Avi Kivity
396 95819af0 Blue Swirl
static int pci_pbm_init_device(SysBusDevice *dev)
397 95819af0 Blue Swirl
{
398 72f44c8c Blue Swirl
    APBState *s;
399 95819af0 Blue Swirl
    unsigned int i;
400 72f44c8c Blue Swirl
401 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
402 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
403 95819af0 Blue Swirl
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
404 95819af0 Blue Swirl
    }
405 95819af0 Blue Swirl
    for (i = 0; i < 32; i++) {
406 95819af0 Blue Swirl
        sysbus_init_irq(dev, &s->pci_irqs[i]);
407 95819af0 Blue Swirl
    }
408 95819af0 Blue Swirl
409 72f44c8c Blue Swirl
    /* apb_config */
410 3812ed0b Avi Kivity
    memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
411 3812ed0b Avi Kivity
                          0x10000);
412 d63baf92 Igor V. Kovalenko
    /* at region 0 */
413 3812ed0b Avi Kivity
    sysbus_init_mmio_region(dev, &s->apb_config);
414 d63baf92 Igor V. Kovalenko
415 3812ed0b Avi Kivity
    memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
416 3812ed0b Avi Kivity
                          0x1000000);
417 d63baf92 Igor V. Kovalenko
    /* at region 1 */
418 3812ed0b Avi Kivity
    sysbus_init_mmio_region(dev, &s->pci_config);
419 d63baf92 Igor V. Kovalenko
420 d63baf92 Igor V. Kovalenko
    /* pci_ioport */
421 3812ed0b Avi Kivity
    memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
422 3812ed0b Avi Kivity
                          "apb-pci-ioport", 0x10000);
423 d63baf92 Igor V. Kovalenko
    /* at region 2 */
424 3812ed0b Avi Kivity
    sysbus_init_mmio_region(dev, &s->pci_ioport);
425 d63baf92 Igor V. Kovalenko
426 81a322d4 Gerd Hoffmann
    return 0;
427 72f44c8c Blue Swirl
}
428 502a5395 pbrook
429 81a322d4 Gerd Hoffmann
static int pbm_pci_host_init(PCIDevice *d)
430 72f44c8c Blue Swirl
{
431 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_COMMAND,
432 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
433 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_STATUS,
434 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
435 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
436 81a322d4 Gerd Hoffmann
    return 0;
437 72f44c8c Blue Swirl
}
438 80b3ada7 pbrook
439 72f44c8c Blue Swirl
static PCIDeviceInfo pbm_pci_host_info = {
440 72f44c8c Blue Swirl
    .qdev.name = "pbm",
441 72f44c8c Blue Swirl
    .qdev.size = sizeof(PCIDevice),
442 72f44c8c Blue Swirl
    .init      = pbm_pci_host_init,
443 92f9a4f1 Isaku Yamahata
    .vendor_id = PCI_VENDOR_ID_SUN,
444 92f9a4f1 Isaku Yamahata
    .device_id = PCI_DEVICE_ID_SUN_SABRE,
445 92f9a4f1 Isaku Yamahata
    .class_id  = PCI_CLASS_BRIDGE_HOST,
446 e327e323 Isaku Yamahata
    .is_bridge = 1,
447 72f44c8c Blue Swirl
};
448 72f44c8c Blue Swirl
449 95819af0 Blue Swirl
static SysBusDeviceInfo pbm_host_info = {
450 95819af0 Blue Swirl
    .qdev.name = "pbm",
451 95819af0 Blue Swirl
    .qdev.size = sizeof(APBState),
452 95819af0 Blue Swirl
    .qdev.reset = pci_pbm_reset,
453 95819af0 Blue Swirl
    .init = pci_pbm_init_device,
454 95819af0 Blue Swirl
};
455 68f79994 Isaku Yamahata
456 68f79994 Isaku Yamahata
static PCIDeviceInfo pbm_pci_bridge_info = {
457 68f79994 Isaku Yamahata
    .qdev.name = "pbm-bridge",
458 68f79994 Isaku Yamahata
    .qdev.size = sizeof(PCIBridge),
459 68f79994 Isaku Yamahata
    .qdev.vmsd = &vmstate_pci_device,
460 68f79994 Isaku Yamahata
    .qdev.reset = pci_bridge_reset,
461 68f79994 Isaku Yamahata
    .init = apb_pci_bridge_initfn,
462 68f79994 Isaku Yamahata
    .exit = pci_bridge_exitfn,
463 92f9a4f1 Isaku Yamahata
    .vendor_id = PCI_VENDOR_ID_SUN,
464 92f9a4f1 Isaku Yamahata
    .device_id = PCI_DEVICE_ID_SUN_SIMBA,
465 92f9a4f1 Isaku Yamahata
    .revision = 0x11,
466 68f79994 Isaku Yamahata
    .config_write = pci_bridge_write_config,
467 68f79994 Isaku Yamahata
    .is_bridge = 1,
468 68f79994 Isaku Yamahata
};
469 68f79994 Isaku Yamahata
470 72f44c8c Blue Swirl
static void pbm_register_devices(void)
471 72f44c8c Blue Swirl
{
472 95819af0 Blue Swirl
    sysbus_register_withprop(&pbm_host_info);
473 72f44c8c Blue Swirl
    pci_qdev_register(&pbm_pci_host_info);
474 68f79994 Isaku Yamahata
    pci_qdev_register(&pbm_pci_bridge_info);
475 502a5395 pbrook
}
476 72f44c8c Blue Swirl
477 72f44c8c Blue Swirl
device_init(pbm_register_devices)