Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 92f9a4f1

History | View | Annotate | Download (13.9 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 "rwhandler.h"
35
#include "apb_pci.h"
36
#include "sysemu.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
    ReadWriteHandler pci_config_handler;
73
    uint32_t iommu[4];
74
    uint32_t pci_control[16];
75
    uint32_t pci_irq_map[8];
76
    uint32_t obio_irq_map[32];
77
    qemu_irq pci_irqs[32];
78
    uint32_t reset_control;
79
    unsigned int nr_resets;
80
} APBState;
81

    
82
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
83
                               uint32_t val)
84
{
85
    APBState *s = opaque;
86

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

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

    
130
static uint32_t apb_config_readl (void *opaque,
131
                                  target_phys_addr_t addr)
132
{
133
    APBState *s = opaque;
134
    uint32_t val;
135

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

    
175
    return val;
176
}
177

    
178
static CPUWriteMemoryFunc * const apb_config_write[] = {
179
    &apb_config_writel,
180
    &apb_config_writel,
181
    &apb_config_writel,
182
};
183

    
184
static CPUReadMemoryFunc * const apb_config_read[] = {
185
    &apb_config_readl,
186
    &apb_config_readl,
187
    &apb_config_readl,
188
};
189

    
190
static void apb_pci_config_write(ReadWriteHandler *h, pcibus_t addr,
191
                                 uint32_t val, int size)
192
{
193
    APBState *s = container_of(h, APBState, pci_config_handler);
194

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

    
200
static uint32_t apb_pci_config_read(ReadWriteHandler *h, pcibus_t addr,
201
                                    int size)
202
{
203
    uint32_t ret;
204
    APBState *s = container_of(h, APBState, pci_config_handler);
205

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

    
212
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
213
                                  uint32_t val)
214
{
215
    cpu_outb(addr & IOPORTS_MASK, val);
216
}
217

    
218
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
219
                                  uint32_t val)
220
{
221
    cpu_outw(addr & IOPORTS_MASK, bswap16(val));
222
}
223

    
224
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
225
                                uint32_t val)
226
{
227
    cpu_outl(addr & IOPORTS_MASK, bswap32(val));
228
}
229

    
230
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
231
{
232
    uint32_t val;
233

    
234
    val = cpu_inb(addr & IOPORTS_MASK);
235
    return val;
236
}
237

    
238
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
239
{
240
    uint32_t val;
241

    
242
    val = bswap16(cpu_inw(addr & IOPORTS_MASK));
243
    return val;
244
}
245

    
246
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
247
{
248
    uint32_t val;
249

    
250
    val = bswap32(cpu_inl(addr & IOPORTS_MASK));
251
    return val;
252
}
253

    
254
static CPUWriteMemoryFunc * const pci_apb_iowrite[] = {
255
    &pci_apb_iowriteb,
256
    &pci_apb_iowritew,
257
    &pci_apb_iowritel,
258
};
259

    
260
static CPUReadMemoryFunc * const pci_apb_ioread[] = {
261
    &pci_apb_ioreadb,
262
    &pci_apb_ioreadw,
263
    &pci_apb_ioreadl,
264
};
265

    
266
/* The APB host has an IRQ line for each IRQ line of each slot.  */
267
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
268
{
269
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
270
}
271

    
272
static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
273
{
274
    int bus_offset;
275
    if (pci_dev->devfn & 1)
276
        bus_offset = 16;
277
    else
278
        bus_offset = 0;
279
    return bus_offset + irq_num;
280
}
281

    
282
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
283
{
284
    APBState *s = opaque;
285

    
286
    /* PCI IRQ map onto the first 32 INO.  */
287
    if (irq_num < 32) {
288
        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
289
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
290
            qemu_set_irq(s->pci_irqs[irq_num], level);
291
        } else {
292
            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
293
            qemu_irq_lower(s->pci_irqs[irq_num]);
294
        }
295
    }
296
}
297

    
298
static int apb_pci_bridge_initfn(PCIDevice *dev)
299
{
300
    int rc;
301

    
302
    rc = pci_bridge_initfn(dev);
303
    if (rc < 0) {
304
        return rc;
305
    }
306

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

    
324
PCIBus *pci_apb_init(target_phys_addr_t special_base,
325
                     target_phys_addr_t mem_base,
326
                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
327
{
328
    DeviceState *dev;
329
    SysBusDevice *s;
330
    APBState *d;
331
    unsigned int i;
332
    PCIDevice *pci_dev;
333
    PCIBridge *br;
334

    
335
    /* Ultrasparc PBM main bus */
336
    dev = qdev_create(NULL, "pbm");
337
    qdev_init_nofail(dev);
338
    s = sysbus_from_qdev(dev);
339
    /* apb_config */
340
    sysbus_mmio_map(s, 0, special_base);
341
    /* PCI configuration space */
342
    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
343
    /* pci_ioport */
344
    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
345
    d = FROM_SYSBUS(APBState, s);
346

    
347
    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
348
                                         pci_apb_set_irq, pci_pbm_map_irq, d,
349
                                         0, 32);
350
    pci_bus_set_mem_base(d->bus, mem_base);
351

    
352
    for (i = 0; i < 32; i++) {
353
        sysbus_connect_irq(s, i, pic[i]);
354
    }
355

    
356
    pci_create_simple(d->bus, 0, "pbm");
357

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

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

    
375
    return d->bus;
376
}
377

    
378
static void pci_pbm_reset(DeviceState *d)
379
{
380
    unsigned int i;
381
    APBState *s = container_of(d, APBState, busdev.qdev);
382

    
383
    for (i = 0; i < 8; i++) {
384
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
385
    }
386

    
387
    if (s->nr_resets++ == 0) {
388
        /* Power on reset */
389
        s->reset_control = POR;
390
    }
391
}
392

    
393
static int pci_pbm_init_device(SysBusDevice *dev)
394
{
395
    APBState *s;
396
    int pci_config, apb_config, pci_ioport;
397
    unsigned int i;
398

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

    
407
    /* apb_config */
408
    apb_config = cpu_register_io_memory(apb_config_read,
409
                                        apb_config_write, s,
410
                                        DEVICE_NATIVE_ENDIAN);
411
    /* at region 0 */
412
    sysbus_init_mmio(dev, 0x10000ULL, apb_config);
413

    
414
    /* PCI configuration space */
415
    s->pci_config_handler.read = apb_pci_config_read;
416
    s->pci_config_handler.write = apb_pci_config_write;
417
    pci_config = cpu_register_io_memory_simple(&s->pci_config_handler,
418
                                               DEVICE_NATIVE_ENDIAN);
419
    assert(pci_config >= 0);
420
    /* at region 1 */
421
    sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
422

    
423
    /* pci_ioport */
424
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
425
                                        pci_apb_iowrite, s,
426
                                        DEVICE_NATIVE_ENDIAN);
427
    /* at region 2 */
428
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
429

    
430
    return 0;
431
}
432

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

    
443
static PCIDeviceInfo pbm_pci_host_info = {
444
    .qdev.name = "pbm",
445
    .qdev.size = sizeof(PCIDevice),
446
    .init      = pbm_pci_host_init,
447
    .vendor_id = PCI_VENDOR_ID_SUN,
448
    .device_id = PCI_DEVICE_ID_SUN_SABRE,
449
    .class_id  = PCI_CLASS_BRIDGE_HOST,
450
    .is_bridge = 1,
451
};
452

    
453
static SysBusDeviceInfo pbm_host_info = {
454
    .qdev.name = "pbm",
455
    .qdev.size = sizeof(APBState),
456
    .qdev.reset = pci_pbm_reset,
457
    .init = pci_pbm_init_device,
458
};
459

    
460
static PCIDeviceInfo pbm_pci_bridge_info = {
461
    .qdev.name = "pbm-bridge",
462
    .qdev.size = sizeof(PCIBridge),
463
    .qdev.vmsd = &vmstate_pci_device,
464
    .qdev.reset = pci_bridge_reset,
465
    .init = apb_pci_bridge_initfn,
466
    .exit = pci_bridge_exitfn,
467
    .vendor_id = PCI_VENDOR_ID_SUN,
468
    .device_id = PCI_DEVICE_ID_SUN_SIMBA,
469
    .revision = 0x11,
470
    .config_write = pci_bridge_write_config,
471
    .is_bridge = 1,
472
};
473

    
474
static void pbm_register_devices(void)
475
{
476
    sysbus_register_withprop(&pbm_host_info);
477
    pci_qdev_register(&pbm_pci_host_info);
478
    pci_qdev_register(&pbm_pci_bridge_info);
479
}
480

    
481
device_init(pbm_register_devices)