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

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_reset(void *opaque)
1.1       root       67: {
1.1.1.2   root       68: }
                     69: 
1.1.1.8   root       70: static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
                     71: {
                     72:     uint32_t retval;
                     73: 
                     74:     if (reg & (1u << 31)) {
                     75:         /* XXX OpenBIOS compatibility hack */
                     76:         retval = reg | (addr & 3);
                     77:     } else if (reg & 1) {
                     78:         /* CFA1 style */
                     79:         retval = (reg & ~7u) | (addr & 7);
                     80:     } else {
                     81:         uint32_t slot, func;
                     82: 
                     83:         /* Grab CFA0 style values */
                     84:         slot = ffs(reg & 0xfffff800) - 1;
                     85:         func = (reg >> 8) & 7;
                     86: 
                     87:         /* ... and then convert them to x86 format */
                     88:         /* config pointer */
                     89:         retval = (reg & (0xff - 7)) | (addr & 7);
                     90:         /* slot */
                     91:         retval |= slot << 11;
                     92:         /* fn */
                     93:         retval |= func << 8;
                     94:     }
                     95: 
                     96: 
                     97:     UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n",
                     98:                  reg, addr, retval);
                     99: 
                    100:     return retval;
                    101: }
                    102: 
                    103: static void unin_data_write(ReadWriteHandler *handler,
                    104:                             pcibus_t addr, uint32_t val, int len)
                    105: {
                    106:     UNINState *s = container_of(handler, UNINState, data_handler);
                    107:     UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
                    108:     pci_data_write(s->host_state.bus,
                    109:                    unin_get_config_reg(s->host_state.config_reg, addr),
                    110:                    val, len);
                    111: }
                    112: 
                    113: static uint32_t unin_data_read(ReadWriteHandler *handler,
                    114:                                pcibus_t addr, int len)
                    115: {
                    116:     UNINState *s = container_of(handler, UNINState, data_handler);
                    117:     uint32_t val;
                    118: 
                    119:     val = pci_data_read(s->host_state.bus,
                    120:                         unin_get_config_reg(s->host_state.config_reg, addr),
                    121:                         len);
                    122:     UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
                    123:     return val;
                    124: }
                    125: 
1.1.1.7   root      126: static int pci_unin_main_init_device(SysBusDevice *dev)
1.1.1.2   root      127: {
1.1.1.7   root      128:     UNINState *s;
                    129:     int pci_mem_config, pci_mem_data;
                    130: 
                    131:     /* Use values found on a real PowerMac */
                    132:     /* Uninorth main bus */
                    133:     s = FROM_SYSBUS(UNINState, dev);
                    134: 
1.1.1.9   root      135:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
                    136:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.8   root      137:     s->data_handler.read = unin_data_read;
                    138:     s->data_handler.write = unin_data_write;
1.1.1.9   root      139:     pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
                    140:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.7   root      141:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    142:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
                    143: 
                    144:     qemu_register_reset(pci_unin_reset, &s->host_state);
                    145:     return 0;
1.1       root      146: }
                    147: 
1.1.1.8   root      148: static int pci_u3_agp_init_device(SysBusDevice *dev)
1.1.1.4   root      149: {
1.1.1.7   root      150:     UNINState *s;
                    151:     int pci_mem_config, pci_mem_data;
1.1.1.4   root      152: 
1.1.1.8   root      153:     /* Uninorth U3 AGP bus */
1.1.1.7   root      154:     s = FROM_SYSBUS(UNINState, dev);
                    155: 
1.1.1.9   root      156:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
                    157:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.8   root      158:     s->data_handler.read = unin_data_read;
                    159:     s->data_handler.write = unin_data_write;
1.1.1.9   root      160:     pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
                    161:                                                  DEVICE_LITTLE_ENDIAN);
1.1.1.7   root      162:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    163:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
1.1.1.8   root      164: 
                    165:     qemu_register_reset(pci_unin_reset, &s->host_state);
                    166: 
1.1.1.7   root      167:     return 0;
1.1.1.4   root      168: }
                    169: 
1.1.1.7   root      170: static int pci_unin_agp_init_device(SysBusDevice *dev)
1.1.1.4   root      171: {
1.1.1.7   root      172:     UNINState *s;
                    173:     int pci_mem_config, pci_mem_data;
1.1.1.4   root      174: 
1.1.1.7   root      175:     /* Uninorth AGP bus */
                    176:     s = FROM_SYSBUS(UNINState, dev);
1.1.1.4   root      177: 
1.1.1.9   root      178:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
                    179:                                                  DEVICE_LITTLE_ENDIAN);
                    180:     pci_mem_data = pci_host_data_register_mmio(&s->host_state,
                    181:                                                DEVICE_LITTLE_ENDIAN);
1.1.1.7   root      182:     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
                    183:     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
                    184:     return 0;
1.1.1.4   root      185: }
                    186: 
1.1.1.7   root      187: static int pci_unin_internal_init_device(SysBusDevice *dev)
1.1.1.4   root      188: {
1.1.1.7   root      189:     UNINState *s;
                    190:     int pci_mem_config, pci_mem_data;
                    191: 
                    192:     /* Uninorth internal bus */
                    193:     s = FROM_SYSBUS(UNINState, dev);
                    194: 
1.1.1.9   root      195:     pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
                    196:                                                  DEVICE_LITTLE_ENDIAN);
                    197:     pci_mem_data = pci_host_data_register_mmio(&s->host_state,
                    198:                                                DEVICE_LITTLE_ENDIAN);
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.3   root      204: PCIBus *pci_pmac_init(qemu_irq *pic)
1.1       root      205: {
1.1.1.7   root      206:     DeviceState *dev;
                    207:     SysBusDevice *s;
                    208:     UNINState *d;
1.1       root      209: 
                    210:     /* Use values found on a real PowerMac */
                    211:     /* Uninorth main bus */
1.1.1.7   root      212:     dev = qdev_create(NULL, "uni-north");
                    213:     qdev_init_nofail(dev);
                    214:     s = sysbus_from_qdev(dev);
                    215:     d = FROM_SYSBUS(UNINState, s);
                    216:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                    217:                                          pci_unin_set_irq, pci_unin_map_irq,
1.1.1.8   root      218:                                          pic, PCI_DEVFN(11, 0), 4);
1.1.1.7   root      219: 
                    220: #if 0
1.1.1.8   root      221:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
1.1.1.7   root      222: #endif
                    223: 
                    224:     sysbus_mmio_map(s, 0, 0xf2800000);
                    225:     sysbus_mmio_map(s, 1, 0xf2c00000);
                    226: 
                    227:     /* DEC 21154 bridge */
                    228: #if 0
                    229:     /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
1.1.1.8   root      230:     pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154");
1.1.1.7   root      231: #endif
                    232: 
                    233:     /* Uninorth AGP bus */
1.1.1.8   root      234:     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp");
1.1.1.7   root      235:     dev = qdev_create(NULL, "uni-north-agp");
                    236:     qdev_init_nofail(dev);
                    237:     s = sysbus_from_qdev(dev);
                    238:     sysbus_mmio_map(s, 0, 0xf0800000);
                    239:     sysbus_mmio_map(s, 1, 0xf0c00000);
                    240: 
                    241:     /* Uninorth internal bus */
                    242: #if 0
                    243:     /* XXX: not needed for now */
1.1.1.8   root      244:     pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0), "uni-north-pci");
1.1.1.7   root      245:     dev = qdev_create(NULL, "uni-north-pci");
                    246:     qdev_init_nofail(dev);
                    247:     s = sysbus_from_qdev(dev);
                    248:     sysbus_mmio_map(s, 0, 0xf4800000);
                    249:     sysbus_mmio_map(s, 1, 0xf4c00000);
                    250: #endif
                    251: 
                    252:     return d->host_state.bus;
                    253: }
                    254: 
1.1.1.8   root      255: PCIBus *pci_pmac_u3_init(qemu_irq *pic)
                    256: {
                    257:     DeviceState *dev;
                    258:     SysBusDevice *s;
                    259:     UNINState *d;
                    260: 
                    261:     /* Uninorth AGP bus */
                    262: 
                    263:     dev = qdev_create(NULL, "u3-agp");
                    264:     qdev_init_nofail(dev);
                    265:     s = sysbus_from_qdev(dev);
                    266:     d = FROM_SYSBUS(UNINState, s);
                    267: 
                    268:     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                    269:                                          pci_unin_set_irq, pci_unin_map_irq,
                    270:                                          pic, PCI_DEVFN(11, 0), 4);
                    271: 
                    272:     sysbus_mmio_map(s, 0, 0xf0800000);
                    273:     sysbus_mmio_map(s, 1, 0xf0c00000);
                    274: 
                    275:     pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp");
                    276: 
                    277:     return d->host_state.bus;
                    278: }
                    279: 
1.1.1.7   root      280: static int unin_main_pci_host_init(PCIDevice *d)
                    281: {
1.1       root      282:     d->config[0x0C] = 0x08; // cache_line_size
                    283:     d->config[0x0D] = 0x10; // latency_timer
                    284:     d->config[0x34] = 0x00; // capabilities_pointer
1.1.1.7   root      285:     return 0;
                    286: }
1.1       root      287: 
1.1.1.7   root      288: static int unin_agp_pci_host_init(PCIDevice *d)
                    289: {
1.1       root      290:     d->config[0x0C] = 0x08; // cache_line_size
                    291:     d->config[0x0D] = 0x10; // latency_timer
                    292:     //    d->config[0x34] = 0x80; // capabilities_pointer
1.1.1.7   root      293:     return 0;
                    294: }
1.1       root      295: 
1.1.1.8   root      296: static int u3_agp_pci_host_init(PCIDevice *d)
                    297: {
                    298:     /* cache line size */
                    299:     d->config[0x0C] = 0x08;
                    300:     /* latency timer */
                    301:     d->config[0x0D] = 0x10;
                    302:     return 0;
                    303: }
                    304: 
1.1.1.7   root      305: static int unin_internal_pci_host_init(PCIDevice *d)
                    306: {
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: }
                    312: 
                    313: static PCIDeviceInfo unin_main_pci_host_info = {
                    314:     .qdev.name = "uni-north",
                    315:     .qdev.size = sizeof(PCIDevice),
                    316:     .init      = unin_main_pci_host_init,
1.1.1.10! root      317:     .vendor_id = PCI_VENDOR_ID_APPLE,
        !           318:     .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
        !           319:     .revision  = 0x00,
        !           320:     .class_id  = PCI_CLASS_BRIDGE_HOST,
1.1.1.7   root      321: };
                    322: 
1.1.1.8   root      323: static PCIDeviceInfo u3_agp_pci_host_info = {
                    324:     .qdev.name = "u3-agp",
1.1.1.7   root      325:     .qdev.size = sizeof(PCIDevice),
1.1.1.8   root      326:     .init      = u3_agp_pci_host_init,
1.1.1.10! root      327:     .vendor_id = PCI_VENDOR_ID_APPLE,
        !           328:     .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
        !           329:     .revision  = 0x00,
        !           330:     .class_id  = PCI_CLASS_BRIDGE_HOST,
1.1.1.7   root      331: };
                    332: 
                    333: static PCIDeviceInfo unin_agp_pci_host_info = {
                    334:     .qdev.name = "uni-north-agp",
                    335:     .qdev.size = sizeof(PCIDevice),
                    336:     .init      = unin_agp_pci_host_init,
1.1.1.10! root      337:     .vendor_id = PCI_VENDOR_ID_APPLE,
        !           338:     .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
        !           339:     .revision  = 0x00,
        !           340:     .class_id  = PCI_CLASS_BRIDGE_HOST,
1.1.1.7   root      341: };
1.1.1.4   root      342: 
1.1.1.7   root      343: static PCIDeviceInfo unin_internal_pci_host_info = {
                    344:     .qdev.name = "uni-north-pci",
                    345:     .qdev.size = sizeof(PCIDevice),
                    346:     .init      = unin_internal_pci_host_init,
1.1.1.10! root      347:     .vendor_id = PCI_VENDOR_ID_APPLE,
        !           348:     .device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI,
        !           349:     .revision  = 0x00,
        !           350:     .class_id  = PCI_CLASS_BRIDGE_HOST,
1.1.1.7   root      351: };
                    352: 
                    353: static void unin_register_devices(void)
                    354: {
                    355:     sysbus_register_dev("uni-north", sizeof(UNINState),
                    356:                         pci_unin_main_init_device);
                    357:     pci_qdev_register(&unin_main_pci_host_info);
1.1.1.8   root      358:     sysbus_register_dev("u3-agp", sizeof(UNINState),
                    359:                         pci_u3_agp_init_device);
                    360:     pci_qdev_register(&u3_agp_pci_host_info);
1.1.1.7   root      361:     sysbus_register_dev("uni-north-agp", sizeof(UNINState),
                    362:                         pci_unin_agp_init_device);
                    363:     pci_qdev_register(&unin_agp_pci_host_info);
                    364:     sysbus_register_dev("uni-north-pci", sizeof(UNINState),
                    365:                         pci_unin_internal_init_device);
                    366:     pci_qdev_register(&unin_internal_pci_host_info);
1.1       root      367: }
1.1.1.7   root      368: 
                    369: 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.