Annotation of qemu/hw/ppc_newworld.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU PowerPC CHRP (currently NewWorld PowerMac) hardware System Emulator
                      3:  *
                      4:  * Copyright (c) 2004-2007 Fabrice Bellard
                      5:  * Copyright (c) 2007 Jocelyn Mayer
                      6:  *
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      8:  * of this software and associated documentation files (the "Software"), to deal
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     23:  * THE SOFTWARE.
                     24:  */
                     25: #include "hw.h"
                     26: #include "ppc.h"
                     27: #include "ppc_mac.h"
                     28: #include "mac_dbdma.h"
                     29: #include "nvram.h"
                     30: #include "pc.h"
                     31: #include "pci.h"
                     32: #include "net.h"
                     33: #include "sysemu.h"
                     34: #include "boards.h"
                     35: #include "fw_cfg.h"
                     36: #include "escc.h"
                     37: #include "openpic.h"
                     38: 
                     39: #define MAX_IDE_BUS 2
                     40: #define VGA_BIOS_SIZE 65536
                     41: #define CFG_ADDR 0xf0000510
                     42: 
                     43: /* debug UniNorth */
                     44: //#define DEBUG_UNIN
                     45: 
                     46: #ifdef DEBUG_UNIN
                     47: #define UNIN_DPRINTF(fmt, args...) \
                     48: do { printf("UNIN: " fmt , ##args); } while (0)
                     49: #else
                     50: #define UNIN_DPRINTF(fmt, args...)
                     51: #endif
                     52: 
                     53: /* UniN device */
                     54: static void unin_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
                     55: {
                     56:     UNIN_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n", addr, value);
                     57: }
                     58: 
                     59: static uint32_t unin_readl (void *opaque, target_phys_addr_t addr)
                     60: {
                     61:     uint32_t value;
                     62: 
                     63:     value = 0;
                     64:     UNIN_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n", addr, value);
                     65: 
                     66:     return value;
                     67: }
                     68: 
                     69: static CPUWriteMemoryFunc *unin_write[] = {
                     70:     &unin_writel,
                     71:     &unin_writel,
                     72:     &unin_writel,
                     73: };
                     74: 
                     75: static CPUReadMemoryFunc *unin_read[] = {
                     76:     &unin_readl,
                     77:     &unin_readl,
                     78:     &unin_readl,
                     79: };
                     80: 
                     81: /* PowerPC Mac99 hardware initialisation */
                     82: static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size,
                     83:                              const char *boot_device,
                     84:                              const char *kernel_filename,
                     85:                              const char *kernel_cmdline,
                     86:                              const char *initrd_filename,
                     87:                              const char *cpu_model)
                     88: {
                     89:     CPUState *env = NULL, *envs[MAX_CPUS];
                     90:     char buf[1024];
                     91:     qemu_irq *pic, **openpic_irqs;
                     92:     int unin_memory;
                     93:     int linux_boot, i;
                     94:     ram_addr_t ram_offset, vga_ram_offset, bios_offset, vga_bios_offset;
                     95:     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
                     96:     PCIBus *pci_bus;
                     97:     MacIONVRAMState *nvr;
                     98:     int nvram_mem_index;
                     99:     int vga_bios_size, bios_size;
                    100:     qemu_irq *dummy_irq;
                    101:     int pic_mem_index, dbdma_mem_index, cuda_mem_index, escc_mem_index;
                    102:     int ppc_boot_device;
                    103:     int index;
                    104:     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
                    105:     void *fw_cfg;
                    106:     void *dbdma;
                    107: 
                    108:     linux_boot = (kernel_filename != NULL);
                    109: 
                    110:     /* init CPUs */
                    111:     if (cpu_model == NULL)
                    112:         cpu_model = "G4";
                    113:     for (i = 0; i < smp_cpus; i++) {
                    114:         env = cpu_init(cpu_model);
                    115:         if (!env) {
                    116:             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
                    117:             exit(1);
                    118:         }
                    119:         /* Set time-base frequency to 100 Mhz */
                    120:         cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
                    121: #if 0
                    122:         env->osi_call = vga_osi_call;
                    123: #endif
                    124:         qemu_register_reset(&cpu_ppc_reset, env);
                    125:         envs[i] = env;
                    126:     }
                    127: 
                    128:     /* allocate RAM */
                    129:     ram_offset = qemu_ram_alloc(ram_size);
                    130:     cpu_register_physical_memory(0, ram_size, ram_offset);
                    131: 
                    132:     /* allocate VGA RAM */
                    133:     vga_ram_offset = qemu_ram_alloc(vga_ram_size);
                    134: 
                    135:     /* allocate and load BIOS */
                    136:     bios_offset = qemu_ram_alloc(BIOS_SIZE);
                    137:     if (bios_name == NULL)
                    138:         bios_name = PROM_FILENAME;
                    139:     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
                    140:     cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE, bios_offset | IO_MEM_ROM);
                    141: 
                    142:     /* Load OpenBIOS (ELF) */
                    143:     bios_size = load_elf(buf, 0, NULL, NULL, NULL);
                    144:     if (bios_size < 0 || bios_size > BIOS_SIZE) {
                    145:         cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
                    146:         exit(1);
                    147:     }
                    148: 
                    149:     /* allocate and load VGA BIOS */
                    150:     vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE);
                    151:     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
                    152:     vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
                    153:     if (vga_bios_size < 0) {
                    154:         /* if no bios is present, we can still work */
                    155:         fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
                    156:         vga_bios_size = 0;
                    157:     } else {
                    158:         /* set a specific header (XXX: find real Apple format for NDRV
                    159:            drivers) */
                    160:         phys_ram_base[vga_bios_offset] = 'N';
                    161:         phys_ram_base[vga_bios_offset + 1] = 'D';
                    162:         phys_ram_base[vga_bios_offset + 2] = 'R';
                    163:         phys_ram_base[vga_bios_offset + 3] = 'V';
                    164:         cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
                    165:                      vga_bios_size);
                    166:         vga_bios_size += 8;
                    167:     }
                    168: 
                    169:     if (linux_boot) {
                    170:         kernel_base = KERNEL_LOAD_ADDR;
                    171:         /* now we can load the kernel */
                    172:         kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
                    173:         if (kernel_size < 0) {
                    174:             cpu_abort(env, "qemu: could not load kernel '%s'\n",
                    175:                       kernel_filename);
                    176:             exit(1);
                    177:         }
                    178:         /* load initrd */
                    179:         if (initrd_filename) {
                    180:             initrd_base = INITRD_LOAD_ADDR;
                    181:             initrd_size = load_image(initrd_filename,
                    182:                                      phys_ram_base + initrd_base);
                    183:             if (initrd_size < 0) {
                    184:                 cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
                    185:                           initrd_filename);
                    186:                 exit(1);
                    187:             }
                    188:         } else {
                    189:             initrd_base = 0;
                    190:             initrd_size = 0;
                    191:         }
                    192:         ppc_boot_device = 'm';
                    193:     } else {
                    194:         kernel_base = 0;
                    195:         kernel_size = 0;
                    196:         initrd_base = 0;
                    197:         initrd_size = 0;
                    198:         ppc_boot_device = '\0';
                    199:         /* We consider that NewWorld PowerMac never have any floppy drive
                    200:          * For now, OHW cannot boot from the network.
                    201:          */
                    202:         for (i = 0; boot_device[i] != '\0'; i++) {
                    203:             if (boot_device[i] >= 'c' && boot_device[i] <= 'f') {
                    204:                 ppc_boot_device = boot_device[i];
                    205:                 break;
                    206:             }
                    207:         }
                    208:         if (ppc_boot_device == '\0') {
                    209:             fprintf(stderr, "No valid boot device for Mac99 machine\n");
                    210:             exit(1);
                    211:         }
                    212:     }
                    213: 
                    214:     isa_mem_base = 0x80000000;
                    215: 
                    216:     /* Register 8 MB of ISA IO space */
                    217:     isa_mmio_init(0xf2000000, 0x00800000);
                    218: 
                    219:     /* UniN init */
                    220:     unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
                    221:     cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
                    222: 
                    223:     openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
                    224:     openpic_irqs[0] =
                    225:         qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
                    226:     for (i = 0; i < smp_cpus; i++) {
                    227:         /* Mac99 IRQ connection between OpenPIC outputs pins
                    228:          * and PowerPC input pins
                    229:          */
                    230:         switch (PPC_INPUT(env)) {
                    231:         case PPC_FLAGS_INPUT_6xx:
                    232:             openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
                    233:             openpic_irqs[i][OPENPIC_OUTPUT_INT] =
                    234:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
                    235:             openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
                    236:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
                    237:             openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
                    238:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
                    239:             /* Not connected ? */
                    240:             openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
                    241:             /* Check this */
                    242:             openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
                    243:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
                    244:             break;
                    245: #if defined(TARGET_PPC64)
                    246:         case PPC_FLAGS_INPUT_970:
                    247:             openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
                    248:             openpic_irqs[i][OPENPIC_OUTPUT_INT] =
                    249:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
                    250:             openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
                    251:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
                    252:             openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
                    253:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
                    254:             /* Not connected ? */
                    255:             openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
                    256:             /* Check this */
                    257:             openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
                    258:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
                    259:             break;
                    260: #endif /* defined(TARGET_PPC64) */
                    261:         default:
                    262:             cpu_abort(env, "Bus model not supported on mac99 machine\n");
                    263:             exit(1);
                    264:         }
                    265:     }
                    266:     pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
                    267:     pci_bus = pci_pmac_init(pic);
                    268:     /* init basic PC hardware */
                    269:     pci_vga_init(pci_bus, phys_ram_base + vga_ram_offset,
                    270:                  vga_ram_offset, vga_ram_size,
                    271:                  vga_bios_offset, vga_bios_size);
                    272: 
                    273:     /* XXX: suppress that */
                    274:     dummy_irq = i8259_init(NULL);
                    275: 
                    276:     escc_mem_index = escc_init(0x80013000, dummy_irq[4], dummy_irq[5],
                    277:                                serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
                    278: 
                    279:     for(i = 0; i < nb_nics; i++)
                    280:         pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");
                    281: 
                    282:     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
                    283:         fprintf(stderr, "qemu: too many IDE bus\n");
                    284:         exit(1);
                    285:     }
                    286:     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
                    287:         index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
                    288:         if (index != -1)
                    289:             hd[i] = drives_table[index].bdrv;
                    290:         else
                    291:             hd[i] = NULL;
                    292:     }
                    293:     dbdma = DBDMA_init(&dbdma_mem_index);
                    294:     pci_cmd646_ide_init(pci_bus, hd, 0);
                    295: 
                    296:     /* cuda also initialize ADB */
                    297:     cuda_init(&cuda_mem_index, pic[0x19]);
                    298: 
                    299:     adb_kbd_init(&adb_bus);
                    300:     adb_mouse_init(&adb_bus);
                    301: 
                    302: 
                    303:     macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem_index,
                    304:                dbdma_mem_index, cuda_mem_index, NULL, 0, NULL,
                    305:                escc_mem_index);
                    306: 
                    307:     if (usb_enabled) {
                    308:         usb_ohci_init_pci(pci_bus, 3, -1);
                    309:     }
                    310: 
                    311:     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
                    312:         graphic_depth = 15;
                    313: 
                    314:     /* The NewWorld NVRAM is not located in the MacIO device */
                    315:     nvr = macio_nvram_init(&nvram_mem_index, 0x2000, 1);
                    316:     pmac_format_nvram_partition(nvr, 0x2000);
                    317:     macio_nvram_map(nvr, 0xFFF04000);
                    318:     /* No PCI init: the BIOS will do it */
                    319: 
                    320:     fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
                    321:     fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
                    322:     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
                    323:     fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_MAC99);
                    324: }
                    325: 
                    326: QEMUMachine core99_machine = {
                    327:     .name = "mac99",
                    328:     .desc = "Mac99 based PowerMAC",
                    329:     .init = ppc_core99_init,
                    330:     .ram_require = BIOS_SIZE + VGA_BIOS_SIZE + VGA_RAM_SIZE,
                    331:     .max_cpus = MAX_CPUS,
                    332: };

unix.superglobalmegacorp.com