Revision 95819af0

b/hw/apb_pci.c
50 50
 * http://www.sun.com/processors/manuals/805-1251.pdf
51 51
 */
52 52

  
53
#define PBM_PCI_IMR_MASK    0x7fffffff
54
#define PBM_PCI_IMR_ENABLED 0x80000000
55

  
56
#define POR          (1 << 31)
57
#define SOFT_POR     (1 << 30)
58
#define SOFT_XIR     (1 << 29)
59
#define BTN_POR      (1 << 28)
60
#define BTN_XIR      (1 << 27)
61
#define RESET_MASK   0xf8000000
62
#define RESET_WCMASK 0x98000000
63
#define RESET_WMASK  0x60000000
64

  
53 65
typedef struct APBState {
54 66
    SysBusDevice busdev;
55 67
    PCIHostState host_state;
68
    uint32_t iommu[4];
69
    uint32_t pci_control[16];
70
    uint32_t pci_irq_map[8];
71
    uint32_t obio_irq_map[32];
72
    qemu_irq pci_irqs[32];
73
    uint32_t reset_control;
56 74
} APBState;
57 75

  
76
static unsigned int nr_resets;
77

  
58 78
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
59 79
                               uint32_t val)
60 80
{
61
    //PCIBus *s = opaque;
62

  
63
    switch (addr & 0x3f) {
64
    case 0x00: // Control/Status
65
    case 0x10: // AFSR
66
    case 0x18: // AFAR
67
    case 0x20: // Diagnostic
68
    case 0x28: // Target address space
69
        // XXX
81
    APBState *s = opaque;
82

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

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

  
81
    switch (addr & 0x3f) {
82
    case 0x00: // Control/Status
83
    case 0x10: // AFSR
84
    case 0x18: // AFAR
85
    case 0x20: // Diagnostic
86
    case 0x28: // Target address space
87
        // XXX
132
    switch (addr & 0xffff) {
133
    case 0x30 ... 0x4f: /* DMA error registers */
134
        val = 0;
135
        /* XXX: not implemented yet */
136
        break;
137
    case 0x200 ... 0x20b: /* IOMMU */
138
        val = s->iommu[(addr & 0xf) >> 2];
139
        break;
140
    case 0x20c ... 0x3ff: /* IOMMU flush */
141
        val = 0;
142
        break;
143
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
144
        if (addr & 4) {
145
            val = s->pci_irq_map[(addr & 0x3f) >> 3];
146
        } else {
147
            val = 0;
148
        }
149
        break;
150
    case 0x2000 ... 0x202f: /* PCI control */
151
        val = s->pci_control[(addr & 0x3f) >> 2];
152
        break;
153
    case 0xf020 ... 0xf027: /* Reset control */
154
        if (addr & 4) {
155
            val = s->reset_control;
156
        } else {
157
            val = 0;
158
        }
159
        break;
160
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
161
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
162
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
163
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
164
        /* we don't care */
88 165
    default:
89 166
        val = 0;
90 167
        break;
91 168
    }
169
    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
170

  
92 171
    return val;
93 172
}
94 173

  
......
252 331

  
253 332
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
254 333
{
255
    qemu_irq *pic = opaque;
334
    APBState *s = opaque;
256 335

  
257 336
    /* PCI IRQ map onto the first 32 INO.  */
258
    qemu_set_irq(pic[irq_num], level);
337
    if (irq_num < 32) {
338
        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
339
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
340
            qemu_set_irq(s->pci_irqs[irq_num], level);
341
        } else {
342
            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
343
            qemu_irq_lower(s->pci_irqs[irq_num]);
344
        }
345
    }
259 346
}
260 347

  
261 348
static void apb_pci_bridge_init(PCIBus *b)
......
284 371
    DeviceState *dev;
285 372
    SysBusDevice *s;
286 373
    APBState *d;
374
    unsigned int i;
287 375

  
288 376
    /* Ultrasparc PBM main bus */
289 377
    dev = qdev_create(NULL, "pbm");
......
299 387
    sysbus_mmio_map(s, 3, mem_base);
300 388
    d = FROM_SYSBUS(APBState, s);
301 389
    d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
302
                                         pci_apb_set_irq, pci_pbm_map_irq, pic,
390
                                         pci_apb_set_irq, pci_pbm_map_irq, d,
303 391
                                         0, 32);
304 392
    pci_bus_set_mem_base(d->host_state.bus, mem_base);
305 393

  
394
    for (i = 0; i < 32; i++) {
395
        sysbus_connect_irq(s, i, pic[i]);
396
    }
397

  
306 398
    pci_create_simple(d->host_state.bus, 0, "pbm");
307 399
    /* APB secondary busses */
308 400
    *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
......
320 412
    return d->host_state.bus;
321 413
}
322 414

  
323
static int pci_pbm_init_device(SysBusDevice *dev)
415
static void pci_pbm_reset(DeviceState *d)
324 416
{
417
    unsigned int i;
418
    APBState *s = container_of(d, APBState, busdev.qdev);
325 419

  
420
    for (i = 0; i < 8; i++) {
421
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
422
    }
423

  
424
    if (nr_resets++ == 0) {
425
        /* Power on reset */
426
        s->reset_control = POR;
427
    }
428
}
429

  
430
static int pci_pbm_init_device(SysBusDevice *dev)
431
{
326 432
    APBState *s;
327 433
    int pci_mem_data, apb_config, pci_ioport, pci_config;
434
    unsigned int i;
328 435

  
329 436
    s = FROM_SYSBUS(APBState, dev);
437
    for (i = 0; i < 8; i++) {
438
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
439
    }
440
    for (i = 0; i < 32; i++) {
441
        sysbus_init_irq(dev, &s->pci_irqs[i]);
442
    }
443

  
330 444
    /* apb_config */
331 445
    apb_config = cpu_register_io_memory(apb_config_read,
332 446
                                        apb_config_write, s);
......
368 482
    .header_type  = PCI_HEADER_TYPE_BRIDGE,
369 483
};
370 484

  
485
static SysBusDeviceInfo pbm_host_info = {
486
    .qdev.name = "pbm",
487
    .qdev.size = sizeof(APBState),
488
    .qdev.reset = pci_pbm_reset,
489
    .init = pci_pbm_init_device,
490
};
371 491
static void pbm_register_devices(void)
372 492
{
373
    sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
493
    sysbus_register_withprop(&pbm_host_info);
374 494
    pci_qdev_register(&pbm_pci_host_info);
375 495
}
376 496

  

Also available in: Unified diff