From 6af40b5b161c999d04981fb1c01c14dce9f566c4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 4 Jan 2017 05:58:44 +0100 Subject: [PATCH] Added a few keyboard controller commands used by the AMI BIOS'es; The port 92 handler in mem.c now flushes MMU cache when toggling the A20 gate; Added ability to reload previous disc after ejecting it; Fixed the START/STOP UNIT command for both SCSI and ATAPI; Applied mainline PCem commit: All XT models can now use 64kb RAM. Patch from ecksemmess . --- src/ide.c | 45 ++++++++++++++--------- src/keyboard_at.c | 92 ++++++++++++++++++++++++++++++++++++++++------- src/mem.c | 1 + src/model.c | 16 ++++----- src/pc.rc | 4 ++- src/resources.h | 1 + src/scsi_cdrom.c | 28 ++++++++++----- src/win.c | 91 ++++++++++++++++++++++++++++++++++++---------- 8 files changed, 215 insertions(+), 63 deletions(-) diff --git a/src/ide.c b/src/ide.c index c9c30fbe7..1355bfb53 100644 --- a/src/ide.c +++ b/src/ide.c @@ -1819,9 +1819,9 @@ static void atapicommand(int ide_board) int real_pos; int track = 0; -#if 0 pclog("ATAPI command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n",idebufferb[0],SCSISense.SenseKey,SCSISense.Asc,SCSISense.Ascq,ins,SCSISense.UnitAttention); +#if 0 int CdbLength; for (CdbLength = 1; CdbLength < 12; CdbLength++) { @@ -2576,23 +2576,30 @@ static void atapicommand(int ide_board) break; case GPCMD_START_STOP_UNIT: - if ((idebufferb[4] != 2) && (idebufferb[4] != 3) && idebufferb[4]) + switch(idebufferb[4] & 3) { - atapi_illegal_opcode(ide); - break; - } - if (!idebufferb[4]) - { - cdrom->stop(); - } - else if (idebufferb[4]==2) - { - cdrom->eject(); - } - else - { - cdrom->load(); + case 0: /* Stop the disc. */ + cdrom->stop(); + break; + case 1: /* Start the disc and read the TOC. */ + cdrom->medium_changed(); /* This causes a TOC reload. */ + break; + case 2: /* Eject the disc if possible. */ + cdrom->stop(); +#ifndef __unix + win_cdrom_eject(); +#endif + break; + case 3: /* Load the disc (close tray). */ +#ifndef __unix + win_cdrom_reload(); +#else + cdrom->load(); +#endif + break; + } + ide->packetstatus = ATAPI_STATUS_COMPLETE; idecallback[ide_board]=50*IDE_TIME; break; @@ -2674,6 +2681,10 @@ static void atapicommand(int ide_board) atapi_out: idebufferb[size_idx] = idx - preamble_len; len=idx; + if (len > alloc_length) + { + len = alloc_length; + } atapi_command_send_init(ide, temp_command, len, alloc_length); @@ -2743,6 +2754,8 @@ atapi_out: atapi_illegal_opcode(ide); break; } + + pclog("SCSI phase: %02X, length: %i\n", ide->secount, ide->cylinder); } static void callnonreadcd(IDE *ide) /* Callabck for non-Read CD commands */ diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 2bfc0c00d..edeeeb39e 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -44,9 +44,11 @@ struct int wantirq, wantirq12; uint8_t command; uint8_t status; - uint8_t mem[0x20]; + uint8_t mem[0x100]; uint8_t out; int out_new; + uint8_t secr_phase; + uint8_t mem_addr; uint8_t input_port; uint8_t output_port; @@ -55,6 +57,9 @@ struct int key_wantdata; int last_irq; + + uint8_t last_scan_code; + uint8_t default_mode; void (*mouse_write)(uint8_t val, void *p); void *mouse_p; @@ -278,6 +283,7 @@ write_register: therefore, set to set 2. */ mode |= 2; } + keyboard_at.default_mode = (mode & 3); first_write = 0; // pclog("Keyboard set to scan code set %i, mode & 0x60 = 0x%02X\n", mode & 3, mode & 0x60); /* No else because in all other cases, translation is off, so we need to keep it @@ -286,6 +292,29 @@ write_register: } break; + case 0xaf: /*AMI - set extended controller RAM*/ + if (keyboard_at.secr_phase == 0) + { + // pclog("Set extended controller RAM - phase 0 (bad)\n"); + goto bad_command; + } + else if (keyboard_at.secr_phase == 1) + { + // pclog("Set extended controller RAM - phase 1\n"); + keyboard_at.mem_addr = val; + keyboard_at.want60 = 1; + keyboard_at.secr_phase = 2; + // pclog("Set extended controller RAM - starting phase 2\n"); + } + else if (keyboard_at.secr_phase == 2) + { + // pclog("Set extended controller RAM - phase 2\n"); + keyboard_at.mem[keyboard_at.mem_addr] = val; + keyboard_at.secr_phase = 0; + // pclog("Set extended controller RAM - starting phase 0\n"); + } + break; + case 0xcb: /*AMI - set keyboard mode*/ break; @@ -321,6 +350,7 @@ write_register: break; default: +bad_command: pclog("Bad AT keyboard controller 0060 write %02X command %02X\n", val, keyboard_at.command); // dumpregs(); // exit(-1); @@ -379,10 +409,21 @@ write_register: keyboard_at_adddata_keyboard(0xfe); break; + case 0x71: /*These two commands are sent by Pentium-era AMI BIOS'es.*/ + case 0x82: + break; + case 0xed: /*Set/reset LEDs*/ keyboard_at.key_wantdata = 1; keyboard_at_adddata_keyboard(0xfa); break; + + case 0xee: /*Diagnostic echo*/ + keyboard_at_adddata_keyboard(0xee); + break; + + case 0xef: /*NOP (No OPeration). Reserved for future use.*/ + break; case 0xf0: /*Get/set scan code set*/ keyboard_at.key_wantdata = 1; @@ -415,7 +456,8 @@ write_register: set3_all_break = 0; set3_all_repeat = 0; memset(set3_flags, 0, 272); - mode = (mode & 0xFC) | 2; + // mode = (mode & 0xFC) | 2; + mode = (mode & 0xFC) | keyboard_at.default_mode; keyboard_at_adddata_keyboard(0xfa); break; @@ -440,6 +482,10 @@ write_register: keyboard_at_adddata_keyboard(0xfa); break; + case 0xfe: /*Resend last scan code*/ + keyboard_at_adddata_keyboard(keyboard_at.last_scan_code); + break; + case 0xff: /*Reset*/ // pclog("KEYBOARD_AT: Set defaults\n"); key_queue_start = key_queue_end = 0; /*Clear key queue*/ @@ -565,6 +611,36 @@ write_register: keyboard_at.mem[0] &= ~0x10; break; + case 0xaf: + switch(romset) + { + case ROM_AMI286: + case ROM_AMI386SX: + case ROM_AMI386DX_OPTI495: + case ROM_MR386DX_OPTI495: + case ROM_AMI486: + case ROM_WIN486: + case ROM_REVENGE: + case ROM_PLATO: + case ROM_ENDEAVOR: + case ROM_THOR: + case ROM_MRTHOR: + /*Set extended controlled RAM*/ + keyboard_at.want60 = 1; + keyboard_at.secr_phase = 1; + // pclog("Set extended controller RAM - starting phase 1\n"); + break; + default: + /*Read keyboard version*/ + keyboard_at_adddata(0x00); + break; + } + break; + + case 0xb0 ... 0xbf: /*Set keyboard lines low (B0-B7) or high (B8-BF)*/ + keyboard_at_adddata(0x00); + break; + case 0xc0: /*Read input port*/ keyboard_at_adddata((keyboard_at.input_port & 0xf0) | 0x80); // keyboard_at_adddata(keyboard_at.input_port | 4); @@ -631,16 +707,6 @@ write_register: cpu_set_edx(); } break; - -#if 0 - case 0xfe: /*Pulse output port - pin 0 selected - x86 reset*/ - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - break; - - case 0xff: /*Pulse output port - but no pins selected - sent by MegaPC BIOS*/ - break; -#endif default: pclog("Bad AT keyboard controller command %02X\n", val); @@ -690,12 +756,14 @@ void keyboard_at_reset() keyboard_at.status = STAT_LOCK | STAT_CD; keyboard_at.mem[0] = 0x11; mode = 0x02 | dtrans; + keyboard_at.default_mode = 2; first_write = 1; keyboard_at.wantirq = 0; keyboard_at.output_port = 0xcf; keyboard_at.input_port = 0xb0; keyboard_at.out_new = -1; keyboard_at.last_irq = 0; + keyboard_at.secr_phase = 0; keyboard_at.key_wantdata = 0; diff --git a/src/mem.c b/src/mem.c index d0d5e4fe6..acc1280cf 100644 --- a/src/mem.c +++ b/src/mem.c @@ -2169,6 +2169,7 @@ void port_92_reset() port_92_reg = 0; mem_a20_alt = 0; mem_a20_recalc(); + flushmmucache(); } uint32_t get_phys_virt,get_phys_phys; diff --git a/src/model.c b/src/model.c index fb17fa28d..1b9868484 100644 --- a/src/model.c +++ b/src/model.c @@ -116,15 +116,15 @@ int AMSTRAD, AT, PCI, TANDY; MODEL models[] = { {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, - {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, {"IBM PCjr", ROM_IBMPCJR, { "", cpus_pcjr, "", NULL, "", NULL}, 1, 0, 128, 640, 128, pcjr_init, &pcjr_device}, - {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, - {"AMI XT clone", ROM_AMIXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, - {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, - {"VTech Laser Turbo XT",ROM_LTXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, - {"VTech Laser XT3", ROM_LXT3, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, - {"Phoenix XT clone", ROM_PXXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, - {"Juko XT clone", ROM_JUKOPC, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, + {"AMI XT clone", ROM_AMIXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, + {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, + {"VTech Laser Turbo XT",ROM_LTXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, + {"VTech Laser XT3", ROM_LXT3, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, + {"Phoenix XT clone", ROM_PXXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, + {"Juko XT clone", ROM_JUKOPC, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, 0, 128, 640, 128, tandy1k_init, &tandy1000_device}, {"Tandy 1000 HX", ROM_TANDY1000HX, { "", cpus_8088, "", NULL, "", NULL}, 1, 0, 256, 640, 128, tandy1k_init, &tandy1000hx_device}, {"Tandy 1000 SL/2", ROM_TANDY1000SL2,{ "", cpus_8086, "", NULL, "", NULL}, 1, 0, 512, 768, 128, tandy1ksl2_init, NULL}, diff --git a/src/pc.rc b/src/pc.rc index 165dc8274..fcb8741dc 100644 --- a/src/pc.rc +++ b/src/pc.rc @@ -40,7 +40,9 @@ BEGIN MENUITEM "&Enabled", IDM_CDROM_ENABLED MENUITEM "&SCSI", IDM_CDROM_SCSI MENUITEM SEPARATOR - MENUITEM "&Empty",IDM_CDROM_EMPTY + MENUITEM "E&mpty",IDM_CDROM_EMPTY + MENUITEM "&Reload previous disc",IDM_CDROM_RELOAD + MENUITEM SEPARATOR MENUITEM "&ISO...",IDM_CDROM_ISO END POPUP "E&xtra IDE controllers" diff --git a/src/resources.h b/src/resources.h index 083275bfd..864b12330 100644 --- a/src/resources.h +++ b/src/resources.h @@ -36,6 +36,7 @@ #define IDM_DISC_3_WP 40083 #define IDM_DISC_4_WP 40084 #define IDM_CDROM_ISO 40100 +#define IDM_CDROM_RELOAD 40101 #define IDM_CDROM_EMPTY 40200 #define IDM_CDROM_REAL 40200 #define IDM_CDROM_ENABLED 40300 diff --git a/src/scsi_cdrom.c b/src/scsi_cdrom.c index 9c73b734f..a26e02ee6 100644 --- a/src/scsi_cdrom.c +++ b/src/scsi_cdrom.c @@ -1061,16 +1061,28 @@ SCSIOut: return; case GPCMD_START_STOP_UNIT: - if (cdb[4]!=2 && cdb[4]!=3 && cdb[4]) + switch(cdb[4] & 3) { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - break; + case 0: /* Stop the disc. */ + cdrom->stop(); + break; + case 1: /* Start the disc and read the TOC. */ + cdrom->medium_changed(); /* This causes a TOC reload. */ + break; + case 2: /* Eject the disc if possible. */ + cdrom->stop(); +#ifndef __unix + win_cdrom_eject(); +#endif + break; + case 3: /* Load the disc (close tray). */ +#ifndef __unix + win_cdrom_reload(); +#else + cdrom->load(); +#endif + break; } - if (!cdb[4]) cdrom->stop(); - else if (cdb[4]==2) cdrom->eject(); - else cdrom->load(); SCSIPhase = SCSI_PHASE_STATUS; SCSIStatus = SCSI_STATUS_OK; diff --git a/src/win.c b/src/win.c index 9e2808ead..ad03db92b 100644 --- a/src/win.c +++ b/src/win.c @@ -1312,6 +1312,73 @@ void video_toggle_option(HMENU hmenu, int *val, int id) saveconfig(); } +void win_cdrom_eject() +{ + HMENU hmenu; + hmenu=GetMenu(ghwnd); + if (cdrom_drive == 0) + { + /* Switch from empty to empty. Do nothing. */ + return; + } + cdrom->exit(); + cdrom_close(); + cdrom_null_open(0); + if (cdrom_enabled) + { + /* Signal disc change to the emulated machine. */ + SCSICDROM_Insert(); + } + CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); + old_cdrom_drive = cdrom_drive; + cdrom_drive=0; + CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED); + saveconfig(); +} + +void win_cdrom_reload() +{ + HMENU hmenu; + hmenu=GetMenu(ghwnd); + int new_cdrom_drive; + if ((cdrom_drive == old_cdrom_drive) || (old_cdrom_drive == 0)) + { + /* Switch from empty to empty. Do nothing. */ + return; + } + if (old_cdrom_drive == 200) + { + iso_open(iso_path); + if (cdrom_enabled) + { + /* Signal disc change to the emulated machine. */ + SCSICDROM_Insert(); + } + CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); + // CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); + cdrom_drive = 200; + CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_CHECKED); + saveconfig(); + } + else + { + new_cdrom_drive = old_cdrom_drive; + ioctl_open(new_cdrom_drive); + if (cdrom_enabled) + { + /* Signal disc change to the emulated machine. */ + SCSICDROM_Insert(); + } + CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); + cdrom_drive = new_cdrom_drive; + CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED); + saveconfig(); + } +} + LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HMENU hmenu; @@ -1750,12 +1817,6 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM break; case IDM_CDROM_EMPTY: - /* if (!cdrom_enabled) - { - if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) - break; - } */ - // if ((cdrom_drive == 0) && cdrom_enabled) if (cdrom_drive == 0) { /* Switch from empty to empty. Do nothing. */ @@ -1770,23 +1831,17 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM SCSICDROM_Insert(); } CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); - // CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); - old_cdrom_drive = cdrom_drive; + CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); + old_cdrom_drive = cdrom_drive; cdrom_drive=0; CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED); saveconfig(); - /* if (!cdrom_enabled) - { - pause = 1; - Sleep(100); - cdrom_enabled = 1; - saveconfig(); - resetpchard(); - pause = 0; - } */ break; + case IDM_CDROM_RELOAD: + win_cdrom_reload(); + break; + case IDM_CDROM_ISO: if (!getfile(hwnd,"CD-ROM image (*.ISO)\0*.ISO\0All files (*.*)\0*.*\0",iso_path)) {