Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 9f6f0423

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