]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.c
Nt32SerialIo driver was changed to produce the flow control device path node when...
[mirror_edk2.git] / Nt32Pkg / WinNtSerialIoDxe / WinNtSerialIo.c
CommitLineData
6ae81428 1/**@file\r
5f44f5b9 2\r
f7c58a94 3Copyright (c) 2006 - 2010, Intel Corporation\r
5f44f5b9 4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 WinNtSerialIo.c\r
15\r
16Abstract:\r
17\r
18 Our DriverBinding member functions operate on the handles\r
19 created by the NT Bus driver.\r
20\r
21 Handle(1) - WinNtIo - DevicePath(1)\r
22\r
23 If a serial port is added to the system this driver creates a new handle.\r
24 The new handle is required, since the serial device must add an UART device\r
25 pathnode.\r
26\r
27 Handle(2) - SerialIo - DevicePath(1)\UART\r
28\r
29 The driver then adds a gEfiWinNtSerialPortGuid as a protocol to Handle(1).\r
30 The instance data for this protocol is the private data used to create\r
31 Handle(2).\r
32\r
33 Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort\r
34\r
35 If the driver is unloaded Handle(2) is removed from the system and\r
36 gEfiWinNtSerialPortGuid is removed from Handle(1).\r
37\r
38 Note: Handle(1) is any handle created by the Win NT Bus driver that is passed\r
39 into the DriverBinding member functions of this driver. This driver requires\r
40 a Handle(1) to contain a WinNtIo protocol, a DevicePath protocol, and\r
41 the TypeGuid in the WinNtIo must be gEfiWinNtSerialPortGuid.\r
42\r
43 If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is\r
44 loaded on the device.\r
45\r
6ae81428 46**/\r
5f44f5b9 47\r
5f44f5b9 48#include "WinNtSerialIo.h"\r
49\r
50EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = {\r
51 WinNtSerialIoDriverBindingSupported,\r
52 WinNtSerialIoDriverBindingStart,\r
53 WinNtSerialIoDriverBindingStop,\r
54 0xa,\r
55 NULL,\r
56 NULL\r
57};\r
58\r
82408a47 59//\r
60// List of supported baud rate\r
61//\r
62UINT64 mBaudRateCurrentSupport[] = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 57600, 115200, SERIAL_PORT_MAX_BAUD_RATE + 1};\r
63\r
ff72001b
RN
64/**\r
65 Check the device path node whether it's the Flow Control node or not.\r
66\r
67 @param[in] FlowControl The device path node to be checked.\r
68 \r
69 @retval TRUE It's the Flow Control node.\r
70 @retval FALSE It's not.\r
71\r
72**/\r
73BOOLEAN\r
74IsUartFlowControlNode (\r
75 IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl\r
76 )\r
77{\r
78 return (BOOLEAN) (\r
79 (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&\r
80 (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&\r
81 (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))\r
82 );\r
83}\r
84\r
85/**\r
86 Check the device path node whether it contains Flow Control node or not.\r
87\r
88 @param[in] DevicePath The device path to be checked.\r
89 \r
90 @retval TRUE It contains the Flow Control node.\r
91 @retval FALSE It doesn't.\r
92\r
93**/\r
94BOOLEAN\r
95ContainsFlowControl (\r
96 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
97 )\r
98{\r
99 while (!IsDevicePathEnd (DevicePath)) {\r
100 if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {\r
101 return TRUE;\r
102 }\r
103 DevicePath = NextDevicePathNode (DevicePath);\r
104 }\r
105\r
106 return FALSE;\r
107}\r
108\r
5f44f5b9 109/**\r
110 The user Entry Point for module WinNtSerialIo. The user code starts with this function.\r
111\r
112 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
113 @param[in] SystemTable A pointer to the EFI System Table.\r
114 \r
115 @retval EFI_SUCCESS The entry point is executed successfully.\r
116 @retval other Some error occurs when executing this entry point.\r
117\r
118**/\r
119EFI_STATUS\r
120EFIAPI\r
121InitializeWinNtSerialIo(\r
122 IN EFI_HANDLE ImageHandle,\r
123 IN EFI_SYSTEM_TABLE *SystemTable\r
124 )\r
125{\r
126 EFI_STATUS Status;\r
127\r
128 //\r
129 // Install driver model protocol(s).\r
130 //\r
04369cd8 131 Status = EfiLibInstallDriverBindingComponentName2 (\r
5f44f5b9 132 ImageHandle,\r
133 SystemTable,\r
134 &gWinNtSerialIoDriverBinding,\r
135 ImageHandle,\r
136 &gWinNtSerialIoComponentName,\r
04369cd8 137 &gWinNtSerialIoComponentName2\r
5f44f5b9 138 );\r
139 ASSERT_EFI_ERROR (Status);\r
140\r
141\r
142 return Status;\r
143}\r
144\r
5f44f5b9 145EFI_STATUS\r
146EFIAPI\r
147WinNtSerialIoDriverBindingSupported (\r
148 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
149 IN EFI_HANDLE Handle,\r
150 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
151 )\r
152/*++\r
153\r
154Routine Description:\r
155\r
156Arguments:\r
157\r
158Returns:\r
159\r
160 None\r
161\r
162--*/\r
163// TODO: This - add argument and description to function comment\r
164// TODO: Handle - add argument and description to function comment\r
165// TODO: RemainingDevicePath - add argument and description to function comment\r
166// TODO: EFI_SUCCESS - add return value to function comment\r
167// TODO: EFI_SUCCESS - add return value to function comment\r
168{\r
ff72001b
RN
169 EFI_STATUS Status;\r
170 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
171 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
172 UART_DEVICE_PATH *UartNode;\r
173 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
174 UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;\r
175 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
176 UINTN EntryCount;\r
177 UINTN Index;\r
5f44f5b9 178\r
f22911b4 179 //\r
180 // Check RemainingDevicePath validation\r
181 //\r
182 if (RemainingDevicePath != NULL) {\r
183 //\r
184 // Check if RemainingDevicePath is the End of Device Path Node, \r
185 // if yes, go on checking other conditions\r
186 //\r
187 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
188 //\r
189 // If RemainingDevicePath isn't the End of Device Path Node,\r
190 // check its validation\r
191 //\r
192 Status = EFI_UNSUPPORTED;\r
193\r
194 UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;\r
195 if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||\r
196 UartNode->Header.SubType != MSG_UART_DP ||\r
197 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)UartNode) != sizeof(UART_DEVICE_PATH)) {\r
198 goto Error;\r
199 }\r
200 if ( UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {\r
201 goto Error;\r
202 }\r
203 if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {\r
204 goto Error;\r
205 }\r
206 if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {\r
207 goto Error;\r
208 }\r
209 if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {\r
210 goto Error;\r
211 }\r
212 if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {\r
213 goto Error;\r
214 }\r
215 if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {\r
216 goto Error;\r
217 }\r
ff72001b
RN
218\r
219 FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);\r
220 if (IsUartFlowControlNode (FlowControlNode)) {\r
221 //\r
222 // If the second node is Flow Control Node,\r
223 // return error when it request other than hardware flow control.\r
224 //\r
225 if ((FlowControlNode->FlowControlMap & ~UART_FLOW_CONTROL_HARDWARE) != 0) {\r
226 goto Error;\r
227 }\r
228 }\r
f22911b4 229 }\r
230 }\r
231\r
5f44f5b9 232 //\r
233 // Open the IO Abstraction(s) needed to perform the supported test\r
234 //\r
235 Status = gBS->OpenProtocol (\r
236 Handle,\r
f22911b4 237 &gEfiWinNtIoProtocolGuid,\r
238 (VOID **) &WinNtIo,\r
5f44f5b9 239 This->DriverBindingHandle,\r
240 Handle,\r
241 EFI_OPEN_PROTOCOL_BY_DRIVER\r
242 );\r
243 if (Status == EFI_ALREADY_STARTED) {\r
ff72001b
RN
244 if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {\r
245 //\r
246 // If RemainingDevicePath is NULL or is the End of Device Path Node\r
247 //\r
248 return EFI_SUCCESS;\r
249 }\r
250 //\r
251 // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,\r
252 // return unsupported, and vice versa.\r
253 //\r
254 Status = gBS->OpenProtocolInformation (\r
255 Handle,\r
256 &gEfiWinNtIoProtocolGuid,\r
257 &OpenInfoBuffer,\r
258 &EntryCount\r
259 );\r
260 if (EFI_ERROR (Status)) {\r
261 return Status;\r
262 }\r
263\r
264 for (Index = 0; Index < EntryCount; Index++) {\r
265 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
266 Status = gBS->OpenProtocol (\r
267 OpenInfoBuffer[Index].ControllerHandle,\r
268 &gEfiDevicePathProtocolGuid,\r
269 (VOID **) &DevicePath,\r
270 This->DriverBindingHandle,\r
271 Handle,\r
272 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
273 );\r
274 if (!EFI_ERROR (Status) &&\r
275 (ContainsFlowControl (RemainingDevicePath) ^ ContainsFlowControl (DevicePath))) {\r
276 Status = EFI_UNSUPPORTED;\r
277 }\r
278 break;\r
279 }\r
280 }\r
281 FreePool (OpenInfoBuffer);\r
282 return Status;\r
5f44f5b9 283 }\r
284\r
285 if (EFI_ERROR (Status)) {\r
286 return Status;\r
287 }\r
288\r
f22911b4 289 //\r
af4a6385 290 // Close the I/O Abstraction(s) used to perform the supported test\r
f22911b4 291 //\r
5f44f5b9 292 gBS->CloseProtocol (\r
293 Handle,\r
f22911b4 294 &gEfiWinNtIoProtocolGuid,\r
5f44f5b9 295 This->DriverBindingHandle,\r
296 Handle\r
297 );\r
298\r
f22911b4 299 //\r
300 // Open the EFI Device Path protocol needed to perform the supported test\r
301 //\r
5f44f5b9 302 Status = gBS->OpenProtocol (\r
303 Handle,\r
f22911b4 304 &gEfiDevicePathProtocolGuid,\r
305 (VOID **) &ParentDevicePath,\r
5f44f5b9 306 This->DriverBindingHandle,\r
307 Handle,\r
308 EFI_OPEN_PROTOCOL_BY_DRIVER\r
309 );\r
310 if (Status == EFI_ALREADY_STARTED) {\r
311 return EFI_SUCCESS;\r
312 }\r
313\r
314 if (EFI_ERROR (Status)) {\r
315 return Status;\r
316 }\r
317\r
f22911b4 318 //\r
319 // Close protocol, don't use device path protocol in the Support() function\r
320 //\r
321 gBS->CloseProtocol (\r
322 Handle,\r
323 &gEfiDevicePathProtocolGuid,\r
324 This->DriverBindingHandle,\r
325 Handle\r
326 );\r
327\r
5f44f5b9 328 //\r
329 // Make sure that the WinNt Thunk Protocol is valid\r
330 //\r
331 if (WinNtIo->WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {\r
332 Status = EFI_UNSUPPORTED;\r
333 goto Error;\r
334 }\r
335\r
336 //\r
337 // Check the GUID to see if this is a handle type the driver supports\r
338 //\r
339 if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtSerialPortGuid)) {\r
340 Status = EFI_UNSUPPORTED;\r
341 goto Error;\r
342 }\r
343\r
f22911b4 344 return EFI_SUCCESS;\r
5f44f5b9 345\r
346Error:\r
5f44f5b9 347 return Status;\r
348}\r
349\r
5f44f5b9 350EFI_STATUS\r
351EFIAPI\r
352WinNtSerialIoDriverBindingStart (\r
353 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
354 IN EFI_HANDLE Handle,\r
355 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
356 )\r
357/*++\r
358\r
359Routine Description:\r
360\r
361Arguments:\r
362\r
363Returns:\r
364\r
365 None\r
366\r
367--*/\r
368// TODO: This - add argument and description to function comment\r
369// TODO: Handle - add argument and description to function comment\r
370// TODO: RemainingDevicePath - add argument and description to function comment\r
371// TODO: EFI_SUCCESS - add return value to function comment\r
372// TODO: EFI_SUCCESS - add return value to function comment\r
373{\r
374 EFI_STATUS Status;\r
375 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
376 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
377 HANDLE NtHandle;\r
ff72001b 378 UART_DEVICE_PATH UartNode;\r
5f44f5b9 379 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
380 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
381 UINTN EntryCount;\r
382 UINTN Index;\r
383 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
ff72001b
RN
384 UART_DEVICE_PATH *Uart;\r
385 UINT32 FlowControlMap;\r
386 UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;\r
387 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
388 UINT32 Control;\r
5f44f5b9 389\r
390 Private = NULL;\r
391 NtHandle = INVALID_HANDLE_VALUE;\r
392\r
393 //\r
ff72001b 394 // Get the Parent Device Path\r
5f44f5b9 395 //\r
396 Status = gBS->OpenProtocol (\r
397 Handle,\r
398 &gEfiDevicePathProtocolGuid,\r
63941829 399 (VOID **) &ParentDevicePath,\r
5f44f5b9 400 This->DriverBindingHandle,\r
401 Handle,\r
402 EFI_OPEN_PROTOCOL_BY_DRIVER\r
403 );\r
404 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
405 return Status;\r
406 }\r
407\r
408 //\r
409 // Grab the IO abstraction we need to get any work done\r
410 //\r
411 Status = gBS->OpenProtocol (\r
412 Handle,\r
413 &gEfiWinNtIoProtocolGuid,\r
63941829 414 (VOID **) &WinNtIo,\r
5f44f5b9 415 This->DriverBindingHandle,\r
416 Handle,\r
417 EFI_OPEN_PROTOCOL_BY_DRIVER\r
418 );\r
419 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
420 gBS->CloseProtocol (\r
421 Handle,\r
422 &gEfiDevicePathProtocolGuid,\r
423 This->DriverBindingHandle,\r
424 Handle\r
425 );\r
426 return Status;\r
427 }\r
428\r
429 if (Status == EFI_ALREADY_STARTED) {\r
430\r
f22911b4 431 if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {\r
432 //\r
433 // If RemainingDevicePath is NULL or is the End of Device Path Node\r
434 //\r
5f44f5b9 435 return EFI_SUCCESS;\r
436 }\r
437\r
438 //\r
439 // Make sure a child handle does not already exist. This driver can only\r
440 // produce one child per serial port.\r
441 //\r
442 Status = gBS->OpenProtocolInformation (\r
443 Handle,\r
444 &gEfiWinNtIoProtocolGuid,\r
445 &OpenInfoBuffer,\r
446 &EntryCount\r
447 );\r
448 if (EFI_ERROR (Status)) {\r
449 return Status;\r
450 }\r
451\r
452 Status = EFI_ALREADY_STARTED;\r
453 for (Index = 0; Index < EntryCount; Index++) {\r
ff72001b 454 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
5f44f5b9 455 Status = gBS->OpenProtocol (\r
456 OpenInfoBuffer[Index].ControllerHandle,\r
457 &gEfiSerialIoProtocolGuid,\r
63941829 458 (VOID **) &SerialIo,\r
5f44f5b9 459 This->DriverBindingHandle,\r
460 Handle,\r
461 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
462 );\r
463 if (!EFI_ERROR (Status)) {\r
ff72001b 464 Uart = (UART_DEVICE_PATH *) RemainingDevicePath;\r
5f44f5b9 465 Status = SerialIo->SetAttributes (\r
ff72001b
RN
466 SerialIo,\r
467 Uart->BaudRate,\r
468 SerialIo->Mode->ReceiveFifoDepth,\r
469 SerialIo->Mode->Timeout,\r
470 (EFI_PARITY_TYPE) Uart->Parity,\r
471 Uart->DataBits,\r
472 (EFI_STOP_BITS_TYPE) Uart->StopBits\r
473 );\r
474 FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);\r
475 if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {\r
476 Status = SerialIo->GetControl (SerialIo, &Control);\r
477 if (!EFI_ERROR (Status)) {\r
478 if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) {\r
479 Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
480 } else {\r
481 Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
482 }\r
483 //\r
484 // Clear the bits that are not allowed to pass to SetControl\r
485 //\r
486 Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
487 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \r
488 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);\r
489 Status = SerialIo->SetControl (SerialIo, Control);\r
490 }\r
491 }\r
5f44f5b9 492 }\r
493 break;\r
494 }\r
495 }\r
9be29006 496\r
5f44f5b9 497 FreePool (OpenInfoBuffer);\r
9be29006 498 return Status;\r
f22911b4 499 }\r
500\r
ff72001b
RN
501 FlowControl = NULL;\r
502 FlowControlMap = 0;\r
f22911b4 503 if (RemainingDevicePath == NULL) {\r
504 //\r
505 // Build the device path by appending the UART node to the ParentDevicePath\r
506 // from the WinNtIo handle. The Uart setings are zero here, since\r
507 // SetAttribute() will update them to match the default setings.\r
508 //\r
ff72001b
RN
509 ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH));\r
510 UartNode.Header.Type = MESSAGING_DEVICE_PATH;\r
511 UartNode.Header.SubType = MSG_UART_DP;\r
512 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH));\r
f22911b4 513\r
514 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
515 //\r
516 // If RemainingDevicePath isn't the End of Device Path Node, \r
517 // only scan the specified device by RemainingDevicePath\r
518 //\r
519 //\r
520 // Match the configuration of the RemainingDevicePath. IsHandleSupported()\r
521 // already checked to make sure the RemainingDevicePath contains settings\r
522 // that we can support.\r
523 //\r
ff72001b
RN
524 CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
525 FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);\r
526 if (IsUartFlowControlNode (FlowControl)) {\r
527 FlowControlMap = FlowControl->FlowControlMap;\r
528 } else {\r
529 FlowControl = NULL;\r
530 }\r
f22911b4 531\r
532 } else {\r
533 //\r
534 // If RemainingDevicePath is the End of Device Path Node,\r
535 // skip enumerate any device and return EFI_SUCESSS\r
536 // \r
537 return EFI_SUCCESS;\r
5f44f5b9 538 }\r
539\r
540 //\r
541 // Check to see if we can access the hardware device. If it's Open in NT we\r
542 // will not get access.\r
543 //\r
544 NtHandle = WinNtIo->WinNtThunk->CreateFile (\r
545 WinNtIo->EnvString,\r
546 GENERIC_READ | GENERIC_WRITE,\r
547 0,\r
548 NULL,\r
549 OPEN_EXISTING,\r
550 0,\r
551 NULL\r
552 );\r
553 if (NtHandle == INVALID_HANDLE_VALUE) {\r
554 Status = EFI_DEVICE_ERROR;\r
555 goto Error;\r
556 }\r
557\r
558 //\r
559 // Construct Private data\r
560 //\r
561 Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA));\r
562 if (Private == NULL) {\r
563 goto Error;\r
564 }\r
565\r
566 //\r
567 // This signature must be valid before any member function is called\r
568 //\r
569 Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE;\r
570 Private->NtHandle = NtHandle;\r
571 Private->ControllerHandle = Handle;\r
572 Private->Handle = NULL;\r
573 Private->WinNtThunk = WinNtIo->WinNtThunk;\r
574 Private->ParentDevicePath = ParentDevicePath;\r
575 Private->ControllerNameTable = NULL;\r
576\r
577 Private->SoftwareLoopbackEnable = FALSE;\r
578 Private->HardwareLoopbackEnable = FALSE;\r
ff72001b 579 Private->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE);\r
5f44f5b9 580 Private->Fifo.First = 0;\r
581 Private->Fifo.Last = 0;\r
582 Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
583\r
ff72001b 584 CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH));\r
f22911b4 585\r
04369cd8 586 AddUnicodeString2 (\r
5f44f5b9 587 "eng",\r
588 gWinNtSerialIoComponentName.SupportedLanguages,\r
589 &Private->ControllerNameTable,\r
04369cd8 590 WinNtIo->EnvString,\r
591 TRUE\r
5f44f5b9 592 );\r
04369cd8 593 AddUnicodeString2 (\r
594 "en",\r
595 gWinNtSerialIoComponentName2.SupportedLanguages,\r
596 &Private->ControllerNameTable,\r
597 WinNtIo->EnvString,\r
598 FALSE\r
599 );\r
600\r
5f44f5b9 601\r
602 Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION;\r
603 Private->SerialIo.Reset = WinNtSerialIoReset;\r
604 Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes;\r
605 Private->SerialIo.SetControl = WinNtSerialIoSetControl;\r
606 Private->SerialIo.GetControl = WinNtSerialIoGetControl;\r
607 Private->SerialIo.Write = WinNtSerialIoWrite;\r
608 Private->SerialIo.Read = WinNtSerialIoRead;\r
609 Private->SerialIo.Mode = &Private->SerialIoMode;\r
610\r
5f44f5b9 611 //\r
612 // Build the device path by appending the UART node to the ParentDevicePath\r
613 // from the WinNtIo handle. The Uart setings are zero here, since\r
614 // SetAttribute() will update them to match the current setings.\r
615 //\r
616 Private->DevicePath = AppendDevicePathNode (\r
617 ParentDevicePath,\r
618 (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath\r
619 );\r
ff72001b
RN
620 //\r
621 // Only produce the FlowControl node when remaining device path has it\r
622 //\r
623 if (FlowControl != NULL) {\r
624 TempDevicePath = Private->DevicePath;\r
625 if (TempDevicePath != NULL) {\r
626 Private->DevicePath = AppendDevicePathNode (\r
627 TempDevicePath,\r
628 (EFI_DEVICE_PATH_PROTOCOL *) FlowControl\r
629 );\r
630 FreePool (TempDevicePath);\r
631 }\r
632 }\r
5f44f5b9 633 if (Private->DevicePath == NULL) {\r
634 Status = EFI_OUT_OF_RESOURCES;\r
635 goto Error;\r
636 }\r
637\r
638 //\r
639 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.\r
640 //\r
641 Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK;\r
642 Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT;\r
643 Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate;\r
644 Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;\r
645 Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits;\r
646 Private->SerialIoMode.Parity = Private->UartDevicePath.Parity;\r
647 Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits;\r
648\r
649 //\r
650 // Issue a reset to initialize the COM port\r
651 //\r
652 Status = Private->SerialIo.Reset (&Private->SerialIo);\r
653 if (EFI_ERROR (Status)) {\r
654 goto Error;\r
655 }\r
656\r
657 //\r
658 // Create new child handle\r
659 //\r
660 Status = gBS->InstallMultipleProtocolInterfaces (\r
661 &Private->Handle,\r
662 &gEfiSerialIoProtocolGuid,\r
663 &Private->SerialIo,\r
664 &gEfiDevicePathProtocolGuid,\r
665 Private->DevicePath,\r
666 NULL\r
667 );\r
668 if (EFI_ERROR (Status)) {\r
669 goto Error;\r
670 }\r
671\r
672 //\r
673 // Open For Child Device\r
674 //\r
675 Status = gBS->OpenProtocol (\r
676 Handle,\r
677 &gEfiWinNtIoProtocolGuid,\r
63941829 678 (VOID **) &WinNtIo,\r
5f44f5b9 679 This->DriverBindingHandle,\r
680 Private->Handle,\r
681 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
682 );\r
683 if (EFI_ERROR (Status)) {\r
684 goto Error;\r
685 }\r
686\r
687 return EFI_SUCCESS;\r
688\r
689Error:\r
690 //\r
691 // Use the Stop() function to free all resources allocated in Start()\r
692 //\r
693 if (Private != NULL) {\r
694 if (Private->Handle != NULL) {\r
695 This->Stop (This, Handle, 1, &Private->Handle);\r
696 } else {\r
697 if (NtHandle != INVALID_HANDLE_VALUE) {\r
698 Private->WinNtThunk->CloseHandle (NtHandle);\r
699 }\r
700\r
701 if (Private->DevicePath != NULL) {\r
702 FreePool (Private->DevicePath);\r
703 }\r
704\r
705 FreeUnicodeStringTable (Private->ControllerNameTable);\r
706\r
707 FreePool (Private);\r
708 }\r
709 }\r
710\r
711 This->Stop (This, Handle, 0, NULL);\r
712\r
713 return Status;\r
714}\r
715\r
5f44f5b9 716EFI_STATUS\r
717EFIAPI\r
718WinNtSerialIoDriverBindingStop (\r
719 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
720 IN EFI_HANDLE Handle,\r
721 IN UINTN NumberOfChildren,\r
722 IN EFI_HANDLE *ChildHandleBuffer\r
723 )\r
724/*++\r
725\r
726Routine Description:\r
727\r
728 TODO: Add function description\r
729\r
730Arguments:\r
731\r
732 This - TODO: add argument description\r
733 Handle - TODO: add argument description\r
734 NumberOfChildren - TODO: add argument description\r
735 ChildHandleBuffer - TODO: add argument description\r
736\r
737Returns:\r
738\r
739 EFI_DEVICE_ERROR - TODO: Add description for return value\r
740 EFI_SUCCESS - TODO: Add description for return value\r
741\r
742--*/\r
743{\r
744 EFI_STATUS Status;\r
745 UINTN Index;\r
746 BOOLEAN AllChildrenStopped;\r
747 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
748 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
749 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
750\r
751 //\r
752 // Complete all outstanding transactions to Controller.\r
753 // Don't allow any new transaction to Controller to be started.\r
754 //\r
755\r
756 if (NumberOfChildren == 0) {\r
757 //\r
758 // Close the bus driver\r
759 //\r
760 Status = gBS->CloseProtocol (\r
761 Handle,\r
762 &gEfiWinNtIoProtocolGuid,\r
763 This->DriverBindingHandle,\r
764 Handle\r
765 );\r
766 Status = gBS->CloseProtocol (\r
767 Handle,\r
768 &gEfiDevicePathProtocolGuid,\r
769 This->DriverBindingHandle,\r
770 Handle\r
771 );\r
772 return Status;\r
773 }\r
774\r
775 AllChildrenStopped = TRUE;\r
776\r
777 for (Index = 0; Index < NumberOfChildren; Index++) {\r
778 Status = gBS->OpenProtocol (\r
779 ChildHandleBuffer[Index],\r
780 &gEfiSerialIoProtocolGuid,\r
63941829 781 (VOID **) &SerialIo,\r
5f44f5b9 782 This->DriverBindingHandle,\r
783 Handle,\r
784 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
785 );\r
786 if (!EFI_ERROR (Status)) {\r
787 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo);\r
788\r
789 ASSERT (Private->Handle == ChildHandleBuffer[Index]);\r
790\r
791 Status = gBS->CloseProtocol (\r
792 Handle,\r
793 &gEfiWinNtIoProtocolGuid,\r
794 This->DriverBindingHandle,\r
795 ChildHandleBuffer[Index]\r
796 );\r
797\r
798 Status = gBS->UninstallMultipleProtocolInterfaces (\r
799 ChildHandleBuffer[Index],\r
800 &gEfiSerialIoProtocolGuid,\r
801 &Private->SerialIo,\r
802 &gEfiDevicePathProtocolGuid,\r
803 Private->DevicePath,\r
804 NULL\r
805 );\r
806\r
807 if (EFI_ERROR (Status)) {\r
808 gBS->OpenProtocol (\r
809 Handle,\r
810 &gEfiWinNtIoProtocolGuid,\r
811 (VOID **) &WinNtIo,\r
812 This->DriverBindingHandle,\r
813 ChildHandleBuffer[Index],\r
814 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
815 );\r
816 } else {\r
817 Private->WinNtThunk->CloseHandle (Private->NtHandle);\r
818\r
819 FreePool (Private->DevicePath);\r
820\r
821 FreeUnicodeStringTable (Private->ControllerNameTable);\r
822\r
823 FreePool (Private);\r
824 }\r
825 }\r
826\r
827 if (EFI_ERROR (Status)) {\r
828 AllChildrenStopped = FALSE;\r
829 }\r
830 }\r
831\r
832 if (!AllChildrenStopped) {\r
833 return EFI_DEVICE_ERROR;\r
834 }\r
835\r
836 return EFI_SUCCESS;\r
837}\r
838\r
839//\r
840// Serial IO Protocol member functions\r
841//\r
842\r
5f44f5b9 843EFI_STATUS\r
844EFIAPI\r
845WinNtSerialIoReset (\r
846 IN EFI_SERIAL_IO_PROTOCOL *This\r
847 )\r
848/*++\r
849\r
850Routine Description:\r
851\r
852 TODO: Add function description\r
853\r
854Arguments:\r
855\r
856 This - TODO: add argument description\r
857\r
858Returns:\r
859\r
860 TODO: add return values\r
861\r
862--*/\r
863{\r
864 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
865 EFI_TPL Tpl;\r
866\r
867 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
868\r
869 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
870\r
871 Private->WinNtThunk->PurgeComm (\r
872 Private->NtHandle,\r
873 PURGE_TXCLEAR | PURGE_RXCLEAR\r
874 );\r
875\r
876 gBS->RestoreTPL (Tpl);\r
877\r
878 return This->SetAttributes (\r
879 This,\r
880 This->Mode->BaudRate,\r
881 This->Mode->ReceiveFifoDepth,\r
882 This->Mode->Timeout,\r
a00ec39b 883 (EFI_PARITY_TYPE)This->Mode->Parity,\r
5f44f5b9 884 (UINT8) This->Mode->DataBits,\r
a00ec39b 885 (EFI_STOP_BITS_TYPE)This->Mode->StopBits\r
5f44f5b9 886 );\r
887}\r
888\r
5f44f5b9 889EFI_STATUS\r
890EFIAPI\r
891WinNtSerialIoSetAttributes (\r
892 IN EFI_SERIAL_IO_PROTOCOL *This,\r
893 IN UINT64 BaudRate,\r
894 IN UINT32 ReceiveFifoDepth,\r
895 IN UINT32 Timeout,\r
896 IN EFI_PARITY_TYPE Parity,\r
897 IN UINT8 DataBits,\r
898 IN EFI_STOP_BITS_TYPE StopBits\r
899 )\r
900/*++\r
901\r
902Routine Description:\r
903\r
904 This function is used to set the attributes.\r
905\r
906Arguments:\r
907\r
908 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.\r
909 BaudRate - The Baud rate of the serial device.\r
910 ReceiveFifoDepth - The request depth of fifo on receive side.\r
911 Timeout - the request timeout for a single charact.\r
912 Parity - The type of parity used in serial device.\r
913 DataBits - Number of deata bits used in serial device.\r
914 StopBits - Number of stop bits used in serial device.\r
915\r
916Returns:\r
917 Status code\r
918\r
919 None\r
920\r
921--*/\r
922// TODO: EFI_SUCCESS - add return value to function comment\r
923// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
924// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
925// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
926// TODO: EFI_SUCCESS - add return value to function comment\r
927// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
928// TODO: EFI_SUCCESS - add return value to function comment\r
929{\r
930 EFI_STATUS Status;\r
82408a47 931 UINTN Index; \r
5f44f5b9 932 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
933 COMMTIMEOUTS PortTimeOuts;\r
934 DWORD ConvertedTime;\r
935 BOOL Result;\r
ff72001b 936 UART_DEVICE_PATH *Uart;\r
5f44f5b9 937 EFI_TPL Tpl;\r
938\r
5f44f5b9 939 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
940\r
941 //\r
942 // Some of our arguments have defaults if a null value is passed in, and\r
943 // we must set the default values if a null argument is passed in.\r
944 //\r
945 if (BaudRate == 0) {\r
f7c58a94 946 BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
5f44f5b9 947 }\r
948\r
949 if (ReceiveFifoDepth == 0) {\r
950 ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;\r
951 }\r
952\r
953 if (Timeout == 0) {\r
954 Timeout = SERIAL_TIMEOUT_DEFAULT;\r
955 }\r
956\r
957 if (Parity == DefaultParity) {\r
f7c58a94 958 Parity = (EFI_PARITY_TYPE) (PcdGet8 (PcdUartDefaultParity));\r
5f44f5b9 959 }\r
960\r
961 if (DataBits == 0) {\r
f7c58a94 962 DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
5f44f5b9 963 }\r
964\r
965 if (StopBits == DefaultStopBits) {\r
f7c58a94 966 StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);\r
5f44f5b9 967 }\r
82408a47 968\r
969 //\r
970 // Make sure all parameters are valid\r
971 //\r
972 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {\r
973 return EFI_INVALID_PARAMETER;\r
974 }\r
975\r
976 //\r
977 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter\r
978 // \r
979 \r
980 for (Index = 1; Index < (sizeof (mBaudRateCurrentSupport) / sizeof (mBaudRateCurrentSupport[0])); Index++) {\r
981 if (BaudRate < mBaudRateCurrentSupport[Index]) {\r
982 BaudRate = mBaudRateCurrentSupport[Index-1];\r
983 break;\r
984 }\r
985 }\r
ff72001b 986\r
82408a47 987 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
988 return EFI_INVALID_PARAMETER;\r
989 }\r
990\r
991 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {\r
992 return EFI_INVALID_PARAMETER;\r
993 }\r
994\r
995 if ((Parity < NoParity) || (Parity > SpaceParity)) {\r
996 return EFI_INVALID_PARAMETER;\r
997 }\r
998\r
999 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {\r
1000 return EFI_INVALID_PARAMETER;\r
1001 }\r
1002\r
1003 //\r
1004 // Now we only support DataBits=7,8.\r
1005 //\r
1006 if ((DataBits < 7) || (DataBits > 8)) {\r
1007 return EFI_INVALID_PARAMETER;\r
1008 }\r
1009 \r
1010 //\r
1011 // Now we only support DataBits=7,8.\r
1012 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.\r
1013 //\r
1014 if (StopBits == OneFiveStopBits) {\r
1015 return EFI_INVALID_PARAMETER;\r
1016 } \r
1017 \r
5f44f5b9 1018 //\r
1019 // See if the new attributes already match the current attributes\r
1020 //\r
1021 if (Private->UartDevicePath.BaudRate == BaudRate &&\r
1022 Private->UartDevicePath.DataBits == DataBits &&\r
1023 Private->UartDevicePath.Parity == Parity &&\r
1024 Private->UartDevicePath.StopBits == StopBits &&\r
1025 Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth &&\r
1026 Private->SerialIoMode.Timeout == Timeout ) {\r
5f44f5b9 1027 return EFI_SUCCESS;\r
1028 }\r
1029\r
82408a47 1030 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1031\r
5f44f5b9 1032 //\r
1033 // Get current values from NT\r
1034 //\r
1035 ZeroMem (&Private->NtDCB, sizeof (DCB));\r
1036 Private->NtDCB.DCBlength = sizeof (DCB);\r
1037\r
1038 if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) {\r
1039 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1040 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError));\r
1041 gBS->RestoreTPL (Tpl);\r
1042 return EFI_DEVICE_ERROR;\r
1043 }\r
1044\r
1045 //\r
1046 // Map EFI com setting to NT\r
1047 //\r
1048 Private->NtDCB.BaudRate = ConvertBaud2Nt (BaudRate);\r
1049 Private->NtDCB.ByteSize = ConvertData2Nt (DataBits);\r
1050 Private->NtDCB.Parity = ConvertParity2Nt (Parity);\r
1051 Private->NtDCB.StopBits = ConvertStop2Nt (StopBits);\r
1052\r
1053 Private->NtDCB.fBinary = TRUE;\r
1054 Private->NtDCB.fParity = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE;\r
1055 Private->NtDCB.fOutxCtsFlow = FALSE;\r
1056 Private->NtDCB.fOutxDsrFlow = FALSE;\r
1057 Private->NtDCB.fDtrControl = DTR_CONTROL_ENABLE;\r
1058 Private->NtDCB.fDsrSensitivity = FALSE;\r
1059 Private->NtDCB.fOutX = FALSE;\r
1060 Private->NtDCB.fInX = FALSE;\r
1061 Private->NtDCB.fRtsControl = RTS_CONTROL_ENABLE;\r
1062 Private->NtDCB.fNull = FALSE;\r
1063\r
1064 //\r
1065 // Set new values\r
1066 //\r
1067 Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB);\r
1068 if (!Result) {\r
1069 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1070 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError));\r
1071 gBS->RestoreTPL (Tpl);\r
1072 return EFI_DEVICE_ERROR;\r
1073 }\r
1074\r
1075 //\r
1076 // Set com port read/write timeout values\r
1077 //\r
1078 ConvertedTime = ConvertTime2Nt (Timeout);\r
1079 PortTimeOuts.ReadIntervalTimeout = MAXDWORD;\r
1080 PortTimeOuts.ReadTotalTimeoutMultiplier = 0;\r
1081 PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime;\r
1082 PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime;\r
1083 PortTimeOuts.WriteTotalTimeoutConstant = 0;\r
1084\r
1085 if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) {\r
1086 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1087 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError));\r
1088 gBS->RestoreTPL (Tpl);\r
1089 return EFI_DEVICE_ERROR;\r
1090 }\r
1091\r
1092 //\r
1093 // Update mode\r
1094 //\r
1095 Private->SerialIoMode.BaudRate = BaudRate;\r
1096 Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth;\r
1097 Private->SerialIoMode.Timeout = Timeout;\r
1098 Private->SerialIoMode.Parity = Parity;\r
1099 Private->SerialIoMode.DataBits = DataBits;\r
1100 Private->SerialIoMode.StopBits = StopBits;\r
1101\r
1102 //\r
1103 // See if Device Path Node has actually changed\r
1104 //\r
1105 if (Private->UartDevicePath.BaudRate == BaudRate &&\r
1106 Private->UartDevicePath.DataBits == DataBits &&\r
1107 Private->UartDevicePath.Parity == Parity &&\r
1108 Private->UartDevicePath.StopBits == StopBits ) {\r
1109 gBS->RestoreTPL(Tpl);\r
1110 return EFI_SUCCESS;\r
1111 }\r
1112\r
1113 //\r
1114 // Update the device path\r
1115 //\r
1116 Private->UartDevicePath.BaudRate = BaudRate;\r
1117 Private->UartDevicePath.DataBits = DataBits;\r
1118 Private->UartDevicePath.Parity = (UINT8) Parity;\r
1119 Private->UartDevicePath.StopBits = (UINT8) StopBits;\r
1120\r
ff72001b 1121 Status = EFI_SUCCESS;\r
5f44f5b9 1122 if (Private->Handle != NULL) {\r
ff72001b
RN
1123 Uart = (UART_DEVICE_PATH *) (\r
1124 (UINTN) Private->DevicePath\r
1125 + GetDevicePathSize (Private->ParentDevicePath)\r
1126 - END_DEVICE_PATH_LENGTH\r
1127 );\r
1128 CopyMem (Uart, &Private->UartDevicePath, sizeof (UART_DEVICE_PATH));\r
5f44f5b9 1129 Status = gBS->ReinstallProtocolInterface (\r
1130 Private->Handle,\r
1131 &gEfiDevicePathProtocolGuid,\r
1132 Private->DevicePath,\r
ff72001b 1133 Private->DevicePath\r
5f44f5b9 1134 );\r
5f44f5b9 1135 }\r
1136\r
5f44f5b9 1137 gBS->RestoreTPL (Tpl);\r
1138\r
ff72001b 1139 return Status;\r
5f44f5b9 1140}\r
1141\r
5f44f5b9 1142EFI_STATUS\r
1143EFIAPI\r
1144WinNtSerialIoSetControl (\r
1145 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1146 IN UINT32 Control\r
1147 )\r
1148/*++\r
1149\r
1150Routine Description:\r
1151\r
1152 TODO: Add function description\r
1153\r
1154Arguments:\r
1155\r
1156 This - TODO: add argument description\r
1157 Control - TODO: add argument description\r
1158\r
1159Returns:\r
1160\r
1161 EFI_DEVICE_ERROR - TODO: Add description for return value\r
1162 EFI_DEVICE_ERROR - TODO: Add description for return value\r
1163 EFI_SUCCESS - TODO: Add description for return value\r
1164\r
1165--*/\r
1166{\r
1167 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
1168 BOOL Result;\r
1169 DCB Dcb;\r
1170 EFI_TPL Tpl;\r
ff72001b
RN
1171 UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;\r
1172 EFI_STATUS Status;\r
5f44f5b9 1173\r
82408a47 1174 //\r
1175 // first determine the parameter is invalid\r
1176 //\r
1177 if (Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
1178 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \r
1179 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) {\r
1180 return EFI_UNSUPPORTED;\r
1181 }\r
1182\r
5f44f5b9 1183 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1184\r
1185 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
1186\r
1187 Result = Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb);\r
1188\r
1189 if (!Result) {\r
1190 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1191 DEBUG ((EFI_D_ERROR, "SerialSetControl: GetCommState %d\n", Private->NtError));\r
1192 gBS->RestoreTPL (Tpl);\r
1193 return EFI_DEVICE_ERROR;\r
1194 }\r
1195\r
1196 Dcb.fRtsControl = RTS_CONTROL_DISABLE;\r
1197 Dcb.fDtrControl = DTR_CONTROL_DISABLE;\r
1198 Private->HardwareFlowControl = FALSE;\r
1199 Private->SoftwareLoopbackEnable = FALSE;\r
1200 Private->HardwareLoopbackEnable = FALSE;\r
1201\r
1202 if (Control & EFI_SERIAL_REQUEST_TO_SEND) {\r
1203 Dcb.fRtsControl = RTS_CONTROL_ENABLE;\r
1204 }\r
1205\r
1206 if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {\r
1207 Dcb.fDtrControl = DTR_CONTROL_ENABLE;\r
1208 }\r
1209\r
1210 if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {\r
1211 Private->HardwareFlowControl = TRUE;\r
1212 }\r
1213\r
1214 if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {\r
1215 Private->SoftwareLoopbackEnable = TRUE;\r
1216 }\r
1217\r
1218 if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {\r
1219 Private->HardwareLoopbackEnable = TRUE;\r
1220 }\r
1221\r
1222 Result = Private->WinNtThunk->SetCommState (\r
1223 Private->NtHandle,\r
1224 &Dcb\r
1225 );\r
1226\r
1227 if (!Result) {\r
1228 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1229 DEBUG ((EFI_D_ERROR, "SerialSetControl: SetCommState %d\n", Private->NtError));\r
1230 gBS->RestoreTPL (Tpl);\r
1231 return EFI_DEVICE_ERROR;\r
1232 }\r
1233\r
ff72001b
RN
1234 Status = EFI_SUCCESS;\r
1235 if (Private->Handle != NULL) {\r
1236 FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (\r
1237 (UINTN) Private->DevicePath\r
1238 + GetDevicePathSize (Private->ParentDevicePath)\r
1239 - END_DEVICE_PATH_LENGTH\r
1240 + sizeof (UART_DEVICE_PATH)\r
1241 );\r
1242 if (IsUartFlowControlNode (FlowControl) &&\r
1243 ((FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) ^ Private->HardwareFlowControl)) {\r
1244 //\r
1245 // Flow Control setting is changed, need to reinstall device path protocol\r
1246 //\r
1247 FlowControl->FlowControlMap = Private->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0;\r
1248 Status = gBS->ReinstallProtocolInterface (\r
1249 Private->Handle,\r
1250 &gEfiDevicePathProtocolGuid,\r
1251 Private->DevicePath,\r
1252 Private->DevicePath\r
1253 );\r
1254 }\r
1255 }\r
1256\r
5f44f5b9 1257 gBS->RestoreTPL (Tpl);\r
1258\r
ff72001b 1259 return Status;\r
5f44f5b9 1260}\r
1261\r
5f44f5b9 1262EFI_STATUS\r
1263EFIAPI\r
1264WinNtSerialIoGetControl (\r
1265 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1266 OUT UINT32 *Control\r
1267 )\r
1268/*++\r
1269\r
1270Routine Description:\r
1271\r
1272 TODO: Add function description\r
1273\r
1274Arguments:\r
1275\r
1276 This - TODO: add argument description\r
1277 Control - TODO: add argument description\r
1278\r
1279Returns:\r
1280\r
1281 EFI_DEVICE_ERROR - TODO: Add description for return value\r
1282 EFI_DEVICE_ERROR - TODO: Add description for return value\r
1283 EFI_DEVICE_ERROR - TODO: Add description for return value\r
1284 EFI_SUCCESS - TODO: Add description for return value\r
1285\r
1286--*/\r
1287{\r
1288 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
1289 DWORD ModemStatus;\r
1290 DWORD Errors;\r
1291 UINT32 Bits;\r
1292 DCB Dcb;\r
1293 EFI_TPL Tpl;\r
1294\r
1295 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1296\r
1297 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
1298\r
1299 //\r
1300 // Get modem status\r
1301 //\r
1302 if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) {\r
1303 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1304 gBS->RestoreTPL (Tpl);\r
1305 return EFI_DEVICE_ERROR;\r
1306 }\r
1307\r
1308 Bits = 0;\r
1309 if (ModemStatus & MS_CTS_ON) {\r
1310 Bits |= EFI_SERIAL_CLEAR_TO_SEND;\r
1311 }\r
1312\r
1313 if (ModemStatus & MS_DSR_ON) {\r
1314 Bits |= EFI_SERIAL_DATA_SET_READY;\r
1315 }\r
1316\r
1317 if (ModemStatus & MS_RING_ON) {\r
1318 Bits |= EFI_SERIAL_RING_INDICATE;\r
1319 }\r
1320\r
1321 if (ModemStatus & MS_RLSD_ON) {\r
1322 Bits |= EFI_SERIAL_CARRIER_DETECT;\r
1323 }\r
1324\r
1325 //\r
1326 // Get ctrl status\r
1327 //\r
1328 if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb)) {\r
1329 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1330 DEBUG ((EFI_D_ERROR, "SerialGetControl: GetCommState %d\n", Private->NtError));\r
1331 gBS->RestoreTPL (Tpl);\r
1332 return EFI_DEVICE_ERROR;\r
1333 }\r
1334\r
1335 if (Dcb.fDtrControl == DTR_CONTROL_ENABLE) {\r
1336 Bits |= EFI_SERIAL_DATA_TERMINAL_READY;\r
1337 }\r
1338\r
1339 if (Dcb.fRtsControl == RTS_CONTROL_ENABLE) {\r
1340 Bits |= EFI_SERIAL_REQUEST_TO_SEND;\r
1341 }\r
1342\r
1343 if (Private->HardwareFlowControl) {\r
1344 Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
1345 }\r
1346\r
1347 if (Private->SoftwareLoopbackEnable) {\r
1348 Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;\r
1349 }\r
1350\r
1351 if (Private->HardwareLoopbackEnable) {\r
1352 Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;\r
1353 }\r
1354\r
1355 //\r
1356 // Get input buffer status\r
1357 //\r
1358 if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) {\r
1359 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1360 DEBUG ((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError));\r
1361 gBS->RestoreTPL (Tpl);\r
1362 return EFI_DEVICE_ERROR;\r
1363 }\r
1364\r
1365 if (Private->NtComStatus.cbInQue == 0) {\r
1366 Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
1367 }\r
1368\r
1369 *Control = Bits;\r
1370\r
1371 gBS->RestoreTPL (Tpl);\r
1372\r
1373 return EFI_SUCCESS;\r
1374}\r
1375\r
5f44f5b9 1376EFI_STATUS\r
1377EFIAPI\r
1378WinNtSerialIoWrite (\r
1379 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1380 IN OUT UINTN *BufferSize,\r
1381 IN VOID *Buffer\r
1382 )\r
1383/*++\r
1384\r
1385Routine Description:\r
1386\r
1387 TODO: Add function description\r
1388\r
1389Arguments:\r
1390\r
1391 This - TODO: add argument description\r
1392 BufferSize - TODO: add argument description\r
1393 Buffer - TODO: add argument description\r
1394\r
1395Returns:\r
1396\r
1397 EFI_DEVICE_ERROR - TODO: Add description for return value\r
1398 EFI_SUCCESS - TODO: Add description for return value\r
1399\r
1400--*/\r
1401{\r
1402 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
1403 UINT8 *ByteBuffer;\r
1404 UINTN TotalBytesWritten;\r
1405 DWORD BytesToGo;\r
1406 DWORD BytesWritten;\r
1407 BOOL Result;\r
1408 UINT32 Index;\r
1409 UINT32 Control;\r
1410 EFI_TPL Tpl;\r
1411\r
1412 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1413\r
1414 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
1415\r
1416 ByteBuffer = (UINT8 *) Buffer;\r
1417 TotalBytesWritten = 0;\r
1418\r
1419 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {\r
1420 for (Index = 0; Index < *BufferSize; Index++) {\r
1421 if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) {\r
1422 TotalBytesWritten++;\r
1423 } else {\r
1424 break;\r
1425 }\r
1426 }\r
1427 } else {\r
1428 BytesToGo = (DWORD) (*BufferSize);\r
1429\r
1430 do {\r
1431 if (Private->HardwareFlowControl) {\r
1432 //\r
1433 // Send RTS\r
1434 //\r
1435 WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
1436 Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
1437 WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
1438 }\r
1439\r
1440 //\r
1441 // Do the write\r
1442 //\r
1443 Result = Private->WinNtThunk->WriteFile (\r
1444 Private->NtHandle,\r
1445 &ByteBuffer[TotalBytesWritten],\r
1446 BytesToGo,\r
1447 &BytesWritten,\r
1448 NULL\r
1449 );\r
1450\r
1451 if (Private->HardwareFlowControl) {\r
1452 //\r
1453 // Assert RTS\r
1454 //\r
1455 WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
1456 Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND;\r
1457 WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
1458 }\r
1459\r
1460 TotalBytesWritten += BytesWritten;\r
1461 BytesToGo -= BytesWritten;\r
1462 if (!Result) {\r
1463 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1464 DEBUG ((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError));\r
1465 *BufferSize = TotalBytesWritten;\r
1466 gBS->RestoreTPL (Tpl);\r
1467 return EFI_DEVICE_ERROR;\r
1468 }\r
1469 } while (BytesToGo > 0);\r
1470 }\r
1471\r
1472 *BufferSize = TotalBytesWritten;\r
1473\r
1474 gBS->RestoreTPL (Tpl);\r
1475\r
1476 return EFI_SUCCESS;\r
1477}\r
1478\r
5f44f5b9 1479EFI_STATUS\r
1480EFIAPI\r
1481WinNtSerialIoRead (\r
1482 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1483 IN OUT UINTN *BufferSize,\r
1484 OUT VOID *Buffer\r
1485 )\r
1486/*++\r
1487\r
1488Routine Description:\r
1489\r
1490 TODO: Add function description\r
1491\r
1492Arguments:\r
1493\r
1494 This - TODO: add argument description\r
1495 BufferSize - TODO: add argument description\r
1496 Buffer - TODO: add argument description\r
1497\r
1498Returns:\r
1499\r
1500 EFI_DEVICE_ERROR - TODO: Add description for return value\r
1501\r
1502--*/\r
1503{\r
1504 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
1505 BOOL Result;\r
1506 DWORD BytesRead;\r
1507 EFI_STATUS Status;\r
1508 UINT32 Index;\r
1509 UINT8 Data;\r
1510 UINT32 Control;\r
1511 EFI_TPL Tpl;\r
1512\r
1513 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1514\r
1515 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
1516\r
1517 //\r
1518 // Do the read\r
1519 //\r
1520 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {\r
1521 for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) {\r
1522 if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) {\r
1523 ((UINT8 *) Buffer)[Index] = Data;\r
1524 BytesRead++;\r
1525 } else {\r
1526 break;\r
1527 }\r
1528 }\r
1529 } else {\r
1530 if (Private->HardwareFlowControl) {\r
1531 WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
1532 Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
1533 WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
1534 }\r
1535\r
1536 Result = Private->WinNtThunk->ReadFile (\r
1537 Private->NtHandle,\r
1538 Buffer,\r
1539 (DWORD) *BufferSize,\r
1540 &BytesRead,\r
1541 NULL\r
1542 );\r
1543\r
1544 if (Private->HardwareFlowControl) {\r
1545 WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
1546 Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY;\r
1547 WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
1548 }\r
1549\r
1550 if (!Result) {\r
1551 Private->NtError = Private->WinNtThunk->GetLastError ();\r
1552 gBS->RestoreTPL (Tpl);\r
1553 return EFI_DEVICE_ERROR;\r
1554 }\r
1555 }\r
1556\r
1557 if (BytesRead != *BufferSize) {\r
1558 Status = EFI_TIMEOUT;\r
1559 } else {\r
1560 Status = EFI_SUCCESS;\r
1561 }\r
1562\r
1563 *BufferSize = (UINTN) BytesRead;\r
1564\r
1565 gBS->RestoreTPL (Tpl);\r
1566\r
1567 return Status;\r
1568}\r
1569\r
1570BOOLEAN\r
1571IsaSerialFifoFull (\r
1572 IN SERIAL_DEV_FIFO *Fifo\r
1573 )\r
1574/*++\r
1575\r
1576 Routine Description:\r
1577 Detect whether specific FIFO is full or not\r
1578\r
1579 Arguments:\r
1580 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
1581\r
1582 Returns:\r
1583 TRUE: the FIFO is full\r
1584 FALSE: the FIFO is not full\r
1585\r
1586--*/\r
1587{\r
1588 if (Fifo->Surplus == 0) {\r
1589 return TRUE;\r
1590 }\r
1591\r
1592 return FALSE;\r
1593}\r
1594\r
1595BOOLEAN\r
1596IsaSerialFifoEmpty (\r
1597 IN SERIAL_DEV_FIFO *Fifo\r
1598 )\r
1599/*++\r
1600\r
1601 Routine Description:\r
1602 Detect whether specific FIFO is empty or not\r
1603\r
1604 Arguments:\r
1605 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
1606\r
1607 Returns:\r
1608 TRUE: the FIFO is empty\r
1609 FALSE: the FIFO is not empty\r
1610\r
1611--*/\r
1612{\r
1613 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {\r
1614 return TRUE;\r
1615 }\r
1616\r
1617 return FALSE;\r
1618}\r
1619\r
1620EFI_STATUS\r
1621IsaSerialFifoAdd (\r
1622 IN SERIAL_DEV_FIFO *Fifo,\r
1623 IN UINT8 Data\r
1624 )\r
1625/*++\r
1626\r
1627 Routine Description:\r
1628 Add data to specific FIFO\r
1629\r
1630 Arguments:\r
1631 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
1632 Data UINT8: the data added to FIFO\r
1633\r
1634 Returns:\r
1635 EFI_SUCCESS: Add data to specific FIFO successfully\r
1636 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full\r
1637\r
1638--*/\r
1639// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1640{\r
1641 //\r
1642 // if FIFO full can not add data\r
1643 //\r
1644 if (IsaSerialFifoFull (Fifo)) {\r
1645 return EFI_OUT_OF_RESOURCES;\r
1646 }\r
1647\r
1648 //\r
1649 // FIFO is not full can add data\r
1650 //\r
1651 Fifo->Data[Fifo->Last] = Data;\r
1652 Fifo->Surplus--;\r
1653 Fifo->Last++;\r
1654 if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) {\r
1655 Fifo->Last = 0;\r
1656 }\r
1657\r
1658 return EFI_SUCCESS;\r
1659}\r
1660\r
1661EFI_STATUS\r
1662IsaSerialFifoRemove (\r
1663 IN SERIAL_DEV_FIFO *Fifo,\r
1664 OUT UINT8 *Data\r
1665 )\r
1666/*++\r
1667\r
1668 Routine Description:\r
1669 Remove data from specific FIFO\r
1670\r
1671 Arguments:\r
1672 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
1673 Data UINT8*: the data removed from FIFO\r
1674\r
1675 Returns:\r
1676 EFI_SUCCESS: Remove data from specific FIFO successfully\r
1677 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty\r
1678\r
1679--*/\r
1680// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1681{\r
1682 //\r
1683 // if FIFO is empty, no data can remove\r
1684 //\r
1685 if (IsaSerialFifoEmpty (Fifo)) {\r
1686 return EFI_OUT_OF_RESOURCES;\r
1687 }\r
1688\r
1689 //\r
1690 // FIFO is not empty, can remove data\r
1691 //\r
1692 *Data = Fifo->Data[Fifo->First];\r
1693 Fifo->Surplus++;\r
1694 Fifo->First++;\r
1695 if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) {\r
1696 Fifo->First = 0;\r
1697 }\r
1698\r
1699 return EFI_SUCCESS;\r
1700}\r