--- trunk/src/machine.c 2007/10/08 16:17:48 2 +++ trunk/src/machine.c 2007/10/08 16:18:00 4 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: machine.c,v 1.406 2005/04/06 23:13:37 debug Exp $ + * $Id: machine.c,v 1.420 2005/04/17 00:15:24 debug Exp $ * * Emulation of specific machines. * @@ -488,6 +488,29 @@ /* + * load_16bit_word(): + * + * Helper function. Prints a warning and returns 0, if the read failed. + * Emulated byte order is taken into account. + */ +uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr) +{ + unsigned char data[2]; + + if ((addr >> 32) == 0) + addr = (int64_t)(int32_t)addr; + cpu->memory_rw(cpu, cpu->mem, + addr, data, sizeof(data), MEM_READ, CACHE_DATA); + + if (cpu->byte_order == EMUL_LITTLE_ENDIAN) { + int tmp = data[0]; data[0] = data[1]; data[1] = tmp; + } + + return (data[0] << 8) + data[1]; +} + + +/* * store_64bit_word_in_host(): * * Stores a 64-bit word in the _host's_ RAM. Emulated byte order is taken @@ -830,37 +853,67 @@ /* * Playstation 2 interrupt routine: + * + * irq_nr = 8 + x normal irq x + * 8 + 16 + y dma irq y + * 8 + 32 + 0 sbus irq 0 (pcmcia) + * 8 + 32 + 1 sbus irq 1 (usb) */ void ps2_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt) { irq_nr -= 8; debug("ps2_interrupt(): irq_nr=0x%x assrt=%i\n", irq_nr, assrt); - if (assrt) { - /* OR into the INTR: */ - if (irq_nr < 0x10000) - m->ps2_data->intr |= irq_nr; + if (irq_nr >= 32) { + int msk = 0; + switch (irq_nr - 32) { + case 0: /* PCMCIA: */ + msk = 0x100; + break; + case 1: /* USB: */ + msk = 0x400; + break; + default: + fatal("ps2_interrupt(): bad irq_nr %i\n", irq_nr); + } + + if (assrt) + m->ps2_data->sbus_smflg |= msk; else - m->ps2_data->dmac_reg[0x601] |= (irq_nr >> 16); + m->ps2_data->sbus_smflg &= ~msk; - /* Assert interrupt: TODO: masks */ - if (irq_nr >= 0x10000) - cpu_interrupt(cpu, 3); + if (m->ps2_data->sbus_smflg != 0) + cpu_interrupt(cpu, 8 + 1); else - cpu_interrupt(cpu, 2); + cpu_interrupt_ack(cpu, 8 + 1); + return; + } + + if (assrt) { + /* OR into the INTR: */ + if (irq_nr < 16) + m->ps2_data->intr |= (1 << irq_nr); + else + m->ps2_data->dmac_reg[0x601] |= (1 << (irq_nr-16)); } else { /* AND out of the INTR: */ - if (irq_nr < 0x10000) - m->ps2_data->intr &= ~irq_nr; + if (irq_nr < 16) + m->ps2_data->intr &= ~(1 << irq_nr); else - m->ps2_data->dmac_reg[0x601] &= ~(irq_nr >> 16); - - /* TODO: masks */ - if ((m->ps2_data->intr & 0xffff) == 0) - cpu_interrupt_ack(cpu, 2); - if ((m->ps2_data->dmac_reg[0x601] & 0xffff) == 0) - cpu_interrupt_ack(cpu, 3); + m->ps2_data->dmac_reg[0x601] &= ~(1 << (irq_nr-16)); } + + /* TODO: Hm? How about the mask? */ + if (m->ps2_data->intr /* & m->ps2_data->imask */ ) + cpu_interrupt(cpu, 2); + else + cpu_interrupt_ack(cpu, 2); + + /* TODO: mask? */ + if (m->ps2_data->dmac_reg[0x601] & 0xffff) + cpu_interrupt(cpu, 3); + else + cpu_interrupt_ack(cpu, 3); } @@ -2384,10 +2437,12 @@ * ohci0: OHCI version 1.0 */ - device_add(machine, "ps2_gs addr=0x12000000"); machine->ps2_data = dev_ps2_stuff_init(machine, mem, 0x10000000); - dev_ps2_ohci_init(cpu, mem, 0x1f801600); + device_add(machine, "ps2_gs addr=0x12000000"); + device_add(machine, "ps2_ether addr=0x14001000"); dev_ram_init(mem, 0x1c000000, 4 * 1048576, DEV_RAM_RAM, 0); /* TODO: how much? */ + /* irq = 8 + 32 + 1 (SBUS/USB) */ + device_add(machine, "ohci addr=0x1f801600 irq=41"); machine->md_interrupt = ps2_interrupt; @@ -2396,15 +2451,32 @@ store_32bit_word(cpu, PLAYSTATION2_BDA + 0, PLAYSTATION2_SIFBIOS); store_buf(cpu, PLAYSTATION2_BDA + 4, "PS2b", 4); -#if 0 - /* Harddisk controller present flag: */ - store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x0, 0x100); - dev_ps2_spd_init(machine, mem, 0x14000000); -#endif + /* Set the Harddisk controller present flag, if either + disk 0 or 1 is present: */ + if (diskimage_exist(machine, 0) || diskimage_exist(machine, 1)) { + store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x0, 0x100); + dev_ps2_spd_init(machine, mem, 0x14000000); + } store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x4, PLAYSTATION2_OPTARGS); - bootstr = "root=/dev/hda1 crtmode=vesa0,60"; - store_string(cpu, PLAYSTATION2_OPTARGS, bootstr); + { + int tmplen = 1000; + char *tmp = malloc(tmplen); + if (tmp == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + strcpy(tmp, "root=/dev/hda1 crtmode=vesa0,60"); + + if (machine->boot_string_argument[0]) + snprintf(tmp+strlen(tmp), tmplen-strlen(tmp), + " %s", machine->boot_string_argument); + tmp[tmplen-1] = '\0'; + + bootstr = tmp; + store_string(cpu, PLAYSTATION2_OPTARGS, bootstr); + } /* TODO: netbsd's bootinfo.h, for symbolic names */ { @@ -2424,10 +2496,7 @@ } /* "BOOTINFO_PCMCIA_TYPE" in NetBSD's bootinfo.h. This contains the sbus controller type. */ - store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x1c, 3); - - /* TODO: Is this necessary? */ - cpu->cd.mips.gpr[MIPS_GPR_SP] = 0x80007f00; + store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x1c, 2); break; @@ -4411,6 +4480,40 @@ /* TODO */ break; + case MACHINE_BAREX86: + machine->machine_name = "\"Bare\" x86 machine"; + break; + + case MACHINE_X86: + machine->machine_name = "Generic x86 PC"; + + if (!machine->use_x11) + fprintf(stderr, "WARNING! You are emulating a PC " + "without -X. You will miss any output going\n" + "to the screen!\n\n"); + + /* + * Initialize all 16-bit interrupt vectors to point to + * somewhere within the PC BIOS area (0xf000:0x8yyy): + */ + for (i=0; i<256; i++) { + store_16bit_word(cpu, i*4, 0x8000 + i); + store_16bit_word(cpu, i*4 + 2, 0xf000); + } + + dev_vga_init(machine, mem, 0xb8000ULL, 0x1000003c0ULL, 80, 25, + "Generic x86 PC"); + + dev_wdc_init(machine, mem, 0x1000001f0ULL, 14, 0); + + /* TODO: disable the "enable" flag when a keyboard has + been added: */ + machine->main_console_handle = dev_ns16550_init(machine, mem, + 0x1000003f8ULL, 4, 1, 1, "com1"); + dev_ns16550_init(machine, mem, 0x100000378ULL, 3, 1, 0, "com2"); + + break; + default: fatal("Unknown emulation type %i\n", machine->machine_type); exit(1); @@ -4714,6 +4817,12 @@ case MACHINE_TESTALPHA: m->cpu_name = strdup("EV4"); break; + + /* x86: */ + case MACHINE_BAREX86: + case MACHINE_X86: + m->cpu_name = strdup("PENTIUM"); + break; } if (m->cpu_name == NULL) { @@ -4962,6 +5071,15 @@ * entries will appear in normal order when listed. :-) */ + /* X86 machine: */ + me = machine_entry_new("x86 (generic PC-style machine)", ARCH_X86, + MACHINE_X86, 2, 0); + me->aliases[0] = "pc"; + me->aliases[1] = "x86"; + if (cpu_family_ptr_by_number(ARCH_X86) != NULL) { + me->next = first_machine_entry; first_machine_entry = me; + } + /* Walnut: (NetBSD/evbppc) */ me = machine_entry_new("Walnut evaluation board", ARCH_PPC, MACHINE_WALNUT, 2, 0); @@ -5159,6 +5277,14 @@ me->next = first_machine_entry; first_machine_entry = me; } + /* Generic "bare" X86 machine: */ + me = machine_entry_new("Generic \"bare\" X86 machine", ARCH_X86, + MACHINE_BAREX86, 1, 0); + me->aliases[0] = "barex86"; + if (cpu_family_ptr_by_number(ARCH_X86) != NULL) { + me->next = first_machine_entry; first_machine_entry = me; + } + /* Generic "bare" URISC machine: */ me = machine_entry_new("Generic \"bare\" URISC machine", ARCH_URISC, MACHINE_BAREURISC, 1, 0);