add option (enabled by default) to allow resetting the DOSBox emulator

if the guest OS or application uses the standard method through the
keyboard controller. This fixes Windows ME's inability to reboot the
system when you select "restart system". Windows 95 and 98 apparently
happened to work regardless because they contained code to fallback to
calling INT 19h from real mode... or something.
This commit is contained in:
Jonathan Campbell
2014-04-13 14:35:20 -07:00
parent 49f72786d4
commit 277b6d0b16
3 changed files with 36 additions and 10 deletions

View File

@@ -1,9 +0,0 @@
Microsoft Windows Millenium Edition
System reboot doesn't work with DOSBox:
- I think it has to do with the fact that the keyboard controller
emulation correctly emulates the A20 gate for the output port
but not the reset line. Perhaps Windows 95/98 happens to work
because they also try port 0x92, while Windows ME for some reason
doesn't try port 0x92.

View File

@@ -269,6 +269,7 @@ void run_hw() {
extern Bitu dosbox_check_nonrecursive_pf_cs; extern Bitu dosbox_check_nonrecursive_pf_cs;
extern Bitu dosbox_check_nonrecursive_pf_eip; extern Bitu dosbox_check_nonrecursive_pf_eip;
extern bool allow_keyb_reset;
static Bitu Normal_Loop(void) { static Bitu Normal_Loop(void) {
Bits ret; Bits ret;
@@ -991,6 +992,11 @@ void DOSBOX_Init(void) {
Pbool->Set_help("Enable emulation of the 8042 auxiliary port. PS/2 mouse emulation requires this to be enabled.\n" Pbool->Set_help("Enable emulation of the 8042 auxiliary port. PS/2 mouse emulation requires this to be enabled.\n"
"You should enable this if you will be running Windows ME or any other OS that does not use the BIOS to receive mouse events."); "You should enable this if you will be running Windows ME or any other OS that does not use the BIOS to receive mouse events.");
Pbool = secprop->Add_bool("allow output port reset",Property::Changeable::OnlyAtStart,true);
Pbool->Set_help("If set (default), allow the application to reset the CPU through the keyboard controller.\n"
"This option is required to allow Windows ME to reboot properly, whereas Windows 9x and earlier\n"
"will reboot without this option using INT 19h");
Pstring = secprop->Add_string("auxdevice",Property::Changeable::OnlyAtStart,"intellimouse"); Pstring = secprop->Add_string("auxdevice",Property::Changeable::OnlyAtStart,"intellimouse");
Pstring->Set_values(auxdevices); Pstring->Set_values(auxdevices);
Pstring->Set_help("Type of PS/2 mouse attached to the AUX port"); Pstring->Set_help("Type of PS/2 mouse attached to the AUX port");

View File

@@ -414,6 +414,12 @@ static void KEYBOARD_AUX_Write(Bitu val) {
}; };
} }
#include "control.h"
bool allow_keyb_reset = true;
void restart_program(std::vector<std::string> & parameters);
static void write_p60(Bitu port,Bitu val,Bitu iolen) { static void write_p60(Bitu port,Bitu val,Bitu iolen) {
switch (keyb.command) { switch (keyb.command) {
case CMD_NONE: /* None */ case CMD_NONE: /* None */
@@ -508,6 +514,17 @@ static void write_p60(Bitu port,Bitu val,Bitu iolen) {
break; break;
case CMD_SETOUTPORT: case CMD_SETOUTPORT:
/* FIXME: if (val & 1 == 0) then reset the computer */ /* FIXME: if (val & 1 == 0) then reset the computer */
if (!(val & 1)) {
if (allow_keyb_reset) {
fprintf(stderr,"Restart by keyboard controller requested\n");
control->startup_params.insert(control->startup_params.begin(),control->cmdline->GetFileName());
restart_program(control->startup_params);
/* does not return */
}
else {
fprintf(stderr,"WARNING: Keyboard output port written with bit 1 clear. Is the guest OS or application attempting to reset the system?\n");
}
}
MEM_A20_Enable((val & 2)>0); MEM_A20_Enable((val & 2)>0);
keyb.command = CMD_NONE; keyb.command = CMD_NONE;
break; break;
@@ -655,7 +672,17 @@ static void write_p64(Bitu port,Bitu val,Bitu iolen) {
case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
/* pulse output register */ /* pulse output register */
/* TODO: If bit 0 == 0, trigger system reset */ if (!(val & 1)) {
if (allow_keyb_reset) {
fprintf(stderr,"Restart by keyboard controller requested\n");
control->startup_params.insert(control->startup_params.begin(),control->cmdline->GetFileName());
restart_program(control->startup_params);
/* does not return */
}
else {
fprintf(stderr,"WARNING: Keyboard output port written (pulsed) with bit 1 clear. Is the guest OS or application attempting to reset the system?\n");
}
}
break; break;
default: default:
LOG(LOG_KEYBOARD,LOG_ERROR)("Port 64 write with val %d",val); LOG(LOG_KEYBOARD,LOG_ERROR)("Port 64 write with val %d",val);
@@ -1206,6 +1233,8 @@ void KEYBOARD_Init(Section* sec) {
LOG(LOG_KEYBOARD,LOG_NORMAL)("Keyboard AUX emulation enabled"); LOG(LOG_KEYBOARD,LOG_NORMAL)("Keyboard AUX emulation enabled");
} }
allow_keyb_reset = section->Get_bool("allow output port reset");
keyb.ps2mouse.int33_taken = 0; keyb.ps2mouse.int33_taken = 0;
const char * sbtype=section->Get_string("auxdevice"); const char * sbtype=section->Get_string("auxdevice");