Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ fa2ddcb4

History | View | Annotate | Download (15.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 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 361dea40 Blue Swirl
#define MAX_IVEC 0x30
70 361dea40 Blue Swirl
71 72f44c8c Blue Swirl
typedef struct APBState {
72 72f44c8c Blue Swirl
    SysBusDevice busdev;
73 d63baf92 Igor V. Kovalenko
    PCIBus      *bus;
74 3812ed0b Avi Kivity
    MemoryRegion apb_config;
75 3812ed0b Avi Kivity
    MemoryRegion pci_config;
76 f69539b1 Blue Swirl
    MemoryRegion pci_mmio;
77 3812ed0b Avi Kivity
    MemoryRegion pci_ioport;
78 95819af0 Blue Swirl
    uint32_t iommu[4];
79 95819af0 Blue Swirl
    uint32_t pci_control[16];
80 95819af0 Blue Swirl
    uint32_t pci_irq_map[8];
81 95819af0 Blue Swirl
    uint32_t obio_irq_map[32];
82 361dea40 Blue Swirl
    qemu_irq *pbm_irqs;
83 361dea40 Blue Swirl
    qemu_irq *ivec_irqs;
84 95819af0 Blue Swirl
    uint32_t reset_control;
85 9c0afd0e Blue Swirl
    unsigned int nr_resets;
86 72f44c8c Blue Swirl
} APBState;
87 502a5395 pbrook
88 94d19914 Artyom Tarasenko
static void pci_apb_set_irq(void *opaque, int irq_num, int level);
89 94d19914 Artyom Tarasenko
90 c227f099 Anthony Liguori
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
91 3812ed0b Avi Kivity
                               uint64_t val, unsigned size)
92 502a5395 pbrook
{
93 95819af0 Blue Swirl
    APBState *s = opaque;
94 95819af0 Blue Swirl
95 361dea40 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
96 95819af0 Blue Swirl
97 95819af0 Blue Swirl
    switch (addr & 0xffff) {
98 95819af0 Blue Swirl
    case 0x30 ... 0x4f: /* DMA error registers */
99 95819af0 Blue Swirl
        /* XXX: not implemented yet */
100 95819af0 Blue Swirl
        break;
101 95819af0 Blue Swirl
    case 0x200 ... 0x20b: /* IOMMU */
102 95819af0 Blue Swirl
        s->iommu[(addr & 0xf) >> 2] = val;
103 95819af0 Blue Swirl
        break;
104 95819af0 Blue Swirl
    case 0x20c ... 0x3ff: /* IOMMU flush */
105 95819af0 Blue Swirl
        break;
106 95819af0 Blue Swirl
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
107 95819af0 Blue Swirl
        if (addr & 4) {
108 95819af0 Blue Swirl
            s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
109 95819af0 Blue Swirl
            s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
110 95819af0 Blue Swirl
        }
111 95819af0 Blue Swirl
        break;
112 361dea40 Blue Swirl
    case 0x1000 ... 0x1080: /* OBIO interrupt control */
113 361dea40 Blue Swirl
        if (addr & 4) {
114 361dea40 Blue Swirl
            s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
115 361dea40 Blue Swirl
            s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
116 361dea40 Blue Swirl
        }
117 361dea40 Blue Swirl
        break;
118 94d19914 Artyom Tarasenko
    case 0x1400 ... 0x143f: /* PCI interrupt clear */
119 94d19914 Artyom Tarasenko
        if (addr & 4) {
120 94d19914 Artyom Tarasenko
            pci_apb_set_irq(s, (addr & 0x3f) >> 3, 0);
121 94d19914 Artyom Tarasenko
        }
122 94d19914 Artyom Tarasenko
        break;
123 94d19914 Artyom Tarasenko
    case 0x1800 ... 0x1860: /* OBIO interrupt clear */
124 94d19914 Artyom Tarasenko
        if (addr & 4) {
125 94d19914 Artyom Tarasenko
            pci_apb_set_irq(s, 0x20 | ((addr & 0xff) >> 3), 0);
126 94d19914 Artyom Tarasenko
        }
127 94d19914 Artyom Tarasenko
        break;
128 95819af0 Blue Swirl
    case 0x2000 ... 0x202f: /* PCI control */
129 95819af0 Blue Swirl
        s->pci_control[(addr & 0x3f) >> 2] = val;
130 95819af0 Blue Swirl
        break;
131 95819af0 Blue Swirl
    case 0xf020 ... 0xf027: /* Reset control */
132 95819af0 Blue Swirl
        if (addr & 4) {
133 95819af0 Blue Swirl
            val &= RESET_MASK;
134 95819af0 Blue Swirl
            s->reset_control &= ~(val & RESET_WCMASK);
135 95819af0 Blue Swirl
            s->reset_control |= val & RESET_WMASK;
136 95819af0 Blue Swirl
            if (val & SOFT_POR) {
137 9c0afd0e Blue Swirl
                s->nr_resets = 0;
138 95819af0 Blue Swirl
                qemu_system_reset_request();
139 95819af0 Blue Swirl
            } else if (val & SOFT_XIR) {
140 95819af0 Blue Swirl
                qemu_system_reset_request();
141 95819af0 Blue Swirl
            }
142 95819af0 Blue Swirl
        }
143 95819af0 Blue Swirl
        break;
144 95819af0 Blue Swirl
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
145 95819af0 Blue Swirl
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
146 95819af0 Blue Swirl
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
147 95819af0 Blue Swirl
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
148 95819af0 Blue Swirl
        /* we don't care */
149 502a5395 pbrook
    default:
150 f930d07e blueswir1
        break;
151 502a5395 pbrook
    }
152 502a5395 pbrook
}
153 502a5395 pbrook
154 3812ed0b Avi Kivity
static uint64_t apb_config_readl (void *opaque,
155 3812ed0b Avi Kivity
                                  target_phys_addr_t addr, unsigned size)
156 502a5395 pbrook
{
157 95819af0 Blue Swirl
    APBState *s = opaque;
158 502a5395 pbrook
    uint32_t val;
159 502a5395 pbrook
160 95819af0 Blue Swirl
    switch (addr & 0xffff) {
161 95819af0 Blue Swirl
    case 0x30 ... 0x4f: /* DMA error registers */
162 95819af0 Blue Swirl
        val = 0;
163 95819af0 Blue Swirl
        /* XXX: not implemented yet */
164 95819af0 Blue Swirl
        break;
165 95819af0 Blue Swirl
    case 0x200 ... 0x20b: /* IOMMU */
166 95819af0 Blue Swirl
        val = s->iommu[(addr & 0xf) >> 2];
167 95819af0 Blue Swirl
        break;
168 95819af0 Blue Swirl
    case 0x20c ... 0x3ff: /* IOMMU flush */
169 95819af0 Blue Swirl
        val = 0;
170 95819af0 Blue Swirl
        break;
171 95819af0 Blue Swirl
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
172 95819af0 Blue Swirl
        if (addr & 4) {
173 95819af0 Blue Swirl
            val = s->pci_irq_map[(addr & 0x3f) >> 3];
174 95819af0 Blue Swirl
        } else {
175 95819af0 Blue Swirl
            val = 0;
176 95819af0 Blue Swirl
        }
177 95819af0 Blue Swirl
        break;
178 361dea40 Blue Swirl
    case 0x1000 ... 0x1080: /* OBIO interrupt control */
179 361dea40 Blue Swirl
        if (addr & 4) {
180 361dea40 Blue Swirl
            val = s->obio_irq_map[(addr & 0xff) >> 3];
181 361dea40 Blue Swirl
        } else {
182 361dea40 Blue Swirl
            val = 0;
183 361dea40 Blue Swirl
        }
184 361dea40 Blue Swirl
        break;
185 95819af0 Blue Swirl
    case 0x2000 ... 0x202f: /* PCI control */
186 95819af0 Blue Swirl
        val = s->pci_control[(addr & 0x3f) >> 2];
187 95819af0 Blue Swirl
        break;
188 95819af0 Blue Swirl
    case 0xf020 ... 0xf027: /* Reset control */
189 95819af0 Blue Swirl
        if (addr & 4) {
190 95819af0 Blue Swirl
            val = s->reset_control;
191 95819af0 Blue Swirl
        } else {
192 95819af0 Blue Swirl
            val = 0;
193 95819af0 Blue Swirl
        }
194 95819af0 Blue Swirl
        break;
195 95819af0 Blue Swirl
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
196 95819af0 Blue Swirl
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
197 95819af0 Blue Swirl
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
198 95819af0 Blue Swirl
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
199 95819af0 Blue Swirl
        /* we don't care */
200 502a5395 pbrook
    default:
201 f930d07e blueswir1
        val = 0;
202 f930d07e blueswir1
        break;
203 502a5395 pbrook
    }
204 95819af0 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
205 95819af0 Blue Swirl
206 502a5395 pbrook
    return val;
207 502a5395 pbrook
}
208 502a5395 pbrook
209 3812ed0b Avi Kivity
static const MemoryRegionOps apb_config_ops = {
210 3812ed0b Avi Kivity
    .read = apb_config_readl,
211 3812ed0b Avi Kivity
    .write = apb_config_writel,
212 3812ed0b Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
213 502a5395 pbrook
};
214 502a5395 pbrook
215 3812ed0b Avi Kivity
static void apb_pci_config_write(void *opaque, target_phys_addr_t addr,
216 3812ed0b Avi Kivity
                                 uint64_t val, unsigned size)
217 5a5d4a76 Blue Swirl
{
218 3812ed0b Avi Kivity
    APBState *s = opaque;
219 63e6f31d Michael S. Tsirkin
220 63e6f31d Michael S. Tsirkin
    val = qemu_bswap_len(val, size);
221 361dea40 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
222 d63baf92 Igor V. Kovalenko
    pci_data_write(s->bus, addr, val, size);
223 5a5d4a76 Blue Swirl
}
224 5a5d4a76 Blue Swirl
225 3812ed0b Avi Kivity
static uint64_t apb_pci_config_read(void *opaque, target_phys_addr_t addr,
226 3812ed0b Avi Kivity
                                    unsigned size)
227 5a5d4a76 Blue Swirl
{
228 5a5d4a76 Blue Swirl
    uint32_t ret;
229 3812ed0b Avi Kivity
    APBState *s = opaque;
230 5a5d4a76 Blue Swirl
231 d63baf92 Igor V. Kovalenko
    ret = pci_data_read(s->bus, addr, size);
232 63e6f31d Michael S. Tsirkin
    ret = qemu_bswap_len(ret, size);
233 5a5d4a76 Blue Swirl
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
234 5a5d4a76 Blue Swirl
    return ret;
235 5a5d4a76 Blue Swirl
}
236 5a5d4a76 Blue Swirl
237 c227f099 Anthony Liguori
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
238 502a5395 pbrook
                                  uint32_t val)
239 502a5395 pbrook
{
240 afcea8cb Blue Swirl
    cpu_outb(addr & IOPORTS_MASK, val);
241 502a5395 pbrook
}
242 502a5395 pbrook
243 c227f099 Anthony Liguori
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
244 502a5395 pbrook
                                  uint32_t val)
245 502a5395 pbrook
{
246 a4d5f62c Blue Swirl
    cpu_outw(addr & IOPORTS_MASK, bswap16(val));
247 502a5395 pbrook
}
248 502a5395 pbrook
249 c227f099 Anthony Liguori
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
250 502a5395 pbrook
                                uint32_t val)
251 502a5395 pbrook
{
252 a4d5f62c Blue Swirl
    cpu_outl(addr & IOPORTS_MASK, bswap32(val));
253 502a5395 pbrook
}
254 502a5395 pbrook
255 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
256 502a5395 pbrook
{
257 502a5395 pbrook
    uint32_t val;
258 502a5395 pbrook
259 afcea8cb Blue Swirl
    val = cpu_inb(addr & IOPORTS_MASK);
260 502a5395 pbrook
    return val;
261 502a5395 pbrook
}
262 502a5395 pbrook
263 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
264 502a5395 pbrook
{
265 502a5395 pbrook
    uint32_t val;
266 502a5395 pbrook
267 a4d5f62c Blue Swirl
    val = bswap16(cpu_inw(addr & IOPORTS_MASK));
268 502a5395 pbrook
    return val;
269 502a5395 pbrook
}
270 502a5395 pbrook
271 c227f099 Anthony Liguori
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
272 502a5395 pbrook
{
273 502a5395 pbrook
    uint32_t val;
274 502a5395 pbrook
275 a4d5f62c Blue Swirl
    val = bswap32(cpu_inl(addr & IOPORTS_MASK));
276 502a5395 pbrook
    return val;
277 502a5395 pbrook
}
278 502a5395 pbrook
279 3812ed0b Avi Kivity
static const MemoryRegionOps pci_ioport_ops = {
280 3812ed0b Avi Kivity
    .old_mmio = {
281 3812ed0b Avi Kivity
        .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
282 3812ed0b Avi Kivity
        .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
283 3812ed0b Avi Kivity
    },
284 3812ed0b Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
285 502a5395 pbrook
};
286 502a5395 pbrook
287 80b3ada7 pbrook
/* The APB host has an IRQ line for each IRQ line of each slot.  */
288 d2b59317 pbrook
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
289 502a5395 pbrook
{
290 80b3ada7 pbrook
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
291 80b3ada7 pbrook
}
292 80b3ada7 pbrook
293 80b3ada7 pbrook
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
294 80b3ada7 pbrook
{
295 80b3ada7 pbrook
    int bus_offset;
296 80b3ada7 pbrook
    if (pci_dev->devfn & 1)
297 80b3ada7 pbrook
        bus_offset = 16;
298 80b3ada7 pbrook
    else
299 80b3ada7 pbrook
        bus_offset = 0;
300 80b3ada7 pbrook
    return bus_offset + irq_num;
301 d2b59317 pbrook
}
302 d2b59317 pbrook
303 5d4e84c8 Juan Quintela
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
304 d2b59317 pbrook
{
305 95819af0 Blue Swirl
    APBState *s = opaque;
306 5d4e84c8 Juan Quintela
307 80b3ada7 pbrook
    /* PCI IRQ map onto the first 32 INO.  */
308 95819af0 Blue Swirl
    if (irq_num < 32) {
309 95819af0 Blue Swirl
        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
310 95819af0 Blue Swirl
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
311 361dea40 Blue Swirl
            qemu_set_irq(s->ivec_irqs[irq_num], level);
312 361dea40 Blue Swirl
        } else {
313 361dea40 Blue Swirl
            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
314 361dea40 Blue Swirl
            qemu_irq_lower(s->ivec_irqs[irq_num]);
315 361dea40 Blue Swirl
        }
316 361dea40 Blue Swirl
    } else {
317 361dea40 Blue Swirl
        /* OBIO IRQ map onto the next 16 INO.  */
318 361dea40 Blue Swirl
        if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
319 361dea40 Blue Swirl
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
320 361dea40 Blue Swirl
            qemu_set_irq(s->ivec_irqs[irq_num], level);
321 95819af0 Blue Swirl
        } else {
322 95819af0 Blue Swirl
            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
323 361dea40 Blue Swirl
            qemu_irq_lower(s->ivec_irqs[irq_num]);
324 95819af0 Blue Swirl
        }
325 95819af0 Blue Swirl
    }
326 502a5395 pbrook
}
327 502a5395 pbrook
328 68f79994 Isaku Yamahata
static int apb_pci_bridge_initfn(PCIDevice *dev)
329 d6318738 Michael S. Tsirkin
{
330 68f79994 Isaku Yamahata
    int rc;
331 68f79994 Isaku Yamahata
332 68f79994 Isaku Yamahata
    rc = pci_bridge_initfn(dev);
333 68f79994 Isaku Yamahata
    if (rc < 0) {
334 68f79994 Isaku Yamahata
        return rc;
335 68f79994 Isaku Yamahata
    }
336 68f79994 Isaku Yamahata
337 d6318738 Michael S. Tsirkin
    /*
338 d6318738 Michael S. Tsirkin
     * command register:
339 d6318738 Michael S. Tsirkin
     * According to PCI bridge spec, after reset
340 d6318738 Michael S. Tsirkin
     *   bus master bit is off
341 d6318738 Michael S. Tsirkin
     *   memory space enable bit is off
342 d6318738 Michael S. Tsirkin
     * According to manual (805-1251.pdf).
343 d6318738 Michael S. Tsirkin
     *   the reset value should be zero unless the boot pin is tied high
344 d6318738 Michael S. Tsirkin
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
345 d6318738 Michael S. Tsirkin
     */
346 d6318738 Michael S. Tsirkin
    pci_set_word(dev->config + PCI_COMMAND,
347 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY);
348 9fe52c7f Blue Swirl
    pci_set_word(dev->config + PCI_STATUS,
349 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
350 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
351 68f79994 Isaku Yamahata
    return 0;
352 d6318738 Michael S. Tsirkin
}
353 d6318738 Michael S. Tsirkin
354 c227f099 Anthony Liguori
PCIBus *pci_apb_init(target_phys_addr_t special_base,
355 c227f099 Anthony Liguori
                     target_phys_addr_t mem_base,
356 361dea40 Blue Swirl
                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
357 361dea40 Blue Swirl
                     qemu_irq **pbm_irqs)
358 502a5395 pbrook
{
359 72f44c8c Blue Swirl
    DeviceState *dev;
360 72f44c8c Blue Swirl
    SysBusDevice *s;
361 72f44c8c Blue Swirl
    APBState *d;
362 68f79994 Isaku Yamahata
    PCIDevice *pci_dev;
363 68f79994 Isaku Yamahata
    PCIBridge *br;
364 502a5395 pbrook
365 80b3ada7 pbrook
    /* Ultrasparc PBM main bus */
366 72f44c8c Blue Swirl
    dev = qdev_create(NULL, "pbm");
367 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
368 72f44c8c Blue Swirl
    s = sysbus_from_qdev(dev);
369 72f44c8c Blue Swirl
    /* apb_config */
370 bae7b517 Blue Swirl
    sysbus_mmio_map(s, 0, special_base);
371 d63baf92 Igor V. Kovalenko
    /* PCI configuration space */
372 d63baf92 Igor V. Kovalenko
    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
373 72f44c8c Blue Swirl
    /* pci_ioport */
374 d63baf92 Igor V. Kovalenko
    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
375 72f44c8c Blue Swirl
    d = FROM_SYSBUS(APBState, s);
376 d63baf92 Igor V. Kovalenko
377 f69539b1 Blue Swirl
    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
378 f69539b1 Blue Swirl
    memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
379 f69539b1 Blue Swirl
380 d63baf92 Igor V. Kovalenko
    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
381 f69539b1 Blue Swirl
                              pci_apb_set_irq, pci_pbm_map_irq, d,
382 f69539b1 Blue Swirl
                              &d->pci_mmio,
383 f69539b1 Blue Swirl
                              get_system_io(),
384 f69539b1 Blue Swirl
                              0, 32);
385 f6b6f1bc Blue Swirl
386 361dea40 Blue Swirl
    *pbm_irqs = d->pbm_irqs;
387 361dea40 Blue Swirl
    d->ivec_irqs = ivec_irqs;
388 95819af0 Blue Swirl
389 73093354 Anthony Liguori
    pci_create_simple(d->bus, 0, "pbm-pci");
390 d63baf92 Igor V. Kovalenko
391 72f44c8c Blue Swirl
    /* APB secondary busses */
392 68f79994 Isaku Yamahata
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
393 68f79994 Isaku Yamahata
                                   "pbm-bridge");
394 68f79994 Isaku Yamahata
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
395 68f79994 Isaku Yamahata
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
396 68f79994 Isaku Yamahata
                       pci_apb_map_irq);
397 68f79994 Isaku Yamahata
    qdev_init_nofail(&pci_dev->qdev);
398 68f79994 Isaku Yamahata
    *bus2 = pci_bridge_get_sec_bus(br);
399 68f79994 Isaku Yamahata
400 68f79994 Isaku Yamahata
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
401 68f79994 Isaku Yamahata
                                   "pbm-bridge");
402 68f79994 Isaku Yamahata
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
403 68f79994 Isaku Yamahata
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
404 68f79994 Isaku Yamahata
                       pci_apb_map_irq);
405 68f79994 Isaku Yamahata
    qdev_init_nofail(&pci_dev->qdev);
406 68f79994 Isaku Yamahata
    *bus3 = pci_bridge_get_sec_bus(br);
407 502a5395 pbrook
408 d63baf92 Igor V. Kovalenko
    return d->bus;
409 72f44c8c Blue Swirl
}
410 72f44c8c Blue Swirl
411 95819af0 Blue Swirl
static void pci_pbm_reset(DeviceState *d)
412 72f44c8c Blue Swirl
{
413 95819af0 Blue Swirl
    unsigned int i;
414 95819af0 Blue Swirl
    APBState *s = container_of(d, APBState, busdev.qdev);
415 72f44c8c Blue Swirl
416 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
417 95819af0 Blue Swirl
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
418 95819af0 Blue Swirl
    }
419 d1d80055 Artyom Tarasenko
    for (i = 0; i < 32; i++) {
420 d1d80055 Artyom Tarasenko
        s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
421 d1d80055 Artyom Tarasenko
    }
422 95819af0 Blue Swirl
423 9c0afd0e Blue Swirl
    if (s->nr_resets++ == 0) {
424 95819af0 Blue Swirl
        /* Power on reset */
425 95819af0 Blue Swirl
        s->reset_control = POR;
426 95819af0 Blue Swirl
    }
427 95819af0 Blue Swirl
}
428 95819af0 Blue Swirl
429 3812ed0b Avi Kivity
static const MemoryRegionOps pci_config_ops = {
430 3812ed0b Avi Kivity
    .read = apb_pci_config_read,
431 3812ed0b Avi Kivity
    .write = apb_pci_config_write,
432 3812ed0b Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
433 3812ed0b Avi Kivity
};
434 3812ed0b Avi Kivity
435 95819af0 Blue Swirl
static int pci_pbm_init_device(SysBusDevice *dev)
436 95819af0 Blue Swirl
{
437 72f44c8c Blue Swirl
    APBState *s;
438 95819af0 Blue Swirl
    unsigned int i;
439 72f44c8c Blue Swirl
440 72f44c8c Blue Swirl
    s = FROM_SYSBUS(APBState, dev);
441 95819af0 Blue Swirl
    for (i = 0; i < 8; i++) {
442 95819af0 Blue Swirl
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
443 95819af0 Blue Swirl
    }
444 d1d80055 Artyom Tarasenko
    for (i = 0; i < 32; i++) {
445 d1d80055 Artyom Tarasenko
        s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
446 d1d80055 Artyom Tarasenko
    }
447 361dea40 Blue Swirl
    s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
448 95819af0 Blue Swirl
449 72f44c8c Blue Swirl
    /* apb_config */
450 3812ed0b Avi Kivity
    memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
451 3812ed0b Avi Kivity
                          0x10000);
452 d63baf92 Igor V. Kovalenko
    /* at region 0 */
453 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->apb_config);
454 d63baf92 Igor V. Kovalenko
455 3812ed0b Avi Kivity
    memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
456 3812ed0b Avi Kivity
                          0x1000000);
457 d63baf92 Igor V. Kovalenko
    /* at region 1 */
458 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->pci_config);
459 d63baf92 Igor V. Kovalenko
460 d63baf92 Igor V. Kovalenko
    /* pci_ioport */
461 3812ed0b Avi Kivity
    memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
462 3812ed0b Avi Kivity
                          "apb-pci-ioport", 0x10000);
463 d63baf92 Igor V. Kovalenko
    /* at region 2 */
464 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->pci_ioport);
465 d63baf92 Igor V. Kovalenko
466 81a322d4 Gerd Hoffmann
    return 0;
467 72f44c8c Blue Swirl
}
468 502a5395 pbrook
469 81a322d4 Gerd Hoffmann
static int pbm_pci_host_init(PCIDevice *d)
470 72f44c8c Blue Swirl
{
471 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_COMMAND,
472 9fe52c7f Blue Swirl
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
473 9fe52c7f Blue Swirl
    pci_set_word(d->config + PCI_STATUS,
474 9fe52c7f Blue Swirl
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
475 9fe52c7f Blue Swirl
                 PCI_STATUS_DEVSEL_MEDIUM);
476 81a322d4 Gerd Hoffmann
    return 0;
477 72f44c8c Blue Swirl
}
478 80b3ada7 pbrook
479 40021f08 Anthony Liguori
static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
480 40021f08 Anthony Liguori
{
481 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
482 40021f08 Anthony Liguori
483 40021f08 Anthony Liguori
    k->init = pbm_pci_host_init;
484 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_SUN;
485 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_SUN_SABRE;
486 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_BRIDGE_HOST;
487 40021f08 Anthony Liguori
}
488 40021f08 Anthony Liguori
489 39bffca2 Anthony Liguori
static TypeInfo pbm_pci_host_info = {
490 39bffca2 Anthony Liguori
    .name          = "pbm-pci",
491 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
492 39bffca2 Anthony Liguori
    .instance_size = sizeof(PCIDevice),
493 39bffca2 Anthony Liguori
    .class_init    = pbm_pci_host_class_init,
494 72f44c8c Blue Swirl
};
495 72f44c8c Blue Swirl
496 999e12bb Anthony Liguori
static void pbm_host_class_init(ObjectClass *klass, void *data)
497 999e12bb Anthony Liguori
{
498 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
499 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
500 999e12bb Anthony Liguori
501 999e12bb Anthony Liguori
    k->init = pci_pbm_init_device;
502 39bffca2 Anthony Liguori
    dc->reset = pci_pbm_reset;
503 999e12bb Anthony Liguori
}
504 999e12bb Anthony Liguori
505 39bffca2 Anthony Liguori
static TypeInfo pbm_host_info = {
506 39bffca2 Anthony Liguori
    .name          = "pbm",
507 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
508 39bffca2 Anthony Liguori
    .instance_size = sizeof(APBState),
509 39bffca2 Anthony Liguori
    .class_init    = pbm_host_class_init,
510 95819af0 Blue Swirl
};
511 68f79994 Isaku Yamahata
512 40021f08 Anthony Liguori
static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
513 40021f08 Anthony Liguori
{
514 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
515 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
516 40021f08 Anthony Liguori
517 40021f08 Anthony Liguori
    k->init = apb_pci_bridge_initfn;
518 40021f08 Anthony Liguori
    k->exit = pci_bridge_exitfn;
519 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_SUN;
520 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
521 40021f08 Anthony Liguori
    k->revision = 0x11;
522 40021f08 Anthony Liguori
    k->config_write = pci_bridge_write_config;
523 40021f08 Anthony Liguori
    k->is_bridge = 1;
524 39bffca2 Anthony Liguori
    dc->reset = pci_bridge_reset;
525 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_pci_device;
526 40021f08 Anthony Liguori
}
527 40021f08 Anthony Liguori
528 39bffca2 Anthony Liguori
static TypeInfo pbm_pci_bridge_info = {
529 39bffca2 Anthony Liguori
    .name          = "pbm-bridge",
530 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
531 39bffca2 Anthony Liguori
    .instance_size = sizeof(PCIBridge),
532 39bffca2 Anthony Liguori
    .class_init    = pbm_pci_bridge_class_init,
533 68f79994 Isaku Yamahata
};
534 68f79994 Isaku Yamahata
535 83f7d43a Andreas Färber
static void pbm_register_types(void)
536 72f44c8c Blue Swirl
{
537 39bffca2 Anthony Liguori
    type_register_static(&pbm_host_info);
538 39bffca2 Anthony Liguori
    type_register_static(&pbm_pci_host_info);
539 39bffca2 Anthony Liguori
    type_register_static(&pbm_pci_bridge_info);
540 502a5395 pbrook
}
541 72f44c8c Blue Swirl
542 83f7d43a Andreas Färber
type_init(pbm_register_types)