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