Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 4e4fa398

History | View | Annotate | Download (14.2 kB)

1
/*
2
 * QEMU Ultrasparc APB PCI host
3
 *
4
 * Copyright (c) 2006 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

    
25
/* XXX This file and most of its contents are somewhat misnamed.  The
26
   Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
27
   the secondary PCI bridge.  */
28

    
29
#include "sysbus.h"
30
#include "pci.h"
31
#include "pci_host.h"
32
#include "pci_bridge.h"
33
#include "pci_internals.h"
34
#include "apb_pci.h"
35
#include "sysemu.h"
36
#include "exec-memory.h"
37

    
38
/* debug APB */
39
//#define DEBUG_APB
40

    
41
#ifdef DEBUG_APB
42
#define APB_DPRINTF(fmt, ...) \
43
do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
44
#else
45
#define APB_DPRINTF(fmt, ...)
46
#endif
47

    
48
/*
49
 * Chipset docs:
50
 * PBM: "UltraSPARC IIi User's Manual",
51
 * http://www.sun.com/processors/manuals/805-0087.pdf
52
 *
53
 * APB: "Advanced PCI Bridge (APB) User's Manual",
54
 * http://www.sun.com/processors/manuals/805-1251.pdf
55
 */
56

    
57
#define PBM_PCI_IMR_MASK    0x7fffffff
58
#define PBM_PCI_IMR_ENABLED 0x80000000
59

    
60
#define POR          (1 << 31)
61
#define SOFT_POR     (1 << 30)
62
#define SOFT_XIR     (1 << 29)
63
#define BTN_POR      (1 << 28)
64
#define BTN_XIR      (1 << 27)
65
#define RESET_MASK   0xf8000000
66
#define RESET_WCMASK 0x98000000
67
#define RESET_WMASK  0x60000000
68

    
69
typedef struct APBState {
70
    SysBusDevice busdev;
71
    PCIBus      *bus;
72
    MemoryRegion apb_config;
73
    MemoryRegion pci_config;
74
    MemoryRegion pci_mmio;
75
    MemoryRegion pci_ioport;
76
    uint32_t iommu[4];
77
    uint32_t pci_control[16];
78
    uint32_t pci_irq_map[8];
79
    uint32_t obio_irq_map[32];
80
    qemu_irq pci_irqs[32];
81
    uint32_t reset_control;
82
    unsigned int nr_resets;
83
} APBState;
84

    
85
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
86
                               uint64_t val, unsigned size)
87
{
88
    APBState *s = opaque;
89

    
90
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
91

    
92
    switch (addr & 0xffff) {
93
    case 0x30 ... 0x4f: /* DMA error registers */
94
        /* XXX: not implemented yet */
95
        break;
96
    case 0x200 ... 0x20b: /* IOMMU */
97
        s->iommu[(addr & 0xf) >> 2] = val;
98
        break;
99
    case 0x20c ... 0x3ff: /* IOMMU flush */
100
        break;
101
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
102
        if (addr & 4) {
103
            s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
104
            s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
105
        }
106
        break;
107
    case 0x2000 ... 0x202f: /* PCI control */
108
        s->pci_control[(addr & 0x3f) >> 2] = val;
109
        break;
110
    case 0xf020 ... 0xf027: /* Reset control */
111
        if (addr & 4) {
112
            val &= RESET_MASK;
113
            s->reset_control &= ~(val & RESET_WCMASK);
114
            s->reset_control |= val & RESET_WMASK;
115
            if (val & SOFT_POR) {
116
                s->nr_resets = 0;
117
                qemu_system_reset_request();
118
            } else if (val & SOFT_XIR) {
119
                qemu_system_reset_request();
120
            }
121
        }
122
        break;
123
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
124
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
125
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
126
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
127
        /* we don't care */
128
    default:
129
        break;
130
    }
131
}
132

    
133
static uint64_t apb_config_readl (void *opaque,
134
                                  target_phys_addr_t addr, unsigned size)
135
{
136
    APBState *s = opaque;
137
    uint32_t val;
138

    
139
    switch (addr & 0xffff) {
140
    case 0x30 ... 0x4f: /* DMA error registers */
141
        val = 0;
142
        /* XXX: not implemented yet */
143
        break;
144
    case 0x200 ... 0x20b: /* IOMMU */
145
        val = s->iommu[(addr & 0xf) >> 2];
146
        break;
147
    case 0x20c ... 0x3ff: /* IOMMU flush */
148
        val = 0;
149
        break;
150
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
151
        if (addr & 4) {
152
            val = s->pci_irq_map[(addr & 0x3f) >> 3];
153
        } else {
154
            val = 0;
155
        }
156
        break;
157
    case 0x2000 ... 0x202f: /* PCI control */
158
        val = s->pci_control[(addr & 0x3f) >> 2];
159
        break;
160
    case 0xf020 ... 0xf027: /* Reset control */
161
        if (addr & 4) {
162
            val = s->reset_control;
163
        } else {
164
            val = 0;
165
        }
166
        break;
167
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
168
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
169
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
170
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
171
        /* we don't care */
172
    default:
173
        val = 0;
174
        break;
175
    }
176
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
177

    
178
    return val;
179
}
180

    
181
static const MemoryRegionOps apb_config_ops = {
182
    .read = apb_config_readl,
183
    .write = apb_config_writel,
184
    .endianness = DEVICE_NATIVE_ENDIAN,
185
};
186

    
187
static void apb_pci_config_write(void *opaque, target_phys_addr_t addr,
188
                                 uint64_t val, unsigned size)
189
{
190
    APBState *s = opaque;
191

    
192
    val = qemu_bswap_len(val, size);
193
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
194
    pci_data_write(s->bus, addr, val, size);
195
}
196

    
197
static uint64_t apb_pci_config_read(void *opaque, target_phys_addr_t addr,
198
                                    unsigned size)
199
{
200
    uint32_t ret;
201
    APBState *s = opaque;
202

    
203
    ret = pci_data_read(s->bus, addr, size);
204
    ret = qemu_bswap_len(ret, size);
205
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
206
    return ret;
207
}
208

    
209
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
210
                                  uint32_t val)
211
{
212
    cpu_outb(addr & IOPORTS_MASK, val);
213
}
214

    
215
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
216
                                  uint32_t val)
217
{
218
    cpu_outw(addr & IOPORTS_MASK, bswap16(val));
219
}
220

    
221
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
222
                                uint32_t val)
223
{
224
    cpu_outl(addr & IOPORTS_MASK, bswap32(val));
225
}
226

    
227
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
228
{
229
    uint32_t val;
230

    
231
    val = cpu_inb(addr & IOPORTS_MASK);
232
    return val;
233
}
234

    
235
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
236
{
237
    uint32_t val;
238

    
239
    val = bswap16(cpu_inw(addr & IOPORTS_MASK));
240
    return val;
241
}
242

    
243
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
244
{
245
    uint32_t val;
246

    
247
    val = bswap32(cpu_inl(addr & IOPORTS_MASK));
248
    return val;
249
}
250

    
251
static const MemoryRegionOps pci_ioport_ops = {
252
    .old_mmio = {
253
        .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
254
        .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
255
    },
256
    .endianness = DEVICE_NATIVE_ENDIAN,
257
};
258

    
259
/* The APB host has an IRQ line for each IRQ line of each slot.  */
260
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
261
{
262
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
263
}
264

    
265
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
266
{
267
    int bus_offset;
268
    if (pci_dev->devfn & 1)
269
        bus_offset = 16;
270
    else
271
        bus_offset = 0;
272
    return bus_offset + irq_num;
273
}
274

    
275
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
276
{
277
    APBState *s = opaque;
278

    
279
    /* PCI IRQ map onto the first 32 INO.  */
280
    if (irq_num < 32) {
281
        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
282
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
283
            qemu_set_irq(s->pci_irqs[irq_num], level);
284
        } else {
285
            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
286
            qemu_irq_lower(s->pci_irqs[irq_num]);
287
        }
288
    }
289
}
290

    
291
static int apb_pci_bridge_initfn(PCIDevice *dev)
292
{
293
    int rc;
294

    
295
    rc = pci_bridge_initfn(dev);
296
    if (rc < 0) {
297
        return rc;
298
    }
299

    
300
    /*
301
     * command register:
302
     * According to PCI bridge spec, after reset
303
     *   bus master bit is off
304
     *   memory space enable bit is off
305
     * According to manual (805-1251.pdf).
306
     *   the reset value should be zero unless the boot pin is tied high
307
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
308
     */
309
    pci_set_word(dev->config + PCI_COMMAND,
310
                 PCI_COMMAND_MEMORY);
311
    pci_set_word(dev->config + PCI_STATUS,
312
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
313
                 PCI_STATUS_DEVSEL_MEDIUM);
314
    return 0;
315
}
316

    
317
PCIBus *pci_apb_init(target_phys_addr_t special_base,
318
                     target_phys_addr_t mem_base,
319
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
320
{
321
    DeviceState *dev;
322
    SysBusDevice *s;
323
    APBState *d;
324
    unsigned int i;
325
    PCIDevice *pci_dev;
326
    PCIBridge *br;
327

    
328
    /* Ultrasparc PBM main bus */
329
    dev = qdev_create(NULL, "pbm");
330
    qdev_init_nofail(dev);
331
    s = sysbus_from_qdev(dev);
332
    /* apb_config */
333
    sysbus_mmio_map(s, 0, special_base);
334
    /* PCI configuration space */
335
    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
336
    /* pci_ioport */
337
    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
338
    d = FROM_SYSBUS(APBState, s);
339

    
340
    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
341
    memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
342

    
343
    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
344
                              pci_apb_set_irq, pci_pbm_map_irq, d,
345
                              &d->pci_mmio,
346
                              get_system_io(),
347
                              0, 32);
348

    
349
    for (i = 0; i < 32; i++) {
350
        sysbus_connect_irq(s, i, pic[i]);
351
    }
352

    
353
    pci_create_simple(d->bus, 0, "pbm-pci");
354

    
355
    /* APB secondary busses */
356
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
357
                                   "pbm-bridge");
358
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
359
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
360
                       pci_apb_map_irq);
361
    qdev_init_nofail(&pci_dev->qdev);
362
    *bus2 = pci_bridge_get_sec_bus(br);
363

    
364
    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
365
                                   "pbm-bridge");
366
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
367
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
368
                       pci_apb_map_irq);
369
    qdev_init_nofail(&pci_dev->qdev);
370
    *bus3 = pci_bridge_get_sec_bus(br);
371

    
372
    return d->bus;
373
}
374

    
375
static void pci_pbm_reset(DeviceState *d)
376
{
377
    unsigned int i;
378
    APBState *s = container_of(d, APBState, busdev.qdev);
379

    
380
    for (i = 0; i < 8; i++) {
381
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
382
    }
383

    
384
    if (s->nr_resets++ == 0) {
385
        /* Power on reset */
386
        s->reset_control = POR;
387
    }
388
}
389

    
390
static const MemoryRegionOps pci_config_ops = {
391
    .read = apb_pci_config_read,
392
    .write = apb_pci_config_write,
393
    .endianness = DEVICE_NATIVE_ENDIAN,
394
};
395

    
396
static int pci_pbm_init_device(SysBusDevice *dev)
397
{
398
    APBState *s;
399
    unsigned int i;
400

    
401
    s = FROM_SYSBUS(APBState, dev);
402
    for (i = 0; i < 8; i++) {
403
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
404
    }
405
    for (i = 0; i < 32; i++) {
406
        sysbus_init_irq(dev, &s->pci_irqs[i]);
407
    }
408

    
409
    /* apb_config */
410
    memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
411
                          0x10000);
412
    /* at region 0 */
413
    sysbus_init_mmio(dev, &s->apb_config);
414

    
415
    memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
416
                          0x1000000);
417
    /* at region 1 */
418
    sysbus_init_mmio(dev, &s->pci_config);
419

    
420
    /* pci_ioport */
421
    memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
422
                          "apb-pci-ioport", 0x10000);
423
    /* at region 2 */
424
    sysbus_init_mmio(dev, &s->pci_ioport);
425

    
426
    return 0;
427
}
428

    
429
static int pbm_pci_host_init(PCIDevice *d)
430
{
431
    pci_set_word(d->config + PCI_COMMAND,
432
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
433
    pci_set_word(d->config + PCI_STATUS,
434
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
435
                 PCI_STATUS_DEVSEL_MEDIUM);
436
    return 0;
437
}
438

    
439
static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
440
{
441
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
442

    
443
    k->init = pbm_pci_host_init;
444
    k->vendor_id = PCI_VENDOR_ID_SUN;
445
    k->device_id = PCI_DEVICE_ID_SUN_SABRE;
446
    k->class_id = PCI_CLASS_BRIDGE_HOST;
447
    k->is_bridge = 1;
448
}
449

    
450
static DeviceInfo pbm_pci_host_info = {
451
    .name = "pbm-pci",
452
    .size = sizeof(PCIDevice),
453
    .class_init = pbm_pci_host_class_init,
454
};
455

    
456
static void pbm_host_class_init(ObjectClass *klass, void *data)
457
{
458
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
459

    
460
    k->init = pci_pbm_init_device;
461
}
462

    
463
static DeviceInfo pbm_host_info = {
464
    .name = "pbm",
465
    .size = sizeof(APBState),
466
    .reset = pci_pbm_reset,
467
    .class_init = pbm_host_class_init,
468
};
469

    
470
static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
471
{
472
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
473

    
474
    k->init = apb_pci_bridge_initfn;
475
    k->exit = pci_bridge_exitfn;
476
    k->vendor_id = PCI_VENDOR_ID_SUN;
477
    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
478
    k->revision = 0x11;
479
    k->config_write = pci_bridge_write_config;
480
    k->is_bridge = 1;
481
}
482

    
483
static DeviceInfo pbm_pci_bridge_info = {
484
    .name = "pbm-bridge",
485
    .size = sizeof(PCIBridge),
486
    .vmsd = &vmstate_pci_device,
487
    .reset = pci_bridge_reset,
488
    .class_init = pbm_pci_bridge_class_init,
489
};
490

    
491
static void pbm_register_devices(void)
492
{
493
    sysbus_register_withprop(&pbm_host_info);
494
    pci_qdev_register(&pbm_pci_host_info);
495
    pci_qdev_register(&pbm_pci_bridge_info);
496
}
497

    
498
device_init(pbm_register_devices)