25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $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 $ |
29 |
* |
* |
30 |
* Emulation of specific machines. |
* Emulation of specific machines. |
31 |
* |
* |
488 |
|
|
489 |
|
|
490 |
/* |
/* |
491 |
|
* load_16bit_word(): |
492 |
|
* |
493 |
|
* Helper function. Prints a warning and returns 0, if the read failed. |
494 |
|
* Emulated byte order is taken into account. |
495 |
|
*/ |
496 |
|
uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr) |
497 |
|
{ |
498 |
|
unsigned char data[2]; |
499 |
|
|
500 |
|
if ((addr >> 32) == 0) |
501 |
|
addr = (int64_t)(int32_t)addr; |
502 |
|
cpu->memory_rw(cpu, cpu->mem, |
503 |
|
addr, data, sizeof(data), MEM_READ, CACHE_DATA); |
504 |
|
|
505 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) { |
506 |
|
int tmp = data[0]; data[0] = data[1]; data[1] = tmp; |
507 |
|
} |
508 |
|
|
509 |
|
return (data[0] << 8) + data[1]; |
510 |
|
} |
511 |
|
|
512 |
|
|
513 |
|
/* |
514 |
* store_64bit_word_in_host(): |
* store_64bit_word_in_host(): |
515 |
* |
* |
516 |
* Stores a 64-bit word in the _host's_ RAM. Emulated byte order is taken |
* Stores a 64-bit word in the _host's_ RAM. Emulated byte order is taken |
853 |
|
|
854 |
/* |
/* |
855 |
* Playstation 2 interrupt routine: |
* Playstation 2 interrupt routine: |
856 |
|
* |
857 |
|
* irq_nr = 8 + x normal irq x |
858 |
|
* 8 + 16 + y dma irq y |
859 |
|
* 8 + 32 + 0 sbus irq 0 (pcmcia) |
860 |
|
* 8 + 32 + 1 sbus irq 1 (usb) |
861 |
*/ |
*/ |
862 |
void ps2_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt) |
void ps2_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt) |
863 |
{ |
{ |
864 |
irq_nr -= 8; |
irq_nr -= 8; |
865 |
debug("ps2_interrupt(): irq_nr=0x%x assrt=%i\n", irq_nr, assrt); |
debug("ps2_interrupt(): irq_nr=0x%x assrt=%i\n", irq_nr, assrt); |
866 |
|
|
867 |
if (assrt) { |
if (irq_nr >= 32) { |
868 |
/* OR into the INTR: */ |
int msk = 0; |
869 |
if (irq_nr < 0x10000) |
switch (irq_nr - 32) { |
870 |
m->ps2_data->intr |= irq_nr; |
case 0: /* PCMCIA: */ |
871 |
|
msk = 0x100; |
872 |
|
break; |
873 |
|
case 1: /* USB: */ |
874 |
|
msk = 0x400; |
875 |
|
break; |
876 |
|
default: |
877 |
|
fatal("ps2_interrupt(): bad irq_nr %i\n", irq_nr); |
878 |
|
} |
879 |
|
|
880 |
|
if (assrt) |
881 |
|
m->ps2_data->sbus_smflg |= msk; |
882 |
else |
else |
883 |
m->ps2_data->dmac_reg[0x601] |= (irq_nr >> 16); |
m->ps2_data->sbus_smflg &= ~msk; |
884 |
|
|
885 |
/* Assert interrupt: TODO: masks */ |
if (m->ps2_data->sbus_smflg != 0) |
886 |
if (irq_nr >= 0x10000) |
cpu_interrupt(cpu, 8 + 1); |
|
cpu_interrupt(cpu, 3); |
|
887 |
else |
else |
888 |
cpu_interrupt(cpu, 2); |
cpu_interrupt_ack(cpu, 8 + 1); |
889 |
|
return; |
890 |
|
} |
891 |
|
|
892 |
|
if (assrt) { |
893 |
|
/* OR into the INTR: */ |
894 |
|
if (irq_nr < 16) |
895 |
|
m->ps2_data->intr |= (1 << irq_nr); |
896 |
|
else |
897 |
|
m->ps2_data->dmac_reg[0x601] |= (1 << (irq_nr-16)); |
898 |
} else { |
} else { |
899 |
/* AND out of the INTR: */ |
/* AND out of the INTR: */ |
900 |
if (irq_nr < 0x10000) |
if (irq_nr < 16) |
901 |
m->ps2_data->intr &= ~irq_nr; |
m->ps2_data->intr &= ~(1 << irq_nr); |
902 |
else |
else |
903 |
m->ps2_data->dmac_reg[0x601] &= ~(irq_nr >> 16); |
m->ps2_data->dmac_reg[0x601] &= ~(1 << (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); |
|
904 |
} |
} |
905 |
|
|
906 |
|
/* TODO: Hm? How about the mask? */ |
907 |
|
if (m->ps2_data->intr /* & m->ps2_data->imask */ ) |
908 |
|
cpu_interrupt(cpu, 2); |
909 |
|
else |
910 |
|
cpu_interrupt_ack(cpu, 2); |
911 |
|
|
912 |
|
/* TODO: mask? */ |
913 |
|
if (m->ps2_data->dmac_reg[0x601] & 0xffff) |
914 |
|
cpu_interrupt(cpu, 3); |
915 |
|
else |
916 |
|
cpu_interrupt_ack(cpu, 3); |
917 |
} |
} |
918 |
|
|
919 |
|
|
2437 |
* ohci0: OHCI version 1.0 |
* ohci0: OHCI version 1.0 |
2438 |
*/ |
*/ |
2439 |
|
|
|
device_add(machine, "ps2_gs addr=0x12000000"); |
|
2440 |
machine->ps2_data = dev_ps2_stuff_init(machine, mem, 0x10000000); |
machine->ps2_data = dev_ps2_stuff_init(machine, mem, 0x10000000); |
2441 |
dev_ps2_ohci_init(cpu, mem, 0x1f801600); |
device_add(machine, "ps2_gs addr=0x12000000"); |
2442 |
|
device_add(machine, "ps2_ether addr=0x14001000"); |
2443 |
dev_ram_init(mem, 0x1c000000, 4 * 1048576, DEV_RAM_RAM, 0); /* TODO: how much? */ |
dev_ram_init(mem, 0x1c000000, 4 * 1048576, DEV_RAM_RAM, 0); /* TODO: how much? */ |
2444 |
|
/* irq = 8 + 32 + 1 (SBUS/USB) */ |
2445 |
|
device_add(machine, "ohci addr=0x1f801600 irq=41"); |
2446 |
|
|
2447 |
machine->md_interrupt = ps2_interrupt; |
machine->md_interrupt = ps2_interrupt; |
2448 |
|
|
2451 |
store_32bit_word(cpu, PLAYSTATION2_BDA + 0, PLAYSTATION2_SIFBIOS); |
store_32bit_word(cpu, PLAYSTATION2_BDA + 0, PLAYSTATION2_SIFBIOS); |
2452 |
store_buf(cpu, PLAYSTATION2_BDA + 4, "PS2b", 4); |
store_buf(cpu, PLAYSTATION2_BDA + 4, "PS2b", 4); |
2453 |
|
|
2454 |
#if 0 |
/* Set the Harddisk controller present flag, if either |
2455 |
/* Harddisk controller present flag: */ |
disk 0 or 1 is present: */ |
2456 |
store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x0, 0x100); |
if (diskimage_exist(machine, 0) || diskimage_exist(machine, 1)) { |
2457 |
dev_ps2_spd_init(machine, mem, 0x14000000); |
store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x0, 0x100); |
2458 |
#endif |
dev_ps2_spd_init(machine, mem, 0x14000000); |
2459 |
|
} |
2460 |
|
|
2461 |
store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x4, PLAYSTATION2_OPTARGS); |
store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x4, PLAYSTATION2_OPTARGS); |
2462 |
bootstr = "root=/dev/hda1 crtmode=vesa0,60"; |
{ |
2463 |
store_string(cpu, PLAYSTATION2_OPTARGS, bootstr); |
int tmplen = 1000; |
2464 |
|
char *tmp = malloc(tmplen); |
2465 |
|
if (tmp == NULL) { |
2466 |
|
fprintf(stderr, "out of memory\n"); |
2467 |
|
exit(1); |
2468 |
|
} |
2469 |
|
|
2470 |
|
strcpy(tmp, "root=/dev/hda1 crtmode=vesa0,60"); |
2471 |
|
|
2472 |
|
if (machine->boot_string_argument[0]) |
2473 |
|
snprintf(tmp+strlen(tmp), tmplen-strlen(tmp), |
2474 |
|
" %s", machine->boot_string_argument); |
2475 |
|
tmp[tmplen-1] = '\0'; |
2476 |
|
|
2477 |
|
bootstr = tmp; |
2478 |
|
store_string(cpu, PLAYSTATION2_OPTARGS, bootstr); |
2479 |
|
} |
2480 |
|
|
2481 |
/* TODO: netbsd's bootinfo.h, for symbolic names */ |
/* TODO: netbsd's bootinfo.h, for symbolic names */ |
2482 |
{ |
{ |
2496 |
} |
} |
2497 |
|
|
2498 |
/* "BOOTINFO_PCMCIA_TYPE" in NetBSD's bootinfo.h. This contains the sbus controller type. */ |
/* "BOOTINFO_PCMCIA_TYPE" in NetBSD's bootinfo.h. This contains the sbus controller type. */ |
2499 |
store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x1c, 3); |
store_32bit_word(cpu, 0xa0000000 + machine->physical_ram_in_mb*1048576 - 0x1000 + 0x1c, 2); |
|
|
|
|
/* TODO: Is this necessary? */ |
|
|
cpu->cd.mips.gpr[MIPS_GPR_SP] = 0x80007f00; |
|
2500 |
|
|
2501 |
break; |
break; |
2502 |
|
|
4480 |
/* TODO */ |
/* TODO */ |
4481 |
break; |
break; |
4482 |
|
|
4483 |
|
case MACHINE_BAREX86: |
4484 |
|
machine->machine_name = "\"Bare\" x86 machine"; |
4485 |
|
break; |
4486 |
|
|
4487 |
|
case MACHINE_X86: |
4488 |
|
machine->machine_name = "Generic x86 PC"; |
4489 |
|
|
4490 |
|
if (!machine->use_x11) |
4491 |
|
fprintf(stderr, "WARNING! You are emulating a PC " |
4492 |
|
"without -X. You will miss any output going\n" |
4493 |
|
"to the screen!\n\n"); |
4494 |
|
|
4495 |
|
/* |
4496 |
|
* Initialize all 16-bit interrupt vectors to point to |
4497 |
|
* somewhere within the PC BIOS area (0xf000:0x8yyy): |
4498 |
|
*/ |
4499 |
|
for (i=0; i<256; i++) { |
4500 |
|
store_16bit_word(cpu, i*4, 0x8000 + i); |
4501 |
|
store_16bit_word(cpu, i*4 + 2, 0xf000); |
4502 |
|
} |
4503 |
|
|
4504 |
|
dev_vga_init(machine, mem, 0xb8000ULL, 0x1000003c0ULL, 80, 25, |
4505 |
|
"Generic x86 PC"); |
4506 |
|
|
4507 |
|
dev_wdc_init(machine, mem, 0x1000001f0ULL, 14, 0); |
4508 |
|
|
4509 |
|
/* TODO: disable the "enable" flag when a keyboard has |
4510 |
|
been added: */ |
4511 |
|
machine->main_console_handle = dev_ns16550_init(machine, mem, |
4512 |
|
0x1000003f8ULL, 4, 1, 1, "com1"); |
4513 |
|
dev_ns16550_init(machine, mem, 0x100000378ULL, 3, 1, 0, "com2"); |
4514 |
|
|
4515 |
|
break; |
4516 |
|
|
4517 |
default: |
default: |
4518 |
fatal("Unknown emulation type %i\n", machine->machine_type); |
fatal("Unknown emulation type %i\n", machine->machine_type); |
4519 |
exit(1); |
exit(1); |
4817 |
case MACHINE_TESTALPHA: |
case MACHINE_TESTALPHA: |
4818 |
m->cpu_name = strdup("EV4"); |
m->cpu_name = strdup("EV4"); |
4819 |
break; |
break; |
4820 |
|
|
4821 |
|
/* x86: */ |
4822 |
|
case MACHINE_BAREX86: |
4823 |
|
case MACHINE_X86: |
4824 |
|
m->cpu_name = strdup("PENTIUM"); |
4825 |
|
break; |
4826 |
} |
} |
4827 |
|
|
4828 |
if (m->cpu_name == NULL) { |
if (m->cpu_name == NULL) { |
5071 |
* entries will appear in normal order when listed. :-) |
* entries will appear in normal order when listed. :-) |
5072 |
*/ |
*/ |
5073 |
|
|
5074 |
|
/* X86 machine: */ |
5075 |
|
me = machine_entry_new("x86 (generic PC-style machine)", ARCH_X86, |
5076 |
|
MACHINE_X86, 2, 0); |
5077 |
|
me->aliases[0] = "pc"; |
5078 |
|
me->aliases[1] = "x86"; |
5079 |
|
if (cpu_family_ptr_by_number(ARCH_X86) != NULL) { |
5080 |
|
me->next = first_machine_entry; first_machine_entry = me; |
5081 |
|
} |
5082 |
|
|
5083 |
/* Walnut: (NetBSD/evbppc) */ |
/* Walnut: (NetBSD/evbppc) */ |
5084 |
me = machine_entry_new("Walnut evaluation board", ARCH_PPC, |
me = machine_entry_new("Walnut evaluation board", ARCH_PPC, |
5085 |
MACHINE_WALNUT, 2, 0); |
MACHINE_WALNUT, 2, 0); |
5277 |
me->next = first_machine_entry; first_machine_entry = me; |
me->next = first_machine_entry; first_machine_entry = me; |
5278 |
} |
} |
5279 |
|
|
5280 |
|
/* Generic "bare" X86 machine: */ |
5281 |
|
me = machine_entry_new("Generic \"bare\" X86 machine", ARCH_X86, |
5282 |
|
MACHINE_BAREX86, 1, 0); |
5283 |
|
me->aliases[0] = "barex86"; |
5284 |
|
if (cpu_family_ptr_by_number(ARCH_X86) != NULL) { |
5285 |
|
me->next = first_machine_entry; first_machine_entry = me; |
5286 |
|
} |
5287 |
|
|
5288 |
/* Generic "bare" URISC machine: */ |
/* Generic "bare" URISC machine: */ |
5289 |
me = machine_entry_new("Generic \"bare\" URISC machine", ARCH_URISC, |
me = machine_entry_new("Generic \"bare\" URISC machine", ARCH_URISC, |
5290 |
MACHINE_BAREURISC, 1, 0); |
MACHINE_BAREURISC, 1, 0); |