Annotation of qemu/hw/unin_pci.c, revision 1.1.1.9

1.1       root        1: /*
                      2:  * QEMU Uninorth PCI host (for all Mac99 and newer machines)
                      3:  *
                      4:  * Copyright (c) 2006 Fabrice Bellard
1.1.1.3   root        5:  *
1.1       root        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:  */
1.1.1.3   root       24: #include "hw.h"
                     25: #include "ppc_mac.h"
                     26: #include "pci.h"
1.1.1.7   root       27: #include "pci_host.h"
1.1.1.3   root       28: 
1.1.1.4   root       29: /* debug UniNorth */
                     30: //#define DEBUG_UNIN
                     31: 
                     32: #ifdef DEBUG_UNIN
1.1.1.5   root       33: #define UNIN_DPRINTF(fmt, ...)                                  \
                     34:     do { printf("UNIN: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.4   root       35: #else
1.1.1.5   root       36: #define UNIN_DPRINTF(fmt, ...)
1.1.1.4   root       37: #endif
                     38: 
1.1.1.8   root       39: static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
                     40: 
1.1.1.7   root       41: typedef struct UNINState {
                     42:     SysBusDevice busdev;
                     43:     PCIHostState host_state;
1.1.1.8   root       44:     ReadWriteHandler data_handler;
1.1.1.7   root       45: } UNINState;
1.1       root       46: 
1.1.1.7   root       47: static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
1.1       root       48: {
1.1.1.8   root       49:     int retval;
                     50:     int devfn = pci_dev->devfn & 0x00FFFFFF;
                     51: 
                     52:     retval = (((devfn >> 11) & 0x1F) + irq_num) & 3;
                     53: 
                     54:     return retval;
1.1       root       55: }
                     56: 
1.1.1.7   root       57: static void pci_unin_set_irq(void *opaque, int irq_num, int level)
1.1       root       58: {
1.1.1.7   root       59:     qemu_irq *pic = opaque;
1.1       root       60: 
1.1.1.8   root       61:     UNIN_DPRINTF("%s: setting INT %d = %d\n", __func__,
                     62:                  unin_irq_line[irq_num], level);
                     63:     qemu_set_irq(pic[unin_irq_line[irq_num]], level);
1.1       root       64: }
                     65: 
1.1.1.7   root       66: static void pci_unin_save(QEMUFile* f, void *opaque)
1.1       root       67: {
1.1.1.7   root       68:     PCIDevice *d = opaque;
1.1       root       69: 
1.1.1.7   root       70:     pci_device_save(d, f);
1.1       root       71: }
                     72: 
1.1.1.7   root       73: static int pci_unin_load(QEMUFile* f, void *opaque, int version_id)
1.1       root       74: {
1.1.1.7   root       75:     PCIDevice *d = opaque;
1.1       root       76: 
1.1.1.7   root       77:     if (version_id != 1)
                     78:         return -EINVAL;
1.1       root       79: 
1.1.1.7   root       80:     return pci_device_load(d, f);
                     81: }
1.1       root       82: 
1.1.1.7   root       83: static void pci_unin_reset(void *opaque)
1.1       root       84: {
1.1.1.2   root       85: }
                     86: 
1.1.1.8   root       87: static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
                     88: {
                     89:     uint32_t retval;
                     90: 
                     91:     if (reg & (1u << 31)) {
                     92:         /* XXX OpenBIOS compatibility hack */
                     93:         retval = reg | (addr & 3);
                     94:     } else if (reg & 1) {
                     95:         /* CFA1 style */
                     96:         retval = (reg & ~7u) | (addr & 7);
                     97:     } else {
                     98:         uint32_t slot, func;
                     99: 
                    100:         /* Grab CFA0 style values */
                    101:         slot = ffs(reg & 0xfffff800) - 1;
                    102:         func = (reg >> 8) & 7;
                    103: 
                    104:         /* ... and then convert them to x86 format */
                    105:         /* config pointer */
                    106:         retval = (reg & (0xff - 7)) | (addr & 7);
                    107:         /* slot */
                    108:         retval |= slot << 11;
                    109:         /* fn */
                    110:         retval |= func << 8;
                    111:     }
                    112: 
                    113: 
                    114:     UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n",
                    115:                  reg, addr, retval);
                    116: 
                    117:     return retval;
                    118: }
                    119: 
                    120: static void unin_data_write(ReadWriteHandler *handler,
                    121:                             pcibus_t addr, uint32_t val, int len)
                    122: {
                    123:     UNINState *s = container_of(handler, UNINState, data_handler);
                    124:     UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
                    125:     pci_data_write(s->host_state.bus,
                    126:                    unin_get_config_reg(s->host_state.config_reg, addr),
                    127:                    val, len);
                    128: }
                    129: 
                    130: static uint32_t unin_data_read(ReadWriteHandler *handler,
                    131:                                pcibus_t addr, int len)
                    132: {
                    133:     UNINState *s = container_of(handler, UNINState, data_handler);
                    134:     uint32_t val;
                    135: 
                    136:     val = pci_data_read(s->host_state.bus,
                    137:                         unin_get_config_reg(s->host_state.config_reg, addr),
                    138:                         len);
                    139:     UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
                    140:     return val;
                    141: }
                    142: 
1.1.1.7   root      143: static int pci_unin_main_init_device(SysBusDevice *dev)
1.1.1.2   root      144: {
1.1.1.7   root      145:     UNINState *s;
                    146:     int pci_mem_config, pci_mem_data;
                    147: 
                    148:     /* Use values found on a real PowerMac */
                    149:     /* Uninorth main bus */
                    150:     s = FROM_SYSBUS(UNINState, dev);
                    151: 
1.1.1.9 ! root      152:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
        !           153:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.8   root      154:     s->data_handler.read = unin_data_read;
                    155:     s->data_handler.write = unin_data_write;
1.1.1.9 ! root      156:     pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
        !           157:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.7   root      158:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    159:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
                    160: 
1.1.1.8   root      161:     register_savevm(&dev->qdev, "uninorth", 0, 1,
                    162:                     pci_unin_save, pci_unin_load, &s->host_state);
1.1.1.7   root      163:     qemu_register_reset(pci_unin_reset, &s->host_state);
                    164:     return 0;
1.1       root      165: }
                    166: 
1.1.1.8   root      167: static int pci_u3_agp_init_device(SysBusDevice *dev)
1.1.1.4   root      168: {
1.1.1.7   root      169:     UNINState *s;
                    170:     int pci_mem_config, pci_mem_data;
1.1.1.4   root      171: 
1.1.1.8   root      172:     /* Uninorth U3 AGP bus */
1.1.1.7   root      173:     s = FROM_SYSBUS(UNINState, dev);
                    174: 
1.1.1.9 ! root      175:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
        !           176:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.8   root      177:     s->data_handler.read = unin_data_read;
                    178:     s->data_handler.write = unin_data_write;
1.1.1.9 ! root      179:     pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
        !           180:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.7   root      181:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    182:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
1.1.1.8   root      183: 
                    184:     register_savevm(&dev->qdev, "uninorth", 0, 1,
                    185:                     pci_unin_save, pci_unin_load, &s->host_state);
                    186:     qemu_register_reset(pci_unin_reset, &s->host_state);
                    187: 
1.1.1.7   root      188:     return 0;
1.1.1.4   root      189: }
                    190: 
1.1.1.7   root      191: static int pci_unin_agp_init_device(SysBusDevice *dev)
1.1.1.4   root      192: {
1.1.1.7   root      193:     UNINState *s;
                    194:     int pci_mem_config, pci_mem_data;
1.1.1.4   root      195: 
1.1.1.7   root      196:     /* Uninorth AGP bus */
                    197:     s = FROM_SYSBUS(UNINState, dev);
1.1.1.4   root      198: 
1.1.1.9 ! root      199:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
        !           200:                                                  DEVICE_LITTLE_ENDIAN);
        !           201:     pci_mem_data = pci_host_data_register_mmio(&s->host_state,
        !           202:                                                DEVICE_LITTLE_ENDIAN);
1.1.1.7   root      203:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    204:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
                    205:     return 0;
1.1.1.4   root      206: }
                    207: 
1.1.1.7   root      208: static int pci_unin_internal_init_device(SysBusDevice *dev)
1.1.1.4   root      209: {
1.1.1.7   root      210:     UNINState *s;
                    211:     int pci_mem_config, pci_mem_data;
                    212: 
                    213:     /* Uninorth internal bus */
                    214:     s = FROM_SYSBUS(UNINState, dev);
                    215: 
1.1.1.9 ! root      216:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
        !           217:                                                  DEVICE_LITTLE_ENDIAN);
        !           218:     pci_mem_data = pci_host_data_register_mmio(&s->host_state,
        !           219:                                                DEVICE_LITTLE_ENDIAN);
1.1.1.7   root      220:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    221:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
                    222:     return 0;
1.1.1.4   root      223: }
                    224: 
1.1.1.3   root      225: PCIBus *pci_pmac_init(qemu_irq *pic)
1.1       root      226: {
1.1.1.7   root      227:     DeviceState *dev;
                    228:     SysBusDevice *s;
                    229:     UNINState *d;
1.1       root      230: 
                    231:     /* Use values found on a real PowerMac */
                    232:     /* Uninorth main bus */
1.1.1.7   root      233:     dev = qdev_create(NULL, "uni-north");
                    234:     qdev_init_nofail(dev);
                    235:     s = sysbus_from_qdev(dev);
                    236:     d = FROM_SYSBUS(UNINState, s);
                    237:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                    238:                                          pci_unin_set_irq, pci_unin_map_irq,
1.1.1.8   root      239:                                          pic, PCI_DEVFN(11, 0), 4);
1.1.1.7   root      240: 
                    241: #if 0
1.1.1.8   root      242:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
1.1.1.7   root      243: #endif
                    244: 
                    245:     sysbus_mmio_map(s, 0, 0xf2800000);
                    246:     sysbus_mmio_map(s, 1, 0xf2c00000);
                    247: 
                    248:     /* DEC 21154 bridge */
                    249: #if 0
                    250:     /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
1.1.1.8   root      251:     pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154");
1.1.1.7   root      252: #endif
                    253: 
                    254:     /* Uninorth AGP bus */
1.1.1.8   root      255:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp");
1.1.1.7   root      256:     dev = qdev_create(NULL, "uni-north-agp");
                    257:     qdev_init_nofail(dev);
                    258:     s = sysbus_from_qdev(dev);
                    259:     sysbus_mmio_map(s, 0, 0xf0800000);
                    260:     sysbus_mmio_map(s, 1, 0xf0c00000);
                    261: 
                    262:     /* Uninorth internal bus */
                    263: #if 0
                    264:     /* XXX: not needed for now */
1.1.1.8   root      265:     pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0), "uni-north-pci");
1.1.1.7   root      266:     dev = qdev_create(NULL, "uni-north-pci");
                    267:     qdev_init_nofail(dev);
                    268:     s = sysbus_from_qdev(dev);
                    269:     sysbus_mmio_map(s, 0, 0xf4800000);
                    270:     sysbus_mmio_map(s, 1, 0xf4c00000);
                    271: #endif
                    272: 
                    273:     return d->host_state.bus;
                    274: }
                    275: 
1.1.1.8   root      276: PCIBus *pci_pmac_u3_init(qemu_irq *pic)
                    277: {
                    278:     DeviceState *dev;
                    279:     SysBusDevice *s;
                    280:     UNINState *d;
                    281: 
                    282:     /* Uninorth AGP bus */
                    283: 
                    284:     dev = qdev_create(NULL, "u3-agp");
                    285:     qdev_init_nofail(dev);
                    286:     s = sysbus_from_qdev(dev);
                    287:     d = FROM_SYSBUS(UNINState, s);
                    288: 
                    289:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                    290:                                          pci_unin_set_irq, pci_unin_map_irq,
                    291:                                          pic, PCI_DEVFN(11, 0), 4);
                    292: 
                    293:     sysbus_mmio_map(s, 0, 0xf0800000);
                    294:     sysbus_mmio_map(s, 1, 0xf0c00000);
                    295: 
                    296:     pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp");
                    297: 
                    298:     return d->host_state.bus;
                    299: }
                    300: 
1.1.1.7   root      301: static int unin_main_pci_host_init(PCIDevice *d)
                    302: {
1.1.1.4   root      303:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
                    304:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_PCI);
1.1       root      305:     d->config[0x08] = 0x00; // revision
1.1.1.4   root      306:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
1.1       root      307:     d->config[0x0C] = 0x08; // cache_line_size
                    308:     d->config[0x0D] = 0x10; // latency_timer
                    309:     d->config[0x34] = 0x00; // capabilities_pointer
1.1.1.7   root      310:     return 0;
                    311: }
1.1       root      312: 
1.1.1.7   root      313: static int unin_agp_pci_host_init(PCIDevice *d)
                    314: {
1.1.1.4   root      315:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
                    316:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
1.1       root      317:     d->config[0x08] = 0x00; // revision
1.1.1.4   root      318:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
1.1       root      319:     d->config[0x0C] = 0x08; // cache_line_size
                    320:     d->config[0x0D] = 0x10; // latency_timer
                    321:     //    d->config[0x34] = 0x80; // capabilities_pointer
1.1.1.7   root      322:     return 0;
                    323: }
1.1       root      324: 
1.1.1.8   root      325: static int u3_agp_pci_host_init(PCIDevice *d)
                    326: {
                    327:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
                    328:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_U3_AGP);
                    329:     /* revision */
                    330:     d->config[0x08] = 0x00;
                    331:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
                    332:     /* cache line size */
                    333:     d->config[0x0C] = 0x08;
                    334:     /* latency timer */
                    335:     d->config[0x0D] = 0x10;
                    336:     return 0;
                    337: }
                    338: 
1.1.1.7   root      339: static int unin_internal_pci_host_init(PCIDevice *d)
                    340: {
1.1.1.4   root      341:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
                    342:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI);
1.1       root      343:     d->config[0x08] = 0x00; // revision
1.1.1.4   root      344:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
1.1       root      345:     d->config[0x0C] = 0x08; // cache_line_size
                    346:     d->config[0x0D] = 0x10; // latency_timer
                    347:     d->config[0x34] = 0x00; // capabilities_pointer
1.1.1.7   root      348:     return 0;
                    349: }
                    350: 
                    351: static PCIDeviceInfo unin_main_pci_host_info = {
                    352:     .qdev.name = "uni-north",
                    353:     .qdev.size = sizeof(PCIDevice),
                    354:     .init      = unin_main_pci_host_init,
                    355: };
                    356: 
1.1.1.8   root      357: static PCIDeviceInfo u3_agp_pci_host_info = {
                    358:     .qdev.name = "u3-agp",
1.1.1.7   root      359:     .qdev.size = sizeof(PCIDevice),
1.1.1.8   root      360:     .init      = u3_agp_pci_host_init,
1.1.1.7   root      361: };
                    362: 
                    363: static PCIDeviceInfo unin_agp_pci_host_info = {
                    364:     .qdev.name = "uni-north-agp",
                    365:     .qdev.size = sizeof(PCIDevice),
                    366:     .init      = unin_agp_pci_host_init,
                    367: };
1.1.1.4   root      368: 
1.1.1.7   root      369: static PCIDeviceInfo unin_internal_pci_host_info = {
                    370:     .qdev.name = "uni-north-pci",
                    371:     .qdev.size = sizeof(PCIDevice),
                    372:     .init      = unin_internal_pci_host_init,
                    373: };
                    374: 
                    375: static void unin_register_devices(void)
                    376: {
                    377:     sysbus_register_dev("uni-north", sizeof(UNINState),
                    378:                         pci_unin_main_init_device);
                    379:     pci_qdev_register(&unin_main_pci_host_info);
1.1.1.8   root      380:     sysbus_register_dev("u3-agp", sizeof(UNINState),
                    381:                         pci_u3_agp_init_device);
                    382:     pci_qdev_register(&u3_agp_pci_host_info);
1.1.1.7   root      383:     sysbus_register_dev("uni-north-agp", sizeof(UNINState),
                    384:                         pci_unin_agp_init_device);
                    385:     pci_qdev_register(&unin_agp_pci_host_info);
                    386:     sysbus_register_dev("uni-north-pci", sizeof(UNINState),
                    387:                         pci_unin_internal_init_device);
                    388:     pci_qdev_register(&unin_internal_pci_host_info);
1.1       root      389: }
1.1.1.7   root      390: 
                    391: device_init(unin_register_devices)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.