Annotation of qemu/hw/mips_r4k.c, revision 1.1.1.14

1.1.1.5   root        1: /*
                      2:  * QEMU/MIPS pseudo-board
                      3:  *
                      4:  * emulates a simple machine with ISA-like bus.
                      5:  * ISA IO space mapped to the 0x14000000 (PHYS) and
                      6:  * ISA memory at the 0x10000000 (PHYS, 16Mb in size).
                      7:  * All peripherial devices are attached to this "bus" with
                      8:  * the standard PC ISA addresses.
                      9: */
1.1.1.6   root       10: #include "hw.h"
                     11: #include "mips.h"
1.1.1.10  root       12: #include "mips_cpudevs.h"
1.1.1.6   root       13: #include "pc.h"
                     14: #include "isa.h"
                     15: #include "net.h"
                     16: #include "sysemu.h"
                     17: #include "boards.h"
1.1.1.7   root       18: #include "flash.h"
                     19: #include "qemu-log.h"
1.1.1.8   root       20: #include "mips-bios.h"
1.1.1.9   root       21: #include "ide.h"
                     22: #include "loader.h"
                     23: #include "elf.h"
1.1.1.10  root       24: #include "mc146818rtc.h"
1.1.1.14! root       25: #include "i8254.h"
1.1.1.11  root       26: #include "blockdev.h"
1.1.1.13  root       27: #include "exec-memory.h"
1.1       root       28: 
1.1.1.6   root       29: #define MAX_IDE_BUS 2
                     30: 
1.1.1.5   root       31: static const int ide_iobase[2] = { 0x1f0, 0x170 };
                     32: static const int ide_iobase2[2] = { 0x3f6, 0x376 };
                     33: static const int ide_irq[2] = { 14, 15 };
1.1       root       34: 
1.1.1.12  root       35: static ISADevice *pit; /* PIT i8254 */
1.1       root       36: 
1.1.1.6   root       37: /* i8254 PIT is attached to the IRQ0 at PIC i8259 */
                     38: 
                     39: static struct _loaderparams {
                     40:     int ram_size;
                     41:     const char *kernel_filename;
                     42:     const char *kernel_cmdline;
                     43:     const char *initrd_filename;
                     44: } loaderparams;
1.1       root       45: 
1.1.1.13  root       46: static void mips_qemu_write (void *opaque, target_phys_addr_t addr,
                     47:                              uint64_t val, unsigned size)
1.1       root       48: {
1.1.1.5   root       49:     if ((addr & 0xffff) == 0 && val == 42)
                     50:         qemu_system_reset_request ();
                     51:     else if ((addr & 0xffff) == 4 && val == 42)
                     52:         qemu_system_shutdown_request ();
1.1       root       53: }
                     54: 
1.1.1.13  root       55: static uint64_t mips_qemu_read (void *opaque, target_phys_addr_t addr,
                     56:                                 unsigned size)
1.1       root       57: {
1.1.1.5   root       58:     return 0;
1.1       root       59: }
                     60: 
1.1.1.13  root       61: static const MemoryRegionOps mips_qemu_ops = {
                     62:     .read = mips_qemu_read,
                     63:     .write = mips_qemu_write,
                     64:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1.1.5   root       65: };
1.1       root       66: 
1.1.1.9   root       67: typedef struct ResetData {
1.1.1.14! root       68:     CPUMIPSState *env;
1.1.1.9   root       69:     uint64_t vector;
                     70: } ResetData;
                     71: 
                     72: static int64_t load_kernel(void)
1.1       root       73: {
1.1.1.10  root       74:     int64_t entry, kernel_high;
1.1.1.9   root       75:     long kernel_size, initrd_size, params_size;
1.1.1.6   root       76:     ram_addr_t initrd_offset;
1.1.1.9   root       77:     uint32_t *params_buf;
                     78:     int big_endian;
1.1       root       79: 
1.1.1.9   root       80: #ifdef TARGET_WORDS_BIGENDIAN
                     81:     big_endian = 1;
                     82: #else
                     83:     big_endian = 0;
                     84: #endif
1.1.1.10  root       85:     kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
                     86:                            NULL, (uint64_t *)&entry, NULL,
                     87:                            (uint64_t *)&kernel_high, big_endian,
                     88:                            ELF_MACHINE, 1);
1.1.1.5   root       89:     if (kernel_size >= 0) {
                     90:         if ((entry & ~0x7fffffffULL) == 0x80000000)
                     91:             entry = (int32_t)entry;
                     92:     } else {
                     93:         fprintf(stderr, "qemu: could not load kernel '%s'\n",
1.1.1.6   root       94:                 loaderparams.kernel_filename);
1.1.1.5   root       95:         exit(1);
                     96:     }
1.1       root       97: 
1.1.1.5   root       98:     /* load initrd */
                     99:     initrd_size = 0;
1.1.1.6   root      100:     initrd_offset = 0;
                    101:     if (loaderparams.initrd_filename) {
                    102:         initrd_size = get_image_size (loaderparams.initrd_filename);
                    103:         if (initrd_size > 0) {
                    104:             initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
                    105:             if (initrd_offset + initrd_size > ram_size) {
                    106:                 fprintf(stderr,
                    107:                         "qemu: memory too small for initial ram disk '%s'\n",
                    108:                         loaderparams.initrd_filename);
                    109:                 exit(1);
                    110:             }
1.1.1.8   root      111:             initrd_size = load_image_targphys(loaderparams.initrd_filename,
                    112:                                               initrd_offset,
                    113:                                               ram_size - initrd_offset);
1.1.1.6   root      114:         }
1.1.1.5   root      115:         if (initrd_size == (target_ulong) -1) {
                    116:             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
1.1.1.6   root      117:                     loaderparams.initrd_filename);
1.1.1.5   root      118:             exit(1);
                    119:         }
                    120:     }
1.1       root      121: 
1.1.1.5   root      122:     /* Store command line.  */
1.1.1.9   root      123:     params_size = 264;
1.1.1.13  root      124:     params_buf = g_malloc(params_size);
1.1.1.9   root      125: 
                    126:     params_buf[0] = tswap32(ram_size);
                    127:     params_buf[1] = tswap32(0x12345678);
                    128: 
1.1.1.5   root      129:     if (initrd_size > 0) {
1.1.1.10  root      130:         snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
                    131:                  cpu_mips_phys_to_kseg0(NULL, initrd_offset),
1.1.1.9   root      132:                  initrd_size, loaderparams.kernel_cmdline);
1.1.1.8   root      133:     } else {
1.1.1.9   root      134:         snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
1.1.1.5   root      135:     }
1.1       root      136: 
1.1.1.9   root      137:     rom_add_blob_fixed("params", params_buf, params_size,
                    138:                        (16 << 20) - 264);
                    139: 
                    140:     return entry;
1.1       root      141: }
                    142: 
1.1.1.5   root      143: static void main_cpu_reset(void *opaque)
1.1       root      144: {
1.1.1.9   root      145:     ResetData *s = (ResetData *)opaque;
1.1.1.14! root      146:     CPUMIPSState *env = s->env;
1.1       root      147: 
1.1.1.14! root      148:     cpu_state_reset(env);
1.1.1.9   root      149:     env->active_tc.PC = s->vector;
1.1       root      150: }
                    151: 
1.1.1.7   root      152: static const int sector_len = 32 * 1024;
1.1.1.6   root      153: static
1.1.1.8   root      154: void mips_r4k_init (ram_addr_t ram_size,
1.1.1.7   root      155:                     const char *boot_device,
1.1       root      156:                     const char *kernel_filename, const char *kernel_cmdline,
1.1.1.6   root      157:                     const char *initrd_filename, const char *cpu_model)
1.1       root      158: {
1.1.1.8   root      159:     char *filename;
1.1.1.13  root      160:     MemoryRegion *address_space_mem = get_system_memory();
                    161:     MemoryRegion *ram = g_new(MemoryRegion, 1);
                    162:     MemoryRegion *bios;
                    163:     MemoryRegion *iomem = g_new(MemoryRegion, 1);
1.1.1.5   root      164:     int bios_size;
1.1.1.14! root      165:     CPUMIPSState *env;
1.1.1.9   root      166:     ResetData *reset_info;
1.1.1.5   root      167:     int i;
1.1.1.6   root      168:     qemu_irq *i8259;
1.1.1.14! root      169:     ISABus *isa_bus;
1.1.1.9   root      170:     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
                    171:     DriveInfo *dinfo;
1.1.1.10  root      172:     int be;
1.1.1.6   root      173: 
                    174:     /* init CPUs */
                    175:     if (cpu_model == NULL) {
                    176: #ifdef TARGET_MIPS64
                    177:         cpu_model = "R4000";
                    178: #else
                    179:         cpu_model = "24Kf";
                    180: #endif
                    181:     }
                    182:     env = cpu_init(cpu_model);
                    183:     if (!env) {
                    184:         fprintf(stderr, "Unable to find CPU definition\n");
                    185:         exit(1);
                    186:     }
1.1.1.13  root      187:     reset_info = g_malloc0(sizeof(ResetData));
1.1.1.9   root      188:     reset_info->env = env;
                    189:     reset_info->vector = env->active_tc.PC;
                    190:     qemu_register_reset(main_cpu_reset, reset_info);
1.1.1.2   root      191: 
1.1       root      192:     /* allocate RAM */
1.1.1.7   root      193:     if (ram_size > (256 << 20)) {
                    194:         fprintf(stderr,
                    195:                 "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
                    196:                 ((unsigned int)ram_size / (1 << 20)));
                    197:         exit(1);
                    198:     }
1.1.1.14! root      199:     memory_region_init_ram(ram, "mips_r4k.ram", ram_size);
        !           200:     vmstate_register_ram_global(ram);
1.1.1.8   root      201: 
1.1.1.13  root      202:     memory_region_add_subregion(address_space_mem, 0, ram);
1.1.1.3   root      203: 
1.1.1.13  root      204:     memory_region_init_io(iomem, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
                    205:     memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
1.1.1.5   root      206: 
1.1.1.3   root      207:     /* Try to load a BIOS image. If this fails, we continue regardless,
                    208:        but initialize the hardware ourselves. When a kernel gets
                    209:        preloaded we also initialize the hardware, since the BIOS wasn't
                    210:        run. */
1.1.1.6   root      211:     if (bios_name == NULL)
                    212:         bios_name = BIOS_FILENAME;
1.1.1.8   root      213:     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
                    214:     if (filename) {
                    215:         bios_size = get_image_size(filename);
                    216:     } else {
                    217:         bios_size = -1;
                    218:     }
1.1.1.10  root      219: #ifdef TARGET_WORDS_BIGENDIAN
                    220:     be = 1;
                    221: #else
                    222:     be = 0;
                    223: #endif
1.1.1.5   root      224:     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
1.1.1.13  root      225:         bios = g_new(MemoryRegion, 1);
1.1.1.14! root      226:         memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE);
        !           227:         vmstate_register_ram_global(bios);
1.1.1.13  root      228:         memory_region_set_readonly(bios, true);
                    229:         memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
1.1.1.8   root      230: 
                    231:         load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
1.1.1.9   root      232:     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
1.1.1.7   root      233:         uint32_t mips_rom = 0x00400000;
1.1.1.13  root      234:         if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
1.1.1.10  root      235:                                    dinfo->bdrv, sector_len,
                    236:                                    mips_rom / sector_len,
                    237:                                    4, 0, 0, 0, 0, be)) {
1.1.1.7   root      238:             fprintf(stderr, "qemu: Error registering flash memory.\n");
                    239:        }
                    240:     }
                    241:     else {
1.1.1.3   root      242:        /* not fatal */
                    243:         fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
1.1.1.8   root      244:                bios_name);
                    245:     }
                    246:     if (filename) {
1.1.1.13  root      247:         g_free(filename);
1.1       root      248:     }
1.1.1.3   root      249: 
                    250:     if (kernel_filename) {
1.1.1.6   root      251:         loaderparams.ram_size = ram_size;
                    252:         loaderparams.kernel_filename = kernel_filename;
                    253:         loaderparams.kernel_cmdline = kernel_cmdline;
                    254:         loaderparams.initrd_filename = initrd_filename;
1.1.1.9   root      255:         reset_info->vector = load_kernel();
1.1       root      256:     }
                    257: 
1.1.1.5   root      258:     /* Init CPU internal devices */
1.1.1.6   root      259:     cpu_mips_irq_init_cpu(env);
1.1.1.2   root      260:     cpu_mips_clock_init(env);
1.1       root      261: 
1.1.1.6   root      262:     /* The PIC is attached to the MIPS CPU INT0 pin */
1.1.1.14! root      263:     isa_bus = isa_bus_new(NULL, get_system_io());
        !           264:     i8259 = i8259_init(isa_bus, env->irq[2]);
        !           265:     isa_bus_irqs(isa_bus, i8259);
1.1.1.6   root      266: 
1.1.1.14! root      267:     rtc_init(isa_bus, 2000, NULL);
1.1.1.5   root      268: 
1.1       root      269:     /* Register 64 KB of ISA IO space at 0x14000000 */
1.1.1.11  root      270:     isa_mmio_init(0x14000000, 0x00010000);
1.1       root      271:     isa_mem_base = 0x10000000;
                    272: 
1.1.1.14! root      273:     pit = pit_init(isa_bus, 0x40, 0, NULL);
1.1.1.5   root      274: 
                    275:     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
                    276:         if (serial_hds[i]) {
1.1.1.14! root      277:             serial_isa_init(isa_bus, i, serial_hds[i]);
1.1.1.5   root      278:         }
                    279:     }
                    280: 
1.1.1.14! root      281:     isa_vga_init(isa_bus);
1.1       root      282: 
1.1.1.7   root      283:     if (nd_table[0].vlan)
1.1.1.14! root      284:         isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
1.1.1.5   root      285: 
1.1.1.12  root      286:     ide_drive_get(hd, MAX_IDE_BUS);
1.1.1.6   root      287:     for(i = 0; i < MAX_IDE_BUS; i++)
1.1.1.14! root      288:         isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
1.1.1.6   root      289:                      hd[MAX_IDE_DEVS * i],
                    290:                     hd[MAX_IDE_DEVS * i + 1]);
                    291: 
1.1.1.14! root      292:     isa_create_simple(isa_bus, "i8042");
1.1       root      293: }
                    294: 
1.1.1.8   root      295: static QEMUMachine mips_machine = {
1.1.1.7   root      296:     .name = "mips",
                    297:     .desc = "mips r4k platform",
                    298:     .init = mips_r4k_init,
1.1       root      299: };
1.1.1.8   root      300: 
                    301: static void mips_machine_init(void)
                    302: {
                    303:     qemu_register_machine(&mips_machine);
                    304: }
                    305: 
                    306: machine_init(mips_machine_init);

unix.superglobalmegacorp.com