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