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