Statistics
| Branch: | Revision:

root / hw / apb_pci.c @ 6bef0436

History | View | Annotate | Download (14 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
    pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_SUN);
308
    pci_config_set_device_id(dev->config, PCI_DEVICE_ID_SUN_SIMBA);
309

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

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

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

    
351
    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
352
                                         pci_apb_set_irq, pci_pbm_map_irq, d,
353
                                         0, 32);
354
    pci_bus_set_mem_base(d->bus, mem_base);
355

    
356
    for (i = 0; i < 32; i++) {
357
        sysbus_connect_irq(s, i, pic[i]);
358
    }
359

    
360
    pci_create_simple(d->bus, 0, "pbm");
361

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

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

    
379
    return d->bus;
380
}
381

    
382
static void pci_pbm_reset(DeviceState *d)
383
{
384
    unsigned int i;
385
    APBState *s = container_of(d, APBState, busdev.qdev);
386

    
387
    for (i = 0; i < 8; i++) {
388
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
389
    }
390

    
391
    if (s->nr_resets++ == 0) {
392
        /* Power on reset */
393
        s->reset_control = POR;
394
    }
395
}
396

    
397
static int pci_pbm_init_device(SysBusDevice *dev)
398
{
399
    APBState *s;
400
    int pci_config, apb_config, pci_ioport;
401
    unsigned int i;
402

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

    
411
    /* apb_config */
412
    apb_config = cpu_register_io_memory(apb_config_read,
413
                                        apb_config_write, s,
414
                                        DEVICE_NATIVE_ENDIAN);
415
    /* at region 0 */
416
    sysbus_init_mmio(dev, 0x10000ULL, apb_config);
417

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

    
427
    /* pci_ioport */
428
    pci_ioport = cpu_register_io_memory(pci_apb_ioread,
429
                                        pci_apb_iowrite, s,
430
                                        DEVICE_NATIVE_ENDIAN);
431
    /* at region 2 */
432
    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
433

    
434
    return 0;
435
}
436

    
437
static int pbm_pci_host_init(PCIDevice *d)
438
{
439
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
440
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
441
    pci_set_word(d->config + PCI_COMMAND,
442
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
443
    pci_set_word(d->config + PCI_STATUS,
444
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
445
                 PCI_STATUS_DEVSEL_MEDIUM);
446
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
447
    return 0;
448
}
449

    
450
static PCIDeviceInfo pbm_pci_host_info = {
451
    .qdev.name = "pbm",
452
    .qdev.size = sizeof(PCIDevice),
453
    .init      = pbm_pci_host_init,
454
    .is_bridge = 1,
455
};
456

    
457
static SysBusDeviceInfo pbm_host_info = {
458
    .qdev.name = "pbm",
459
    .qdev.size = sizeof(APBState),
460
    .qdev.reset = pci_pbm_reset,
461
    .init = pci_pbm_init_device,
462
};
463

    
464
static PCIDeviceInfo pbm_pci_bridge_info = {
465
    .qdev.name = "pbm-bridge",
466
    .qdev.size = sizeof(PCIBridge),
467
    .qdev.vmsd = &vmstate_pci_device,
468
    .qdev.reset = pci_bridge_reset,
469
    .init = apb_pci_bridge_initfn,
470
    .exit = pci_bridge_exitfn,
471
    .config_write = pci_bridge_write_config,
472
    .is_bridge = 1,
473
};
474

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

    
482
device_init(pbm_register_devices)