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