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
,
87 FixedPcdGetBool (PcdIsaBusSerialUseHalfHandshake
) //UseHalfHandshake
91 The user Entry Point for module IsaSerial. The user code starts with this function.
93 @param[in] ImageHandle The firmware allocated handle for the EFI image.
94 @param[in] SystemTable A pointer to the EFI System Table.
96 @retval EFI_SUCCESS The entry point is executed successfully.
97 @retval other Some error occurs when executing this entry point.
102 InitializeIsaSerial (
103 IN EFI_HANDLE ImageHandle
,
104 IN EFI_SYSTEM_TABLE
*SystemTable
110 // Install driver model protocol(s).
112 Status
= EfiLibInstallDriverBindingComponentName2 (
115 &gSerialControllerDriver
,
117 &gIsaSerialComponentName
,
118 &gIsaSerialComponentName2
120 ASSERT_EFI_ERROR (Status
);
127 Check to see if this driver supports the given controller
129 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
130 @param Controller The handle of the controller to test.
131 @param RemainingDevicePath A pointer to the remaining portion of a device path.
133 @return EFI_SUCCESS This driver can support the given controller
138 SerialControllerDriverSupported (
139 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
140 IN EFI_HANDLE Controller
,
141 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
146 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
147 EFI_ISA_IO_PROTOCOL
*IsaIo
;
148 UART_DEVICE_PATH UartNode
;
151 // Ignore the RemainingDevicePath
154 // Open the IO Abstraction(s) needed to perform the supported test
156 Status
= gBS
->OpenProtocol (
158 &gEfiDevicePathProtocolGuid
,
159 (VOID
**) &ParentDevicePath
,
160 This
->DriverBindingHandle
,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
164 if (Status
== EFI_ALREADY_STARTED
) {
168 if (EFI_ERROR (Status
)) {
174 &gEfiDevicePathProtocolGuid
,
175 This
->DriverBindingHandle
,
179 Status
= gBS
->OpenProtocol (
181 &gEfiIsaIoProtocolGuid
,
183 This
->DriverBindingHandle
,
185 EFI_OPEN_PROTOCOL_BY_DRIVER
188 if (Status
== EFI_ALREADY_STARTED
) {
192 if (EFI_ERROR (Status
)) {
196 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
197 // can be managed by this driver.
199 Status
= EFI_SUCCESS
;
200 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x501)) {
201 Status
= EFI_UNSUPPORTED
;
205 // Make sure RemainingDevicePath is valid
207 if (RemainingDevicePath
!= NULL
) {
208 Status
= EFI_UNSUPPORTED
;
211 (UART_DEVICE_PATH
*) RemainingDevicePath
,
212 sizeof (UART_DEVICE_PATH
)
214 if (UartNode
.Header
.Type
!= MESSAGING_DEVICE_PATH
||
215 UartNode
.Header
.SubType
!= MSG_UART_DP
||
216 sizeof (UART_DEVICE_PATH
) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &UartNode
)
221 if (UartNode
.BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
225 if (UartNode
.Parity
< NoParity
|| UartNode
.Parity
> SpaceParity
) {
229 if (UartNode
.DataBits
< 5 || UartNode
.DataBits
> 8) {
233 if (UartNode
.StopBits
< OneStopBit
|| UartNode
.StopBits
> TwoStopBits
) {
237 if ((UartNode
.DataBits
== 5) && (UartNode
.StopBits
== TwoStopBits
)) {
241 if ((UartNode
.DataBits
>= 6) && (UartNode
.DataBits
<= 8) && (UartNode
.StopBits
== OneFiveStopBits
)) {
245 Status
= EFI_SUCCESS
;
250 // Close the I/O Abstraction(s) used to perform the supported test
254 &gEfiIsaIoProtocolGuid
,
255 This
->DriverBindingHandle
,
263 Start to management the controller passed in
265 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
266 @param Controller The handle of the controller to test.
267 @param RemainingDevicePath A pointer to the remaining portion of a device path.
269 @return EFI_SUCCESS Driver is started successfully
274 SerialControllerDriverStart (
275 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
276 IN EFI_HANDLE Controller
,
277 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
282 EFI_ISA_IO_PROTOCOL
*IsaIo
;
283 SERIAL_DEV
*SerialDevice
;
285 UART_DEVICE_PATH Node
;
286 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
287 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
289 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
293 // Get the Parent Device Path
295 Status
= gBS
->OpenProtocol (
297 &gEfiDevicePathProtocolGuid
,
298 (VOID
**) &ParentDevicePath
,
299 This
->DriverBindingHandle
,
301 EFI_OPEN_PROTOCOL_BY_DRIVER
303 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
307 // Report status code enable the serial
309 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
311 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
316 // Grab the IO abstraction we need to get any work done
318 Status
= gBS
->OpenProtocol (
320 &gEfiIsaIoProtocolGuid
,
322 This
->DriverBindingHandle
,
324 EFI_OPEN_PROTOCOL_BY_DRIVER
326 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
330 if (Status
== EFI_ALREADY_STARTED
) {
332 if (RemainingDevicePath
== NULL
) {
336 // Make sure a child handle does not already exist. This driver can only
337 // produce one child per serial port.
339 Status
= gBS
->OpenProtocolInformation (
341 &gEfiIsaIoProtocolGuid
,
345 if (EFI_ERROR (Status
)) {
349 Status
= EFI_ALREADY_STARTED
;
350 for (Index
= 0; Index
< EntryCount
; Index
++) {
351 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
352 Status
= gBS
->OpenProtocol (
353 OpenInfoBuffer
[Index
].ControllerHandle
,
354 &gEfiSerialIoProtocolGuid
,
356 This
->DriverBindingHandle
,
358 EFI_OPEN_PROTOCOL_GET_PROTOCOL
360 if (!EFI_ERROR (Status
)) {
361 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
362 Status
= SerialIo
->SetAttributes (
365 SerialIo
->Mode
->ReceiveFifoDepth
,
366 SerialIo
->Mode
->Timeout
,
367 (EFI_PARITY_TYPE
) Node
.Parity
,
369 (EFI_STOP_BITS_TYPE
) Node
.StopBits
376 gBS
->FreePool (OpenInfoBuffer
);
380 // Initialize the serial device instance
382 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTempate
);
383 if (SerialDevice
== NULL
) {
384 Status
= EFI_OUT_OF_RESOURCES
;
388 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
389 SerialDevice
->IsaIo
= IsaIo
;
390 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
392 AddName (SerialDevice
, IsaIo
);
394 for (Index
= 0; SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
395 if (SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
396 SerialDevice
->BaseAddress
= (UINT16
) SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
400 // Report status code the serial present
402 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
404 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
408 if (!IsaSerialPortPresent (SerialDevice
)) {
409 Status
= EFI_DEVICE_ERROR
;
410 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
412 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
418 if (RemainingDevicePath
!= NULL
) {
420 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
421 // already checked to make sure the RemainingDevicePath contains settings
422 // that we can support.
424 CopyMem (&SerialDevice
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
427 // Use the values from the gSerialDevTempate as no remaining device path was
432 // Build the device path by appending the UART node to the ParentDevicePath
433 // from the WinNtIo handle. The Uart setings are zero here, since
434 // SetAttribute() will update them to match the current setings.
436 SerialDevice
->DevicePath
= AppendDevicePathNode (
438 (EFI_DEVICE_PATH_PROTOCOL
*)&SerialDevice
->UartDevicePath
440 if (SerialDevice
->DevicePath
== NULL
) {
441 Status
= EFI_DEVICE_ERROR
;
446 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
448 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
449 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
450 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
451 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
454 // Issue a reset to initialize the COM port
456 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
457 if (EFI_ERROR (Status
)) {
458 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
460 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
466 // Install protocol interfaces for the serial device.
468 Status
= gBS
->InstallMultipleProtocolInterfaces (
469 &SerialDevice
->Handle
,
470 &gEfiDevicePathProtocolGuid
,
471 SerialDevice
->DevicePath
,
472 &gEfiSerialIoProtocolGuid
,
473 &SerialDevice
->SerialIo
,
476 if (EFI_ERROR (Status
)) {
480 // Open For Child Device
482 Status
= gBS
->OpenProtocol (
484 &gEfiIsaIoProtocolGuid
,
486 This
->DriverBindingHandle
,
487 SerialDevice
->Handle
,
488 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
492 if (EFI_ERROR (Status
)) {
495 &gEfiDevicePathProtocolGuid
,
496 This
->DriverBindingHandle
,
501 &gEfiIsaIoProtocolGuid
,
502 This
->DriverBindingHandle
,
505 if (SerialDevice
!= NULL
) {
506 if (SerialDevice
->DevicePath
!= NULL
) {
507 gBS
->FreePool (SerialDevice
->DevicePath
);
510 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
511 gBS
->FreePool (SerialDevice
);
519 Disconnect this driver with the controller, uninstall related protocol instance
521 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
522 @param Controller The handle of the controller to test.
523 @param NumberOfChildren Number of child device.
524 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
526 @retval EFI_SUCCESS Operation successfully
527 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
532 SerialControllerDriverStop (
533 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
534 IN EFI_HANDLE Controller
,
535 IN UINTN NumberOfChildren
,
536 IN EFI_HANDLE
*ChildHandleBuffer
542 BOOLEAN AllChildrenStopped
;
543 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
544 SERIAL_DEV
*SerialDevice
;
545 EFI_ISA_IO_PROTOCOL
*IsaIo
;
546 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
548 Status
= gBS
->HandleProtocol (
550 &gEfiDevicePathProtocolGuid
,
551 (VOID
**) &DevicePath
555 // Report the status code disable the serial
557 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
559 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
564 // Complete all outstanding transactions to Controller.
565 // Don't allow any new transaction to Controller to be started.
567 if (NumberOfChildren
== 0) {
569 // Close the bus driver
571 Status
= gBS
->CloseProtocol (
573 &gEfiIsaIoProtocolGuid
,
574 This
->DriverBindingHandle
,
578 Status
= gBS
->CloseProtocol (
580 &gEfiDevicePathProtocolGuid
,
581 This
->DriverBindingHandle
,
587 AllChildrenStopped
= TRUE
;
589 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
591 Status
= gBS
->OpenProtocol (
592 ChildHandleBuffer
[Index
],
593 &gEfiSerialIoProtocolGuid
,
595 This
->DriverBindingHandle
,
597 EFI_OPEN_PROTOCOL_GET_PROTOCOL
599 if (!EFI_ERROR (Status
)) {
601 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
603 Status
= gBS
->CloseProtocol (
605 &gEfiIsaIoProtocolGuid
,
606 This
->DriverBindingHandle
,
607 ChildHandleBuffer
[Index
]
610 Status
= gBS
->UninstallMultipleProtocolInterfaces (
611 ChildHandleBuffer
[Index
],
612 &gEfiDevicePathProtocolGuid
,
613 SerialDevice
->DevicePath
,
614 &gEfiSerialIoProtocolGuid
,
615 &SerialDevice
->SerialIo
,
618 if (EFI_ERROR (Status
)) {
621 &gEfiIsaIoProtocolGuid
,
623 This
->DriverBindingHandle
,
624 ChildHandleBuffer
[Index
],
625 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
628 if (SerialDevice
->DevicePath
!= NULL
) {
629 gBS
->FreePool (SerialDevice
->DevicePath
);
632 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
633 gBS
->FreePool (SerialDevice
);
637 if (EFI_ERROR (Status
)) {
638 AllChildrenStopped
= FALSE
;
642 if (!AllChildrenStopped
) {
643 return EFI_DEVICE_ERROR
;
650 Detect whether specific FIFO is full or not.
652 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
654 @return whether specific FIFO is full or not
659 IN SERIAL_DEV_FIFO
*Fifo
663 if (Fifo
->Surplus
== 0) {
671 Detect whether specific FIFO is empty or not.
673 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
675 @return whether specific FIFO is empty or not
680 IN SERIAL_DEV_FIFO
*Fifo
684 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
692 Add data to specific FIFO.
694 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
695 @param Data the data added to FIFO
697 @retval EFI_SUCCESS Add data to specific FIFO successfully
698 @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
703 IN SERIAL_DEV_FIFO
*Fifo
,
709 // if FIFO full can not add data
711 if (IsaSerialFifoFull (Fifo
)) {
712 return EFI_OUT_OF_RESOURCES
;
715 // FIFO is not full can add data
717 Fifo
->Data
[Fifo
->Last
] = Data
;
720 if (Fifo
->Last
== SERIAL_MAX_BUFFER_SIZE
) {
728 Remove data from specific FIFO.
730 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
731 @param Data the data removed from FIFO
733 @retval EFI_SUCCESS Remove data from specific FIFO successfully
734 @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
738 IsaSerialFifoRemove (
739 IN SERIAL_DEV_FIFO
*Fifo
,
745 // if FIFO is empty, no data can remove
747 if (IsaSerialFifoEmpty (Fifo
)) {
748 return EFI_OUT_OF_RESOURCES
;
751 // FIFO is not empty, can remove data
753 *Data
= Fifo
->Data
[Fifo
->First
];
756 if (Fifo
->First
== SERIAL_MAX_BUFFER_SIZE
) {
764 Reads and writes all avaliable data.
766 @param SerialDevice The device to flush
768 @retval EFI_SUCCESS Data was read/written successfully.
769 @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
770 this happens, pending writes are not done.
774 IsaSerialReceiveTransmit (
775 IN SERIAL_DEV
*SerialDevice
781 BOOLEAN ReceiveFifoFull
;
789 // Begin the read or write
791 if (SerialDevice
->SoftwareLoopbackEnable
) {
793 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
794 if (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
795 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
796 if (ReceiveFifoFull
) {
797 return EFI_OUT_OF_RESOURCES
;
800 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
802 } while (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
804 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
806 // For full handshake flow control, tell the peer to send data
807 // if receive buffer is available.
809 if (SerialDevice
->HardwareFlowControl
&&
810 !SerialDevice
->UseHalfHandshake
&&
813 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
815 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
818 Lsr
.Data
= READ_LSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
821 // Flush incomming data to prevent a an overrun during a long write
823 if ((Lsr
.Bits
.Dr
== 1) && !ReceiveFifoFull
) {
824 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
825 if (!ReceiveFifoFull
) {
826 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Oe
== 1 || Lsr
.Bits
.Pe
== 1 || Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
827 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
829 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
830 SerialDevice
->DevicePath
832 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Pe
== 1|| Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
833 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
838 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
840 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
843 // For full handshake flow control, if receive buffer full
844 // tell the peer to stop sending data.
846 if (SerialDevice
->HardwareFlowControl
&&
847 !SerialDevice
->UseHalfHandshake
&&
848 IsaSerialFifoFull (&SerialDevice
->Receive
)
850 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
852 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
855 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
859 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
861 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER
| EFI_PERIPHERAL_SERIAL_PORT
,
862 SerialDevice
->DevicePath
869 if (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
871 // Make sure the transmit data will not be missed
873 if (SerialDevice
->HardwareFlowControl
) {
875 // For half handshake flow control assert RTS before sending.
877 if (SerialDevice
->UseHalfHandshake
) {
878 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
880 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
886 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
887 while (Msr
.Bits
.Dcd
== 1 && (!Msr
.Bits
.Cts
^ SerialDevice
->UseHalfHandshake
)) {
888 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
894 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
897 if (Msr
.Bits
.Dcd
== 0 || (Msr
.Bits
.Cts
^ SerialDevice
->UseHalfHandshake
)) {
898 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
899 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
903 // For half handshake flow control, tell DCE we are done.
905 if (SerialDevice
->UseHalfHandshake
) {
906 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
908 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
911 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
912 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
915 } while (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
922 // Interface Functions
927 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
929 @retval EFI_SUCCESS Reset successfully
930 @retval EFI_DEVICE_ERROR Failed to reset
936 IN EFI_SERIAL_IO_PROTOCOL
*This
940 SERIAL_DEV
*SerialDevice
;
947 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
950 // Report the status code reset the serial
952 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
954 EFI_P_PC_RESET
| EFI_PERIPHERAL_SERIAL_PORT
,
955 SerialDevice
->DevicePath
958 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
961 // Make sure DLAB is 0.
963 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
965 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
968 // Turn off all interrupts
970 Ier
.Data
= READ_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
975 WRITE_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Ier
.Data
);
980 Fcr
.Bits
.TrFIFOE
= 0;
981 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
984 // Turn off loopback and disable device interrupt.
986 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
990 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
993 // Clear the scratch pad register
995 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0);
998 // Go set the current attributes
1000 Status
= This
->SetAttributes (
1002 This
->Mode
->BaudRate
,
1003 This
->Mode
->ReceiveFifoDepth
,
1004 This
->Mode
->Timeout
,
1005 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
1006 (UINT8
) This
->Mode
->DataBits
,
1007 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
1010 if (EFI_ERROR (Status
)) {
1011 gBS
->RestoreTPL (Tpl
);
1012 return EFI_DEVICE_ERROR
;
1015 // Go set the current control bits
1017 Status
= This
->SetControl (
1019 This
->Mode
->ControlMask
1022 if (EFI_ERROR (Status
)) {
1023 gBS
->RestoreTPL (Tpl
);
1024 return EFI_DEVICE_ERROR
;
1027 // for 16550A enable FIFO, 16550 disable FIFO
1029 Fcr
.Bits
.TrFIFOE
= 1;
1030 Fcr
.Bits
.ResetRF
= 1;
1031 Fcr
.Bits
.ResetTF
= 1;
1032 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1035 // Reset the software FIFO
1037 SerialDevice
->Receive
.First
= 0;
1038 SerialDevice
->Receive
.Last
= 0;
1039 SerialDevice
->Receive
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1040 SerialDevice
->Transmit
.First
= 0;
1041 SerialDevice
->Transmit
.Last
= 0;
1042 SerialDevice
->Transmit
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1044 gBS
->RestoreTPL (Tpl
);
1047 // Device reset is complete
1053 Set new attributes to a serial device.
1055 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1056 @param BaudRate The baudrate of the serial device
1057 @param ReceiveFifoDepth The depth of receive FIFO buffer
1058 @param Timeout The request timeout for a single char
1059 @param Parity The type of parity used in serial device
1060 @param DataBits Number of databits used in serial device
1061 @param StopBits Number of stopbits used in serial device
1063 @retval EFI_SUCCESS The new attributes were set
1064 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
1065 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
1066 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
1071 IsaSerialSetAttributes (
1072 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1074 IN UINT32 ReceiveFifoDepth
,
1076 IN EFI_PARITY_TYPE Parity
,
1078 IN EFI_STOP_BITS_TYPE StopBits
1082 SERIAL_DEV
*SerialDevice
;
1085 SERIAL_PORT_LCR Lcr
;
1086 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
1089 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1092 // Check for default settings and fill in actual values.
1094 if (BaudRate
== 0) {
1095 BaudRate
= FixedPcdGet64 (PcdUartDefaultBaudRate
);
1098 if (ReceiveFifoDepth
== 0) {
1099 ReceiveFifoDepth
= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
;
1103 Timeout
= SERIAL_PORT_DEFAULT_TIMEOUT
;
1106 if (Parity
== DefaultParity
) {
1107 Parity
= (EFI_PARITY_TYPE
)FixedPcdGet8 (PcdUartDefaultParity
);
1110 if (DataBits
== 0) {
1111 DataBits
= FixedPcdGet8 (PcdUartDefaultDataBits
);
1114 if (StopBits
== DefaultStopBits
) {
1115 StopBits
= (EFI_STOP_BITS_TYPE
) FixedPcdGet8 (PcdUartDefaultStopBits
);
1118 // 5 and 6 data bits can not be verified on a 16550A UART
1119 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
1121 if ((DataBits
== 5) || (DataBits
== 6)) {
1122 return EFI_INVALID_PARAMETER
;
1125 // Make sure all parameters are valid
1127 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
1128 return EFI_INVALID_PARAMETER
;
1131 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
1132 // 38400,57600,115200
1134 if (BaudRate
< 75) {
1136 } else if (BaudRate
< 110) {
1138 } else if (BaudRate
< 134) {
1140 } else if (BaudRate
< 150) {
1142 } else if (BaudRate
< 300) {
1144 } else if (BaudRate
< 600) {
1146 } else if (BaudRate
< 1200) {
1148 } else if (BaudRate
< 1800) {
1150 } else if (BaudRate
< 2000) {
1152 } else if (BaudRate
< 2400) {
1154 } else if (BaudRate
< 3600) {
1156 } else if (BaudRate
< 4800) {
1158 } else if (BaudRate
< 7200) {
1160 } else if (BaudRate
< 9600) {
1162 } else if (BaudRate
< 19200) {
1164 } else if (BaudRate
< 38400) {
1166 } else if (BaudRate
< 57600) {
1168 } else if (BaudRate
< 115200) {
1170 } else if (BaudRate
<= SERIAL_PORT_MAX_BAUD_RATE
) {
1174 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
1175 return EFI_INVALID_PARAMETER
;
1178 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
1179 return EFI_INVALID_PARAMETER
;
1182 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
1183 return EFI_INVALID_PARAMETER
;
1186 if ((DataBits
< 5) || (DataBits
> 8)) {
1187 return EFI_INVALID_PARAMETER
;
1190 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
1191 return EFI_INVALID_PARAMETER
;
1194 // for DataBits = 5, StopBits can not set TwoStopBits
1196 // if ((DataBits == 5) && (StopBits == TwoStopBits)) {
1197 // return EFI_INVALID_PARAMETER;
1200 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
1202 if ((DataBits
>= 6) && (DataBits
<= 8) && (StopBits
== OneFiveStopBits
)) {
1203 return EFI_INVALID_PARAMETER
;
1207 // Compute divisor use to program the baud rate using a round determination
1209 Divisor
= (UINT32
) DivU64x32Remainder (
1210 SERIAL_PORT_INPUT_CLOCK
,
1211 ((UINT32
) BaudRate
* 16),
1214 if (Remained
!= 0) {
1218 if ((Divisor
== 0) || ((Divisor
& 0xffff0000) != 0)) {
1219 return EFI_INVALID_PARAMETER
;
1222 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1225 // Compute the actual baud rate that the serial port will be programmed for.
1227 BaudRate
= SERIAL_PORT_INPUT_CLOCK
/ Divisor
/ 16;
1230 // Put serial port on Divisor Latch Mode
1232 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1234 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1237 // Write the divisor to the serial port
1239 WRITE_DLL (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) (Divisor
& 0xff));
1240 WRITE_DLM (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) ((Divisor
>> 8) & 0xff));
1243 // Put serial port back in normal mode and set remaining attributes.
1250 Lcr
.Bits
.EvenPar
= 0;
1251 Lcr
.Bits
.SticPar
= 0;
1256 Lcr
.Bits
.EvenPar
= 1;
1257 Lcr
.Bits
.SticPar
= 0;
1262 Lcr
.Bits
.EvenPar
= 0;
1263 Lcr
.Bits
.SticPar
= 0;
1268 Lcr
.Bits
.EvenPar
= 1;
1269 Lcr
.Bits
.SticPar
= 1;
1274 Lcr
.Bits
.EvenPar
= 0;
1275 Lcr
.Bits
.SticPar
= 1;
1287 case OneFiveStopBits
:
1298 Lcr
.Bits
.SerialDB
= (UINT8
) ((DataBits
- 5) & 0x03);
1299 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1302 // Set the Serial I/O mode
1304 This
->Mode
->BaudRate
= BaudRate
;
1305 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
1306 This
->Mode
->Timeout
= Timeout
;
1307 This
->Mode
->Parity
= Parity
;
1308 This
->Mode
->DataBits
= DataBits
;
1309 This
->Mode
->StopBits
= StopBits
;
1312 // See if Device Path Node has actually changed
1314 if (SerialDevice
->UartDevicePath
.BaudRate
== BaudRate
&&
1315 SerialDevice
->UartDevicePath
.DataBits
== DataBits
&&
1316 SerialDevice
->UartDevicePath
.Parity
== Parity
&&
1317 SerialDevice
->UartDevicePath
.StopBits
== StopBits
1319 gBS
->RestoreTPL (Tpl
);
1323 // Update the device path
1325 SerialDevice
->UartDevicePath
.BaudRate
= BaudRate
;
1326 SerialDevice
->UartDevicePath
.DataBits
= DataBits
;
1327 SerialDevice
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1328 SerialDevice
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1330 NewDevicePath
= AppendDevicePathNode (
1331 SerialDevice
->ParentDevicePath
,
1332 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
1334 if (NewDevicePath
== NULL
) {
1335 gBS
->RestoreTPL (Tpl
);
1336 return EFI_DEVICE_ERROR
;
1339 if (SerialDevice
->Handle
!= NULL
) {
1340 Status
= gBS
->ReinstallProtocolInterface (
1341 SerialDevice
->Handle
,
1342 &gEfiDevicePathProtocolGuid
,
1343 SerialDevice
->DevicePath
,
1346 if (EFI_ERROR (Status
)) {
1347 gBS
->RestoreTPL (Tpl
);
1352 if (SerialDevice
->DevicePath
!= NULL
) {
1353 gBS
->FreePool (SerialDevice
->DevicePath
);
1356 SerialDevice
->DevicePath
= NewDevicePath
;
1358 gBS
->RestoreTPL (Tpl
);
1366 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1367 @param Control Control bits that can be settable
1369 @retval EFI_SUCCESS New Control bits were set successfully
1370 @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
1375 IsaSerialSetControl (
1376 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1380 SERIAL_DEV
*SerialDevice
;
1381 SERIAL_PORT_MCR Mcr
;
1385 // The control bits that can be set are :
1386 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
1387 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
1388 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
1389 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
1391 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1394 // first determine the parameter is invalid
1396 if ((Control
& 0xffff8ffc) != 0) {
1397 return EFI_UNSUPPORTED
;
1400 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1402 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1406 SerialDevice
->SoftwareLoopbackEnable
= FALSE
;
1407 SerialDevice
->HardwareFlowControl
= FALSE
;
1409 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
1413 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
1417 if ((Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1421 if ((Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1422 SerialDevice
->HardwareFlowControl
= TRUE
;
1425 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1427 if ((Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1428 SerialDevice
->SoftwareLoopbackEnable
= TRUE
;
1431 gBS
->RestoreTPL (Tpl
);
1439 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1440 @param Control Control signals of the serial device
1442 @retval EFI_SUCCESS Get Control signals successfully
1447 IsaSerialGetControl (
1448 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1452 SERIAL_DEV
*SerialDevice
;
1453 SERIAL_PORT_MSR Msr
;
1454 SERIAL_PORT_MCR Mcr
;
1457 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1459 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1464 // Read the Modem Status Register
1466 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1468 if (Msr
.Bits
.Cts
== 1) {
1469 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
1472 if (Msr
.Bits
.Dsr
== 1) {
1473 *Control
|= EFI_SERIAL_DATA_SET_READY
;
1476 if (Msr
.Bits
.Ri
== 1) {
1477 *Control
|= EFI_SERIAL_RING_INDICATE
;
1480 if (Msr
.Bits
.Dcd
== 1) {
1481 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
1484 // Read the Modem Control Register
1486 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1488 if (Mcr
.Bits
.DtrC
== 1) {
1489 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1492 if (Mcr
.Bits
.Rts
== 1) {
1493 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1496 if (Mcr
.Bits
.Lme
== 1) {
1497 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1500 if (SerialDevice
->HardwareFlowControl
) {
1501 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1504 // See if the Transmit FIFO is empty
1506 IsaSerialReceiveTransmit (SerialDevice
);
1508 if (IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1509 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
1512 // See if the Receive FIFO is empty.
1514 IsaSerialReceiveTransmit (SerialDevice
);
1516 if (IsaSerialFifoEmpty (&SerialDevice
->Receive
)) {
1517 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1520 if (SerialDevice
->SoftwareLoopbackEnable
) {
1521 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1524 gBS
->RestoreTPL (Tpl
);
1530 Write the specified number of bytes to serial device.
1532 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1533 @param BufferSize On input the size of Buffer, on output the amount of
1534 data actually written
1535 @param Buffer The buffer of data to write
1537 @retval EFI_SUCCESS The data were written successfully
1538 @retval EFI_DEVICE_ERROR The device reported an error
1539 @retval EFI_TIMEOUT The write operation was stopped due to timeout
1545 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1546 IN OUT UINTN
*BufferSize
,
1550 SERIAL_DEV
*SerialDevice
;
1557 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1561 if (*BufferSize
== 0) {
1565 if (Buffer
== NULL
) {
1566 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1568 EFI_P_EC_OUTPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1569 SerialDevice
->DevicePath
1572 return EFI_DEVICE_ERROR
;
1575 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1577 CharBuffer
= (UINT8
*) Buffer
;
1579 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1580 IsaSerialFifoAdd (&SerialDevice
->Transmit
, CharBuffer
[Index
]);
1582 while (IsaSerialReceiveTransmit (SerialDevice
) != EFI_SUCCESS
|| !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1584 // Unsuccessful write so check if timeout has expired, if not,
1585 // stall for a bit, increment time elapsed, and try again
1587 if (Elapsed
>= This
->Mode
->Timeout
) {
1588 *BufferSize
= ActualWrite
;
1589 gBS
->RestoreTPL (Tpl
);
1593 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1595 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1600 // Successful write so reset timeout
1605 gBS
->RestoreTPL (Tpl
);
1611 Read the specified number of bytes from serial device.
1613 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1614 @param BufferSize On input the size of Buffer, on output the amount of
1615 data returned in buffer
1616 @param Buffer The buffer to return the data into
1618 @retval EFI_SUCCESS The data were read successfully
1619 @retval EFI_DEVICE_ERROR The device reported an error
1620 @retval EFI_TIMEOUT The read operation was stopped due to timeout
1626 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1627 IN OUT UINTN
*BufferSize
,
1631 SERIAL_DEV
*SerialDevice
;
1638 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1641 if (*BufferSize
== 0) {
1645 if (Buffer
== NULL
) {
1646 return EFI_DEVICE_ERROR
;
1649 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1651 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1653 if (EFI_ERROR (Status
)) {
1656 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1658 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1659 SerialDevice
->DevicePath
1662 gBS
->RestoreTPL (Tpl
);
1664 return EFI_DEVICE_ERROR
;
1667 CharBuffer
= (UINT8
*) Buffer
;
1668 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1669 while (IsaSerialFifoRemove (&SerialDevice
->Receive
, &(CharBuffer
[Index
])) != EFI_SUCCESS
) {
1671 // Unsuccessful read so check if timeout has expired, if not,
1672 // stall for a bit, increment time elapsed, and try again
1673 // Need this time out to get conspliter to work.
1675 if (Elapsed
>= This
->Mode
->Timeout
) {
1676 *BufferSize
= Index
;
1677 gBS
->RestoreTPL (Tpl
);
1681 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1682 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1684 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1685 if (Status
== EFI_DEVICE_ERROR
) {
1686 *BufferSize
= Index
;
1687 gBS
->RestoreTPL (Tpl
);
1688 return EFI_DEVICE_ERROR
;
1692 // Successful read so reset timeout
1697 IsaSerialReceiveTransmit (SerialDevice
);
1699 gBS
->RestoreTPL (Tpl
);
1705 Use scratchpad register to test if this serial port is present.
1707 @param SerialDevice Pointer to serial device structure
1709 @return if this serial port is present
1712 IsaSerialPortPresent (
1713 IN SERIAL_DEV
*SerialDevice
1725 Temp
= READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1726 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0xAA);
1728 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0xAA) {
1732 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0x55);
1734 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0x55) {
1740 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Temp
);
1745 Use IsaIo protocol to read serial port.
1747 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1748 @param BaseAddress Serial port register group base address
1749 @param Offset Offset in register group
1751 @return Data read from serial port
1756 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1757 IN UINT16 BaseAddress
,
1764 // Use IsaIo to access IO
1769 BaseAddress
+ Offset
,
1777 Use IsaIo protocol to write serial port.
1779 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1780 @param BaseAddress Serial port register group base address
1781 @param Offset Offset in register group
1782 @param Data data which is to be written to some serial port register
1786 IsaSerialWritePort (
1787 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1788 IN UINT16 BaseAddress
,
1794 // Use IsaIo to access IO
1799 BaseAddress
+ Offset
,