* Comment out some unused but set variables, remove some others.
[reactos.git] / reactos / ntoskrnl / ex / hdlsterm.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/ex/hdlsterm.c
5 * PURPOSE: Headless Terminal Support
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #include <debug.h>
13
14 /* GLOBALS *******************************************************************/
15
16 PHEADLESS_GLOBALS HeadlessGlobals;
17
18 /* FUNCTIONS *****************************************************************/
19
20 VOID
21 NTAPI
22 HdlspSendStringAtBaud(
23 IN PUCHAR String
24 )
25 {
26 /* Send every byte */
27 while (*String++ != ANSI_NULL)
28 {
29 InbvPortPutByte(HeadlessGlobals->TerminalPort, *String);
30 }
31 }
32
33 NTSTATUS
34 NTAPI
35 HdlspEnableTerminal(
36 IN BOOLEAN Enable
37 )
38 {
39 /* Enable if requested, as long as this isn't a PCI serial port crashing */
40 if ((Enable) &&
41 !(HeadlessGlobals->TerminalEnabled) &&
42 !((HeadlessGlobals->IsMMIODevice) && (HeadlessGlobals->InBugCheck)))
43 {
44 /* Initialize the COM port with cportlib */
45 HeadlessGlobals->TerminalEnabled = InbvPortInitialize(
46 HeadlessGlobals->TerminalBaudRate,
47 HeadlessGlobals->TerminalPortNumber,
48 HeadlessGlobals->TerminalPortAddress,
49 &HeadlessGlobals->TerminalPort,
50 HeadlessGlobals->IsMMIODevice);
51 if (!HeadlessGlobals->TerminalEnabled) return STATUS_UNSUCCESSFUL;
52
53 /* Cleanup the screen and reset the cursor */
54 HdlspSendStringAtBaud((PUCHAR)"\x1B[2J");
55 HdlspSendStringAtBaud((PUCHAR)"\x1B[H");
56
57 /* Enable FIFO */
58 InbvPortEnableFifo(HeadlessGlobals->TerminalPort, TRUE);
59 }
60 else if (!Enable)
61 {
62 /* Specific case when headless is being disabled */
63 InbvPortTerminate(HeadlessGlobals->TerminalPort);
64 HeadlessGlobals->TerminalPort = 0;
65 HeadlessGlobals->TerminalEnabled = FALSE;
66 }
67 return STATUS_SUCCESS;
68 }
69
70 VOID
71 NTAPI
72 INIT_FUNCTION
73 HeadlessInit(
74 IN PLOADER_PARAMETER_BLOCK LoaderBlock
75 )
76 {
77 PHEADLESS_LOADER_BLOCK HeadlessBlock;
78
79 HeadlessBlock = LoaderBlock->Extension->HeadlessLoaderBlock;
80 if (!HeadlessBlock) return;
81 if ((HeadlessBlock->PortNumber > 4) && (HeadlessBlock->UsedBiosSettings)) return;
82
83 HeadlessGlobals = ExAllocatePoolWithTag(
84 NonPagedPool,
85 sizeof(HEADLESS_GLOBALS),
86 'sldH');
87 if (!HeadlessGlobals) return;
88
89 /* Zero and copy loader data */
90 RtlZeroMemory(HeadlessGlobals, sizeof(HEADLESS_GLOBALS));
91 HeadlessGlobals->TerminalPortNumber = HeadlessBlock->PortNumber;
92 HeadlessGlobals->TerminalPortAddress = HeadlessBlock->PortAddress;
93 HeadlessGlobals->TerminalBaudRate = HeadlessBlock->BaudRate;
94 HeadlessGlobals->TerminalParity = HeadlessBlock->Parity;
95 HeadlessGlobals->TerminalStopBits = HeadlessBlock->StopBits;
96 HeadlessGlobals->UsedBiosSettings = HeadlessBlock->UsedBiosSettings;
97 HeadlessGlobals->IsMMIODevice = HeadlessBlock->IsMMIODevice;
98 HeadlessGlobals->TerminalType = HeadlessBlock->TerminalType;
99 HeadlessGlobals->SystemGUID = HeadlessBlock->SystemGUID;
100
101 /* These two are opposites of each other */
102 if (HeadlessGlobals->IsMMIODevice) HeadlessGlobals->IsNonLegacyDevice = TRUE;
103
104 /* Check for a PCI device, warn that this isn't supported */
105 if (HeadlessBlock->PciDeviceId != PCI_INVALID_VENDORID)
106 {
107 DPRINT1("PCI Serial Ports not supported\n");
108 }
109
110 /* Log entries are not yet supported */
111 DPRINT1("FIXME: No Headless logging support\n");
112
113 /* Allocate temporary buffer */
114 HeadlessGlobals->TmpBuffer = ExAllocatePoolWithTag(NonPagedPool, 80, 'sldH');
115 if (!HeadlessGlobals->TmpBuffer) return;
116
117 /* Windows seems to apply some special hacks for 9600 bps */
118 if (HeadlessGlobals->TerminalBaudRate == 9600)
119 {
120 DPRINT1("Please use other baud rate than 9600bps for now\n");
121 }
122
123 /* Enable the terminal */
124 HdlspEnableTerminal(TRUE);
125 }
126
127 VOID
128 NTAPI
129 HdlspPutString(
130 IN PUCHAR String
131 )
132 {
133 PUCHAR Dest = HeadlessGlobals->TmpBuffer;
134 UCHAR Char = 0;
135
136 /* Scan each character */
137 while (*String != ANSI_NULL)
138 {
139 /* Check for rotate, send existing buffer and restart from where we are */
140 if (Dest >= &HeadlessGlobals->TmpBuffer[79])
141 {
142 HeadlessGlobals->TmpBuffer[79] = ANSI_NULL;
143 HdlspSendStringAtBaud(HeadlessGlobals->TmpBuffer);
144 Dest = HeadlessGlobals->TmpBuffer;
145 }
146 else
147 {
148 /* Get the current character and check for special graphical chars */
149 Char = *String;
150 if (Char & 0x80)
151 {
152 switch (Char)
153 {
154 case 0xB0: case 0xB3: case 0xBA:
155 Char = '|';
156 break;
157 case 0xB1: case 0xDC: case 0xDD: case 0xDE: case 0xDF:
158 Char = '%';
159 break;
160 case 0xB2: case 0xDB:
161 Char = '#';
162 break;
163 case 0xA9: case 0xAA: case 0xBB: case 0xBC: case 0xBF:
164 case 0xC0: case 0xC8: case 0xC9: case 0xD9: case 0xDA:
165 Char = '+';
166 break;
167 case 0xC4:
168 Char = '-';
169 break;
170 case 0xCD:
171 Char = '=';
172 break;
173 }
174 }
175
176 /* Anything else must be Unicode */
177 if (Char & 0x80)
178 {
179 /* Can't do Unicode yet */
180 UNIMPLEMENTED;
181 }
182 else
183 {
184 /* Add the modified char to the temporary buffer */
185 *Dest++ = Char;
186 }
187
188 /* Check the next char */
189 String++;
190 }
191 }
192
193 /* Finish and send */
194 *Dest = ANSI_NULL;
195 HdlspSendStringAtBaud(HeadlessGlobals->TmpBuffer);
196 }
197
198 NTSTATUS
199 NTAPI
200 HdlspDispatch(
201 IN HEADLESS_CMD Command,
202 IN PVOID InputBuffer,
203 IN SIZE_T InputBufferSize,
204 OUT PVOID OutputBuffer,
205 OUT PSIZE_T OutputBufferSize
206 )
207 {
208 //NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
209 ASSERT(HeadlessGlobals != NULL);
210 // ASSERT(HeadlessGlobals->PageLockHandle != NULL);
211
212 /* FIXME: This should be using the headless spinlock */
213
214 /* Ignore non-reentrant commands */
215 if ((Command != HeadlessCmdAddLogEntry) &&
216 (Command != HeadlessCmdStartBugCheck) &&
217 (Command != HeadlessCmdSendBlueScreenData) &&
218 (Command != HeadlessCmdDoBugCheckProcessing))
219 {
220 if (HeadlessGlobals->ProcessingCmd) return STATUS_UNSUCCESSFUL;
221
222 /* Don't allow these commands next time */
223 HeadlessGlobals->ProcessingCmd = TRUE;
224 }
225
226 /* Handle each command */
227 switch (Command)
228 {
229 case HeadlessCmdEnableTerminal:
230 break;
231 case HeadlessCmdCheckForReboot:
232 break;
233
234 case HeadlessCmdPutString:
235
236 /* Validate the existence of an input buffer */
237 if (!InputBuffer)
238 {
239 //Status = STATUS_INVALID_PARAMETER;
240 goto Reset;
241 }
242
243 /* Terminal should be on */
244 if (HeadlessGlobals->TerminalEnabled)
245 {
246 /* Print each byte in the string making sure VT100 chars are used */
247 PHEADLESS_CMD_PUT_STRING PutString = (PVOID)InputBuffer;
248 HdlspPutString(PutString->String);
249 }
250
251 /* Return success either way */
252 //Status = STATUS_SUCCESS;
253 break;
254 case HeadlessCmdClearDisplay:
255 break;
256 case HeadlessCmdClearToEndOfDisplay:
257 break;
258 case HeadlessCmdClearToEndOfLine:
259 break;
260 case HeadlessCmdDisplayAttributesOff:
261 break;
262 case HeadlessCmdDisplayInverseVideo:
263 break;
264 case HeadlessCmdSetColor:
265 break;
266 case HeadlessCmdPositionCursor:
267 break;
268 case HeadlessCmdTerminalPoll:
269 break;
270 case HeadlessCmdGetByte:
271 break;
272 case HeadlessCmdGetLine:
273 break;
274 case HeadlessCmdStartBugCheck:
275 break;
276 case HeadlessCmdDoBugCheckProcessing:
277 break;
278 case HeadlessCmdQueryInformation:
279 break;
280 case HeadlessCmdAddLogEntry:
281 break;
282 case HeadlessCmdDisplayLog:
283 break;
284 case HeadlessCmdSetBlueScreenData:
285 break;
286 case HeadlessCmdSendBlueScreenData:
287 break;
288 case HeadlessCmdQueryGUID:
289 break;
290 case HeadlessCmdPutData:
291 break;
292 default:
293 break;
294 }
295
296 Reset:
297 /* Unset prcessing state */
298 if ((Command != HeadlessCmdAddLogEntry) &&
299 (Command != HeadlessCmdStartBugCheck) &&
300 (Command != HeadlessCmdSendBlueScreenData) &&
301 (Command != HeadlessCmdDoBugCheckProcessing))
302 {
303 ASSERT(HeadlessGlobals->ProcessingCmd == TRUE);
304 HeadlessGlobals->ProcessingCmd = FALSE;
305 }
306
307 //UNIMPLEMENTED;
308 return STATUS_SUCCESS;
309 }
310
311 /*
312 * @unimplemented
313 */
314 NTSTATUS
315 NTAPI
316 HeadlessDispatch(
317 IN HEADLESS_CMD Command,
318 IN PVOID InputBuffer,
319 IN SIZE_T InputBufferSize,
320 OUT PVOID OutputBuffer,
321 OUT PSIZE_T OutputBufferSize
322 )
323 {
324 /* Check for stubs that will expect something even with headless off */
325 if (!HeadlessGlobals)
326 {
327 /* Don't allow the SAC to connect */
328 if (Command == HeadlessCmdEnableTerminal) return STATUS_UNSUCCESSFUL;
329
330 /* Send bogus reply */
331 if ((Command == HeadlessCmdQueryInformation) ||
332 (Command == HeadlessCmdGetByte) ||
333 (Command == HeadlessCmdGetLine) ||
334 (Command == HeadlessCmdCheckForReboot) ||
335 (Command == HeadlessCmdTerminalPoll))
336 {
337 if (!(OutputBuffer) || !(OutputBufferSize)) return STATUS_INVALID_PARAMETER;
338 RtlZeroMemory(OutputBuffer, *OutputBufferSize);
339 }
340 return STATUS_SUCCESS;
341 }
342
343 /* Do the real work */
344 return HdlspDispatch(
345 Command,
346 InputBuffer,
347 InputBufferSize,
348 OutputBuffer,
349 OutputBufferSize);
350 }
351
352 /* EOF */