diff --git a/hw/sun4m.c b/hw/sun4m.c index dd0433afca3876719f007a3af48797173955f8c1..83963d9827fa2465d82f06b6a91f720b691e72f9 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -88,7 +88,7 @@ #define MAX_CPUS 16 #define MAX_PILS 16 -struct hwdef { +struct sun4m_hwdef { target_phys_addr_t iommu_base, slavio_base; target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base; target_phys_addr_t serial_base, fd_base; @@ -96,7 +96,6 @@ struct hwdef { target_phys_addr_t tcx_base, cs_base, apc_base, aux1_base, aux2_base; target_phys_addr_t ecc_base; uint32_t ecc_version; - target_phys_addr_t sun4c_intctl_base, sun4c_counter_base; long vram_size, nvram_size; // IRQ numbers are not PIL ones, but master interrupt controller // register bit numbers @@ -131,6 +130,25 @@ struct sun4d_hwdef { const char * const default_cpu_model; }; +struct sun4c_hwdef { + target_phys_addr_t iommu_base, slavio_base; + target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base; + target_phys_addr_t serial_base, fd_base; + target_phys_addr_t idreg_base, dma_base, esp_base, le_base; + target_phys_addr_t tcx_base, cs_base, apc_base, aux1_base, aux2_base; + long vram_size, nvram_size; + // IRQ numbers are not PIL ones, but master interrupt controller + // register bit numbers + int intctl_g_intr, esp_irq, le_irq, clock_irq, clock1_irq; + int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq; + uint8_t nvram_machine_id; + uint16_t machine_id; + uint32_t iommu_version; + uint32_t intbit_to_level[32]; + uint64_t max_mem; + const char * const default_cpu_model; +}; + int DMA_get_channel_mode (int nchan) { return 0; @@ -395,7 +413,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename, return kernel_size; } -static void sun4m_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size, +static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, const char *boot_device, DisplayState *ds, const char *kernel_filename, const char *kernel_cmdline, @@ -584,158 +602,6 @@ static void sun4m_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size, fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth); } -static void sun4c_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size, - const char *boot_device, - DisplayState *ds, const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) -{ - CPUState *env; - unsigned int i; - void *iommu, *espdma, *ledma, *main_esp, *nvram; - qemu_irq *cpu_irqs, *slavio_irq, *espdma_irq, *ledma_irq; - qemu_irq *esp_reset, *le_reset; - qemu_irq *fdc_tc; - unsigned long prom_offset, kernel_size; - int ret; - char buf[1024]; - BlockDriverState *fd[MAX_FD]; - int drive_index; - void *fw_cfg; - - /* init CPU */ - if (!cpu_model) - cpu_model = hwdef->default_cpu_model; - - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); - exit(1); - } - - cpu_sparc_set_id(env, 0); - - qemu_register_reset(main_cpu_reset, env); - cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); - env->prom_addr = hwdef->slavio_base; - - /* allocate RAM */ - if ((uint64_t)RAM_size > hwdef->max_mem) { - fprintf(stderr, - "qemu: Too much memory for this machine: %d, maximum %d\n", - (unsigned int)(RAM_size / (1024 * 1024)), - (unsigned int)(hwdef->max_mem / (1024 * 1024))); - exit(1); - } - cpu_register_physical_memory(0, RAM_size, 0); - - /* load boot prom */ - prom_offset = RAM_size + hwdef->vram_size; - cpu_register_physical_memory(hwdef->slavio_base, - (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & - TARGET_PAGE_MASK, - prom_offset | IO_MEM_ROM); - - if (bios_name == NULL) - bios_name = PROM_FILENAME; - snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); - ret = load_elf(buf, hwdef->slavio_base - PROM_VADDR, NULL, NULL, NULL); - if (ret < 0 || ret > PROM_SIZE_MAX) - ret = load_image_targphys(buf, hwdef->slavio_base, PROM_SIZE_MAX); - if (ret < 0 || ret > PROM_SIZE_MAX) { - fprintf(stderr, "qemu: could not load prom '%s'\n", - buf); - exit(1); - } - prom_offset += (ret + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; - - /* set up devices */ - slavio_intctl = sun4c_intctl_init(hwdef->sun4c_intctl_base, - &slavio_irq, cpu_irqs); - - iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version, - slavio_irq[hwdef->me_irq]); - - espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq], - iommu, &espdma_irq, &esp_reset); - - ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, - slavio_irq[hwdef->le_irq], iommu, &ledma_irq, - &le_reset); - - if (graphic_depth != 8 && graphic_depth != 24) { - fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth); - exit (1); - } - tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size, - hwdef->vram_size, graphic_width, graphic_height, graphic_depth); - - if (nd_table[0].model == NULL - || strcmp(nd_table[0].model, "lance") == 0) { - lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset); - } else if (strcmp(nd_table[0].model, "?") == 0) { - fprintf(stderr, "qemu: Supported NICs: lance\n"); - exit (1); - } else { - fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model); - exit (1); - } - - nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, - hwdef->nvram_size, 2); - - slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq], - nographic); - // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device - // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device - slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq], - serial_hds[1], serial_hds[0]); - - slavio_misc = slavio_misc_init(0, hwdef->apc_base, - hwdef->aux1_base, hwdef->aux2_base, - slavio_irq[hwdef->me_irq], env, &fdc_tc); - - if (hwdef->fd_base != (target_phys_addr_t)-1) { - /* there is zero or one floppy drive */ - fd[1] = fd[0] = NULL; - drive_index = drive_get_index(IF_FLOPPY, 0, 0); - if (drive_index != -1) - fd[0] = drives_table[drive_index].bdrv; - - sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd, - fdc_tc); - } - - if (drive_get_max_bus(IF_SCSI) > 0) { - fprintf(stderr, "qemu: too many SCSI bus\n"); - exit(1); - } - - main_esp = esp_init(hwdef->esp_base, 2, - espdma_memory_read, espdma_memory_write, - espdma, *espdma_irq, esp_reset); - - for (i = 0; i < ESP_MAX_DEVS; i++) { - drive_index = drive_get_index(IF_SCSI, 0, i); - if (drive_index == -1) - continue; - esp_scsi_attach(main_esp, drives_table[drive_index].bdrv, i); - } - - kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, - RAM_size); - - nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, - boot_device, RAM_size, kernel_size, graphic_width, - graphic_height, graphic_depth, hwdef->nvram_machine_id, - "Sun4c"); - - fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); - fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); -} - enum { ss2_id = 0, ss5_id = 32, @@ -751,7 +617,7 @@ enum { ss2000_id, }; -static const struct hwdef hwdefs[] = { +static const struct sun4m_hwdef sun4m_hwdefs[] = { /* SS-5 */ { .iommu_base = 0x10000000, @@ -772,8 +638,6 @@ static const struct hwdef hwdefs[] = { .aux1_base = 0x71900000, .aux2_base = 0x71910000, .ecc_base = -1, - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -816,8 +680,6 @@ static const struct hwdef hwdefs[] = { .aux2_base = 0xff1a01000ULL, .ecc_base = 0xf00000000ULL, .ecc_version = 0x10000000, // version 0, implementation 1 - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -861,8 +723,6 @@ static const struct hwdef hwdefs[] = { .aux2_base = 0xff1a01000ULL, // XXX should not exist .ecc_base = 0xf00000000ULL, .ecc_version = 0x00000000, // version 0, implementation 0 - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -906,8 +766,6 @@ static const struct hwdef hwdefs[] = { .aux2_base = 0xff1a01000ULL, .ecc_base = 0xf00000000ULL, .ecc_version = 0x20000000, // version 0, implementation 2 - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -930,42 +788,6 @@ static const struct hwdef hwdefs[] = { .max_mem = 0xf00000000ULL, .default_cpu_model = "TI SuperSparc II", }, - /* SS-2 */ - { - .iommu_base = 0xf8000000, - .tcx_base = 0xfe000000, - .cs_base = -1, - .slavio_base = 0xf6000000, - .ms_kb_base = 0xf0000000, - .serial_base = 0xf1000000, - .nvram_base = 0xf2000000, - .fd_base = 0xf7200000, - .counter_base = -1, - .intctl_base = -1, - .dma_base = 0xf8400000, - .esp_base = 0xf8800000, - .le_base = 0xf8c00000, - .apc_base = -1, - .aux1_base = 0xf7400003, - .aux2_base = -1, - .sun4c_intctl_base = 0xf5000000, - .sun4c_counter_base = 0xf3000000, - .vram_size = 0x00100000, - .nvram_size = 0x800, - .esp_irq = 2, - .le_irq = 3, - .clock_irq = 5, - .clock1_irq = 7, - .ms_kb_irq = 1, - .ser_irq = 1, - .fd_irq = 1, - .me_irq = 1, - .cs_irq = -1, - .nvram_machine_id = 0x55, - .machine_id = ss2_id, - .max_mem = 0x10000000, - .default_cpu_model = "Cypress CY7C601", - }, /* Voyager */ { .iommu_base = 0x10000000, @@ -986,8 +808,6 @@ static const struct hwdef hwdefs[] = { .aux1_base = 0x71900000, .aux2_base = 0x71910000, .ecc_base = -1, - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -1029,8 +849,6 @@ static const struct hwdef hwdefs[] = { .aux1_base = 0x71900000, .aux2_base = 0x71910000, .ecc_base = -1, - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -1072,8 +890,6 @@ static const struct hwdef hwdefs[] = { .aux1_base = 0x71900000, .aux2_base = 0x71910000, .ecc_base = -1, - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -1115,8 +931,6 @@ static const struct hwdef hwdefs[] = { .aux1_base = 0x71900000, .aux2_base = 0x71910000, .ecc_base = -1, - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -1158,8 +972,6 @@ static const struct hwdef hwdefs[] = { .aux1_base = 0x71900000, .aux2_base = 0x71910000, .ecc_base = -1, - .sun4c_intctl_base = -1, - .sun4c_counter_base = -1, .vram_size = 0x00100000, .nvram_size = 0x2000, .esp_irq = 18, @@ -1189,7 +1001,7 @@ static void ss5_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[0], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[0], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1199,7 +1011,7 @@ static void ss10_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[1], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[1], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1210,7 +1022,7 @@ static void ss600mp_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[2], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[2], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1220,17 +1032,7 @@ static void ss20_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[3], RAM_size, boot_device, ds, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model); -} - -/* SPARCstation 2 hardware initialisation */ -static void ss2_init(ram_addr_t RAM_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) -{ - sun4c_hw_init(&hwdefs[4], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[3], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1240,7 +1042,7 @@ static void vger_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[5], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[4], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1250,7 +1052,7 @@ static void ss_lx_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[6], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[5], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1260,7 +1062,7 @@ static void ss4_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[7], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[6], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1270,7 +1072,7 @@ static void scls_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[8], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[7], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1280,7 +1082,7 @@ static void sbook_init(ram_addr_t RAM_size, int vga_ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - sun4m_hw_init(&hwdefs[9], RAM_size, boot_device, ds, kernel_filename, + sun4m_hw_init(&sun4m_hwdefs[8], RAM_size, boot_device, ds, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -1324,16 +1126,6 @@ QEMUMachine ss20_machine = { .max_cpus = 16, }; -QEMUMachine ss2_machine = { - .name = "SS-2", - .desc = "Sun4c platform, SPARCstation 2", - .init = ss2_init, - .ram_require = PROM_SIZE_MAX + TCX_SIZE, - .nodisk_ok = 1, - .use_scsi = 1, - .max_cpus = 16, -}; - QEMUMachine voyager_machine = { .name = "Voyager", .desc = "Sun4m platform, SPARCstation Voyager", @@ -1642,3 +1434,213 @@ QEMUMachine ss2000_machine = { .use_scsi = 1, .max_cpus = 16, }; + +static const struct sun4c_hwdef sun4c_hwdefs[] = { + /* SS-2 */ + { + .iommu_base = 0xf8000000, + .tcx_base = 0xfe000000, + .cs_base = -1, + .slavio_base = 0xf6000000, + .intctl_base = 0xf5000000, + .counter_base = 0xf3000000, + .ms_kb_base = 0xf0000000, + .serial_base = 0xf1000000, + .nvram_base = 0xf2000000, + .fd_base = 0xf7200000, + .dma_base = 0xf8400000, + .esp_base = 0xf8800000, + .le_base = 0xf8c00000, + .apc_base = -1, + .aux1_base = 0xf7400003, + .aux2_base = -1, + .vram_size = 0x00100000, + .nvram_size = 0x800, + .esp_irq = 2, + .le_irq = 3, + .clock_irq = 5, + .clock1_irq = 7, + .ms_kb_irq = 1, + .ser_irq = 1, + .fd_irq = 1, + .me_irq = 1, + .cs_irq = -1, + .nvram_machine_id = 0x55, + .machine_id = ss2_id, + .max_mem = 0x10000000, + .default_cpu_model = "Cypress CY7C601", + }, +}; + +static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, + const char *boot_device, + DisplayState *ds, const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + CPUState *env; + unsigned int i; + void *iommu, *espdma, *ledma, *main_esp, *nvram; + qemu_irq *cpu_irqs, *slavio_irq, *espdma_irq, *ledma_irq; + qemu_irq *esp_reset, *le_reset; + qemu_irq *fdc_tc; + unsigned long prom_offset, kernel_size; + int ret; + char buf[1024]; + BlockDriverState *fd[MAX_FD]; + int drive_index; + void *fw_cfg; + + /* init CPU */ + if (!cpu_model) + cpu_model = hwdef->default_cpu_model; + + env = cpu_init(cpu_model); + if (!env) { + fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); + exit(1); + } + + cpu_sparc_set_id(env, 0); + + qemu_register_reset(main_cpu_reset, env); + cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); + env->prom_addr = hwdef->slavio_base; + + /* allocate RAM */ + if ((uint64_t)RAM_size > hwdef->max_mem) { + fprintf(stderr, + "qemu: Too much memory for this machine: %d, maximum %d\n", + (unsigned int)(RAM_size / (1024 * 1024)), + (unsigned int)(hwdef->max_mem / (1024 * 1024))); + exit(1); + } + cpu_register_physical_memory(0, RAM_size, 0); + + /* load boot prom */ + prom_offset = RAM_size + hwdef->vram_size; + cpu_register_physical_memory(hwdef->slavio_base, + (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & + TARGET_PAGE_MASK, + prom_offset | IO_MEM_ROM); + + if (bios_name == NULL) + bios_name = PROM_FILENAME; + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); + ret = load_elf(buf, hwdef->slavio_base - PROM_VADDR, NULL, NULL, NULL); + if (ret < 0 || ret > PROM_SIZE_MAX) + ret = load_image_targphys(buf, hwdef->slavio_base, PROM_SIZE_MAX); + if (ret < 0 || ret > PROM_SIZE_MAX) { + fprintf(stderr, "qemu: could not load prom '%s'\n", + buf); + exit(1); + } + prom_offset += (ret + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; + + /* set up devices */ + slavio_intctl = sun4c_intctl_init(hwdef->intctl_base, + &slavio_irq, cpu_irqs); + + iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version, + slavio_irq[hwdef->me_irq]); + + espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq], + iommu, &espdma_irq, &esp_reset); + + ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, + slavio_irq[hwdef->le_irq], iommu, &ledma_irq, + &le_reset); + + if (graphic_depth != 8 && graphic_depth != 24) { + fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth); + exit (1); + } + tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size, + hwdef->vram_size, graphic_width, graphic_height, graphic_depth); + + if (nd_table[0].model == NULL + || strcmp(nd_table[0].model, "lance") == 0) { + lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset); + } else if (strcmp(nd_table[0].model, "?") == 0) { + fprintf(stderr, "qemu: Supported NICs: lance\n"); + exit (1); + } else { + fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model); + exit (1); + } + + nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, + hwdef->nvram_size, 2); + + slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq], + nographic); + // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device + // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device + slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq], + serial_hds[1], serial_hds[0]); + + slavio_misc = slavio_misc_init(0, hwdef->apc_base, + hwdef->aux1_base, hwdef->aux2_base, + slavio_irq[hwdef->me_irq], env, &fdc_tc); + + if (hwdef->fd_base != (target_phys_addr_t)-1) { + /* there is zero or one floppy drive */ + fd[1] = fd[0] = NULL; + drive_index = drive_get_index(IF_FLOPPY, 0, 0); + if (drive_index != -1) + fd[0] = drives_table[drive_index].bdrv; + + sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd, + fdc_tc); + } + + if (drive_get_max_bus(IF_SCSI) > 0) { + fprintf(stderr, "qemu: too many SCSI bus\n"); + exit(1); + } + + main_esp = esp_init(hwdef->esp_base, 2, + espdma_memory_read, espdma_memory_write, + espdma, *espdma_irq, esp_reset); + + for (i = 0; i < ESP_MAX_DEVS; i++) { + drive_index = drive_get_index(IF_SCSI, 0, i); + if (drive_index == -1) + continue; + esp_scsi_attach(main_esp, drives_table[drive_index].bdrv, i); + } + + kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, + RAM_size); + + nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, + boot_device, RAM_size, kernel_size, graphic_width, + graphic_height, graphic_depth, hwdef->nvram_machine_id, + "Sun4c"); + + fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); + fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); +} + +/* SPARCstation 2 hardware initialisation */ +static void ss2_init(ram_addr_t RAM_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + sun4c_hw_init(&sun4c_hwdefs[0], RAM_size, boot_device, ds, kernel_filename, + kernel_cmdline, initrd_filename, cpu_model); +} + +QEMUMachine ss2_machine = { + .name = "SS-2", + .desc = "Sun4c platform, SPARCstation 2", + .init = ss2_init, + .ram_require = PROM_SIZE_MAX + TCX_SIZE, + .nodisk_ok = 1, + .use_scsi = 1, + .max_cpus = 16, +}; +