2015-03-26 00:21:25 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS Virtual DOS Machine
|
2015-09-18 17:01:49 +00:00
|
|
|
* FILE: subsystems/mvdm/ntvdm/dos/dos32krnl/condrv.c
|
2015-03-26 00:21:25 +00:00
|
|
|
* PURPOSE: DOS32 CON Driver
|
|
|
|
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
|
|
|
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
|
|
|
*/
|
|
|
|
|
2015-10-04 11:49:28 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
2015-10-03 19:17:55 +00:00
|
|
|
#include "ntvdm.h"
|
|
|
|
|
2015-03-26 00:21:25 +00:00
|
|
|
#define NDEBUG
|
2015-10-03 19:17:55 +00:00
|
|
|
#include <debug.h>
|
2015-03-26 00:21:25 +00:00
|
|
|
|
2015-10-04 11:49:28 +00:00
|
|
|
#include "emulator.h"
|
|
|
|
|
|
|
|
#include "dos.h"
|
|
|
|
#include "dos/dem.h"
|
|
|
|
|
|
|
|
#include "bios/bios.h"
|
|
|
|
|
2015-03-26 00:21:25 +00:00
|
|
|
/* PRIVATE VARIABLES **********************************************************/
|
|
|
|
|
2015-03-26 23:31:01 +00:00
|
|
|
PDOS_DEVICE_NODE Con = NULL;
|
2015-03-26 23:19:22 +00:00
|
|
|
BYTE ExtendedCode = 0;
|
2015-03-26 00:21:25 +00:00
|
|
|
|
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
|
|
|
|
|
|
|
WORD NTAPI ConDrvReadInput(PDOS_DEVICE_NODE Device, DWORD Buffer, PWORD Length)
|
|
|
|
{
|
|
|
|
CHAR Character;
|
2015-03-26 23:19:22 +00:00
|
|
|
WORD BytesRead = 0;
|
2015-03-26 00:21:25 +00:00
|
|
|
PCHAR Pointer = (PCHAR)FAR_POINTER(Buffer);
|
|
|
|
|
|
|
|
/* Save AX */
|
|
|
|
USHORT AX = getAX();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use BIOS Get Keystroke function
|
|
|
|
*/
|
2015-03-26 23:19:22 +00:00
|
|
|
while (BytesRead < *Length)
|
2015-03-26 00:21:25 +00:00
|
|
|
{
|
2015-03-26 23:19:22 +00:00
|
|
|
if (!ExtendedCode)
|
|
|
|
{
|
2015-05-05 18:16:56 +00:00
|
|
|
/* Call the BIOS INT 16h, AH=00h "Get Keystroke" */
|
|
|
|
setAH(0x00);
|
2015-03-26 23:19:22 +00:00
|
|
|
Int32Call(&DosContext, BIOS_KBD_INTERRUPT);
|
|
|
|
|
|
|
|
/* Retrieve the character in AL (scan code is in AH) */
|
|
|
|
Character = getAL();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Return the extended code */
|
|
|
|
Character = ExtendedCode;
|
|
|
|
|
|
|
|
/* And then clear it */
|
|
|
|
ExtendedCode = 0;
|
|
|
|
}
|
2015-03-26 00:21:25 +00:00
|
|
|
|
2015-03-26 23:19:22 +00:00
|
|
|
/* Check if this is a special character */
|
2015-05-05 18:16:56 +00:00
|
|
|
if (Character == 0) ExtendedCode = getAH();
|
2015-03-26 00:21:25 +00:00
|
|
|
|
2015-03-26 23:19:22 +00:00
|
|
|
Pointer[BytesRead++] = Character;
|
2015-03-26 00:21:25 +00:00
|
|
|
|
|
|
|
/* Stop on first carriage return */
|
2015-09-25 22:00:57 +00:00
|
|
|
if (Character == '\r') break;
|
2015-03-26 00:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*Length = BytesRead;
|
|
|
|
|
|
|
|
/* Restore AX */
|
|
|
|
setAX(AX);
|
|
|
|
return DOS_DEVSTAT_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
WORD NTAPI ConDrvInputStatus(PDOS_DEVICE_NODE Device)
|
|
|
|
{
|
|
|
|
/* Save AX */
|
|
|
|
USHORT AX = getAX();
|
|
|
|
|
|
|
|
/* Call the BIOS */
|
|
|
|
setAH(0x01); // or 0x11 for enhanced, but what to choose?
|
|
|
|
Int32Call(&DosContext, BIOS_KBD_INTERRUPT);
|
|
|
|
|
|
|
|
/* Restore AX */
|
|
|
|
setAX(AX);
|
|
|
|
|
|
|
|
/* If ZF is set, set the busy bit */
|
2015-05-06 20:09:38 +00:00
|
|
|
if (getZF() && !ExtendedCode) return DOS_DEVSTAT_BUSY;
|
2015-03-26 00:21:25 +00:00
|
|
|
else return DOS_DEVSTAT_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
WORD NTAPI ConDrvWriteOutput(PDOS_DEVICE_NODE Device, DWORD Buffer, PWORD Length)
|
|
|
|
{
|
|
|
|
WORD BytesWritten;
|
|
|
|
PCHAR Pointer = (PCHAR)FAR_POINTER(Buffer);
|
|
|
|
|
2015-03-31 03:05:09 +00:00
|
|
|
/* Save AX */
|
2015-03-26 00:21:25 +00:00
|
|
|
USHORT AX = getAX();
|
|
|
|
|
|
|
|
for (BytesWritten = 0; BytesWritten < *Length; BytesWritten++)
|
|
|
|
{
|
2015-03-31 03:05:09 +00:00
|
|
|
/* Set the character */
|
2015-03-26 00:21:25 +00:00
|
|
|
setAL(Pointer[BytesWritten]);
|
|
|
|
|
2015-03-31 03:05:09 +00:00
|
|
|
/* Call the BIOS INT 29h "Fast Console Output" function */
|
|
|
|
Int32Call(&DosContext, 0x29);
|
2015-03-26 00:21:25 +00:00
|
|
|
}
|
|
|
|
|
2015-03-31 03:05:09 +00:00
|
|
|
/* Restore AX */
|
2015-03-26 00:21:25 +00:00
|
|
|
setAX(AX);
|
|
|
|
return DOS_DEVSTAT_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
WORD NTAPI ConDrvOpen(PDOS_DEVICE_NODE Device)
|
|
|
|
{
|
|
|
|
DPRINT("Handle to %Z opened\n", &Device->Name);
|
|
|
|
return DOS_DEVSTAT_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
WORD NTAPI ConDrvClose(PDOS_DEVICE_NODE Device)
|
|
|
|
{
|
|
|
|
DPRINT("Handle to %Z closed\n", &Device->Name);
|
|
|
|
return DOS_DEVSTAT_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
|
|
|
|
2015-03-26 23:31:01 +00:00
|
|
|
VOID ConDrvInitialize(VOID)
|
2015-03-26 00:21:25 +00:00
|
|
|
{
|
2015-03-26 23:31:01 +00:00
|
|
|
Con = DosCreateDevice(DOS_DEVATTR_STDIN
|
|
|
|
| DOS_DEVATTR_STDOUT
|
|
|
|
| DOS_DEVATTR_CON
|
|
|
|
| DOS_DEVATTR_CHARACTER,
|
|
|
|
"CON");
|
|
|
|
|
|
|
|
Con->ReadRoutine = ConDrvReadInput;
|
|
|
|
Con->InputStatusRoutine = ConDrvInputStatus;
|
|
|
|
Con->WriteRoutine = ConDrvWriteOutput;
|
|
|
|
Con->OpenRoutine = ConDrvOpen;
|
|
|
|
Con->CloseRoutine = ConDrvClose;
|
2015-03-26 00:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID ConDrvCleanup(VOID)
|
|
|
|
{
|
2015-03-26 23:31:01 +00:00
|
|
|
if (Con) DosDeleteDevice(Con);
|
2015-03-26 00:21:25 +00:00
|
|
|
}
|