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