Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 2eb9f241

History | View | Annotate | Download (14 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 68f79994 Isaku Yamahata
    pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_SUN);
308 68f79994 Isaku Yamahata
    pci_config_set_device_id(dev->config, PCI_DEVICE_ID_SUN_SIMBA);
309 d6318738 Michael S. Tsirkin
310 d6318738 Michael S. Tsirkin
    /*
311 d6318738 Michael S. Tsirkin
     * command register:
312 d6318738 Michael S. Tsirkin
     * According to PCI bridge spec, after reset
313 d6318738 Michael S. Tsirkin
     *   bus master bit is off
314 d6318738 Michael S. Tsirkin
     *   memory space enable bit is off
315 d6318738 Michael S. Tsirkin
     * According to manual (805-1251.pdf).
316 d6318738 Michael S. Tsirkin
     *   the reset value should be zero unless the boot pin is tied high
317 d6318738 Michael S. Tsirkin
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
318 d6318738 Michael S. Tsirkin
     */
319 d6318738 Michael S. Tsirkin
    pci_set_word(dev->config + PCI_COMMAND,
320 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY);
321 9fe52c7f Blue Swirl
    pci_set_word(dev->config + PCI_STATUS,
322 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
323 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
324 9fe52c7f Blue Swirl
    pci_set_byte(dev->config + PCI_REVISION_ID, 0x11);
325 68f79994 Isaku Yamahata
    return 0;
326 d6318738 Michael S. Tsirkin
}
327 d6318738 Michael S. Tsirkin
328 c227f099 Anthony Liguori
PCIBus *pci_apb_init(target_phys_addr_t special_base,
329 c227f099 Anthony Liguori
                     target_phys_addr_t mem_base,
330 c190ea07 blueswir1
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
331 502a5395 pbrook
{
332 72f44c8c Blue Swirl
    DeviceState *dev;
333 72f44c8c Blue Swirl
    SysBusDevice *s;
334 72f44c8c Blue Swirl
    APBState *d;
335 95819af0 Blue Swirl
    unsigned int i;
336 68f79994 Isaku Yamahata
    PCIDevice *pci_dev;
337 68f79994 Isaku Yamahata
    PCIBridge *br;
338 502a5395 pbrook
339 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
340 72f44c8c Blue Swirl
    dev = qdev_create(NULL, "pbm");
341 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
342 72f44c8c Blue Swirl
    s = sysbus_from_qdev(dev);
343 72f44c8c Blue Swirl
    /* apb_config */
344 bae7b517 Blue Swirl
    sysbus_mmio_map(s, 0, special_base);
345 d63baf92 Igor V. Kovalenko
    /* PCI configuration space */
346 d63baf92 Igor V. Kovalenko
    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
347 72f44c8c Blue Swirl
    /* pci_ioport */
348 d63baf92 Igor V. Kovalenko
    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
349 72f44c8c Blue Swirl
    d = FROM_SYSBUS(APBState, s);
350 d63baf92 Igor V. Kovalenko
351 d63baf92 Igor V. Kovalenko
    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
352 95819af0 Blue Swirl
                                         pci_apb_set_irq, pci_pbm_map_irq, d,
353 72f44c8c Blue Swirl
                                         0, 32);
354 d63baf92 Igor V. Kovalenko
    pci_bus_set_mem_base(d->bus, mem_base);
355 f6b6f1bc Blue Swirl
356 95819af0 Blue Swirl
    for (i = 0; i < 32; i++) {
357 95819af0 Blue Swirl
        sysbus_connect_irq(s, i, pic[i]);
358 95819af0 Blue Swirl
    }
359 95819af0 Blue Swirl
360 d63baf92 Igor V. Kovalenko
    pci_create_simple(d->bus, 0, "pbm");
361 d63baf92 Igor V. Kovalenko
362 72f44c8c Blue Swirl
    /* APB secondary busses */
363 68f79994 Isaku Yamahata
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
364 68f79994 Isaku Yamahata
                                   "pbm-bridge");
365 68f79994 Isaku Yamahata
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
366 68f79994 Isaku Yamahata
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
367 68f79994 Isaku Yamahata
                       pci_apb_map_irq);
368 68f79994 Isaku Yamahata
    qdev_init_nofail(&pci_dev->qdev);
369 68f79994 Isaku Yamahata
    *bus2 = pci_bridge_get_sec_bus(br);
370 68f79994 Isaku Yamahata
371 68f79994 Isaku Yamahata
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
372 68f79994 Isaku Yamahata
                                   "pbm-bridge");
373 68f79994 Isaku Yamahata
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
374 68f79994 Isaku Yamahata
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
375 68f79994 Isaku Yamahata
                       pci_apb_map_irq);
376 68f79994 Isaku Yamahata
    qdev_init_nofail(&pci_dev->qdev);
377 68f79994 Isaku Yamahata
    *bus3 = pci_bridge_get_sec_bus(br);
378 502a5395 pbrook
379 d63baf92 Igor V. Kovalenko
    return d->bus;
380 72f44c8c Blue Swirl
}
381 72f44c8c Blue Swirl
382 95819af0 Blue Swirl
static void pci_pbm_reset(DeviceState *d)
383 72f44c8c Blue Swirl
{
384 95819af0 Blue Swirl
    unsigned int i;
385 95819af0 Blue Swirl
    APBState *s = container_of(d, APBState, busdev.qdev);
386 72f44c8c Blue Swirl
387 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
388 95819af0 Blue Swirl
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
389 95819af0 Blue Swirl
    }
390 95819af0 Blue Swirl
391 9c0afd0e Blue Swirl
    if (s->nr_resets++ == 0) {
392 95819af0 Blue Swirl
        /* Power on reset */
393 95819af0 Blue Swirl
        s->reset_control = POR;
394 95819af0 Blue Swirl
    }
395 95819af0 Blue Swirl
}
396 95819af0 Blue Swirl
397 95819af0 Blue Swirl
static int pci_pbm_init_device(SysBusDevice *dev)
398 95819af0 Blue Swirl
{
399 72f44c8c Blue Swirl
    APBState *s;
400 d63baf92 Igor V. Kovalenko
    int pci_config, apb_config, pci_ioport;
401 95819af0 Blue Swirl
    unsigned int i;
402 72f44c8c Blue Swirl
403 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
404 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
405 95819af0 Blue Swirl
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
406 95819af0 Blue Swirl
    }
407 95819af0 Blue Swirl
    for (i = 0; i < 32; i++) {
408 95819af0 Blue Swirl
        sysbus_init_irq(dev, &s->pci_irqs[i]);
409 95819af0 Blue Swirl
    }
410 95819af0 Blue Swirl
411 72f44c8c Blue Swirl
    /* apb_config */
412 1eed09cb Avi Kivity
    apb_config = cpu_register_io_memory(apb_config_read,
413 2507c12a Alexander Graf
                                        apb_config_write, s,
414 2507c12a Alexander Graf
                                        DEVICE_NATIVE_ENDIAN);
415 d63baf92 Igor V. Kovalenko
    /* at region 0 */
416 bae7b517 Blue Swirl
    sysbus_init_mmio(dev, 0x10000ULL, apb_config);
417 d63baf92 Igor V. Kovalenko
418 d63baf92 Igor V. Kovalenko
    /* PCI configuration space */
419 63e6f31d Michael S. Tsirkin
    s->pci_config_handler.read = apb_pci_config_read;
420 63e6f31d Michael S. Tsirkin
    s->pci_config_handler.write = apb_pci_config_write;
421 6bef0436 Alexander Graf
    pci_config = cpu_register_io_memory_simple(&s->pci_config_handler,
422 6bef0436 Alexander Graf
                                               DEVICE_NATIVE_ENDIAN);
423 63e6f31d Michael S. Tsirkin
    assert(pci_config >= 0);
424 d63baf92 Igor V. Kovalenko
    /* at region 1 */
425 5a5d4a76 Blue Swirl
    sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
426 d63baf92 Igor V. Kovalenko
427 d63baf92 Igor V. Kovalenko
    /* pci_ioport */
428 d63baf92 Igor V. Kovalenko
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
429 2507c12a Alexander Graf
                                        pci_apb_iowrite, s,
430 2507c12a Alexander Graf
                                        DEVICE_NATIVE_ENDIAN);
431 d63baf92 Igor V. Kovalenko
    /* at region 2 */
432 d63baf92 Igor V. Kovalenko
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
433 d63baf92 Igor V. Kovalenko
434 81a322d4 Gerd Hoffmann
    return 0;
435 72f44c8c Blue Swirl
}
436 502a5395 pbrook
437 81a322d4 Gerd Hoffmann
static int pbm_pci_host_init(PCIDevice *d)
438 72f44c8c Blue Swirl
{
439 deb54399 aliguori
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
440 deb54399 aliguori
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
441 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_COMMAND,
442 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
443 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_STATUS,
444 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
445 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
446 173a543b blueswir1
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
447 81a322d4 Gerd Hoffmann
    return 0;
448 72f44c8c Blue Swirl
}
449 80b3ada7 pbrook
450 72f44c8c Blue Swirl
static PCIDeviceInfo pbm_pci_host_info = {
451 72f44c8c Blue Swirl
    .qdev.name = "pbm",
452 72f44c8c Blue Swirl
    .qdev.size = sizeof(PCIDevice),
453 72f44c8c Blue Swirl
    .init      = pbm_pci_host_init,
454 e327e323 Isaku Yamahata
    .is_bridge = 1,
455 72f44c8c Blue Swirl
};
456 72f44c8c Blue Swirl
457 95819af0 Blue Swirl
static SysBusDeviceInfo pbm_host_info = {
458 95819af0 Blue Swirl
    .qdev.name = "pbm",
459 95819af0 Blue Swirl
    .qdev.size = sizeof(APBState),
460 95819af0 Blue Swirl
    .qdev.reset = pci_pbm_reset,
461 95819af0 Blue Swirl
    .init = pci_pbm_init_device,
462 95819af0 Blue Swirl
};
463 68f79994 Isaku Yamahata
464 68f79994 Isaku Yamahata
static PCIDeviceInfo pbm_pci_bridge_info = {
465 68f79994 Isaku Yamahata
    .qdev.name = "pbm-bridge",
466 68f79994 Isaku Yamahata
    .qdev.size = sizeof(PCIBridge),
467 68f79994 Isaku Yamahata
    .qdev.vmsd = &vmstate_pci_device,
468 68f79994 Isaku Yamahata
    .qdev.reset = pci_bridge_reset,
469 68f79994 Isaku Yamahata
    .init = apb_pci_bridge_initfn,
470 68f79994 Isaku Yamahata
    .exit = pci_bridge_exitfn,
471 68f79994 Isaku Yamahata
    .config_write = pci_bridge_write_config,
472 68f79994 Isaku Yamahata
    .is_bridge = 1,
473 68f79994 Isaku Yamahata
};
474 68f79994 Isaku Yamahata
475 72f44c8c Blue Swirl
static void pbm_register_devices(void)
476 72f44c8c Blue Swirl
{
477 95819af0 Blue Swirl
    sysbus_register_withprop(&pbm_host_info);
478 72f44c8c Blue Swirl
    pci_qdev_register(&pbm_pci_host_info);
479 68f79994 Isaku Yamahata
    pci_qdev_register(&pbm_pci_bridge_info);
480 502a5395 pbrook
}
481 72f44c8c Blue Swirl
482 72f44c8c Blue Swirl
device_init(pbm_register_devices)