Annotation of qemu/hw/ppc_chrp.c, revision 1.1.1.6

1.1       root        1: /*
1.1.1.6 ! root        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:  *
1.1       root        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:  */
1.1.1.6 ! root       25: #include "hw.h"
        !            26: #include "ppc.h"
        !            27: #include "ppc_mac.h"
        !            28: #include "nvram.h"
        !            29: #include "pc.h"
        !            30: #include "pci.h"
        !            31: #include "net.h"
        !            32: #include "sysemu.h"
        !            33: #include "boards.h"
1.1       root       34: 
1.1.1.6 ! root       35: #define MAX_IDE_BUS 2
1.1       root       36: 
                     37: /* UniN device */
                     38: static void unin_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
                     39: {
                     40: }
                     41: 
                     42: static uint32_t unin_readl (void *opaque, target_phys_addr_t addr)
                     43: {
                     44:     return 0;
                     45: }
                     46: 
                     47: static CPUWriteMemoryFunc *unin_write[] = {
                     48:     &unin_writel,
                     49:     &unin_writel,
                     50:     &unin_writel,
                     51: };
                     52: 
                     53: static CPUReadMemoryFunc *unin_read[] = {
                     54:     &unin_readl,
                     55:     &unin_readl,
                     56:     &unin_readl,
                     57: };
                     58: 
1.1.1.6 ! root       59: /* PowerPC Mac99 hardware initialisation */
        !            60: static void ppc_core99_init (int ram_size, int vga_ram_size,
        !            61:                              const char *boot_device, DisplayState *ds,
        !            62:                              const char *kernel_filename,
        !            63:                              const char *kernel_cmdline,
        !            64:                              const char *initrd_filename,
        !            65:                              const char *cpu_model)
1.1       root       66: {
1.1.1.6 ! root       67:     CPUState *env = NULL, *envs[MAX_CPUS];
1.1       root       68:     char buf[1024];
1.1.1.6 ! root       69:     qemu_irq *pic, **openpic_irqs;
1.1.1.5   root       70:     int unin_memory;
1.1       root       71:     int linux_boot, i;
                     72:     unsigned long bios_offset, vga_bios_offset;
                     73:     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
                     74:     PCIBus *pci_bus;
1.1.1.6 ! root       75:     nvram_t nvram;
        !            76: #if 0
        !            77:     MacIONVRAMState *nvr;
        !            78:     int nvram_mem_index;
        !            79: #endif
        !            80:     m48t59_t *m48t59;
1.1       root       81:     int vga_bios_size, bios_size;
1.1.1.6 ! root       82:     qemu_irq *dummy_irq;
        !            83:     int pic_mem_index, dbdma_mem_index, cuda_mem_index;
        !            84:     int ide_mem_index[2];
        !            85:     int ppc_boot_device;
        !            86:     int index;
        !            87:     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
1.1       root       88: 
                     89:     linux_boot = (kernel_filename != NULL);
                     90: 
1.1.1.2   root       91:     /* init CPUs */
1.1.1.6 ! root       92:     if (cpu_model == NULL)
        !            93:         cpu_model = "default";
        !            94:     for (i = 0; i < smp_cpus; i++) {
        !            95:         env = cpu_init(cpu_model);
        !            96:         if (!env) {
        !            97:             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
        !            98:             exit(1);
        !            99:         }
        !           100:         /* Set time-base frequency to 100 Mhz */
        !           101:         cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
        !           102: #if 0
        !           103:         env->osi_call = vga_osi_call;
        !           104: #endif
        !           105:         qemu_register_reset(&cpu_ppc_reset, env);
        !           106:         register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
        !           107:         envs[i] = env;
        !           108:     }
        !           109:     if (env->nip < 0xFFF80000) {
        !           110:         /* Special test for PowerPC 601:
        !           111:          * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
        !           112:          * But the NVRAM is located at 0xFFF04000...
        !           113:          */
        !           114:         cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
        !           115:     }
1.1.1.2   root      116: 
1.1       root      117:     /* allocate RAM */
                    118:     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
                    119: 
                    120:     /* allocate and load BIOS */
                    121:     bios_offset = ram_size + vga_ram_size;
1.1.1.6 ! root      122:     if (bios_name == NULL)
        !           123:         bios_name = BIOS_FILENAME;
        !           124:     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
1.1       root      125:     bios_size = load_image(buf, phys_ram_base + bios_offset);
                    126:     if (bios_size < 0 || bios_size > BIOS_SIZE) {
1.1.1.6 ! root      127:         cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
1.1       root      128:         exit(1);
                    129:     }
                    130:     bios_size = (bios_size + 0xfff) & ~0xfff;
1.1.1.6 ! root      131:     if (bios_size > 0x00080000) {
        !           132:         /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */
        !           133:         cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
        !           134:     }
        !           135:     cpu_register_physical_memory((uint32_t)(-bios_size),
1.1       root      136:                                  bios_size, bios_offset | IO_MEM_ROM);
1.1.1.6 ! root      137: 
1.1       root      138:     /* allocate and load VGA BIOS */
                    139:     vga_bios_offset = bios_offset + bios_size;
                    140:     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
                    141:     vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
                    142:     if (vga_bios_size < 0) {
                    143:         /* if no bios is present, we can still work */
                    144:         fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
                    145:         vga_bios_size = 0;
                    146:     } else {
                    147:         /* set a specific header (XXX: find real Apple format for NDRV
                    148:            drivers) */
                    149:         phys_ram_base[vga_bios_offset] = 'N';
                    150:         phys_ram_base[vga_bios_offset + 1] = 'D';
                    151:         phys_ram_base[vga_bios_offset + 2] = 'R';
                    152:         phys_ram_base[vga_bios_offset + 3] = 'V';
1.1.1.6 ! root      153:         cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
1.1       root      154:                      vga_bios_size);
                    155:         vga_bios_size += 8;
                    156:     }
                    157:     vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;
1.1.1.6 ! root      158: 
1.1       root      159:     if (linux_boot) {
                    160:         kernel_base = KERNEL_LOAD_ADDR;
                    161:         /* now we can load the kernel */
                    162:         kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
                    163:         if (kernel_size < 0) {
1.1.1.6 ! root      164:             cpu_abort(env, "qemu: could not load kernel '%s'\n",
        !           165:                       kernel_filename);
1.1       root      166:             exit(1);
                    167:         }
                    168:         /* load initrd */
                    169:         if (initrd_filename) {
                    170:             initrd_base = INITRD_LOAD_ADDR;
                    171:             initrd_size = load_image(initrd_filename,
                    172:                                      phys_ram_base + initrd_base);
                    173:             if (initrd_size < 0) {
1.1.1.6 ! root      174:                 cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
        !           175:                           initrd_filename);
1.1       root      176:                 exit(1);
                    177:             }
                    178:         } else {
                    179:             initrd_base = 0;
                    180:             initrd_size = 0;
                    181:         }
1.1.1.6 ! root      182:         ppc_boot_device = 'm';
1.1       root      183:     } else {
                    184:         kernel_base = 0;
                    185:         kernel_size = 0;
                    186:         initrd_base = 0;
                    187:         initrd_size = 0;
1.1.1.6 ! root      188:         ppc_boot_device = '\0';
        !           189:         /* We consider that NewWorld PowerMac never have any floppy drive
        !           190:          * For now, OHW cannot boot from the network.
        !           191:          */
        !           192:         for (i = 0; boot_device[i] != '\0'; i++) {
        !           193:             if (boot_device[i] >= 'c' && boot_device[i] <= 'f') {
        !           194:                 ppc_boot_device = boot_device[i];
        !           195:                 break;
        !           196:             }
        !           197:         }
        !           198:         if (ppc_boot_device == '\0') {
        !           199:             fprintf(stderr, "No valid boot device for Mac99 machine\n");
        !           200:             exit(1);
        !           201:         }
1.1       root      202:     }
                    203: 
1.1.1.6 ! root      204:     isa_mem_base = 0x80000000;
1.1       root      205: 
1.1.1.6 ! root      206:     /* Register 8 MB of ISA IO space */
        !           207:     isa_mmio_init(0xf2000000, 0x00800000);
1.1       root      208: 
1.1.1.6 ! root      209:     /* UniN init */
        !           210:     unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
        !           211:     cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
        !           212: 
        !           213:     openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
        !           214:     openpic_irqs[0] =
        !           215:         qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
        !           216:     for (i = 0; i < smp_cpus; i++) {
        !           217:         /* Mac99 IRQ connection between OpenPIC outputs pins
        !           218:          * and PowerPC input pins
        !           219:          */
        !           220:         switch (PPC_INPUT(env)) {
        !           221:         case PPC_FLAGS_INPUT_6xx:
        !           222:             openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
        !           223:             openpic_irqs[i][OPENPIC_OUTPUT_INT] =
        !           224:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
        !           225:             openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
        !           226:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
        !           227:             openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
        !           228:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
        !           229:             /* Not connected ? */
        !           230:             openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
        !           231:             /* Check this */
        !           232:             openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
        !           233:                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
        !           234:             break;
        !           235: #if defined(TARGET_PPC64)
        !           236:         case PPC_FLAGS_INPUT_970:
        !           237:             openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
        !           238:             openpic_irqs[i][OPENPIC_OUTPUT_INT] =
        !           239:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
        !           240:             openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
        !           241:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
        !           242:             openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
        !           243:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
        !           244:             /* Not connected ? */
        !           245:             openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
        !           246:             /* Check this */
        !           247:             openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
        !           248:                 ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
        !           249:             break;
        !           250: #endif /* defined(TARGET_PPC64) */
        !           251:         default:
        !           252:             cpu_abort(env, "Bus model not supported on mac99 machine\n");
        !           253:             exit(1);
1.1       root      254:         }
1.1.1.6 ! root      255:     }
        !           256:     pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
        !           257:     pci_bus = pci_pmac_init(pic);
        !           258:     /* init basic PC hardware */
        !           259:     pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
        !           260:                  ram_size, vga_ram_size,
        !           261:                  vga_bios_offset, vga_bios_size);
        !           262: 
        !           263:     /* XXX: suppress that */
        !           264:     dummy_irq = i8259_init(NULL);
        !           265: 
        !           266:     /* XXX: use Mac Serial port */
        !           267:     serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
        !           268:     for(i = 0; i < nb_nics; i++) {
        !           269:         if (!nd_table[i].model)
        !           270:             nd_table[i].model = "ne2k_pci";
        !           271:         pci_nic_init(pci_bus, &nd_table[i], -1);
        !           272:     }
        !           273:     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        !           274:         fprintf(stderr, "qemu: too many IDE bus\n");
        !           275:         exit(1);
        !           276:     }
        !           277:     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
        !           278:         index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
        !           279:         if (index != -1)
        !           280:             hd[i] = drives_table[index].bdrv;
        !           281:         else
        !           282:             hd[i] = NULL;
        !           283:     }
1.1       root      284: #if 1
1.1.1.6 ! root      285:     ide_mem_index[0] = pmac_ide_init(&hd[0], pic[0x13]);
        !           286:     ide_mem_index[1] = pmac_ide_init(&hd[2], pic[0x14]);
1.1       root      287: #else
1.1.1.6 ! root      288:     pci_cmd646_ide_init(pci_bus, &hd[0], 0);
1.1       root      289: #endif
1.1.1.6 ! root      290:     /* cuda also initialize ADB */
        !           291:     cuda_init(&cuda_mem_index, pic[0x19]);
        !           292: 
        !           293:     adb_kbd_init(&adb_bus);
        !           294:     adb_mouse_init(&adb_bus);
        !           295: 
        !           296:     dbdma_init(&dbdma_mem_index);
        !           297: 
        !           298:     macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
        !           299:                cuda_mem_index, NULL, 2, ide_mem_index);
1.1.1.4   root      300: 
                    301:     if (usb_enabled) {
1.1.1.6 ! root      302:         usb_ohci_init_pci(pci_bus, 3, -1);
1.1.1.4   root      303:     }
                    304: 
1.1       root      305:     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
                    306:         graphic_depth = 15;
1.1.1.6 ! root      307: #if 0 /* XXX: this is ugly but needed for now, or OHW won't boot */
        !           308:     /* The NewWorld NVRAM is not located in the MacIO device */
        !           309:     nvr = macio_nvram_init(&nvram_mem_index, 0x2000);
        !           310:     pmac_format_nvram_partition(nvr, 0x2000);
        !           311:     macio_nvram_map(nvr, 0xFFF04000);
        !           312:     nvram.opaque = nvr;
        !           313:     nvram.read_fn = &macio_nvram_read;
        !           314:     nvram.write_fn = &macio_nvram_write;
        !           315: #else
        !           316:     m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
        !           317:     nvram.opaque = m48t59;
        !           318:     nvram.read_fn = &m48t59_read;
        !           319:     nvram.write_fn = &m48t59_write;
        !           320: #endif
        !           321:     PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "MAC99", ram_size,
        !           322:                          ppc_boot_device, kernel_base, kernel_size,
1.1       root      323:                          kernel_cmdline,
                    324:                          initrd_base, initrd_size,
                    325:                          /* XXX: need an option to load a NVRAM image */
                    326:                          0,
                    327:                          graphic_width, graphic_height, graphic_depth);
                    328:     /* No PCI init: the BIOS will do it */
                    329: 
                    330:     /* Special port to get debug messages from Open-Firmware */
                    331:     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
                    332: }
                    333: 
                    334: QEMUMachine core99_machine = {
                    335:     "mac99",
                    336:     "Mac99 based PowerMAC",
                    337:     ppc_core99_init,
                    338: };

unix.superglobalmegacorp.com

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