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