2 Serial driver for standard UARTS on an ISA bus.
4 Copyright (c) 2006 - 2010, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // ISA Serial Driver Global Variables
20 EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver
= {
21 SerialControllerDriverSupported
,
22 SerialControllerDriverStart
,
23 SerialControllerDriverStop
,
30 SERIAL_DEV gSerialDevTempate
= {
34 SERIAL_IO_INTERFACE_REVISION
,
36 IsaSerialSetAttributes
,
44 SERIAL_PORT_DEFAULT_CONTROL_MASK
,
45 SERIAL_PORT_DEFAULT_TIMEOUT
,
46 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
47 SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
,
48 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
49 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
50 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
56 MESSAGING_DEVICE_PATH
,
59 (UINT8
) (sizeof (UART_DEVICE_PATH
)),
60 (UINT8
) ((sizeof (UART_DEVICE_PATH
)) >> 8)
64 FixedPcdGet64 (PcdUartDefaultBaudRate
),
65 FixedPcdGet8 (PcdUartDefaultDataBits
),
66 FixedPcdGet8 (PcdUartDefaultParity
),
67 FixedPcdGet8 (PcdUartDefaultStopBits
)
74 SERIAL_MAX_BUFFER_SIZE
,
80 SERIAL_MAX_BUFFER_SIZE
,
90 The user Entry Point for module IsaSerial. The user code starts with this function.
92 @param[in] ImageHandle The firmware allocated handle for the EFI image.
93 @param[in] SystemTable A pointer to the EFI System Table.
95 @retval EFI_SUCCESS The entry point is executed successfully.
96 @retval other Some error occurs when executing this entry point.
101 InitializeIsaSerial (
102 IN EFI_HANDLE ImageHandle
,
103 IN EFI_SYSTEM_TABLE
*SystemTable
109 // Install driver model protocol(s).
111 Status
= EfiLibInstallDriverBindingComponentName2 (
114 &gSerialControllerDriver
,
116 &gIsaSerialComponentName
,
117 &gIsaSerialComponentName2
119 ASSERT_EFI_ERROR (Status
);
126 Check to see if this driver supports the given controller
128 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
129 @param Controller The handle of the controller to test.
130 @param RemainingDevicePath A pointer to the remaining portion of a device path.
132 @return EFI_SUCCESS This driver can support the given controller
137 SerialControllerDriverSupported (
138 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
139 IN EFI_HANDLE Controller
,
140 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
145 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
146 EFI_ISA_IO_PROTOCOL
*IsaIo
;
147 UART_DEVICE_PATH
*UartNode
;
150 // Check RemainingDevicePath validation
152 if (RemainingDevicePath
!= NULL
) {
154 // Check if RemainingDevicePath is the End of Device Path Node,
155 // if yes, go on checking other conditions
157 if (!IsDevicePathEnd (RemainingDevicePath
)) {
159 // If RemainingDevicePath isn't the End of Device Path Node,
160 // check its validation
162 Status
= EFI_UNSUPPORTED
;
164 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
165 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
166 UartNode
->Header
.SubType
!= MSG_UART_DP
||
167 sizeof (UART_DEVICE_PATH
) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) UartNode
)
172 if (UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
176 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
180 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
184 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
188 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
192 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
196 Status
= EFI_SUCCESS
;
201 // Open the IO Abstraction(s) needed to perform the supported test
203 Status
= gBS
->OpenProtocol (
205 &gEfiIsaIoProtocolGuid
,
207 This
->DriverBindingHandle
,
209 EFI_OPEN_PROTOCOL_BY_DRIVER
211 if (Status
== EFI_ALREADY_STARTED
) {
215 if (EFI_ERROR (Status
)) {
220 // Close the I/O Abstraction(s) used to perform the supported test
224 &gEfiIsaIoProtocolGuid
,
225 This
->DriverBindingHandle
,
230 // Open the EFI Device Path protocol needed to perform the supported test
232 Status
= gBS
->OpenProtocol (
234 &gEfiDevicePathProtocolGuid
,
235 (VOID
**) &ParentDevicePath
,
236 This
->DriverBindingHandle
,
238 EFI_OPEN_PROTOCOL_BY_DRIVER
240 if (Status
== EFI_ALREADY_STARTED
) {
244 if (EFI_ERROR (Status
)) {
248 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
249 // can be managed by this driver.
251 Status
= EFI_SUCCESS
;
252 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x501)) {
253 Status
= EFI_UNSUPPORTED
;
259 // Close protocol, don't use device path protocol in the Support() function
263 &gEfiDevicePathProtocolGuid
,
264 This
->DriverBindingHandle
,
272 Start to management the controller passed in
274 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
275 @param Controller The handle of the controller to test.
276 @param RemainingDevicePath A pointer to the remaining portion of a device path.
278 @return EFI_SUCCESS Driver is started successfully
283 SerialControllerDriverStart (
284 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
285 IN EFI_HANDLE Controller
,
286 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
291 EFI_ISA_IO_PROTOCOL
*IsaIo
;
292 SERIAL_DEV
*SerialDevice
;
294 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
295 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
297 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
298 UART_DEVICE_PATH
*UartNode
;
302 // Get the Parent Device Path
304 Status
= gBS
->OpenProtocol (
306 &gEfiDevicePathProtocolGuid
,
307 (VOID
**) &ParentDevicePath
,
308 This
->DriverBindingHandle
,
310 EFI_OPEN_PROTOCOL_BY_DRIVER
312 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
316 // Report status code enable the serial
318 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
320 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
325 // Grab the IO abstraction we need to get any work done
327 Status
= gBS
->OpenProtocol (
329 &gEfiIsaIoProtocolGuid
,
331 This
->DriverBindingHandle
,
333 EFI_OPEN_PROTOCOL_BY_DRIVER
335 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
339 if (Status
== EFI_ALREADY_STARTED
) {
341 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
343 // If RemainingDevicePath is NULL or is the End of Device Path Node
349 // Make sure a child handle does not already exist. This driver can only
350 // produce one child per serial port.
352 Status
= gBS
->OpenProtocolInformation (
354 &gEfiIsaIoProtocolGuid
,
358 if (EFI_ERROR (Status
)) {
362 Status
= EFI_ALREADY_STARTED
;
363 for (Index
= 0; Index
< EntryCount
; Index
++) {
364 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
365 Status
= gBS
->OpenProtocol (
366 OpenInfoBuffer
[Index
].ControllerHandle
,
367 &gEfiSerialIoProtocolGuid
,
369 This
->DriverBindingHandle
,
371 EFI_OPEN_PROTOCOL_GET_PROTOCOL
373 if (!EFI_ERROR (Status
)) {
374 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
375 Status
= SerialIo
->SetAttributes (
378 SerialIo
->Mode
->ReceiveFifoDepth
,
379 SerialIo
->Mode
->Timeout
,
380 (EFI_PARITY_TYPE
) UartNode
->Parity
,
382 (EFI_STOP_BITS_TYPE
) UartNode
->StopBits
389 FreePool (OpenInfoBuffer
);
393 if (RemainingDevicePath
!= NULL
) {
394 if (IsDevicePathEnd (RemainingDevicePath
)) {
396 // If RemainingDevicePath is the End of Device Path Node,
397 // skip enumerate any device and return EFI_SUCESSS
404 // Initialize the serial device instance
406 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTempate
);
407 if (SerialDevice
== NULL
) {
408 Status
= EFI_OUT_OF_RESOURCES
;
412 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
413 SerialDevice
->IsaIo
= IsaIo
;
414 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
417 // Check if RemainingDevicePath is NULL,
418 // if yes, use the values from the gSerialDevTempate as no remaining device path was
421 if (RemainingDevicePath
!= NULL
) {
423 // If RemainingDevicePath isn't NULL,
424 // match the configuration of the RemainingDevicePath. IsHandleSupported()
425 // already checked to make sure the RemainingDevicePath contains settings
426 // that we can support.
428 CopyMem (&SerialDevice
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
431 AddName (SerialDevice
, IsaIo
);
433 for (Index
= 0; SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
434 if (SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
435 SerialDevice
->BaseAddress
= (UINT16
) SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
439 // Report status code the serial present
441 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
443 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
447 if (!IsaSerialPortPresent (SerialDevice
)) {
448 Status
= EFI_DEVICE_ERROR
;
449 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
451 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
458 // Build the device path by appending the UART node to the ParentDevicePath.
459 //The Uart setings are zero here, since SetAttribute() will update them to match
460 // the default setings.
462 SerialDevice
->DevicePath
= AppendDevicePathNode (
464 (EFI_DEVICE_PATH_PROTOCOL
*)&SerialDevice
->UartDevicePath
466 if (SerialDevice
->DevicePath
== NULL
) {
467 Status
= EFI_DEVICE_ERROR
;
472 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
474 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
475 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
476 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
477 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
480 // Issue a reset to initialize the COM port
482 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
483 if (EFI_ERROR (Status
)) {
484 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
486 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
492 // Install protocol interfaces for the serial device.
494 Status
= gBS
->InstallMultipleProtocolInterfaces (
495 &SerialDevice
->Handle
,
496 &gEfiDevicePathProtocolGuid
,
497 SerialDevice
->DevicePath
,
498 &gEfiSerialIoProtocolGuid
,
499 &SerialDevice
->SerialIo
,
502 if (EFI_ERROR (Status
)) {
506 // Open For Child Device
508 Status
= gBS
->OpenProtocol (
510 &gEfiIsaIoProtocolGuid
,
512 This
->DriverBindingHandle
,
513 SerialDevice
->Handle
,
514 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
518 if (EFI_ERROR (Status
)) {
521 &gEfiDevicePathProtocolGuid
,
522 This
->DriverBindingHandle
,
527 &gEfiIsaIoProtocolGuid
,
528 This
->DriverBindingHandle
,
531 if (SerialDevice
!= NULL
) {
532 if (SerialDevice
->DevicePath
!= NULL
) {
533 gBS
->FreePool (SerialDevice
->DevicePath
);
536 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
537 gBS
->FreePool (SerialDevice
);
545 Disconnect this driver with the controller, uninstall related protocol instance
547 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
548 @param Controller The handle of the controller to test.
549 @param NumberOfChildren Number of child device.
550 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
552 @retval EFI_SUCCESS Operation successfully
553 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
558 SerialControllerDriverStop (
559 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
560 IN EFI_HANDLE Controller
,
561 IN UINTN NumberOfChildren
,
562 IN EFI_HANDLE
*ChildHandleBuffer
568 BOOLEAN AllChildrenStopped
;
569 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
570 SERIAL_DEV
*SerialDevice
;
571 EFI_ISA_IO_PROTOCOL
*IsaIo
;
572 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
574 Status
= gBS
->HandleProtocol (
576 &gEfiDevicePathProtocolGuid
,
577 (VOID
**) &DevicePath
581 // Report the status code disable the serial
583 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
585 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
590 // Complete all outstanding transactions to Controller.
591 // Don't allow any new transaction to Controller to be started.
593 if (NumberOfChildren
== 0) {
595 // Close the bus driver
597 Status
= gBS
->CloseProtocol (
599 &gEfiIsaIoProtocolGuid
,
600 This
->DriverBindingHandle
,
604 Status
= gBS
->CloseProtocol (
606 &gEfiDevicePathProtocolGuid
,
607 This
->DriverBindingHandle
,
613 AllChildrenStopped
= TRUE
;
615 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
617 Status
= gBS
->OpenProtocol (
618 ChildHandleBuffer
[Index
],
619 &gEfiSerialIoProtocolGuid
,
621 This
->DriverBindingHandle
,
623 EFI_OPEN_PROTOCOL_GET_PROTOCOL
625 if (!EFI_ERROR (Status
)) {
627 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
629 Status
= gBS
->CloseProtocol (
631 &gEfiIsaIoProtocolGuid
,
632 This
->DriverBindingHandle
,
633 ChildHandleBuffer
[Index
]
636 Status
= gBS
->UninstallMultipleProtocolInterfaces (
637 ChildHandleBuffer
[Index
],
638 &gEfiDevicePathProtocolGuid
,
639 SerialDevice
->DevicePath
,
640 &gEfiSerialIoProtocolGuid
,
641 &SerialDevice
->SerialIo
,
644 if (EFI_ERROR (Status
)) {
647 &gEfiIsaIoProtocolGuid
,
649 This
->DriverBindingHandle
,
650 ChildHandleBuffer
[Index
],
651 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
654 if (SerialDevice
->DevicePath
!= NULL
) {
655 gBS
->FreePool (SerialDevice
->DevicePath
);
658 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
659 gBS
->FreePool (SerialDevice
);
663 if (EFI_ERROR (Status
)) {
664 AllChildrenStopped
= FALSE
;
668 if (!AllChildrenStopped
) {
669 return EFI_DEVICE_ERROR
;
676 Detect whether specific FIFO is full or not.
678 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
680 @return whether specific FIFO is full or not
685 IN SERIAL_DEV_FIFO
*Fifo
689 if (Fifo
->Surplus
== 0) {
697 Detect whether specific FIFO is empty or not.
699 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
701 @return whether specific FIFO is empty or not
706 IN SERIAL_DEV_FIFO
*Fifo
710 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
718 Add data to specific FIFO.
720 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
721 @param Data the data added to FIFO
723 @retval EFI_SUCCESS Add data to specific FIFO successfully
724 @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
729 IN SERIAL_DEV_FIFO
*Fifo
,
735 // if FIFO full can not add data
737 if (IsaSerialFifoFull (Fifo
)) {
738 return EFI_OUT_OF_RESOURCES
;
741 // FIFO is not full can add data
743 Fifo
->Data
[Fifo
->Last
] = Data
;
746 if (Fifo
->Last
== SERIAL_MAX_BUFFER_SIZE
) {
754 Remove data from specific FIFO.
756 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
757 @param Data the data removed from FIFO
759 @retval EFI_SUCCESS Remove data from specific FIFO successfully
760 @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
764 IsaSerialFifoRemove (
765 IN SERIAL_DEV_FIFO
*Fifo
,
771 // if FIFO is empty, no data can remove
773 if (IsaSerialFifoEmpty (Fifo
)) {
774 return EFI_OUT_OF_RESOURCES
;
777 // FIFO is not empty, can remove data
779 *Data
= Fifo
->Data
[Fifo
->First
];
782 if (Fifo
->First
== SERIAL_MAX_BUFFER_SIZE
) {
790 Reads and writes all avaliable data.
792 @param SerialDevice The device to flush
794 @retval EFI_SUCCESS Data was read/written successfully.
795 @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
796 this happens, pending writes are not done.
800 IsaSerialReceiveTransmit (
801 IN SERIAL_DEV
*SerialDevice
807 BOOLEAN ReceiveFifoFull
;
815 // Begin the read or write
817 if (SerialDevice
->SoftwareLoopbackEnable
) {
819 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
820 if (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
821 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
822 if (ReceiveFifoFull
) {
823 return EFI_OUT_OF_RESOURCES
;
826 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
828 } while (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
830 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
832 // For full handshake flow control, tell the peer to send data
833 // if receive buffer is available.
835 if (SerialDevice
->HardwareFlowControl
&&
836 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)&&
839 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
841 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
844 Lsr
.Data
= READ_LSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
847 // Flush incomming data to prevent a an overrun during a long write
849 if ((Lsr
.Bits
.Dr
== 1) && !ReceiveFifoFull
) {
850 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
851 if (!ReceiveFifoFull
) {
852 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Oe
== 1 || Lsr
.Bits
.Pe
== 1 || Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
853 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
855 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
856 SerialDevice
->DevicePath
858 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Pe
== 1|| Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
859 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
864 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
866 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
869 // For full handshake flow control, if receive buffer full
870 // tell the peer to stop sending data.
872 if (SerialDevice
->HardwareFlowControl
&&
873 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
) &&
874 IsaSerialFifoFull (&SerialDevice
->Receive
)
876 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
878 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
884 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
886 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER
| EFI_PERIPHERAL_SERIAL_PORT
,
887 SerialDevice
->DevicePath
894 if (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
896 // Make sure the transmit data will not be missed
898 if (SerialDevice
->HardwareFlowControl
) {
900 // For half handshake flow control assert RTS before sending.
902 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
903 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
905 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
911 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
912 while ((Msr
.Bits
.Dcd
== 1) && ((Msr
.Bits
.Cts
== 0) || FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
913 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
919 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
922 if ((Msr
.Bits
.Dcd
== 0) && ((Msr
.Bits
.Cts
== 1) || FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
923 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
924 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
928 // For half handshake flow control, tell DCE we are done.
930 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
931 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
933 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
936 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
937 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
940 } while (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
947 // Interface Functions
952 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
954 @retval EFI_SUCCESS Reset successfully
955 @retval EFI_DEVICE_ERROR Failed to reset
961 IN EFI_SERIAL_IO_PROTOCOL
*This
965 SERIAL_DEV
*SerialDevice
;
972 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
975 // Report the status code reset the serial
977 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
979 EFI_P_PC_RESET
| EFI_PERIPHERAL_SERIAL_PORT
,
980 SerialDevice
->DevicePath
983 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
986 // Make sure DLAB is 0.
988 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
990 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
993 // Turn off all interrupts
995 Ier
.Data
= READ_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1000 WRITE_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Ier
.Data
);
1003 // Disable the FIFO.
1005 Fcr
.Bits
.TrFIFOE
= 0;
1006 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1009 // Turn off loopback and disable device interrupt.
1011 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1015 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1018 // Clear the scratch pad register
1020 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0);
1023 // Go set the current attributes
1025 Status
= This
->SetAttributes (
1027 This
->Mode
->BaudRate
,
1028 This
->Mode
->ReceiveFifoDepth
,
1029 This
->Mode
->Timeout
,
1030 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
1031 (UINT8
) This
->Mode
->DataBits
,
1032 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
1035 if (EFI_ERROR (Status
)) {
1036 gBS
->RestoreTPL (Tpl
);
1037 return EFI_DEVICE_ERROR
;
1040 // Go set the current control bits
1042 Status
= This
->SetControl (
1044 This
->Mode
->ControlMask
1047 if (EFI_ERROR (Status
)) {
1048 gBS
->RestoreTPL (Tpl
);
1049 return EFI_DEVICE_ERROR
;
1052 // for 16550A enable FIFO, 16550 disable FIFO
1054 Fcr
.Bits
.TrFIFOE
= 1;
1055 Fcr
.Bits
.ResetRF
= 1;
1056 Fcr
.Bits
.ResetTF
= 1;
1057 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1060 // Reset the software FIFO
1062 SerialDevice
->Receive
.First
= 0;
1063 SerialDevice
->Receive
.Last
= 0;
1064 SerialDevice
->Receive
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1065 SerialDevice
->Transmit
.First
= 0;
1066 SerialDevice
->Transmit
.Last
= 0;
1067 SerialDevice
->Transmit
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1069 gBS
->RestoreTPL (Tpl
);
1072 // Device reset is complete
1078 Set new attributes to a serial device.
1080 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1081 @param BaudRate The baudrate of the serial device
1082 @param ReceiveFifoDepth The depth of receive FIFO buffer
1083 @param Timeout The request timeout for a single char
1084 @param Parity The type of parity used in serial device
1085 @param DataBits Number of databits used in serial device
1086 @param StopBits Number of stopbits used in serial device
1088 @retval EFI_SUCCESS The new attributes were set
1089 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
1090 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
1091 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
1096 IsaSerialSetAttributes (
1097 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1099 IN UINT32 ReceiveFifoDepth
,
1101 IN EFI_PARITY_TYPE Parity
,
1103 IN EFI_STOP_BITS_TYPE StopBits
1107 SERIAL_DEV
*SerialDevice
;
1110 SERIAL_PORT_LCR Lcr
;
1111 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
1114 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1117 // Check for default settings and fill in actual values.
1119 if (BaudRate
== 0) {
1120 BaudRate
= FixedPcdGet64 (PcdUartDefaultBaudRate
);
1123 if (ReceiveFifoDepth
== 0) {
1124 ReceiveFifoDepth
= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
;
1128 Timeout
= SERIAL_PORT_DEFAULT_TIMEOUT
;
1131 if (Parity
== DefaultParity
) {
1132 Parity
= (EFI_PARITY_TYPE
)FixedPcdGet8 (PcdUartDefaultParity
);
1135 if (DataBits
== 0) {
1136 DataBits
= FixedPcdGet8 (PcdUartDefaultDataBits
);
1139 if (StopBits
== DefaultStopBits
) {
1140 StopBits
= (EFI_STOP_BITS_TYPE
) FixedPcdGet8 (PcdUartDefaultStopBits
);
1143 // 5 and 6 data bits can not be verified on a 16550A UART
1144 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
1146 if ((DataBits
== 5) || (DataBits
== 6)) {
1147 return EFI_INVALID_PARAMETER
;
1150 // Make sure all parameters are valid
1152 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
1153 return EFI_INVALID_PARAMETER
;
1156 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
1157 // 38400,57600,115200
1159 if (BaudRate
< 75) {
1161 } else if (BaudRate
< 110) {
1163 } else if (BaudRate
< 134) {
1165 } else if (BaudRate
< 150) {
1167 } else if (BaudRate
< 300) {
1169 } else if (BaudRate
< 600) {
1171 } else if (BaudRate
< 1200) {
1173 } else if (BaudRate
< 1800) {
1175 } else if (BaudRate
< 2000) {
1177 } else if (BaudRate
< 2400) {
1179 } else if (BaudRate
< 3600) {
1181 } else if (BaudRate
< 4800) {
1183 } else if (BaudRate
< 7200) {
1185 } else if (BaudRate
< 9600) {
1187 } else if (BaudRate
< 19200) {
1189 } else if (BaudRate
< 38400) {
1191 } else if (BaudRate
< 57600) {
1193 } else if (BaudRate
< 115200) {
1195 } else if (BaudRate
<= SERIAL_PORT_MAX_BAUD_RATE
) {
1199 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
1200 return EFI_INVALID_PARAMETER
;
1203 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
1204 return EFI_INVALID_PARAMETER
;
1207 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
1208 return EFI_INVALID_PARAMETER
;
1211 if ((DataBits
< 5) || (DataBits
> 8)) {
1212 return EFI_INVALID_PARAMETER
;
1215 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
1216 return EFI_INVALID_PARAMETER
;
1220 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
1222 if ((DataBits
>= 6) && (DataBits
<= 8) && (StopBits
== OneFiveStopBits
)) {
1223 return EFI_INVALID_PARAMETER
;
1227 // Compute divisor use to program the baud rate using a round determination
1229 Divisor
= (UINT32
) DivU64x32Remainder (
1230 SERIAL_PORT_INPUT_CLOCK
,
1231 ((UINT32
) BaudRate
* 16),
1234 if (Remained
!= 0) {
1238 if ((Divisor
== 0) || ((Divisor
& 0xffff0000) != 0)) {
1239 return EFI_INVALID_PARAMETER
;
1242 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1245 // Compute the actual baud rate that the serial port will be programmed for.
1247 BaudRate
= SERIAL_PORT_INPUT_CLOCK
/ Divisor
/ 16;
1250 // Put serial port on Divisor Latch Mode
1252 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1254 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1257 // Write the divisor to the serial port
1259 WRITE_DLL (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) (Divisor
& 0xff));
1260 WRITE_DLM (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) ((Divisor
>> 8) & 0xff));
1263 // Put serial port back in normal mode and set remaining attributes.
1270 Lcr
.Bits
.EvenPar
= 0;
1271 Lcr
.Bits
.SticPar
= 0;
1276 Lcr
.Bits
.EvenPar
= 1;
1277 Lcr
.Bits
.SticPar
= 0;
1282 Lcr
.Bits
.EvenPar
= 0;
1283 Lcr
.Bits
.SticPar
= 0;
1288 Lcr
.Bits
.EvenPar
= 1;
1289 Lcr
.Bits
.SticPar
= 1;
1294 Lcr
.Bits
.EvenPar
= 0;
1295 Lcr
.Bits
.SticPar
= 1;
1307 case OneFiveStopBits
:
1318 Lcr
.Bits
.SerialDB
= (UINT8
) ((DataBits
- 5) & 0x03);
1319 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1322 // Set the Serial I/O mode
1324 This
->Mode
->BaudRate
= BaudRate
;
1325 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
1326 This
->Mode
->Timeout
= Timeout
;
1327 This
->Mode
->Parity
= Parity
;
1328 This
->Mode
->DataBits
= DataBits
;
1329 This
->Mode
->StopBits
= StopBits
;
1332 // See if Device Path Node has actually changed
1334 if (SerialDevice
->UartDevicePath
.BaudRate
== BaudRate
&&
1335 SerialDevice
->UartDevicePath
.DataBits
== DataBits
&&
1336 SerialDevice
->UartDevicePath
.Parity
== Parity
&&
1337 SerialDevice
->UartDevicePath
.StopBits
== StopBits
1339 gBS
->RestoreTPL (Tpl
);
1343 // Update the device path
1345 SerialDevice
->UartDevicePath
.BaudRate
= BaudRate
;
1346 SerialDevice
->UartDevicePath
.DataBits
= DataBits
;
1347 SerialDevice
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1348 SerialDevice
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1350 NewDevicePath
= AppendDevicePathNode (
1351 SerialDevice
->ParentDevicePath
,
1352 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
1354 if (NewDevicePath
== NULL
) {
1355 gBS
->RestoreTPL (Tpl
);
1356 return EFI_DEVICE_ERROR
;
1359 if (SerialDevice
->Handle
!= NULL
) {
1360 Status
= gBS
->ReinstallProtocolInterface (
1361 SerialDevice
->Handle
,
1362 &gEfiDevicePathProtocolGuid
,
1363 SerialDevice
->DevicePath
,
1366 if (EFI_ERROR (Status
)) {
1367 gBS
->RestoreTPL (Tpl
);
1372 if (SerialDevice
->DevicePath
!= NULL
) {
1373 gBS
->FreePool (SerialDevice
->DevicePath
);
1376 SerialDevice
->DevicePath
= NewDevicePath
;
1378 gBS
->RestoreTPL (Tpl
);
1386 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1387 @param Control Control bits that can be settable
1389 @retval EFI_SUCCESS New Control bits were set successfully
1390 @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
1395 IsaSerialSetControl (
1396 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1400 SERIAL_DEV
*SerialDevice
;
1401 SERIAL_PORT_MCR Mcr
;
1405 // The control bits that can be set are :
1406 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
1407 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
1408 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
1409 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
1411 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1414 // first determine the parameter is invalid
1416 if ((Control
& 0xffff8ffc) != 0) {
1417 return EFI_UNSUPPORTED
;
1420 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1422 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1426 SerialDevice
->SoftwareLoopbackEnable
= FALSE
;
1427 SerialDevice
->HardwareFlowControl
= FALSE
;
1429 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
1433 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
1437 if ((Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1441 if ((Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1442 SerialDevice
->HardwareFlowControl
= TRUE
;
1445 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1447 if ((Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1448 SerialDevice
->SoftwareLoopbackEnable
= TRUE
;
1451 gBS
->RestoreTPL (Tpl
);
1459 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1460 @param Control Control signals of the serial device
1462 @retval EFI_SUCCESS Get Control signals successfully
1467 IsaSerialGetControl (
1468 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1472 SERIAL_DEV
*SerialDevice
;
1473 SERIAL_PORT_MSR Msr
;
1474 SERIAL_PORT_MCR Mcr
;
1477 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1479 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1484 // Read the Modem Status Register
1486 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1488 if (Msr
.Bits
.Cts
== 1) {
1489 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
1492 if (Msr
.Bits
.Dsr
== 1) {
1493 *Control
|= EFI_SERIAL_DATA_SET_READY
;
1496 if (Msr
.Bits
.Ri
== 1) {
1497 *Control
|= EFI_SERIAL_RING_INDICATE
;
1500 if (Msr
.Bits
.Dcd
== 1) {
1501 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
1504 // Read the Modem Control Register
1506 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1508 if (Mcr
.Bits
.DtrC
== 1) {
1509 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1512 if (Mcr
.Bits
.Rts
== 1) {
1513 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1516 if (Mcr
.Bits
.Lme
== 1) {
1517 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1520 if (SerialDevice
->HardwareFlowControl
) {
1521 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1524 // See if the Transmit FIFO is empty
1526 IsaSerialReceiveTransmit (SerialDevice
);
1528 if (IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1529 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
1532 // See if the Receive FIFO is empty.
1534 IsaSerialReceiveTransmit (SerialDevice
);
1536 if (IsaSerialFifoEmpty (&SerialDevice
->Receive
)) {
1537 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1540 if (SerialDevice
->SoftwareLoopbackEnable
) {
1541 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1544 gBS
->RestoreTPL (Tpl
);
1550 Write the specified number of bytes to serial device.
1552 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1553 @param BufferSize On input the size of Buffer, on output the amount of
1554 data actually written
1555 @param Buffer The buffer of data to write
1557 @retval EFI_SUCCESS The data were written successfully
1558 @retval EFI_DEVICE_ERROR The device reported an error
1559 @retval EFI_TIMEOUT The write operation was stopped due to timeout
1565 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1566 IN OUT UINTN
*BufferSize
,
1570 SERIAL_DEV
*SerialDevice
;
1577 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1581 if (*BufferSize
== 0) {
1585 if (Buffer
== NULL
) {
1586 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1588 EFI_P_EC_OUTPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1589 SerialDevice
->DevicePath
1592 return EFI_DEVICE_ERROR
;
1595 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1597 CharBuffer
= (UINT8
*) Buffer
;
1599 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1600 IsaSerialFifoAdd (&SerialDevice
->Transmit
, CharBuffer
[Index
]);
1602 while (IsaSerialReceiveTransmit (SerialDevice
) != EFI_SUCCESS
|| !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1604 // Unsuccessful write so check if timeout has expired, if not,
1605 // stall for a bit, increment time elapsed, and try again
1607 if (Elapsed
>= This
->Mode
->Timeout
) {
1608 *BufferSize
= ActualWrite
;
1609 gBS
->RestoreTPL (Tpl
);
1613 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1615 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1620 // Successful write so reset timeout
1625 gBS
->RestoreTPL (Tpl
);
1631 Read the specified number of bytes from serial device.
1633 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1634 @param BufferSize On input the size of Buffer, on output the amount of
1635 data returned in buffer
1636 @param Buffer The buffer to return the data into
1638 @retval EFI_SUCCESS The data were read successfully
1639 @retval EFI_DEVICE_ERROR The device reported an error
1640 @retval EFI_TIMEOUT The read operation was stopped due to timeout
1646 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1647 IN OUT UINTN
*BufferSize
,
1651 SERIAL_DEV
*SerialDevice
;
1658 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1661 if (*BufferSize
== 0) {
1665 if (Buffer
== NULL
) {
1666 return EFI_DEVICE_ERROR
;
1669 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1671 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1673 if (EFI_ERROR (Status
)) {
1676 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1678 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1679 SerialDevice
->DevicePath
1682 gBS
->RestoreTPL (Tpl
);
1684 return EFI_DEVICE_ERROR
;
1687 CharBuffer
= (UINT8
*) Buffer
;
1688 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1689 while (IsaSerialFifoRemove (&SerialDevice
->Receive
, &(CharBuffer
[Index
])) != EFI_SUCCESS
) {
1691 // Unsuccessful read so check if timeout has expired, if not,
1692 // stall for a bit, increment time elapsed, and try again
1693 // Need this time out to get conspliter to work.
1695 if (Elapsed
>= This
->Mode
->Timeout
) {
1696 *BufferSize
= Index
;
1697 gBS
->RestoreTPL (Tpl
);
1701 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1702 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1704 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1705 if (Status
== EFI_DEVICE_ERROR
) {
1706 *BufferSize
= Index
;
1707 gBS
->RestoreTPL (Tpl
);
1708 return EFI_DEVICE_ERROR
;
1712 // Successful read so reset timeout
1717 IsaSerialReceiveTransmit (SerialDevice
);
1719 gBS
->RestoreTPL (Tpl
);
1725 Use scratchpad register to test if this serial port is present.
1727 @param SerialDevice Pointer to serial device structure
1729 @return if this serial port is present
1732 IsaSerialPortPresent (
1733 IN SERIAL_DEV
*SerialDevice
1745 Temp
= READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1746 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0xAA);
1748 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0xAA) {
1752 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0x55);
1754 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0x55) {
1760 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Temp
);
1765 Use IsaIo protocol to read serial port.
1767 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1768 @param BaseAddress Serial port register group base address
1769 @param Offset Offset in register group
1771 @return Data read from serial port
1776 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1777 IN UINT16 BaseAddress
,
1784 // Use IsaIo to access IO
1789 BaseAddress
+ Offset
,
1797 Use IsaIo protocol to write serial port.
1799 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1800 @param BaseAddress Serial port register group base address
1801 @param Offset Offset in register group
1802 @param Data data which is to be written to some serial port register
1806 IsaSerialWritePort (
1807 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1808 IN UINT16 BaseAddress
,
1814 // Use IsaIo to access IO
1819 BaseAddress
+ Offset
,