Enhanced module to handle half handshake flow control.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8816 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
gikidy 2009-07-08 09:29:08 +00:00
parent 5b3ea840c4
commit fa70a2c4cc
5 changed files with 49 additions and 36 deletions

View File

@ -65,3 +65,4 @@
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8 gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1 gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1 gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE

View File

@ -83,7 +83,8 @@ SERIAL_DEV gSerialDevTempate = {
FALSE, FALSE,
FALSE, FALSE,
Uart16550A, Uart16550A,
NULL NULL,
FixedPcdGetBool (PcdIsaBusSerialUseHalfHandshake) //UseHalfHandshake
}; };
/** /**
@ -801,6 +802,18 @@ IsaSerialReceiveTransmit (
} while (!IsaSerialFifoEmpty (&SerialDevice->Transmit)); } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit));
} else { } else {
ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive); ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
//
// For full handshake flow control, tell the peer to send data
// if receive buffer is available.
//
if (SerialDevice->HardwareFlowControl &&
!SerialDevice->UseHalfHandshake &&
!ReceiveFifoFull
) {
Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
Mcr.Bits.Rts = 1;
WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
}
do { do {
Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
@ -821,23 +834,21 @@ IsaSerialReceiveTransmit (
continue; continue;
} }
} }
//
// Make sure the receive data will not be missed, Assert DTR
//
if (SerialDevice->HardwareFlowControl) {
Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
Mcr.Bits.DtrC &= 0;
WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
}
Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress); Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
IsaSerialFifoAdd (&SerialDevice->Receive, Data);
// //
// Deassert DTR // For full handshake flow control, if receive buffer full
// tell the peer to stop sending data.
// //
if (SerialDevice->HardwareFlowControl) { if (SerialDevice->HardwareFlowControl &&
Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); !SerialDevice->UseHalfHandshake &&
Mcr.Bits.DtrC |= 1; IsaSerialFifoFull (&SerialDevice->Receive)
) {
Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
Mcr.Bits.Rts = 0;
WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
} }
@ -861,17 +872,19 @@ IsaSerialReceiveTransmit (
// //
if (SerialDevice->HardwareFlowControl) { if (SerialDevice->HardwareFlowControl) {
// //
// Send RTS // For half handshake flow control assert RTS before sending.
// //
Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress); if (SerialDevice->UseHalfHandshake) {
Mcr.Bits.Rts |= 1; Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data); Mcr.Bits.Rts= 0;
WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
}
// //
// Wait for CTS // Wait for CTS
// //
TimeOut = 0; TimeOut = 0;
Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
while (Msr.Bits.Cts == 0) { while (Msr.Bits.Dcd == 1 && (!Msr.Bits.Cts ^ SerialDevice->UseHalfHandshake)) {
gBS->Stall (TIMEOUT_STALL_INTERVAL); gBS->Stall (TIMEOUT_STALL_INTERVAL);
TimeOut++; TimeOut++;
if (TimeOut > 5) { if (TimeOut > 5) {
@ -881,29 +894,23 @@ IsaSerialReceiveTransmit (
Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress); Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
} }
if (Msr.Bits.Cts == 1) { if (Msr.Bits.Dcd== 0 || (Msr.Bits.Cts ^ SerialDevice->UseHalfHandshake)) {
IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data); WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
} }
}
// //
// write the data out // For half handshake flow control, tell DCE we are done.
// //
if (!SerialDevice->HardwareFlowControl) { if (SerialDevice->UseHalfHandshake) {
Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
Mcr.Bits.Rts = 1;
WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
}
} else {
IsaSerialFifoRemove (&SerialDevice->Transmit, &Data); IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data); WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
} }
//
// Make sure the transmit data will not be missed
//
if (SerialDevice->HardwareFlowControl) {
//
// Assert RTS
//
Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
Mcr.Bits.Rts &= 0;
WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
}
} }
} while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)); } while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit));
} }

View File

@ -109,6 +109,7 @@ typedef struct {
BOOLEAN HardwareFlowControl; BOOLEAN HardwareFlowControl;
EFI_UART_TYPE Type; EFI_UART_TYPE Type;
EFI_UNICODE_STRING_TABLE *ControllerNameTable; EFI_UNICODE_STRING_TABLE *ControllerNameTable;
BOOLEAN UseHalfHandshake;
} SERIAL_DEV; } SERIAL_DEV;
#define SERIAL_DEV_FROM_THIS(a) CR (a, SERIAL_DEV, SerialIo, SERIAL_DEV_SIGNATURE) #define SERIAL_DEV_FROM_THIS(a) CR (a, SERIAL_DEV, SerialIo, SERIAL_DEV_SIGNATURE)

View File

@ -143,6 +143,9 @@
# The default value in DxePhase is 128 KBytes. # The default value in DxePhase is 128 KBytes.
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|UINT16|0x00010025 gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|UINT16|0x00010025
## This PCD specifies whether Serial device use half hand shake.
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE|BOOLEAN|0x00010043
[PcdsDynamic] [PcdsDynamic]
## PCD is used to mark if the machine has complete one boot cycle before. ## PCD is used to mark if the machine has complete one boot cycle before.
# After the complete boot, the variable BootState will be set to TRUE. # After the complete boot, the variable BootState will be set to TRUE.

View File

@ -153,7 +153,8 @@
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1 gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1 gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|0 gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|0
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE
[PcdsDynamicDefault.PEIM.DEFAULT] [PcdsDynamicDefault.PEIM.DEFAULT]
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1 gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1