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