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

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:     val = qemu_bswap_len(val, len);
        !           125:     UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
        !           126:     pci_data_write(s->host_state.bus,
        !           127:                    unin_get_config_reg(s->host_state.config_reg, addr),
        !           128:                    val, len);
        !           129: }
        !           130: 
        !           131: static uint32_t unin_data_read(ReadWriteHandler *handler,
        !           132:                                pcibus_t addr, int len)
        !           133: {
        !           134:     UNINState *s = container_of(handler, UNINState, data_handler);
        !           135:     uint32_t val;
        !           136: 
        !           137:     val = pci_data_read(s->host_state.bus,
        !           138:                         unin_get_config_reg(s->host_state.config_reg, addr),
        !           139:                         len);
        !           140:     UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
        !           141:     val = qemu_bswap_len(val, len);
        !           142:     return val;
        !           143: }
        !           144: 
1.1.1.7   root      145: static int pci_unin_main_init_device(SysBusDevice *dev)
1.1.1.2   root      146: {
1.1.1.7   root      147:     UNINState *s;
                    148:     int pci_mem_config, pci_mem_data;
                    149: 
                    150:     /* Use values found on a real PowerMac */
                    151:     /* Uninorth main bus */
                    152:     s = FROM_SYSBUS(UNINState, dev);
                    153: 
1.1.1.8 ! root      154:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 1);
        !           155:     s->data_handler.read = unin_data_read;
        !           156:     s->data_handler.write = unin_data_write;
        !           157:     pci_mem_data = cpu_register_io_memory_simple(&s->data_handler);
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.8 ! root      175:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 1);
        !           176:     s->data_handler.read = unin_data_read;
        !           177:     s->data_handler.write = unin_data_write;
        !           178:     pci_mem_data = cpu_register_io_memory_simple(&s->data_handler);
1.1.1.7   root      179:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    180:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
1.1.1.8 ! root      181: 
        !           182:     register_savevm(&dev->qdev, "uninorth", 0, 1,
        !           183:                     pci_unin_save, pci_unin_load, &s->host_state);
        !           184:     qemu_register_reset(pci_unin_reset, &s->host_state);
        !           185: 
1.1.1.7   root      186:     return 0;
1.1.1.4   root      187: }
                    188: 
1.1.1.7   root      189: static int pci_unin_agp_init_device(SysBusDevice *dev)
1.1.1.4   root      190: {
1.1.1.7   root      191:     UNINState *s;
                    192:     int pci_mem_config, pci_mem_data;
1.1.1.4   root      193: 
1.1.1.7   root      194:     /* Uninorth AGP bus */
                    195:     s = FROM_SYSBUS(UNINState, dev);
1.1.1.4   root      196: 
1.1.1.8 ! root      197:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 0);
        !           198:     pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
1.1.1.7   root      199:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    200:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
                    201:     return 0;
1.1.1.4   root      202: }
                    203: 
1.1.1.7   root      204: static int pci_unin_internal_init_device(SysBusDevice *dev)
1.1.1.4   root      205: {
1.1.1.7   root      206:     UNINState *s;
                    207:     int pci_mem_config, pci_mem_data;
                    208: 
                    209:     /* Uninorth internal bus */
                    210:     s = FROM_SYSBUS(UNINState, dev);
                    211: 
1.1.1.8 ! root      212:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 0);
        !           213:     pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
1.1.1.7   root      214:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    215:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
                    216:     return 0;
1.1.1.4   root      217: }
                    218: 
1.1.1.3   root      219: PCIBus *pci_pmac_init(qemu_irq *pic)
1.1       root      220: {
1.1.1.7   root      221:     DeviceState *dev;
                    222:     SysBusDevice *s;
                    223:     UNINState *d;
1.1       root      224: 
                    225:     /* Use values found on a real PowerMac */
                    226:     /* Uninorth main bus */
1.1.1.7   root      227:     dev = qdev_create(NULL, "uni-north");
                    228:     qdev_init_nofail(dev);
                    229:     s = sysbus_from_qdev(dev);
                    230:     d = FROM_SYSBUS(UNINState, s);
                    231:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                    232:                                          pci_unin_set_irq, pci_unin_map_irq,
1.1.1.8 ! root      233:                                          pic, PCI_DEVFN(11, 0), 4);
1.1.1.7   root      234: 
                    235: #if 0
1.1.1.8 ! root      236:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
1.1.1.7   root      237: #endif
                    238: 
                    239:     sysbus_mmio_map(s, 0, 0xf2800000);
                    240:     sysbus_mmio_map(s, 1, 0xf2c00000);
                    241: 
                    242:     /* DEC 21154 bridge */
                    243: #if 0
                    244:     /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
1.1.1.8 ! root      245:     pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154");
1.1.1.7   root      246: #endif
                    247: 
                    248:     /* Uninorth AGP bus */
1.1.1.8 ! root      249:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp");
1.1.1.7   root      250:     dev = qdev_create(NULL, "uni-north-agp");
                    251:     qdev_init_nofail(dev);
                    252:     s = sysbus_from_qdev(dev);
                    253:     sysbus_mmio_map(s, 0, 0xf0800000);
                    254:     sysbus_mmio_map(s, 1, 0xf0c00000);
                    255: 
                    256:     /* Uninorth internal bus */
                    257: #if 0
                    258:     /* XXX: not needed for now */
1.1.1.8 ! root      259:     pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0), "uni-north-pci");
1.1.1.7   root      260:     dev = qdev_create(NULL, "uni-north-pci");
                    261:     qdev_init_nofail(dev);
                    262:     s = sysbus_from_qdev(dev);
                    263:     sysbus_mmio_map(s, 0, 0xf4800000);
                    264:     sysbus_mmio_map(s, 1, 0xf4c00000);
                    265: #endif
                    266: 
                    267:     return d->host_state.bus;
                    268: }
                    269: 
1.1.1.8 ! root      270: PCIBus *pci_pmac_u3_init(qemu_irq *pic)
        !           271: {
        !           272:     DeviceState *dev;
        !           273:     SysBusDevice *s;
        !           274:     UNINState *d;
        !           275: 
        !           276:     /* Uninorth AGP bus */
        !           277: 
        !           278:     dev = qdev_create(NULL, "u3-agp");
        !           279:     qdev_init_nofail(dev);
        !           280:     s = sysbus_from_qdev(dev);
        !           281:     d = FROM_SYSBUS(UNINState, s);
        !           282: 
        !           283:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
        !           284:                                          pci_unin_set_irq, pci_unin_map_irq,
        !           285:                                          pic, PCI_DEVFN(11, 0), 4);
        !           286: 
        !           287:     sysbus_mmio_map(s, 0, 0xf0800000);
        !           288:     sysbus_mmio_map(s, 1, 0xf0c00000);
        !           289: 
        !           290:     pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp");
        !           291: 
        !           292:     return d->host_state.bus;
        !           293: }
        !           294: 
1.1.1.7   root      295: static int unin_main_pci_host_init(PCIDevice *d)
                    296: {
1.1.1.4   root      297:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
                    298:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_PCI);
1.1       root      299:     d->config[0x08] = 0x00; // revision
1.1.1.4   root      300:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
1.1       root      301:     d->config[0x0C] = 0x08; // cache_line_size
                    302:     d->config[0x0D] = 0x10; // latency_timer
                    303:     d->config[0x34] = 0x00; // capabilities_pointer
1.1.1.7   root      304:     return 0;
                    305: }
1.1       root      306: 
1.1.1.7   root      307: static int unin_agp_pci_host_init(PCIDevice *d)
                    308: {
1.1.1.4   root      309:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
                    310:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
1.1       root      311:     d->config[0x08] = 0x00; // revision
1.1.1.4   root      312:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
1.1       root      313:     d->config[0x0C] = 0x08; // cache_line_size
                    314:     d->config[0x0D] = 0x10; // latency_timer
                    315:     //    d->config[0x34] = 0x80; // capabilities_pointer
1.1.1.7   root      316:     return 0;
                    317: }
1.1       root      318: 
1.1.1.8 ! root      319: static int u3_agp_pci_host_init(PCIDevice *d)
        !           320: {
        !           321:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
        !           322:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_U3_AGP);
        !           323:     /* revision */
        !           324:     d->config[0x08] = 0x00;
        !           325:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
        !           326:     /* cache line size */
        !           327:     d->config[0x0C] = 0x08;
        !           328:     /* latency timer */
        !           329:     d->config[0x0D] = 0x10;
        !           330:     return 0;
        !           331: }
        !           332: 
1.1.1.7   root      333: static int unin_internal_pci_host_init(PCIDevice *d)
                    334: {
1.1.1.4   root      335:     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
                    336:     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI);
1.1       root      337:     d->config[0x08] = 0x00; // revision
1.1.1.4   root      338:     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
1.1       root      339:     d->config[0x0C] = 0x08; // cache_line_size
                    340:     d->config[0x0D] = 0x10; // latency_timer
                    341:     d->config[0x34] = 0x00; // capabilities_pointer
1.1.1.7   root      342:     return 0;
                    343: }
                    344: 
                    345: static PCIDeviceInfo unin_main_pci_host_info = {
                    346:     .qdev.name = "uni-north",
                    347:     .qdev.size = sizeof(PCIDevice),
                    348:     .init      = unin_main_pci_host_init,
                    349: };
                    350: 
1.1.1.8 ! root      351: static PCIDeviceInfo u3_agp_pci_host_info = {
        !           352:     .qdev.name = "u3-agp",
1.1.1.7   root      353:     .qdev.size = sizeof(PCIDevice),
1.1.1.8 ! root      354:     .init      = u3_agp_pci_host_init,
1.1.1.7   root      355: };
                    356: 
                    357: static PCIDeviceInfo unin_agp_pci_host_info = {
                    358:     .qdev.name = "uni-north-agp",
                    359:     .qdev.size = sizeof(PCIDevice),
                    360:     .init      = unin_agp_pci_host_init,
                    361: };
1.1.1.4   root      362: 
1.1.1.7   root      363: static PCIDeviceInfo unin_internal_pci_host_info = {
                    364:     .qdev.name = "uni-north-pci",
                    365:     .qdev.size = sizeof(PCIDevice),
                    366:     .init      = unin_internal_pci_host_init,
                    367: };
                    368: 
                    369: static void unin_register_devices(void)
                    370: {
                    371:     sysbus_register_dev("uni-north", sizeof(UNINState),
                    372:                         pci_unin_main_init_device);
                    373:     pci_qdev_register(&unin_main_pci_host_info);
1.1.1.8 ! root      374:     sysbus_register_dev("u3-agp", sizeof(UNINState),
        !           375:                         pci_u3_agp_init_device);
        !           376:     pci_qdev_register(&u3_agp_pci_host_info);
1.1.1.7   root      377:     sysbus_register_dev("uni-north-agp", sizeof(UNINState),
                    378:                         pci_unin_agp_init_device);
                    379:     pci_qdev_register(&unin_agp_pci_host_info);
                    380:     sysbus_register_dev("uni-north-pci", sizeof(UNINState),
                    381:                         pci_unin_internal_init_device);
                    382:     pci_qdev_register(&unin_internal_pci_host_info);
1.1       root      383: }
1.1.1.7   root      384: 
                    385: 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.