Fix warnings generated by GCC.
[edk2.git] / Nt32Pkg / WinNtSerialIoDxe / WinNtSerialIo.c
blob17e4fdacf63f2b53fd78c6f848c4cf6fa112a42d
1 /**@file
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
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.
12 Module Name:
14 WinNtSerialIo.c
16 Abstract:
18 Our DriverBinding member functions operate on the handles
19 created by the NT Bus driver.
21 Handle(1) - WinNtIo - DevicePath(1)
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.
27 Handle(2) - SerialIo - DevicePath(1)\UART
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).
33 Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort
35 If the driver is unloaded Handle(2) is removed from the system and
36 gEfiWinNtSerialPortGuid is removed from Handle(1).
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.
43 If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is
44 loaded on the device.
46 **/
48 #include "WinNtSerialIo.h"
50 EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = {
51 WinNtSerialIoDriverBindingSupported,
52 WinNtSerialIoDriverBindingStart,
53 WinNtSerialIoDriverBindingStop,
54 0xa,
55 NULL,
56 NULL
60 // List of supported baud rate
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};
64 /**
65 The user Entry Point for module WinNtSerialIo. The user code starts with this function.
67 @param[in] ImageHandle The firmware allocated handle for the EFI image.
68 @param[in] SystemTable A pointer to the EFI System Table.
70 @retval EFI_SUCCESS The entry point is executed successfully.
71 @retval other Some error occurs when executing this entry point.
73 **/
74 EFI_STATUS
75 EFIAPI
76 InitializeWinNtSerialIo(
77 IN EFI_HANDLE ImageHandle,
78 IN EFI_SYSTEM_TABLE *SystemTable
81 EFI_STATUS Status;
84 // Install driver model protocol(s).
86 Status = EfiLibInstallDriverBindingComponentName2 (
87 ImageHandle,
88 SystemTable,
89 &gWinNtSerialIoDriverBinding,
90 ImageHandle,
91 &gWinNtSerialIoComponentName,
92 &gWinNtSerialIoComponentName2
94 ASSERT_EFI_ERROR (Status);
97 return Status;
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
107 /*++
109 Routine Description:
111 Arguments:
113 Returns:
115 None
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
124 EFI_STATUS Status;
125 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
126 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
127 UART_DEVICE_PATH *UartNode;
130 // Check RemainingDevicePath validation
132 if (RemainingDevicePath != NULL) {
134 // Check if RemainingDevicePath is the End of Device Path Node,
135 // if yes, go on checking other conditions
137 if (!IsDevicePathEnd (RemainingDevicePath)) {
139 // If RemainingDevicePath isn't the End of Device Path Node,
140 // check its validation
142 Status = EFI_UNSUPPORTED;
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;
150 if ( UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
151 goto Error;
153 if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {
154 goto Error;
156 if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {
157 goto Error;
159 if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {
160 goto Error;
162 if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {
163 goto Error;
165 if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {
166 goto Error;
172 // Open the IO Abstraction(s) needed to perform the supported test
174 Status = gBS->OpenProtocol (
175 Handle,
176 &gEfiWinNtIoProtocolGuid,
177 (VOID **) &WinNtIo,
178 This->DriverBindingHandle,
179 Handle,
180 EFI_OPEN_PROTOCOL_BY_DRIVER
182 if (Status == EFI_ALREADY_STARTED) {
183 return EFI_SUCCESS;
186 if (EFI_ERROR (Status)) {
187 return Status;
191 // Close the I/O Abstraction(s) used to perform the supported test
193 gBS->CloseProtocol (
194 Handle,
195 &gEfiWinNtIoProtocolGuid,
196 This->DriverBindingHandle,
197 Handle
201 // Open the EFI Device Path protocol needed to perform the supported test
203 Status = gBS->OpenProtocol (
204 Handle,
205 &gEfiDevicePathProtocolGuid,
206 (VOID **) &ParentDevicePath,
207 This->DriverBindingHandle,
208 Handle,
209 EFI_OPEN_PROTOCOL_BY_DRIVER
211 if (Status == EFI_ALREADY_STARTED) {
212 return EFI_SUCCESS;
215 if (EFI_ERROR (Status)) {
216 return Status;
220 // Close protocol, don't use device path protocol in the Support() function
222 gBS->CloseProtocol (
223 Handle,
224 &gEfiDevicePathProtocolGuid,
225 This->DriverBindingHandle,
226 Handle
230 // Make sure that the WinNt Thunk Protocol is valid
232 if (WinNtIo->WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {
233 Status = EFI_UNSUPPORTED;
234 goto Error;
238 // Check the GUID to see if this is a handle type the driver supports
240 if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtSerialPortGuid)) {
241 Status = EFI_UNSUPPORTED;
242 goto Error;
245 return EFI_SUCCESS;
247 Error:
248 return Status;
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
258 /*++
260 Routine Description:
262 Arguments:
264 Returns:
266 None
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
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;
287 Private = NULL;
288 NtHandle = INVALID_HANDLE_VALUE;
291 // Grab the protocols we need
293 Status = gBS->OpenProtocol (
294 Handle,
295 &gEfiDevicePathProtocolGuid,
296 (VOID **) &ParentDevicePath,
297 This->DriverBindingHandle,
298 Handle,
299 EFI_OPEN_PROTOCOL_BY_DRIVER
301 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
302 return Status;
306 // Grab the IO abstraction we need to get any work done
308 Status = gBS->OpenProtocol (
309 Handle,
310 &gEfiWinNtIoProtocolGuid,
311 (VOID **) &WinNtIo,
312 This->DriverBindingHandle,
313 Handle,
314 EFI_OPEN_PROTOCOL_BY_DRIVER
316 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
317 gBS->CloseProtocol (
318 Handle,
319 &gEfiDevicePathProtocolGuid,
320 This->DriverBindingHandle,
321 Handle
323 return Status;
326 if (Status == EFI_ALREADY_STARTED) {
328 if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
330 // If RemainingDevicePath is NULL or is the End of Device Path Node
332 return EFI_SUCCESS;
336 // Make sure a child handle does not already exist. This driver can only
337 // produce one child per serial port.
339 Status = gBS->OpenProtocolInformation (
340 Handle,
341 &gEfiWinNtIoProtocolGuid,
342 &OpenInfoBuffer,
343 &EntryCount
345 if (EFI_ERROR (Status)) {
346 return Status;
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
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
372 break;
376 FreePool (OpenInfoBuffer);
377 return Status;
380 if (RemainingDevicePath == NULL) {
382 // Build the device path by appending the UART node to the ParentDevicePath
383 // from the WinNtIo handle. The Uart setings are zero here, since
384 // SetAttribute() will update them to match the default setings.
386 ZeroMem (&Node, sizeof (UART_DEVICE_PATH));
387 Node.Header.Type = MESSAGING_DEVICE_PATH;
388 Node.Header.SubType = MSG_UART_DP;
389 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &Node, sizeof (UART_DEVICE_PATH));
391 } else if (!IsDevicePathEnd (RemainingDevicePath)) {
393 // If RemainingDevicePath isn't the End of Device Path Node,
394 // only scan the specified device by RemainingDevicePath
397 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
398 // already checked to make sure the RemainingDevicePath contains settings
399 // that we can support.
401 CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
403 } else {
405 // If RemainingDevicePath is the End of Device Path Node,
406 // skip enumerate any device and return EFI_SUCESSS
408 return EFI_SUCCESS;
412 // Check to see if we can access the hardware device. If it's Open in NT we
413 // will not get access.
415 NtHandle = WinNtIo->WinNtThunk->CreateFile (
416 WinNtIo->EnvString,
417 GENERIC_READ | GENERIC_WRITE,
419 NULL,
420 OPEN_EXISTING,
422 NULL
424 if (NtHandle == INVALID_HANDLE_VALUE) {
425 Status = EFI_DEVICE_ERROR;
426 goto Error;
430 // Construct Private data
432 Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA));
433 if (Private == NULL) {
434 goto Error;
438 // This signature must be valid before any member function is called
440 Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE;
441 Private->NtHandle = NtHandle;
442 Private->ControllerHandle = Handle;
443 Private->Handle = NULL;
444 Private->WinNtThunk = WinNtIo->WinNtThunk;
445 Private->ParentDevicePath = ParentDevicePath;
446 Private->ControllerNameTable = NULL;
448 Private->SoftwareLoopbackEnable = FALSE;
449 Private->HardwareLoopbackEnable = FALSE;
450 Private->HardwareFlowControl = FALSE;
451 Private->Fifo.First = 0;
452 Private->Fifo.Last = 0;
453 Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE;
455 CopyMem (&Private->UartDevicePath, &Node, sizeof (UART_DEVICE_PATH));
457 AddUnicodeString2 (
458 "eng",
459 gWinNtSerialIoComponentName.SupportedLanguages,
460 &Private->ControllerNameTable,
461 WinNtIo->EnvString,
462 TRUE
464 AddUnicodeString2 (
465 "en",
466 gWinNtSerialIoComponentName2.SupportedLanguages,
467 &Private->ControllerNameTable,
468 WinNtIo->EnvString,
469 FALSE
473 Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION;
474 Private->SerialIo.Reset = WinNtSerialIoReset;
475 Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes;
476 Private->SerialIo.SetControl = WinNtSerialIoSetControl;
477 Private->SerialIo.GetControl = WinNtSerialIoGetControl;
478 Private->SerialIo.Write = WinNtSerialIoWrite;
479 Private->SerialIo.Read = WinNtSerialIoRead;
480 Private->SerialIo.Mode = &Private->SerialIoMode;
483 // Build the device path by appending the UART node to the ParentDevicePath
484 // from the WinNtIo handle. The Uart setings are zero here, since
485 // SetAttribute() will update them to match the current setings.
487 Private->DevicePath = AppendDevicePathNode (
488 ParentDevicePath,
489 (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath
491 if (Private->DevicePath == NULL) {
492 Status = EFI_OUT_OF_RESOURCES;
493 goto Error;
497 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
499 Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK;
500 Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT;
501 Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate;
502 Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;
503 Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits;
504 Private->SerialIoMode.Parity = Private->UartDevicePath.Parity;
505 Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits;
508 // Issue a reset to initialize the COM port
510 Status = Private->SerialIo.Reset (&Private->SerialIo);
511 if (EFI_ERROR (Status)) {
512 goto Error;
516 // Create new child handle
518 Status = gBS->InstallMultipleProtocolInterfaces (
519 &Private->Handle,
520 &gEfiSerialIoProtocolGuid,
521 &Private->SerialIo,
522 &gEfiDevicePathProtocolGuid,
523 Private->DevicePath,
524 NULL
526 if (EFI_ERROR (Status)) {
527 goto Error;
531 // Open For Child Device
533 Status = gBS->OpenProtocol (
534 Handle,
535 &gEfiWinNtIoProtocolGuid,
536 (VOID **) &WinNtIo,
537 This->DriverBindingHandle,
538 Private->Handle,
539 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
541 if (EFI_ERROR (Status)) {
542 goto Error;
545 return EFI_SUCCESS;
547 Error:
549 // Use the Stop() function to free all resources allocated in Start()
551 if (Private != NULL) {
552 if (Private->Handle != NULL) {
553 This->Stop (This, Handle, 1, &Private->Handle);
554 } else {
555 if (NtHandle != INVALID_HANDLE_VALUE) {
556 Private->WinNtThunk->CloseHandle (NtHandle);
559 if (Private->DevicePath != NULL) {
560 FreePool (Private->DevicePath);
563 FreeUnicodeStringTable (Private->ControllerNameTable);
565 FreePool (Private);
569 This->Stop (This, Handle, 0, NULL);
571 return Status;
574 EFI_STATUS
575 EFIAPI
576 WinNtSerialIoDriverBindingStop (
577 IN EFI_DRIVER_BINDING_PROTOCOL *This,
578 IN EFI_HANDLE Handle,
579 IN UINTN NumberOfChildren,
580 IN EFI_HANDLE *ChildHandleBuffer
582 /*++
584 Routine Description:
586 TODO: Add function description
588 Arguments:
590 This - TODO: add argument description
591 Handle - TODO: add argument description
592 NumberOfChildren - TODO: add argument description
593 ChildHandleBuffer - TODO: add argument description
595 Returns:
597 EFI_DEVICE_ERROR - TODO: Add description for return value
598 EFI_SUCCESS - TODO: Add description for return value
600 --*/
602 EFI_STATUS Status;
603 UINTN Index;
604 BOOLEAN AllChildrenStopped;
605 EFI_SERIAL_IO_PROTOCOL *SerialIo;
606 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
607 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
610 // Complete all outstanding transactions to Controller.
611 // Don't allow any new transaction to Controller to be started.
614 if (NumberOfChildren == 0) {
616 // Close the bus driver
618 Status = gBS->CloseProtocol (
619 Handle,
620 &gEfiWinNtIoProtocolGuid,
621 This->DriverBindingHandle,
622 Handle
624 Status = gBS->CloseProtocol (
625 Handle,
626 &gEfiDevicePathProtocolGuid,
627 This->DriverBindingHandle,
628 Handle
630 return Status;
633 AllChildrenStopped = TRUE;
635 for (Index = 0; Index < NumberOfChildren; Index++) {
636 Status = gBS->OpenProtocol (
637 ChildHandleBuffer[Index],
638 &gEfiSerialIoProtocolGuid,
639 (VOID **) &SerialIo,
640 This->DriverBindingHandle,
641 Handle,
642 EFI_OPEN_PROTOCOL_GET_PROTOCOL
644 if (!EFI_ERROR (Status)) {
645 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo);
647 ASSERT (Private->Handle == ChildHandleBuffer[Index]);
649 Status = gBS->CloseProtocol (
650 Handle,
651 &gEfiWinNtIoProtocolGuid,
652 This->DriverBindingHandle,
653 ChildHandleBuffer[Index]
656 Status = gBS->UninstallMultipleProtocolInterfaces (
657 ChildHandleBuffer[Index],
658 &gEfiSerialIoProtocolGuid,
659 &Private->SerialIo,
660 &gEfiDevicePathProtocolGuid,
661 Private->DevicePath,
662 NULL
665 if (EFI_ERROR (Status)) {
666 gBS->OpenProtocol (
667 Handle,
668 &gEfiWinNtIoProtocolGuid,
669 (VOID **) &WinNtIo,
670 This->DriverBindingHandle,
671 ChildHandleBuffer[Index],
672 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
674 } else {
675 Private->WinNtThunk->CloseHandle (Private->NtHandle);
677 FreePool (Private->DevicePath);
679 FreeUnicodeStringTable (Private->ControllerNameTable);
681 FreePool (Private);
685 if (EFI_ERROR (Status)) {
686 AllChildrenStopped = FALSE;
690 if (!AllChildrenStopped) {
691 return EFI_DEVICE_ERROR;
694 return EFI_SUCCESS;
698 // Serial IO Protocol member functions
701 EFI_STATUS
702 EFIAPI
703 WinNtSerialIoReset (
704 IN EFI_SERIAL_IO_PROTOCOL *This
706 /*++
708 Routine Description:
710 TODO: Add function description
712 Arguments:
714 This - TODO: add argument description
716 Returns:
718 TODO: add return values
720 --*/
722 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
723 EFI_TPL Tpl;
725 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
727 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
729 Private->WinNtThunk->PurgeComm (
730 Private->NtHandle,
731 PURGE_TXCLEAR | PURGE_RXCLEAR
734 gBS->RestoreTPL (Tpl);
736 return This->SetAttributes (
737 This,
738 This->Mode->BaudRate,
739 This->Mode->ReceiveFifoDepth,
740 This->Mode->Timeout,
741 (EFI_PARITY_TYPE)This->Mode->Parity,
742 (UINT8) This->Mode->DataBits,
743 (EFI_STOP_BITS_TYPE)This->Mode->StopBits
747 EFI_STATUS
748 EFIAPI
749 WinNtSerialIoSetAttributes (
750 IN EFI_SERIAL_IO_PROTOCOL *This,
751 IN UINT64 BaudRate,
752 IN UINT32 ReceiveFifoDepth,
753 IN UINT32 Timeout,
754 IN EFI_PARITY_TYPE Parity,
755 IN UINT8 DataBits,
756 IN EFI_STOP_BITS_TYPE StopBits
758 /*++
760 Routine Description:
762 This function is used to set the attributes.
764 Arguments:
766 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
767 BaudRate - The Baud rate of the serial device.
768 ReceiveFifoDepth - The request depth of fifo on receive side.
769 Timeout - the request timeout for a single charact.
770 Parity - The type of parity used in serial device.
771 DataBits - Number of deata bits used in serial device.
772 StopBits - Number of stop bits used in serial device.
774 Returns:
775 Status code
777 None
779 --*/
780 // TODO: EFI_SUCCESS - add return value to function comment
781 // TODO: EFI_DEVICE_ERROR - add return value to function comment
782 // TODO: EFI_DEVICE_ERROR - add return value to function comment
783 // TODO: EFI_DEVICE_ERROR - add return value to function comment
784 // TODO: EFI_SUCCESS - add return value to function comment
785 // TODO: EFI_DEVICE_ERROR - add return value to function comment
786 // TODO: EFI_SUCCESS - add return value to function comment
788 EFI_STATUS Status;
789 UINTN Index;
790 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
791 COMMTIMEOUTS PortTimeOuts;
792 DWORD ConvertedTime;
793 BOOL Result;
794 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
795 EFI_TPL Tpl;
797 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
800 // Some of our arguments have defaults if a null value is passed in, and
801 // we must set the default values if a null argument is passed in.
803 if (BaudRate == 0) {
804 BaudRate = FixedPcdGet64 (PcdUartDefaultBaudRate);
807 if (ReceiveFifoDepth == 0) {
808 ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;
811 if (Timeout == 0) {
812 Timeout = SERIAL_TIMEOUT_DEFAULT;
815 if (Parity == DefaultParity) {
816 Parity = (EFI_PARITY_TYPE) (FixedPcdGet8 (PcdUartDefaultParity));
819 if (DataBits == 0) {
820 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
823 if (StopBits == DefaultStopBits) {
824 StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);
828 // Make sure all parameters are valid
830 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
831 return EFI_INVALID_PARAMETER;
835 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
838 for (Index = 1; Index < (sizeof (mBaudRateCurrentSupport) / sizeof (mBaudRateCurrentSupport[0])); Index++) {
839 if (BaudRate < mBaudRateCurrentSupport[Index]) {
840 BaudRate = mBaudRateCurrentSupport[Index-1];
841 break;
845 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
846 return EFI_INVALID_PARAMETER;
849 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
850 return EFI_INVALID_PARAMETER;
853 if ((Parity < NoParity) || (Parity > SpaceParity)) {
854 return EFI_INVALID_PARAMETER;
857 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
858 return EFI_INVALID_PARAMETER;
862 // Now we only support DataBits=7,8.
864 if ((DataBits < 7) || (DataBits > 8)) {
865 return EFI_INVALID_PARAMETER;
869 // Now we only support DataBits=7,8.
870 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
872 if (StopBits == OneFiveStopBits) {
873 return EFI_INVALID_PARAMETER;
877 // See if the new attributes already match the current attributes
879 if (Private->UartDevicePath.BaudRate == BaudRate &&
880 Private->UartDevicePath.DataBits == DataBits &&
881 Private->UartDevicePath.Parity == Parity &&
882 Private->UartDevicePath.StopBits == StopBits &&
883 Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth &&
884 Private->SerialIoMode.Timeout == Timeout ) {
885 return EFI_SUCCESS;
888 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
891 // Get current values from NT
893 ZeroMem (&Private->NtDCB, sizeof (DCB));
894 Private->NtDCB.DCBlength = sizeof (DCB);
896 if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) {
897 Private->NtError = Private->WinNtThunk->GetLastError ();
898 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError));
899 gBS->RestoreTPL (Tpl);
900 return EFI_DEVICE_ERROR;
904 // Map EFI com setting to NT
906 Private->NtDCB.BaudRate = ConvertBaud2Nt (BaudRate);
907 Private->NtDCB.ByteSize = ConvertData2Nt (DataBits);
908 Private->NtDCB.Parity = ConvertParity2Nt (Parity);
909 Private->NtDCB.StopBits = ConvertStop2Nt (StopBits);
911 Private->NtDCB.fBinary = TRUE;
912 Private->NtDCB.fParity = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE;
913 Private->NtDCB.fOutxCtsFlow = FALSE;
914 Private->NtDCB.fOutxDsrFlow = FALSE;
915 Private->NtDCB.fDtrControl = DTR_CONTROL_ENABLE;
916 Private->NtDCB.fDsrSensitivity = FALSE;
917 Private->NtDCB.fOutX = FALSE;
918 Private->NtDCB.fInX = FALSE;
919 Private->NtDCB.fRtsControl = RTS_CONTROL_ENABLE;
920 Private->NtDCB.fNull = FALSE;
923 // Set new values
925 Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB);
926 if (!Result) {
927 Private->NtError = Private->WinNtThunk->GetLastError ();
928 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError));
929 gBS->RestoreTPL (Tpl);
930 return EFI_DEVICE_ERROR;
934 // Set com port read/write timeout values
936 ConvertedTime = ConvertTime2Nt (Timeout);
937 PortTimeOuts.ReadIntervalTimeout = MAXDWORD;
938 PortTimeOuts.ReadTotalTimeoutMultiplier = 0;
939 PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime;
940 PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime;
941 PortTimeOuts.WriteTotalTimeoutConstant = 0;
943 if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) {
944 Private->NtError = Private->WinNtThunk->GetLastError ();
945 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError));
946 gBS->RestoreTPL (Tpl);
947 return EFI_DEVICE_ERROR;
951 // Update mode
953 Private->SerialIoMode.BaudRate = BaudRate;
954 Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth;
955 Private->SerialIoMode.Timeout = Timeout;
956 Private->SerialIoMode.Parity = Parity;
957 Private->SerialIoMode.DataBits = DataBits;
958 Private->SerialIoMode.StopBits = StopBits;
961 // See if Device Path Node has actually changed
963 if (Private->UartDevicePath.BaudRate == BaudRate &&
964 Private->UartDevicePath.DataBits == DataBits &&
965 Private->UartDevicePath.Parity == Parity &&
966 Private->UartDevicePath.StopBits == StopBits ) {
967 gBS->RestoreTPL(Tpl);
968 return EFI_SUCCESS;
972 // Update the device path
974 Private->UartDevicePath.BaudRate = BaudRate;
975 Private->UartDevicePath.DataBits = DataBits;
976 Private->UartDevicePath.Parity = (UINT8) Parity;
977 Private->UartDevicePath.StopBits = (UINT8) StopBits;
979 NewDevicePath = AppendDevicePathNode (
980 Private->ParentDevicePath,
981 (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath
983 if (NewDevicePath == NULL) {
984 gBS->RestoreTPL (Tpl);
985 return EFI_DEVICE_ERROR;
988 if (Private->Handle != NULL) {
989 Status = gBS->ReinstallProtocolInterface (
990 Private->Handle,
991 &gEfiDevicePathProtocolGuid,
992 Private->DevicePath,
993 NewDevicePath
995 if (EFI_ERROR (Status)) {
996 gBS->RestoreTPL (Tpl);
997 return Status;
1001 if (Private->DevicePath != NULL) {
1002 FreePool (Private->DevicePath);
1005 Private->DevicePath = NewDevicePath;
1007 gBS->RestoreTPL (Tpl);
1009 return EFI_SUCCESS;
1012 EFI_STATUS
1013 EFIAPI
1014 WinNtSerialIoSetControl (
1015 IN EFI_SERIAL_IO_PROTOCOL *This,
1016 IN UINT32 Control
1018 /*++
1020 Routine Description:
1022 TODO: Add function description
1024 Arguments:
1026 This - TODO: add argument description
1027 Control - TODO: add argument description
1029 Returns:
1031 EFI_DEVICE_ERROR - TODO: Add description for return value
1032 EFI_DEVICE_ERROR - TODO: Add description for return value
1033 EFI_SUCCESS - TODO: Add description for return value
1035 --*/
1037 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
1038 BOOL Result;
1039 DCB Dcb;
1040 EFI_TPL Tpl;
1043 // first determine the parameter is invalid
1045 if (Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
1046 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
1047 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) {
1048 return EFI_UNSUPPORTED;
1051 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1053 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1055 Result = Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb);
1057 if (!Result) {
1058 Private->NtError = Private->WinNtThunk->GetLastError ();
1059 DEBUG ((EFI_D_ERROR, "SerialSetControl: GetCommState %d\n", Private->NtError));
1060 gBS->RestoreTPL (Tpl);
1061 return EFI_DEVICE_ERROR;
1064 Dcb.fRtsControl = RTS_CONTROL_DISABLE;
1065 Dcb.fDtrControl = DTR_CONTROL_DISABLE;
1066 Private->HardwareFlowControl = FALSE;
1067 Private->SoftwareLoopbackEnable = FALSE;
1068 Private->HardwareLoopbackEnable = FALSE;
1070 if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
1071 Dcb.fRtsControl = RTS_CONTROL_ENABLE;
1074 if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
1075 Dcb.fDtrControl = DTR_CONTROL_ENABLE;
1078 if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
1079 Private->HardwareFlowControl = TRUE;
1082 if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
1083 Private->SoftwareLoopbackEnable = TRUE;
1086 if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
1087 Private->HardwareLoopbackEnable = TRUE;
1090 Result = Private->WinNtThunk->SetCommState (
1091 Private->NtHandle,
1092 &Dcb
1095 if (!Result) {
1096 Private->NtError = Private->WinNtThunk->GetLastError ();
1097 DEBUG ((EFI_D_ERROR, "SerialSetControl: SetCommState %d\n", Private->NtError));
1098 gBS->RestoreTPL (Tpl);
1099 return EFI_DEVICE_ERROR;
1102 gBS->RestoreTPL (Tpl);
1104 return EFI_SUCCESS;
1107 EFI_STATUS
1108 EFIAPI
1109 WinNtSerialIoGetControl (
1110 IN EFI_SERIAL_IO_PROTOCOL *This,
1111 OUT UINT32 *Control
1113 /*++
1115 Routine Description:
1117 TODO: Add function description
1119 Arguments:
1121 This - TODO: add argument description
1122 Control - TODO: add argument description
1124 Returns:
1126 EFI_DEVICE_ERROR - TODO: Add description for return value
1127 EFI_DEVICE_ERROR - TODO: Add description for return value
1128 EFI_DEVICE_ERROR - TODO: Add description for return value
1129 EFI_SUCCESS - TODO: Add description for return value
1131 --*/
1133 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
1134 DWORD ModemStatus;
1135 DWORD Errors;
1136 UINT32 Bits;
1137 DCB Dcb;
1138 EFI_TPL Tpl;
1140 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1142 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1145 // Get modem status
1147 if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) {
1148 Private->NtError = Private->WinNtThunk->GetLastError ();
1149 gBS->RestoreTPL (Tpl);
1150 return EFI_DEVICE_ERROR;
1153 Bits = 0;
1154 if (ModemStatus & MS_CTS_ON) {
1155 Bits |= EFI_SERIAL_CLEAR_TO_SEND;
1158 if (ModemStatus & MS_DSR_ON) {
1159 Bits |= EFI_SERIAL_DATA_SET_READY;
1162 if (ModemStatus & MS_RING_ON) {
1163 Bits |= EFI_SERIAL_RING_INDICATE;
1166 if (ModemStatus & MS_RLSD_ON) {
1167 Bits |= EFI_SERIAL_CARRIER_DETECT;
1171 // Get ctrl status
1173 if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb)) {
1174 Private->NtError = Private->WinNtThunk->GetLastError ();
1175 DEBUG ((EFI_D_ERROR, "SerialGetControl: GetCommState %d\n", Private->NtError));
1176 gBS->RestoreTPL (Tpl);
1177 return EFI_DEVICE_ERROR;
1180 if (Dcb.fDtrControl == DTR_CONTROL_ENABLE) {
1181 Bits |= EFI_SERIAL_DATA_TERMINAL_READY;
1184 if (Dcb.fRtsControl == RTS_CONTROL_ENABLE) {
1185 Bits |= EFI_SERIAL_REQUEST_TO_SEND;
1188 if (Private->HardwareFlowControl) {
1189 Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1192 if (Private->SoftwareLoopbackEnable) {
1193 Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
1196 if (Private->HardwareLoopbackEnable) {
1197 Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
1201 // Get input buffer status
1203 if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) {
1204 Private->NtError = Private->WinNtThunk->GetLastError ();
1205 DEBUG ((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError));
1206 gBS->RestoreTPL (Tpl);
1207 return EFI_DEVICE_ERROR;
1210 if (Private->NtComStatus.cbInQue == 0) {
1211 Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
1214 *Control = Bits;
1216 gBS->RestoreTPL (Tpl);
1218 return EFI_SUCCESS;
1221 EFI_STATUS
1222 EFIAPI
1223 WinNtSerialIoWrite (
1224 IN EFI_SERIAL_IO_PROTOCOL *This,
1225 IN OUT UINTN *BufferSize,
1226 IN VOID *Buffer
1228 /*++
1230 Routine Description:
1232 TODO: Add function description
1234 Arguments:
1236 This - TODO: add argument description
1237 BufferSize - TODO: add argument description
1238 Buffer - TODO: add argument description
1240 Returns:
1242 EFI_DEVICE_ERROR - TODO: Add description for return value
1243 EFI_SUCCESS - TODO: Add description for return value
1245 --*/
1247 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
1248 UINT8 *ByteBuffer;
1249 UINTN TotalBytesWritten;
1250 DWORD BytesToGo;
1251 DWORD BytesWritten;
1252 BOOL Result;
1253 UINT32 Index;
1254 UINT32 Control;
1255 EFI_TPL Tpl;
1257 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1259 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1261 ByteBuffer = (UINT8 *) Buffer;
1262 TotalBytesWritten = 0;
1264 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
1265 for (Index = 0; Index < *BufferSize; Index++) {
1266 if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) {
1267 TotalBytesWritten++;
1268 } else {
1269 break;
1272 } else {
1273 BytesToGo = (DWORD) (*BufferSize);
1275 do {
1276 if (Private->HardwareFlowControl) {
1278 // Send RTS
1280 WinNtSerialIoGetControl (&Private->SerialIo, &Control);
1281 Control |= EFI_SERIAL_REQUEST_TO_SEND;
1282 WinNtSerialIoSetControl (&Private->SerialIo, Control);
1286 // Do the write
1288 Result = Private->WinNtThunk->WriteFile (
1289 Private->NtHandle,
1290 &ByteBuffer[TotalBytesWritten],
1291 BytesToGo,
1292 &BytesWritten,
1293 NULL
1296 if (Private->HardwareFlowControl) {
1298 // Assert RTS
1300 WinNtSerialIoGetControl (&Private->SerialIo, &Control);
1301 Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND;
1302 WinNtSerialIoSetControl (&Private->SerialIo, Control);
1305 TotalBytesWritten += BytesWritten;
1306 BytesToGo -= BytesWritten;
1307 if (!Result) {
1308 Private->NtError = Private->WinNtThunk->GetLastError ();
1309 DEBUG ((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError));
1310 *BufferSize = TotalBytesWritten;
1311 gBS->RestoreTPL (Tpl);
1312 return EFI_DEVICE_ERROR;
1314 } while (BytesToGo > 0);
1317 *BufferSize = TotalBytesWritten;
1319 gBS->RestoreTPL (Tpl);
1321 return EFI_SUCCESS;
1324 EFI_STATUS
1325 EFIAPI
1326 WinNtSerialIoRead (
1327 IN EFI_SERIAL_IO_PROTOCOL *This,
1328 IN OUT UINTN *BufferSize,
1329 OUT VOID *Buffer
1331 /*++
1333 Routine Description:
1335 TODO: Add function description
1337 Arguments:
1339 This - TODO: add argument description
1340 BufferSize - TODO: add argument description
1341 Buffer - TODO: add argument description
1343 Returns:
1345 EFI_DEVICE_ERROR - TODO: Add description for return value
1347 --*/
1349 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
1350 BOOL Result;
1351 DWORD BytesRead;
1352 EFI_STATUS Status;
1353 UINT32 Index;
1354 UINT8 Data;
1355 UINT32 Control;
1356 EFI_TPL Tpl;
1358 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1360 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
1363 // Do the read
1365 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
1366 for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) {
1367 if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) {
1368 ((UINT8 *) Buffer)[Index] = Data;
1369 BytesRead++;
1370 } else {
1371 break;
1374 } else {
1375 if (Private->HardwareFlowControl) {
1376 WinNtSerialIoGetControl (&Private->SerialIo, &Control);
1377 Control |= EFI_SERIAL_DATA_TERMINAL_READY;
1378 WinNtSerialIoSetControl (&Private->SerialIo, Control);
1381 Result = Private->WinNtThunk->ReadFile (
1382 Private->NtHandle,
1383 Buffer,
1384 (DWORD) *BufferSize,
1385 &BytesRead,
1386 NULL
1389 if (Private->HardwareFlowControl) {
1390 WinNtSerialIoGetControl (&Private->SerialIo, &Control);
1391 Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY;
1392 WinNtSerialIoSetControl (&Private->SerialIo, Control);
1395 if (!Result) {
1396 Private->NtError = Private->WinNtThunk->GetLastError ();
1397 gBS->RestoreTPL (Tpl);
1398 return EFI_DEVICE_ERROR;
1402 if (BytesRead != *BufferSize) {
1403 Status = EFI_TIMEOUT;
1404 } else {
1405 Status = EFI_SUCCESS;
1408 *BufferSize = (UINTN) BytesRead;
1410 gBS->RestoreTPL (Tpl);
1412 return Status;
1415 BOOLEAN
1416 IsaSerialFifoFull (
1417 IN SERIAL_DEV_FIFO *Fifo
1419 /*++
1421 Routine Description:
1422 Detect whether specific FIFO is full or not
1424 Arguments:
1425 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1427 Returns:
1428 TRUE: the FIFO is full
1429 FALSE: the FIFO is not full
1431 --*/
1433 if (Fifo->Surplus == 0) {
1434 return TRUE;
1437 return FALSE;
1440 BOOLEAN
1441 IsaSerialFifoEmpty (
1442 IN SERIAL_DEV_FIFO *Fifo
1444 /*++
1446 Routine Description:
1447 Detect whether specific FIFO is empty or not
1449 Arguments:
1450 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1452 Returns:
1453 TRUE: the FIFO is empty
1454 FALSE: the FIFO is not empty
1456 --*/
1458 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
1459 return TRUE;
1462 return FALSE;
1465 EFI_STATUS
1466 IsaSerialFifoAdd (
1467 IN SERIAL_DEV_FIFO *Fifo,
1468 IN UINT8 Data
1470 /*++
1472 Routine Description:
1473 Add data to specific FIFO
1475 Arguments:
1476 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1477 Data UINT8: the data added to FIFO
1479 Returns:
1480 EFI_SUCCESS: Add data to specific FIFO successfully
1481 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1483 --*/
1484 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1487 // if FIFO full can not add data
1489 if (IsaSerialFifoFull (Fifo)) {
1490 return EFI_OUT_OF_RESOURCES;
1494 // FIFO is not full can add data
1496 Fifo->Data[Fifo->Last] = Data;
1497 Fifo->Surplus--;
1498 Fifo->Last++;
1499 if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) {
1500 Fifo->Last = 0;
1503 return EFI_SUCCESS;
1506 EFI_STATUS
1507 IsaSerialFifoRemove (
1508 IN SERIAL_DEV_FIFO *Fifo,
1509 OUT UINT8 *Data
1511 /*++
1513 Routine Description:
1514 Remove data from specific FIFO
1516 Arguments:
1517 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1518 Data UINT8*: the data removed from FIFO
1520 Returns:
1521 EFI_SUCCESS: Remove data from specific FIFO successfully
1522 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1524 --*/
1525 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1528 // if FIFO is empty, no data can remove
1530 if (IsaSerialFifoEmpty (Fifo)) {
1531 return EFI_OUT_OF_RESOURCES;
1535 // FIFO is not empty, can remove data
1537 *Data = Fifo->Data[Fifo->First];
1538 Fifo->Surplus++;
1539 Fifo->First++;
1540 if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) {
1541 Fifo->First = 0;
1544 return EFI_SUCCESS;