[NTVDM]
[reactos.git] / reactos / subsystems / mvdm / ntvdm / dos / dos32krnl / condrv.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: dos/dos32krnl/condrv.c
5 * PURPOSE: DOS32 CON Driver
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #define NDEBUG
13
14 #include "ntvdm.h"
15 #include "emulator.h"
16
17 #include "dos.h"
18 #include "dos/dem.h"
19
20 #include "bios/bios.h"
21
22 /* PRIVATE VARIABLES **********************************************************/
23
24 PDOS_DEVICE_NODE Con = NULL;
25 BYTE ExtendedCode = 0;
26
27 /* PRIVATE FUNCTIONS **********************************************************/
28
29 WORD NTAPI ConDrvReadInput(PDOS_DEVICE_NODE Device, DWORD Buffer, PWORD Length)
30 {
31 CHAR Character;
32 WORD BytesRead = 0;
33 PCHAR Pointer = (PCHAR)FAR_POINTER(Buffer);
34
35 /* Save AX */
36 USHORT AX = getAX();
37
38 /*
39 * Use BIOS Get Keystroke function
40 */
41 while (BytesRead < *Length)
42 {
43 if (!ExtendedCode)
44 {
45 /* Call the BIOS INT 16h, AH=00h "Get Keystroke" */
46 setAH(0x00);
47 Int32Call(&DosContext, BIOS_KBD_INTERRUPT);
48
49 /* Retrieve the character in AL (scan code is in AH) */
50 Character = getAL();
51 }
52 else
53 {
54 /* Return the extended code */
55 Character = ExtendedCode;
56
57 /* And then clear it */
58 ExtendedCode = 0;
59 }
60
61 /* Check if this is a special character */
62 if (Character == 0) ExtendedCode = getAH();
63
64 if (DoEcho) DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
65 Pointer[BytesRead++] = Character;
66
67 /* Stop on first carriage return */
68 if (Character == '\r')
69 {
70 if (DoEcho) DosPrintCharacter(DOS_OUTPUT_HANDLE, '\n');
71 break;
72 }
73 }
74
75 *Length = BytesRead;
76
77 /* Restore AX */
78 setAX(AX);
79 return DOS_DEVSTAT_DONE;
80 }
81
82 WORD NTAPI ConDrvInputStatus(PDOS_DEVICE_NODE Device)
83 {
84 /* Save AX */
85 USHORT AX = getAX();
86
87 /* Call the BIOS */
88 setAH(0x01); // or 0x11 for enhanced, but what to choose?
89 Int32Call(&DosContext, BIOS_KBD_INTERRUPT);
90
91 /* Restore AX */
92 setAX(AX);
93
94 /* If ZF is set, set the busy bit */
95 if (getZF()) return DOS_DEVSTAT_BUSY;
96 else return DOS_DEVSTAT_DONE;
97 }
98
99 WORD NTAPI ConDrvWriteOutput(PDOS_DEVICE_NODE Device, DWORD Buffer, PWORD Length)
100 {
101 WORD BytesWritten;
102 PCHAR Pointer = (PCHAR)FAR_POINTER(Buffer);
103
104 /* Save AX */
105 USHORT AX = getAX();
106
107 for (BytesWritten = 0; BytesWritten < *Length; BytesWritten++)
108 {
109 /* Set the character */
110 setAL(Pointer[BytesWritten]);
111
112 /* Call the BIOS INT 29h "Fast Console Output" function */
113 Int32Call(&DosContext, 0x29);
114 }
115
116 /* Restore AX */
117 setAX(AX);
118 return DOS_DEVSTAT_DONE;
119 }
120
121 WORD NTAPI ConDrvOpen(PDOS_DEVICE_NODE Device)
122 {
123 DPRINT("Handle to %Z opened\n", &Device->Name);
124 return DOS_DEVSTAT_DONE;
125 }
126
127 WORD NTAPI ConDrvClose(PDOS_DEVICE_NODE Device)
128 {
129 DPRINT("Handle to %Z closed\n", &Device->Name);
130 return DOS_DEVSTAT_DONE;
131 }
132
133 /* PUBLIC FUNCTIONS ***********************************************************/
134
135 VOID ConDrvInitialize(VOID)
136 {
137 Con = DosCreateDevice(DOS_DEVATTR_STDIN
138 | DOS_DEVATTR_STDOUT
139 | DOS_DEVATTR_CON
140 | DOS_DEVATTR_CHARACTER,
141 "CON");
142
143 Con->ReadRoutine = ConDrvReadInput;
144 Con->InputStatusRoutine = ConDrvInputStatus;
145 Con->WriteRoutine = ConDrvWriteOutput;
146 Con->OpenRoutine = ConDrvOpen;
147 Con->CloseRoutine = ConDrvClose;
148 }
149
150 VOID ConDrvCleanup(VOID)
151 {
152 if (Con) DosDeleteDevice(Con);
153 }