2 Serial driver for standard UARTS on an ISA bus.
4 Copyright (c) 2006 - 2009, 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 // Ignore the RemainingDevicePath
153 // Open the IO Abstraction(s) needed to perform the supported test
155 Status
= gBS
->OpenProtocol (
157 &gEfiDevicePathProtocolGuid
,
158 (VOID
**) &ParentDevicePath
,
159 This
->DriverBindingHandle
,
161 EFI_OPEN_PROTOCOL_BY_DRIVER
163 if (Status
== EFI_ALREADY_STARTED
) {
167 if (EFI_ERROR (Status
)) {
173 &gEfiDevicePathProtocolGuid
,
174 This
->DriverBindingHandle
,
178 Status
= gBS
->OpenProtocol (
180 &gEfiIsaIoProtocolGuid
,
182 This
->DriverBindingHandle
,
184 EFI_OPEN_PROTOCOL_BY_DRIVER
187 if (Status
== EFI_ALREADY_STARTED
) {
191 if (EFI_ERROR (Status
)) {
195 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
196 // can be managed by this driver.
198 Status
= EFI_SUCCESS
;
199 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x501)) {
200 Status
= EFI_UNSUPPORTED
;
204 // Make sure RemainingDevicePath is valid
206 if (RemainingDevicePath
!= NULL
) {
207 Status
= EFI_UNSUPPORTED
;
210 (UART_DEVICE_PATH
*) RemainingDevicePath
,
211 sizeof (UART_DEVICE_PATH
)
213 if (UartNode
.Header
.Type
!= MESSAGING_DEVICE_PATH
||
214 UartNode
.Header
.SubType
!= MSG_UART_DP
||
215 sizeof (UART_DEVICE_PATH
) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &UartNode
)
220 if (UartNode
.BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
224 if (UartNode
.Parity
< NoParity
|| UartNode
.Parity
> SpaceParity
) {
228 if (UartNode
.DataBits
< 5 || UartNode
.DataBits
> 8) {
232 if (UartNode
.StopBits
< OneStopBit
|| UartNode
.StopBits
> TwoStopBits
) {
236 if ((UartNode
.DataBits
== 5) && (UartNode
.StopBits
== TwoStopBits
)) {
240 if ((UartNode
.DataBits
>= 6) && (UartNode
.DataBits
<= 8) && (UartNode
.StopBits
== OneFiveStopBits
)) {
244 Status
= EFI_SUCCESS
;
249 // Close the I/O Abstraction(s) used to perform the supported test
253 &gEfiIsaIoProtocolGuid
,
254 This
->DriverBindingHandle
,
262 Start to management the controller passed in
264 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
265 @param Controller The handle of the controller to test.
266 @param RemainingDevicePath A pointer to the remaining portion of a device path.
268 @return EFI_SUCCESS Driver is started successfully
273 SerialControllerDriverStart (
274 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
275 IN EFI_HANDLE Controller
,
276 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
281 EFI_ISA_IO_PROTOCOL
*IsaIo
;
282 SERIAL_DEV
*SerialDevice
;
284 UART_DEVICE_PATH Node
;
285 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
286 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
288 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
292 // Get the Parent Device Path
294 Status
= gBS
->OpenProtocol (
296 &gEfiDevicePathProtocolGuid
,
297 (VOID
**) &ParentDevicePath
,
298 This
->DriverBindingHandle
,
300 EFI_OPEN_PROTOCOL_BY_DRIVER
302 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
306 // Report status code enable the serial
308 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
310 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
315 // Grab the IO abstraction we need to get any work done
317 Status
= gBS
->OpenProtocol (
319 &gEfiIsaIoProtocolGuid
,
321 This
->DriverBindingHandle
,
323 EFI_OPEN_PROTOCOL_BY_DRIVER
325 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
329 if (Status
== EFI_ALREADY_STARTED
) {
331 if (RemainingDevicePath
== NULL
) {
335 // Make sure a child handle does not already exist. This driver can only
336 // produce one child per serial port.
338 Status
= gBS
->OpenProtocolInformation (
340 &gEfiIsaIoProtocolGuid
,
344 if (EFI_ERROR (Status
)) {
348 Status
= EFI_ALREADY_STARTED
;
349 for (Index
= 0; Index
< EntryCount
; Index
++) {
350 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
351 Status
= gBS
->OpenProtocol (
352 OpenInfoBuffer
[Index
].ControllerHandle
,
353 &gEfiSerialIoProtocolGuid
,
355 This
->DriverBindingHandle
,
357 EFI_OPEN_PROTOCOL_GET_PROTOCOL
359 if (!EFI_ERROR (Status
)) {
360 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
361 Status
= SerialIo
->SetAttributes (
364 SerialIo
->Mode
->ReceiveFifoDepth
,
365 SerialIo
->Mode
->Timeout
,
366 (EFI_PARITY_TYPE
) Node
.Parity
,
368 (EFI_STOP_BITS_TYPE
) Node
.StopBits
375 gBS
->FreePool (OpenInfoBuffer
);
379 // Initialize the serial device instance
381 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTempate
);
382 if (SerialDevice
== NULL
) {
383 Status
= EFI_OUT_OF_RESOURCES
;
387 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
388 SerialDevice
->IsaIo
= IsaIo
;
389 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
391 AddName (SerialDevice
, IsaIo
);
393 for (Index
= 0; SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
394 if (SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
395 SerialDevice
->BaseAddress
= (UINT16
) SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
399 // Report status code the serial present
401 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
403 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
407 if (!IsaSerialPortPresent (SerialDevice
)) {
408 Status
= EFI_DEVICE_ERROR
;
409 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
411 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
417 if (RemainingDevicePath
!= NULL
) {
419 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
420 // already checked to make sure the RemainingDevicePath contains settings
421 // that we can support.
423 CopyMem (&SerialDevice
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
426 // Use the values from the gSerialDevTempate as no remaining device path was
431 // Build the device path by appending the UART node to the ParentDevicePath
432 // from the WinNtIo handle. The Uart setings are zero here, since
433 // SetAttribute() will update them to match the current setings.
435 SerialDevice
->DevicePath
= AppendDevicePathNode (
437 (EFI_DEVICE_PATH_PROTOCOL
*)&SerialDevice
->UartDevicePath
439 if (SerialDevice
->DevicePath
== NULL
) {
440 Status
= EFI_DEVICE_ERROR
;
445 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
447 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
448 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
449 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
450 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
453 // Issue a reset to initialize the COM port
455 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
456 if (EFI_ERROR (Status
)) {
457 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
459 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
465 // Install protocol interfaces for the serial device.
467 Status
= gBS
->InstallMultipleProtocolInterfaces (
468 &SerialDevice
->Handle
,
469 &gEfiDevicePathProtocolGuid
,
470 SerialDevice
->DevicePath
,
471 &gEfiSerialIoProtocolGuid
,
472 &SerialDevice
->SerialIo
,
475 if (EFI_ERROR (Status
)) {
479 // Open For Child Device
481 Status
= gBS
->OpenProtocol (
483 &gEfiIsaIoProtocolGuid
,
485 This
->DriverBindingHandle
,
486 SerialDevice
->Handle
,
487 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
491 if (EFI_ERROR (Status
)) {
494 &gEfiDevicePathProtocolGuid
,
495 This
->DriverBindingHandle
,
500 &gEfiIsaIoProtocolGuid
,
501 This
->DriverBindingHandle
,
504 if (SerialDevice
!= NULL
) {
505 if (SerialDevice
->DevicePath
!= NULL
) {
506 gBS
->FreePool (SerialDevice
->DevicePath
);
509 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
510 gBS
->FreePool (SerialDevice
);
518 Disconnect this driver with the controller, uninstall related protocol instance
520 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
521 @param Controller The handle of the controller to test.
522 @param NumberOfChildren Number of child device.
523 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
525 @retval EFI_SUCCESS Operation successfully
526 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
531 SerialControllerDriverStop (
532 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
533 IN EFI_HANDLE Controller
,
534 IN UINTN NumberOfChildren
,
535 IN EFI_HANDLE
*ChildHandleBuffer
541 BOOLEAN AllChildrenStopped
;
542 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
543 SERIAL_DEV
*SerialDevice
;
544 EFI_ISA_IO_PROTOCOL
*IsaIo
;
545 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
547 Status
= gBS
->HandleProtocol (
549 &gEfiDevicePathProtocolGuid
,
550 (VOID
**) &DevicePath
554 // Report the status code disable the serial
556 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
558 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
563 // Complete all outstanding transactions to Controller.
564 // Don't allow any new transaction to Controller to be started.
566 if (NumberOfChildren
== 0) {
568 // Close the bus driver
570 Status
= gBS
->CloseProtocol (
572 &gEfiIsaIoProtocolGuid
,
573 This
->DriverBindingHandle
,
577 Status
= gBS
->CloseProtocol (
579 &gEfiDevicePathProtocolGuid
,
580 This
->DriverBindingHandle
,
586 AllChildrenStopped
= TRUE
;
588 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
590 Status
= gBS
->OpenProtocol (
591 ChildHandleBuffer
[Index
],
592 &gEfiSerialIoProtocolGuid
,
594 This
->DriverBindingHandle
,
596 EFI_OPEN_PROTOCOL_GET_PROTOCOL
598 if (!EFI_ERROR (Status
)) {
600 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
602 Status
= gBS
->CloseProtocol (
604 &gEfiIsaIoProtocolGuid
,
605 This
->DriverBindingHandle
,
606 ChildHandleBuffer
[Index
]
609 Status
= gBS
->UninstallMultipleProtocolInterfaces (
610 ChildHandleBuffer
[Index
],
611 &gEfiDevicePathProtocolGuid
,
612 SerialDevice
->DevicePath
,
613 &gEfiSerialIoProtocolGuid
,
614 &SerialDevice
->SerialIo
,
617 if (EFI_ERROR (Status
)) {
620 &gEfiIsaIoProtocolGuid
,
622 This
->DriverBindingHandle
,
623 ChildHandleBuffer
[Index
],
624 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
627 if (SerialDevice
->DevicePath
!= NULL
) {
628 gBS
->FreePool (SerialDevice
->DevicePath
);
631 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
632 gBS
->FreePool (SerialDevice
);
636 if (EFI_ERROR (Status
)) {
637 AllChildrenStopped
= FALSE
;
641 if (!AllChildrenStopped
) {
642 return EFI_DEVICE_ERROR
;
649 Detect whether specific FIFO is full or not.
651 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
653 @return whether specific FIFO is full or not
658 IN SERIAL_DEV_FIFO
*Fifo
662 if (Fifo
->Surplus
== 0) {
670 Detect whether specific FIFO is empty or not.
672 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
674 @return whether specific FIFO is empty or not
679 IN SERIAL_DEV_FIFO
*Fifo
683 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
691 Add data to specific FIFO.
693 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
694 @param Data the data added to FIFO
696 @retval EFI_SUCCESS Add data to specific FIFO successfully
697 @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
702 IN SERIAL_DEV_FIFO
*Fifo
,
708 // if FIFO full can not add data
710 if (IsaSerialFifoFull (Fifo
)) {
711 return EFI_OUT_OF_RESOURCES
;
714 // FIFO is not full can add data
716 Fifo
->Data
[Fifo
->Last
] = Data
;
719 if (Fifo
->Last
== SERIAL_MAX_BUFFER_SIZE
) {
727 Remove data from specific FIFO.
729 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
730 @param Data the data removed from FIFO
732 @retval EFI_SUCCESS Remove data from specific FIFO successfully
733 @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
737 IsaSerialFifoRemove (
738 IN SERIAL_DEV_FIFO
*Fifo
,
744 // if FIFO is empty, no data can remove
746 if (IsaSerialFifoEmpty (Fifo
)) {
747 return EFI_OUT_OF_RESOURCES
;
750 // FIFO is not empty, can remove data
752 *Data
= Fifo
->Data
[Fifo
->First
];
755 if (Fifo
->First
== SERIAL_MAX_BUFFER_SIZE
) {
763 Reads and writes all avaliable data.
765 @param SerialDevice The device to flush
767 @retval EFI_SUCCESS Data was read/written successfully.
768 @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
769 this happens, pending writes are not done.
773 IsaSerialReceiveTransmit (
774 IN SERIAL_DEV
*SerialDevice
780 BOOLEAN ReceiveFifoFull
;
788 // Begin the read or write
790 if (SerialDevice
->SoftwareLoopbackEnable
) {
792 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
793 if (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
794 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
795 if (ReceiveFifoFull
) {
796 return EFI_OUT_OF_RESOURCES
;
799 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
801 } while (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
803 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
805 // For full handshake flow control, tell the peer to send data
806 // if receive buffer is available.
808 if (SerialDevice
->HardwareFlowControl
&&
809 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)&&
812 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
814 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
817 Lsr
.Data
= READ_LSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
820 // Flush incomming data to prevent a an overrun during a long write
822 if ((Lsr
.Bits
.Dr
== 1) && !ReceiveFifoFull
) {
823 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
824 if (!ReceiveFifoFull
) {
825 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Oe
== 1 || Lsr
.Bits
.Pe
== 1 || Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
826 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
828 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
829 SerialDevice
->DevicePath
831 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Pe
== 1|| Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
832 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
837 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
839 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
842 // For full handshake flow control, if receive buffer full
843 // tell the peer to stop sending data.
845 if (SerialDevice
->HardwareFlowControl
&&
846 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
) &&
847 IsaSerialFifoFull (&SerialDevice
->Receive
)
849 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
851 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
857 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
859 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER
| EFI_PERIPHERAL_SERIAL_PORT
,
860 SerialDevice
->DevicePath
867 if (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
869 // Make sure the transmit data will not be missed
871 if (SerialDevice
->HardwareFlowControl
) {
873 // For half handshake flow control assert RTS before sending.
875 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
876 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
878 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
884 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
885 while ((Msr
.Bits
.Dcd
== 1) && ((Msr
.Bits
.Cts
== 0) || FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
886 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
892 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
895 if ((Msr
.Bits
.Dcd
== 0) && ((Msr
.Bits
.Cts
== 1) || FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
896 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
897 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
901 // For half handshake flow control, tell DCE we are done.
903 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
904 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
906 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
909 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
910 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
913 } while (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
920 // Interface Functions
925 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
927 @retval EFI_SUCCESS Reset successfully
928 @retval EFI_DEVICE_ERROR Failed to reset
934 IN EFI_SERIAL_IO_PROTOCOL
*This
938 SERIAL_DEV
*SerialDevice
;
945 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
948 // Report the status code reset the serial
950 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
952 EFI_P_PC_RESET
| EFI_PERIPHERAL_SERIAL_PORT
,
953 SerialDevice
->DevicePath
956 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
959 // Make sure DLAB is 0.
961 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
963 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
966 // Turn off all interrupts
968 Ier
.Data
= READ_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
973 WRITE_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Ier
.Data
);
978 Fcr
.Bits
.TrFIFOE
= 0;
979 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
982 // Turn off loopback and disable device interrupt.
984 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
988 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
991 // Clear the scratch pad register
993 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0);
996 // Go set the current attributes
998 Status
= This
->SetAttributes (
1000 This
->Mode
->BaudRate
,
1001 This
->Mode
->ReceiveFifoDepth
,
1002 This
->Mode
->Timeout
,
1003 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
1004 (UINT8
) This
->Mode
->DataBits
,
1005 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
1008 if (EFI_ERROR (Status
)) {
1009 gBS
->RestoreTPL (Tpl
);
1010 return EFI_DEVICE_ERROR
;
1013 // Go set the current control bits
1015 Status
= This
->SetControl (
1017 This
->Mode
->ControlMask
1020 if (EFI_ERROR (Status
)) {
1021 gBS
->RestoreTPL (Tpl
);
1022 return EFI_DEVICE_ERROR
;
1025 // for 16550A enable FIFO, 16550 disable FIFO
1027 Fcr
.Bits
.TrFIFOE
= 1;
1028 Fcr
.Bits
.ResetRF
= 1;
1029 Fcr
.Bits
.ResetTF
= 1;
1030 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1033 // Reset the software FIFO
1035 SerialDevice
->Receive
.First
= 0;
1036 SerialDevice
->Receive
.Last
= 0;
1037 SerialDevice
->Receive
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1038 SerialDevice
->Transmit
.First
= 0;
1039 SerialDevice
->Transmit
.Last
= 0;
1040 SerialDevice
->Transmit
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1042 gBS
->RestoreTPL (Tpl
);
1045 // Device reset is complete
1051 Set new attributes to a serial device.
1053 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1054 @param BaudRate The baudrate of the serial device
1055 @param ReceiveFifoDepth The depth of receive FIFO buffer
1056 @param Timeout The request timeout for a single char
1057 @param Parity The type of parity used in serial device
1058 @param DataBits Number of databits used in serial device
1059 @param StopBits Number of stopbits used in serial device
1061 @retval EFI_SUCCESS The new attributes were set
1062 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
1063 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
1064 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
1069 IsaSerialSetAttributes (
1070 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1072 IN UINT32 ReceiveFifoDepth
,
1074 IN EFI_PARITY_TYPE Parity
,
1076 IN EFI_STOP_BITS_TYPE StopBits
1080 SERIAL_DEV
*SerialDevice
;
1083 SERIAL_PORT_LCR Lcr
;
1084 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
1087 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1090 // Check for default settings and fill in actual values.
1092 if (BaudRate
== 0) {
1093 BaudRate
= FixedPcdGet64 (PcdUartDefaultBaudRate
);
1096 if (ReceiveFifoDepth
== 0) {
1097 ReceiveFifoDepth
= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
;
1101 Timeout
= SERIAL_PORT_DEFAULT_TIMEOUT
;
1104 if (Parity
== DefaultParity
) {
1105 Parity
= (EFI_PARITY_TYPE
)FixedPcdGet8 (PcdUartDefaultParity
);
1108 if (DataBits
== 0) {
1109 DataBits
= FixedPcdGet8 (PcdUartDefaultDataBits
);
1112 if (StopBits
== DefaultStopBits
) {
1113 StopBits
= (EFI_STOP_BITS_TYPE
) FixedPcdGet8 (PcdUartDefaultStopBits
);
1116 // 5 and 6 data bits can not be verified on a 16550A UART
1117 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
1119 if ((DataBits
== 5) || (DataBits
== 6)) {
1120 return EFI_INVALID_PARAMETER
;
1123 // Make sure all parameters are valid
1125 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
1126 return EFI_INVALID_PARAMETER
;
1129 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
1130 // 38400,57600,115200
1132 if (BaudRate
< 75) {
1134 } else if (BaudRate
< 110) {
1136 } else if (BaudRate
< 134) {
1138 } else if (BaudRate
< 150) {
1140 } else if (BaudRate
< 300) {
1142 } else if (BaudRate
< 600) {
1144 } else if (BaudRate
< 1200) {
1146 } else if (BaudRate
< 1800) {
1148 } else if (BaudRate
< 2000) {
1150 } else if (BaudRate
< 2400) {
1152 } else if (BaudRate
< 3600) {
1154 } else if (BaudRate
< 4800) {
1156 } else if (BaudRate
< 7200) {
1158 } else if (BaudRate
< 9600) {
1160 } else if (BaudRate
< 19200) {
1162 } else if (BaudRate
< 38400) {
1164 } else if (BaudRate
< 57600) {
1166 } else if (BaudRate
< 115200) {
1168 } else if (BaudRate
<= SERIAL_PORT_MAX_BAUD_RATE
) {
1172 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
1173 return EFI_INVALID_PARAMETER
;
1176 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
1177 return EFI_INVALID_PARAMETER
;
1180 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
1181 return EFI_INVALID_PARAMETER
;
1184 if ((DataBits
< 5) || (DataBits
> 8)) {
1185 return EFI_INVALID_PARAMETER
;
1188 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
1189 return EFI_INVALID_PARAMETER
;
1193 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
1195 if ((DataBits
>= 6) && (DataBits
<= 8) && (StopBits
== OneFiveStopBits
)) {
1196 return EFI_INVALID_PARAMETER
;
1200 // Compute divisor use to program the baud rate using a round determination
1202 Divisor
= (UINT32
) DivU64x32Remainder (
1203 SERIAL_PORT_INPUT_CLOCK
,
1204 ((UINT32
) BaudRate
* 16),
1207 if (Remained
!= 0) {
1211 if ((Divisor
== 0) || ((Divisor
& 0xffff0000) != 0)) {
1212 return EFI_INVALID_PARAMETER
;
1215 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1218 // Compute the actual baud rate that the serial port will be programmed for.
1220 BaudRate
= SERIAL_PORT_INPUT_CLOCK
/ Divisor
/ 16;
1223 // Put serial port on Divisor Latch Mode
1225 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1227 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1230 // Write the divisor to the serial port
1232 WRITE_DLL (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) (Divisor
& 0xff));
1233 WRITE_DLM (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) ((Divisor
>> 8) & 0xff));
1236 // Put serial port back in normal mode and set remaining attributes.
1243 Lcr
.Bits
.EvenPar
= 0;
1244 Lcr
.Bits
.SticPar
= 0;
1249 Lcr
.Bits
.EvenPar
= 1;
1250 Lcr
.Bits
.SticPar
= 0;
1255 Lcr
.Bits
.EvenPar
= 0;
1256 Lcr
.Bits
.SticPar
= 0;
1261 Lcr
.Bits
.EvenPar
= 1;
1262 Lcr
.Bits
.SticPar
= 1;
1267 Lcr
.Bits
.EvenPar
= 0;
1268 Lcr
.Bits
.SticPar
= 1;
1280 case OneFiveStopBits
:
1291 Lcr
.Bits
.SerialDB
= (UINT8
) ((DataBits
- 5) & 0x03);
1292 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1295 // Set the Serial I/O mode
1297 This
->Mode
->BaudRate
= BaudRate
;
1298 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
1299 This
->Mode
->Timeout
= Timeout
;
1300 This
->Mode
->Parity
= Parity
;
1301 This
->Mode
->DataBits
= DataBits
;
1302 This
->Mode
->StopBits
= StopBits
;
1305 // See if Device Path Node has actually changed
1307 if (SerialDevice
->UartDevicePath
.BaudRate
== BaudRate
&&
1308 SerialDevice
->UartDevicePath
.DataBits
== DataBits
&&
1309 SerialDevice
->UartDevicePath
.Parity
== Parity
&&
1310 SerialDevice
->UartDevicePath
.StopBits
== StopBits
1312 gBS
->RestoreTPL (Tpl
);
1316 // Update the device path
1318 SerialDevice
->UartDevicePath
.BaudRate
= BaudRate
;
1319 SerialDevice
->UartDevicePath
.DataBits
= DataBits
;
1320 SerialDevice
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1321 SerialDevice
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1323 NewDevicePath
= AppendDevicePathNode (
1324 SerialDevice
->ParentDevicePath
,
1325 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
1327 if (NewDevicePath
== NULL
) {
1328 gBS
->RestoreTPL (Tpl
);
1329 return EFI_DEVICE_ERROR
;
1332 if (SerialDevice
->Handle
!= NULL
) {
1333 Status
= gBS
->ReinstallProtocolInterface (
1334 SerialDevice
->Handle
,
1335 &gEfiDevicePathProtocolGuid
,
1336 SerialDevice
->DevicePath
,
1339 if (EFI_ERROR (Status
)) {
1340 gBS
->RestoreTPL (Tpl
);
1345 if (SerialDevice
->DevicePath
!= NULL
) {
1346 gBS
->FreePool (SerialDevice
->DevicePath
);
1349 SerialDevice
->DevicePath
= NewDevicePath
;
1351 gBS
->RestoreTPL (Tpl
);
1359 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1360 @param Control Control bits that can be settable
1362 @retval EFI_SUCCESS New Control bits were set successfully
1363 @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
1368 IsaSerialSetControl (
1369 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1373 SERIAL_DEV
*SerialDevice
;
1374 SERIAL_PORT_MCR Mcr
;
1378 // The control bits that can be set are :
1379 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
1380 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
1381 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
1382 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
1384 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1387 // first determine the parameter is invalid
1389 if ((Control
& 0xffff8ffc) != 0) {
1390 return EFI_UNSUPPORTED
;
1393 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1395 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1399 SerialDevice
->SoftwareLoopbackEnable
= FALSE
;
1400 SerialDevice
->HardwareFlowControl
= FALSE
;
1402 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
1406 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
1410 if ((Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1414 if ((Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1415 SerialDevice
->HardwareFlowControl
= TRUE
;
1418 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1420 if ((Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1421 SerialDevice
->SoftwareLoopbackEnable
= TRUE
;
1424 gBS
->RestoreTPL (Tpl
);
1432 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1433 @param Control Control signals of the serial device
1435 @retval EFI_SUCCESS Get Control signals successfully
1440 IsaSerialGetControl (
1441 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1445 SERIAL_DEV
*SerialDevice
;
1446 SERIAL_PORT_MSR Msr
;
1447 SERIAL_PORT_MCR Mcr
;
1450 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1452 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1457 // Read the Modem Status Register
1459 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1461 if (Msr
.Bits
.Cts
== 1) {
1462 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
1465 if (Msr
.Bits
.Dsr
== 1) {
1466 *Control
|= EFI_SERIAL_DATA_SET_READY
;
1469 if (Msr
.Bits
.Ri
== 1) {
1470 *Control
|= EFI_SERIAL_RING_INDICATE
;
1473 if (Msr
.Bits
.Dcd
== 1) {
1474 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
1477 // Read the Modem Control Register
1479 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1481 if (Mcr
.Bits
.DtrC
== 1) {
1482 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1485 if (Mcr
.Bits
.Rts
== 1) {
1486 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1489 if (Mcr
.Bits
.Lme
== 1) {
1490 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1493 if (SerialDevice
->HardwareFlowControl
) {
1494 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1497 // See if the Transmit FIFO is empty
1499 IsaSerialReceiveTransmit (SerialDevice
);
1501 if (IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1502 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
1505 // See if the Receive FIFO is empty.
1507 IsaSerialReceiveTransmit (SerialDevice
);
1509 if (IsaSerialFifoEmpty (&SerialDevice
->Receive
)) {
1510 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1513 if (SerialDevice
->SoftwareLoopbackEnable
) {
1514 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1517 gBS
->RestoreTPL (Tpl
);
1523 Write the specified number of bytes to serial device.
1525 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1526 @param BufferSize On input the size of Buffer, on output the amount of
1527 data actually written
1528 @param Buffer The buffer of data to write
1530 @retval EFI_SUCCESS The data were written successfully
1531 @retval EFI_DEVICE_ERROR The device reported an error
1532 @retval EFI_TIMEOUT The write operation was stopped due to timeout
1538 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1539 IN OUT UINTN
*BufferSize
,
1543 SERIAL_DEV
*SerialDevice
;
1550 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1554 if (*BufferSize
== 0) {
1558 if (Buffer
== NULL
) {
1559 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1561 EFI_P_EC_OUTPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1562 SerialDevice
->DevicePath
1565 return EFI_DEVICE_ERROR
;
1568 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1570 CharBuffer
= (UINT8
*) Buffer
;
1572 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1573 IsaSerialFifoAdd (&SerialDevice
->Transmit
, CharBuffer
[Index
]);
1575 while (IsaSerialReceiveTransmit (SerialDevice
) != EFI_SUCCESS
|| !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1577 // Unsuccessful write so check if timeout has expired, if not,
1578 // stall for a bit, increment time elapsed, and try again
1580 if (Elapsed
>= This
->Mode
->Timeout
) {
1581 *BufferSize
= ActualWrite
;
1582 gBS
->RestoreTPL (Tpl
);
1586 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1588 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1593 // Successful write so reset timeout
1598 gBS
->RestoreTPL (Tpl
);
1604 Read the specified number of bytes from serial device.
1606 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1607 @param BufferSize On input the size of Buffer, on output the amount of
1608 data returned in buffer
1609 @param Buffer The buffer to return the data into
1611 @retval EFI_SUCCESS The data were read successfully
1612 @retval EFI_DEVICE_ERROR The device reported an error
1613 @retval EFI_TIMEOUT The read operation was stopped due to timeout
1619 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1620 IN OUT UINTN
*BufferSize
,
1624 SERIAL_DEV
*SerialDevice
;
1631 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1634 if (*BufferSize
== 0) {
1638 if (Buffer
== NULL
) {
1639 return EFI_DEVICE_ERROR
;
1642 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1644 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1646 if (EFI_ERROR (Status
)) {
1649 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1651 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1652 SerialDevice
->DevicePath
1655 gBS
->RestoreTPL (Tpl
);
1657 return EFI_DEVICE_ERROR
;
1660 CharBuffer
= (UINT8
*) Buffer
;
1661 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1662 while (IsaSerialFifoRemove (&SerialDevice
->Receive
, &(CharBuffer
[Index
])) != EFI_SUCCESS
) {
1664 // Unsuccessful read so check if timeout has expired, if not,
1665 // stall for a bit, increment time elapsed, and try again
1666 // Need this time out to get conspliter to work.
1668 if (Elapsed
>= This
->Mode
->Timeout
) {
1669 *BufferSize
= Index
;
1670 gBS
->RestoreTPL (Tpl
);
1674 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1675 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1677 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1678 if (Status
== EFI_DEVICE_ERROR
) {
1679 *BufferSize
= Index
;
1680 gBS
->RestoreTPL (Tpl
);
1681 return EFI_DEVICE_ERROR
;
1685 // Successful read so reset timeout
1690 IsaSerialReceiveTransmit (SerialDevice
);
1692 gBS
->RestoreTPL (Tpl
);
1698 Use scratchpad register to test if this serial port is present.
1700 @param SerialDevice Pointer to serial device structure
1702 @return if this serial port is present
1705 IsaSerialPortPresent (
1706 IN SERIAL_DEV
*SerialDevice
1718 Temp
= READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1719 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0xAA);
1721 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0xAA) {
1725 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0x55);
1727 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0x55) {
1733 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Temp
);
1738 Use IsaIo protocol to read serial port.
1740 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1741 @param BaseAddress Serial port register group base address
1742 @param Offset Offset in register group
1744 @return Data read from serial port
1749 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1750 IN UINT16 BaseAddress
,
1757 // Use IsaIo to access IO
1762 BaseAddress
+ Offset
,
1770 Use IsaIo protocol to write serial port.
1772 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1773 @param BaseAddress Serial port register group base address
1774 @param Offset Offset in register group
1775 @param Data data which is to be written to some serial port register
1779 IsaSerialWritePort (
1780 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1781 IN UINT16 BaseAddress
,
1787 // Use IsaIo to access IO
1792 BaseAddress
+ Offset
,