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

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.11! root       44:     MemoryRegion pci_mmio;
        !            45:     MemoryRegion pci_hole;
1.1.1.7   root       46: } UNINState;
1.1       root       47: 
1.1.1.7   root       48: static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
1.1       root       49: {
1.1.1.8   root       50:     int retval;
                     51:     int devfn = pci_dev->devfn & 0x00FFFFFF;
                     52: 
                     53:     retval = (((devfn >> 11) & 0x1F) + irq_num) & 3;
                     54: 
                     55:     return retval;
1.1       root       56: }
                     57: 
1.1.1.7   root       58: static void pci_unin_set_irq(void *opaque, int irq_num, int level)
1.1       root       59: {
1.1.1.7   root       60:     qemu_irq *pic = opaque;
1.1       root       61: 
1.1.1.8   root       62:     UNIN_DPRINTF("%s: setting INT %d = %d\n", __func__,
                     63:                  unin_irq_line[irq_num], level);
                     64:     qemu_set_irq(pic[unin_irq_line[irq_num]], level);
1.1       root       65: }
                     66: 
1.1.1.7   root       67: static void pci_unin_reset(void *opaque)
1.1       root       68: {
1.1.1.2   root       69: }
                     70: 
1.1.1.8   root       71: static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
                     72: {
                     73:     uint32_t retval;
                     74: 
                     75:     if (reg & (1u << 31)) {
                     76:         /* XXX OpenBIOS compatibility hack */
                     77:         retval = reg | (addr & 3);
                     78:     } else if (reg & 1) {
                     79:         /* CFA1 style */
                     80:         retval = (reg & ~7u) | (addr & 7);
                     81:     } else {
                     82:         uint32_t slot, func;
                     83: 
                     84:         /* Grab CFA0 style values */
                     85:         slot = ffs(reg & 0xfffff800) - 1;
                     86:         func = (reg >> 8) & 7;
                     87: 
                     88:         /* ... and then convert them to x86 format */
                     89:         /* config pointer */
                     90:         retval = (reg & (0xff - 7)) | (addr & 7);
                     91:         /* slot */
                     92:         retval |= slot << 11;
                     93:         /* fn */
                     94:         retval |= func << 8;
                     95:     }
                     96: 
                     97: 
                     98:     UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n",
                     99:                  reg, addr, retval);
                    100: 
                    101:     return retval;
                    102: }
                    103: 
1.1.1.11! root      104: static void unin_data_write(void *opaque, target_phys_addr_t addr,
        !           105:                             uint64_t val, unsigned len)
1.1.1.8   root      106: {
1.1.1.11! root      107:     UNINState *s = opaque;
        !           108:     UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
        !           109:                  addr, len, val);
1.1.1.8   root      110:     pci_data_write(s->host_state.bus,
                    111:                    unin_get_config_reg(s->host_state.config_reg, addr),
                    112:                    val, len);
                    113: }
                    114: 
1.1.1.11! root      115: static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr,
        !           116:                                unsigned len)
1.1.1.8   root      117: {
1.1.1.11! root      118:     UNINState *s = opaque;
1.1.1.8   root      119:     uint32_t val;
                    120: 
                    121:     val = pci_data_read(s->host_state.bus,
                    122:                         unin_get_config_reg(s->host_state.config_reg, addr),
                    123:                         len);
1.1.1.11! root      124:     UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
        !           125:                  addr, len, val);
1.1.1.8   root      126:     return val;
                    127: }
                    128: 
1.1.1.11! root      129: static const MemoryRegionOps unin_data_ops = {
        !           130:     .read = unin_data_read,
        !           131:     .write = unin_data_write,
        !           132:     .endianness = DEVICE_LITTLE_ENDIAN,
        !           133: };
        !           134: 
1.1.1.7   root      135: static int pci_unin_main_init_device(SysBusDevice *dev)
1.1.1.2   root      136: {
1.1.1.7   root      137:     UNINState *s;
                    138: 
                    139:     /* Use values found on a real PowerMac */
                    140:     /* Uninorth main bus */
                    141:     s = FROM_SYSBUS(UNINState, dev);
                    142: 
1.1.1.11! root      143:     memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
        !           144:                           &s->host_state, "pci-conf-idx", 0x1000);
        !           145:     memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
        !           146:                           "pci-conf-data", 0x1000);
        !           147:     sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
        !           148:     sysbus_init_mmio_region(dev, &s->host_state.data_mem);
1.1.1.7   root      149: 
                    150:     qemu_register_reset(pci_unin_reset, &s->host_state);
                    151:     return 0;
1.1       root      152: }
                    153: 
1.1.1.11! root      154: 
1.1.1.8   root      155: static int pci_u3_agp_init_device(SysBusDevice *dev)
1.1.1.4   root      156: {
1.1.1.7   root      157:     UNINState *s;
1.1.1.4   root      158: 
1.1.1.8   root      159:     /* Uninorth U3 AGP bus */
1.1.1.7   root      160:     s = FROM_SYSBUS(UNINState, dev);
                    161: 
1.1.1.11! root      162:     memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
        !           163:                           &s->host_state, "pci-conf-idx", 0x1000);
        !           164:     memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
        !           165:                           "pci-conf-data", 0x1000);
        !           166:     sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
        !           167:     sysbus_init_mmio_region(dev, &s->host_state.data_mem);
1.1.1.8   root      168: 
                    169:     qemu_register_reset(pci_unin_reset, &s->host_state);
                    170: 
1.1.1.7   root      171:     return 0;
1.1.1.4   root      172: }
                    173: 
1.1.1.7   root      174: static int pci_unin_agp_init_device(SysBusDevice *dev)
1.1.1.4   root      175: {
1.1.1.7   root      176:     UNINState *s;
1.1.1.4   root      177: 
1.1.1.7   root      178:     /* Uninorth AGP bus */
                    179:     s = FROM_SYSBUS(UNINState, dev);
1.1.1.4   root      180: 
1.1.1.11! root      181:     memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
        !           182:                           &s->host_state, "pci-conf-idx", 0x1000);
        !           183:     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
        !           184:                           &s->host_state, "pci-conf-data", 0x1000);
        !           185:     sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
        !           186:     sysbus_init_mmio_region(dev, &s->host_state.data_mem);
1.1.1.7   root      187:     return 0;
1.1.1.4   root      188: }
                    189: 
1.1.1.7   root      190: static int pci_unin_internal_init_device(SysBusDevice *dev)
1.1.1.4   root      191: {
1.1.1.7   root      192:     UNINState *s;
                    193: 
                    194:     /* Uninorth internal bus */
                    195:     s = FROM_SYSBUS(UNINState, dev);
                    196: 
1.1.1.11! root      197:     memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
        !           198:                           &s->host_state, "pci-conf-idx", 0x1000);
        !           199:     memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
        !           200:                           &s->host_state, "pci-conf-data", 0x1000);
        !           201:     sysbus_init_mmio_region(dev, &s->host_state.conf_mem);
        !           202:     sysbus_init_mmio_region(dev, &s->host_state.data_mem);
1.1.1.7   root      203:     return 0;
1.1.1.4   root      204: }
                    205: 
1.1.1.11! root      206: PCIBus *pci_pmac_init(qemu_irq *pic,
        !           207:                       MemoryRegion *address_space_mem,
        !           208:                       MemoryRegion *address_space_io)
1.1       root      209: {
1.1.1.7   root      210:     DeviceState *dev;
                    211:     SysBusDevice *s;
                    212:     UNINState *d;
1.1       root      213: 
                    214:     /* Use values found on a real PowerMac */
                    215:     /* Uninorth main bus */
1.1.1.7   root      216:     dev = qdev_create(NULL, "uni-north");
                    217:     qdev_init_nofail(dev);
                    218:     s = sysbus_from_qdev(dev);
                    219:     d = FROM_SYSBUS(UNINState, s);
1.1.1.11! root      220:     memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
        !           221:     memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
        !           222:                              0x80000000ULL, 0x70000000ULL);
        !           223:     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
        !           224:                                 &d->pci_hole);
        !           225: 
1.1.1.7   root      226:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                    227:                                          pci_unin_set_irq, pci_unin_map_irq,
1.1.1.11! root      228:                                          pic,
        !           229:                                          &d->pci_mmio,
        !           230:                                          address_space_io,
        !           231:                                          PCI_DEVFN(11, 0), 4);
1.1.1.7   root      232: 
                    233: #if 0
1.1.1.8   root      234:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
1.1.1.7   root      235: #endif
                    236: 
                    237:     sysbus_mmio_map(s, 0, 0xf2800000);
                    238:     sysbus_mmio_map(s, 1, 0xf2c00000);
                    239: 
                    240:     /* DEC 21154 bridge */
                    241: #if 0
                    242:     /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
1.1.1.8   root      243:     pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154");
1.1.1.7   root      244: #endif
                    245: 
                    246:     /* Uninorth AGP bus */
1.1.1.8   root      247:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp");
1.1.1.7   root      248:     dev = qdev_create(NULL, "uni-north-agp");
                    249:     qdev_init_nofail(dev);
                    250:     s = sysbus_from_qdev(dev);
                    251:     sysbus_mmio_map(s, 0, 0xf0800000);
                    252:     sysbus_mmio_map(s, 1, 0xf0c00000);
                    253: 
                    254:     /* Uninorth internal bus */
                    255: #if 0
                    256:     /* XXX: not needed for now */
1.1.1.8   root      257:     pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0), "uni-north-pci");
1.1.1.7   root      258:     dev = qdev_create(NULL, "uni-north-pci");
                    259:     qdev_init_nofail(dev);
                    260:     s = sysbus_from_qdev(dev);
                    261:     sysbus_mmio_map(s, 0, 0xf4800000);
                    262:     sysbus_mmio_map(s, 1, 0xf4c00000);
                    263: #endif
                    264: 
                    265:     return d->host_state.bus;
                    266: }
                    267: 
1.1.1.11! root      268: PCIBus *pci_pmac_u3_init(qemu_irq *pic,
        !           269:                          MemoryRegion *address_space_mem,
        !           270:                          MemoryRegion *address_space_io)
1.1.1.8   root      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: 
1.1.1.11! root      283:     memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
        !           284:     memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
        !           285:                              0x80000000ULL, 0x70000000ULL);
        !           286:     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
        !           287:                                 &d->pci_hole);
        !           288: 
1.1.1.8   root      289:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                    290:                                          pci_unin_set_irq, pci_unin_map_irq,
1.1.1.11! root      291:                                          pic,
        !           292:                                          &d->pci_mmio,
        !           293:                                          address_space_io,
        !           294:                                          PCI_DEVFN(11, 0), 4);
1.1.1.8   root      295: 
                    296:     sysbus_mmio_map(s, 0, 0xf0800000);
                    297:     sysbus_mmio_map(s, 1, 0xf0c00000);
                    298: 
                    299:     pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp");
                    300: 
                    301:     return d->host_state.bus;
                    302: }
                    303: 
1.1.1.7   root      304: static int unin_main_pci_host_init(PCIDevice *d)
                    305: {
1.1       root      306:     d->config[0x0C] = 0x08; // cache_line_size
                    307:     d->config[0x0D] = 0x10; // latency_timer
                    308:     d->config[0x34] = 0x00; // capabilities_pointer
1.1.1.7   root      309:     return 0;
                    310: }
1.1       root      311: 
1.1.1.7   root      312: static int unin_agp_pci_host_init(PCIDevice *d)
                    313: {
1.1       root      314:     d->config[0x0C] = 0x08; // cache_line_size
                    315:     d->config[0x0D] = 0x10; // latency_timer
                    316:     //    d->config[0x34] = 0x80; // capabilities_pointer
1.1.1.7   root      317:     return 0;
                    318: }
1.1       root      319: 
1.1.1.8   root      320: static int u3_agp_pci_host_init(PCIDevice *d)
                    321: {
                    322:     /* cache line size */
                    323:     d->config[0x0C] = 0x08;
                    324:     /* latency timer */
                    325:     d->config[0x0D] = 0x10;
                    326:     return 0;
                    327: }
                    328: 
1.1.1.7   root      329: static int unin_internal_pci_host_init(PCIDevice *d)
                    330: {
1.1       root      331:     d->config[0x0C] = 0x08; // cache_line_size
                    332:     d->config[0x0D] = 0x10; // latency_timer
                    333:     d->config[0x34] = 0x00; // capabilities_pointer
1.1.1.7   root      334:     return 0;
                    335: }
                    336: 
                    337: static PCIDeviceInfo unin_main_pci_host_info = {
                    338:     .qdev.name = "uni-north",
                    339:     .qdev.size = sizeof(PCIDevice),
                    340:     .init      = unin_main_pci_host_init,
1.1.1.10  root      341:     .vendor_id = PCI_VENDOR_ID_APPLE,
                    342:     .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
                    343:     .revision  = 0x00,
                    344:     .class_id  = PCI_CLASS_BRIDGE_HOST,
1.1.1.7   root      345: };
                    346: 
1.1.1.8   root      347: static PCIDeviceInfo u3_agp_pci_host_info = {
                    348:     .qdev.name = "u3-agp",
1.1.1.7   root      349:     .qdev.size = sizeof(PCIDevice),
1.1.1.8   root      350:     .init      = u3_agp_pci_host_init,
1.1.1.10  root      351:     .vendor_id = PCI_VENDOR_ID_APPLE,
                    352:     .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
                    353:     .revision  = 0x00,
                    354:     .class_id  = PCI_CLASS_BRIDGE_HOST,
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,
1.1.1.10  root      361:     .vendor_id = PCI_VENDOR_ID_APPLE,
                    362:     .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
                    363:     .revision  = 0x00,
                    364:     .class_id  = PCI_CLASS_BRIDGE_HOST,
1.1.1.7   root      365: };
1.1.1.4   root      366: 
1.1.1.7   root      367: static PCIDeviceInfo unin_internal_pci_host_info = {
                    368:     .qdev.name = "uni-north-pci",
                    369:     .qdev.size = sizeof(PCIDevice),
                    370:     .init      = unin_internal_pci_host_init,
1.1.1.10  root      371:     .vendor_id = PCI_VENDOR_ID_APPLE,
                    372:     .device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI,
                    373:     .revision  = 0x00,
                    374:     .class_id  = PCI_CLASS_BRIDGE_HOST,
1.1.1.7   root      375: };
                    376: 
                    377: static void unin_register_devices(void)
                    378: {
                    379:     sysbus_register_dev("uni-north", sizeof(UNINState),
                    380:                         pci_unin_main_init_device);
                    381:     pci_qdev_register(&unin_main_pci_host_info);
1.1.1.8   root      382:     sysbus_register_dev("u3-agp", sizeof(UNINState),
                    383:                         pci_u3_agp_init_device);
                    384:     pci_qdev_register(&u3_agp_pci_host_info);
1.1.1.7   root      385:     sysbus_register_dev("uni-north-agp", sizeof(UNINState),
                    386:                         pci_unin_agp_init_device);
                    387:     pci_qdev_register(&unin_agp_pci_host_info);
                    388:     sysbus_register_dev("uni-north-pci", sizeof(UNINState),
                    389:                         pci_unin_internal_init_device);
                    390:     pci_qdev_register(&unin_internal_pci_host_info);
1.1       root      391: }
1.1.1.7   root      392: 
                    393: 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.