static VOID XmsLocalDisableA20(VOID) { UCHAR Result = XMS_STATUS_SUCCESS; /* Disable A20 only if we can do so, otherwise make the caller believe we disabled it */ if (!CanChangeA20) goto Quit; /* If the count is already zero, fail */ if (A20EnableCount == 0) goto Fail; --A20EnableCount; /* The count is zero so disable A20 */ if (A20EnableCount == 0) EmulatorSetA20(FALSE); // Result = XMS_STATUS_SUCCESS; else Result = XMS_STATUS_A20_STILL_ENABLED; Quit: setAX(0x0001); /* Line successfully disabled */ setBL(Result); return; Fail: setAX(0x0000); /* Line failed to be disabled */ setBL(XMS_STATUS_A20_ERROR); return; }
static VOID XmsLocalEnableA20(VOID) { /* Enable A20 only if we can do so, otherwise make the caller believe we enabled it */ if (!CanChangeA20) goto Quit; /* The count is zero so enable A20 */ if (A20EnableCount == 0) EmulatorSetA20(TRUE); ++A20EnableCount; Quit: setAX(0x0001); /* Line successfully enabled */ setBL(XMS_STATUS_SUCCESS); return; }
static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data) { if (Port == PS2_CONTROL_PORT) { switch (Data) { /* Read configuration byte */ case 0x20: { OutputBuffer = ControllerConfig; StatusRegister |= (1 << 0); // There is something to read break; } /* Write configuration byte */ case 0x60: /* Write controller output port */ case 0xD1: /* Write to the first PS/2 port output buffer */ case 0xD2: /* Write to the second PS/2 port output buffer */ case 0xD3: /* Write to the second PS/2 port input buffer */ case 0xD4: { /* These commands require a response */ ControllerCommand = Data; StatusRegister |= (1 << 3); // This is a controller command break; } /* Disable second PS/2 port */ case 0xA7: { Ports[1].IsEnabled = FALSE; break; } /* Enable second PS/2 port */ case 0xA8: { Ports[1].IsEnabled = TRUE; break; } /* Test second PS/2 port */ case 0xA9: { OutputBuffer = 0x00; // Success code StatusRegister |= (1 << 0); // There is something to read break; } /* Test PS/2 controller */ case 0xAA: { OutputBuffer = 0x55; // Success code StatusRegister |= (1 << 0); // There is something to read break; } /* Test first PS/2 port */ case 0xAB: { OutputBuffer = 0x00; // Success code StatusRegister |= (1 << 0); // There is something to read break; } /* Disable first PS/2 port */ case 0xAD: { Ports[0].IsEnabled = FALSE; break; } /* Enable first PS/2 port */ case 0xAE: { Ports[0].IsEnabled = TRUE; break; } /* Read controller output port */ case 0xD0: { // TODO: Not implemented break; } /* CPU Reset */ case 0xF0: case 0xF2: case 0xF4: case 0xF6: case 0xF8: case 0xFA: case 0xFC: case 0xFE: { /* Stop the VDM */ EmulatorTerminate(); break; } } } else if (Port == PS2_DATA_PORT) { /* Check if the controller is waiting for a response */ if (StatusRegister & (1 << 3)) // If we have data for the controller { StatusRegister &= ~(1 << 3); /* Check which command it was */ switch (ControllerCommand) { /* Write configuration byte */ case 0x60: { ControllerConfig = Data; break; } /* Write controller output */ case 0xD1: { /* Check if bit 0 is unset */ if (!(Data & (1 << 0))) { /* CPU disabled - Stop the VDM */ EmulatorTerminate(); } /* Update the A20 line setting */ EmulatorSetA20(Data & (1 << 1)); break; } /* Push the data byte into the first PS/2 port queue */ case 0xD2: { PS2QueuePush(0, Data); break; } /* Push the data byte into the second PS/2 port queue */ case 0xD3: { PS2QueuePush(1, Data); break; } /* * Send a command to the second PS/2 port (by default * it is a command for the first PS/2 port) */ case 0xD4: { PS2SendCommand(&Ports[1], Data); break; } } return; } /* By default, send a command to the first PS/2 port */ PS2SendCommand(&Ports[0], Data); } }