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