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