Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 269eba07

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