mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
8.3 KiB
373 lines
8.3 KiB
/*
|
|
* CRYSTAL.C
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
#ifndef IRMINILIB
|
|
|
|
#include "dongle.h"
|
|
|
|
|
|
/*
|
|
* The programming interface to a UART (COM serial port)
|
|
* consists of eight consecutive registers.
|
|
* These are the port offsets from the UART's base I/O address.
|
|
*/
|
|
typedef enum comPortRegOffsets {
|
|
XFER_REG_OFFSET = 0,
|
|
INT_ENABLE_REG_OFFSET = 1,
|
|
INT_ID_AND_FIFO_CNTRL_REG_OFFSET = 2,
|
|
LINE_CONTROL_REG_OFFSET = 3,
|
|
MODEM_CONTROL_REG_OFFSET = 4,
|
|
LINE_STAT_REG_OFFSET = 5,
|
|
MODEM_STAT_REG_OFFSET = 6,
|
|
SCRATCH_REG_OFFSET = 7
|
|
} comPortRegOffset;
|
|
|
|
|
|
/*
|
|
* Bits in the UART line-status register.
|
|
*/
|
|
#define LINESTAT_DATAREADY (UCHAR)(1 << 0)
|
|
#define LINESTAT_OVERRUNERROR (UCHAR)(1 << 1)
|
|
#define LINESTAT_PARITYERROR (UCHAR)(1 << 2)
|
|
#define LINESTAT_FRAMINGERROR (UCHAR)(1 << 3)
|
|
#define LINESTAT_BREAK (UCHAR)(1 << 4)
|
|
#define LINESTAT_XMIT_HOLDING_REG_EMPTY (UCHAR)(1 << 5)
|
|
#define LINESTAT_XMIT_SHIFT_AND_HOLDING_REG_EMPTY (UCHAR)(1 << 6)
|
|
|
|
|
|
#define CRYSTAL_IRDA_SPEEDS ( \
|
|
NDIS_IRDA_SPEED_2400 | \
|
|
NDIS_IRDA_SPEED_9600 | \
|
|
NDIS_IRDA_SPEED_19200 | \
|
|
NDIS_IRDA_SPEED_38400 | \
|
|
NDIS_IRDA_SPEED_57600 | \
|
|
NDIS_IRDA_SPEED_115200 \
|
|
)
|
|
|
|
|
|
|
|
/*
|
|
* Command sequences for configuring CRYSTAL chip.
|
|
*/
|
|
UCHAR CrystalSetPrimaryRegisterSet[] = { 0xD0 };
|
|
UCHAR CrystalSetSecondaryRegisterSet[] = { 0xD1 };
|
|
UCHAR CrystalSetSpeed2400[] = { 0x10, 0x8F, 0x95, 0x11 };
|
|
UCHAR CrystalSetSpeed9600[] = { 0x10, 0x87, 0x91, 0x11 };
|
|
UCHAR CrystalSetSpeed19200[] = { 0x10, 0x8B, 0x90, 0x11 };
|
|
UCHAR CrystalSetSpeed38400[] = { 0x10, 0x85, 0x90, 0x11 };
|
|
UCHAR CrystalSetSpeed57600[] = { 0x10, 0x83, 0x90, 0x11 };
|
|
UCHAR CrystalSetSpeed115200[] = { 0x10, 0x81, 0x90, 0x11 };
|
|
UCHAR CrystalSetIrdaMode[] = { 0x0B, 0x53, 0x47, 0x63, 0x74, 0xD1, 0x56, 0xD0 };
|
|
UCHAR CrystalSetASKMode[] = { 0x0b, 0x43, 0x62, 0x54 };
|
|
UCHAR CrystalSetLowPower[] = { 0x09, 0x00 };
|
|
|
|
|
|
|
|
|
|
/*
|
|
*************************************************************************
|
|
* CrystalWrite
|
|
*************************************************************************
|
|
*
|
|
*/
|
|
BOOLEAN CrystalWrite(UINT comBase, UCHAR *data, UINT numBytes)
|
|
{
|
|
UINT i;
|
|
UCHAR lineStatReg;
|
|
BOOLEAN result = TRUE;
|
|
|
|
/*
|
|
* Write databytes as long as we have them and the UART's FIFO hasn't filled up.
|
|
*/
|
|
while (numBytes){
|
|
|
|
/*
|
|
* Wait for ready-to-send.
|
|
*/
|
|
i = 0;
|
|
do {
|
|
IRMINI_RawReadPort(comBase+LINE_STAT_REG_OFFSET, &lineStatReg);
|
|
IRMINI_StallExecution(20000);
|
|
} while (!(lineStatReg & LINESTAT_XMIT_HOLDING_REG_EMPTY) && (++i < 4));
|
|
if (!(lineStatReg & LINESTAT_XMIT_HOLDING_REG_EMPTY)){
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Send the next byte.
|
|
*/
|
|
IRMINI_RawWritePort(comBase+XFER_REG_OFFSET, *data++);
|
|
IRMINI_StallExecution(20000);
|
|
numBytes--;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOLEAN CrystalRead(UINT comBase, UCHAR *data, UINT numBytes)
|
|
{
|
|
UINT i;
|
|
UCHAR lineStatReg;
|
|
|
|
while (numBytes--){
|
|
i = 0;
|
|
do {
|
|
IRMINI_RawReadPort(comBase+LINE_STAT_REG_OFFSET, &lineStatReg);
|
|
IRMINI_StallExecution(10000);
|
|
} while (!(lineStatReg & LINESTAT_DATAREADY) && (++i < 10));
|
|
|
|
if (lineStatReg & LINESTAT_DATAREADY){
|
|
IRMINI_RawReadPort(comBase+XFER_REG_OFFSET, data++);
|
|
IRMINI_StallExecution(10000);
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN CrystalWriteCmdString(UINT comBase, UCHAR *cmds, UINT len)
|
|
{
|
|
UCHAR byte;
|
|
|
|
/*
|
|
* Clear read FIFO
|
|
*/
|
|
while (CrystalRead(comBase, &byte, 1)){ }
|
|
|
|
while (len--){
|
|
UCHAR thisByte = *cmds++;
|
|
|
|
if (!CrystalWrite(comBase, &thisByte, 1)){
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CrystalRead(comBase, &byte, 1)){
|
|
return FALSE;
|
|
}
|
|
|
|
if (byte != thisByte){
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOLEAN CrystalReadRev(UINT comBase, UCHAR *rev)
|
|
{
|
|
UCHAR readval, writeval = 0xC0;
|
|
|
|
/*
|
|
* Set secondary register set
|
|
*/
|
|
if (!CrystalWriteCmdString(comBase, CrystalSetSecondaryRegisterSet, sizeof(CrystalSetSecondaryRegisterSet))){
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CrystalWrite(comBase, &writeval, 1)){
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CrystalRead(comBase, &readval, 1)){
|
|
return FALSE;
|
|
}
|
|
|
|
if ((readval & 0xF0) != writeval){
|
|
return FALSE;
|
|
}
|
|
|
|
*rev = (readval & 0x0F);
|
|
|
|
/*
|
|
* Switch back to primary register set
|
|
*/
|
|
if (!CrystalWriteCmdString(comBase, CrystalSetPrimaryRegisterSet, sizeof(CrystalSetPrimaryRegisterSet))){
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* CrystalSetIrDAMode
|
|
*
|
|
* Returns with Crystal chip in command mode.
|
|
*/
|
|
BOOLEAN CrystalSetIrDAMode(UINT comBase, UCHAR *crystalRev)
|
|
{
|
|
UINT attempts;
|
|
BOOLEAN result = FALSE;
|
|
UCHAR modemCntrlVal;
|
|
|
|
IRMINI_RawReadPort(comBase+MODEM_CONTROL_REG_OFFSET, &modemCntrlVal);
|
|
|
|
/*
|
|
* Try to set IrDA mode up to five times
|
|
*/
|
|
for (attempts = 0; !result && (attempts < 5); attempts++){
|
|
/*
|
|
* Reset and leave Crystal in command mode (DTR high)
|
|
*/
|
|
modemCntrlVal |= 3;
|
|
IRMINI_RawWritePort(comBase+MODEM_CONTROL_REG_OFFSET, modemCntrlVal);
|
|
IRMINI_StallExecution(50000);
|
|
modemCntrlVal &= ~2;
|
|
IRMINI_RawWritePort(comBase+MODEM_CONTROL_REG_OFFSET, modemCntrlVal);
|
|
IRMINI_StallExecution(50000);
|
|
|
|
/*
|
|
* Set IrDA mode.
|
|
*/
|
|
if (CrystalWriteCmdString(comBase, CrystalSetIrdaMode, sizeof(CrystalSetIrdaMode)) &&
|
|
CrystalReadRev(comBase, crystalRev)){
|
|
|
|
result = TRUE;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* CRYSTAL_Init
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
BOOLEAN CRYSTAL_Init(UINT comBase, dongleCapabilities *caps, UINT *context)
|
|
{
|
|
UCHAR modemCntrlVal, crystalRev;
|
|
|
|
IRMINI_RawReadPort(comBase+MODEM_CONTROL_REG_OFFSET, &modemCntrlVal);
|
|
|
|
/*
|
|
* Set command mode
|
|
*/
|
|
modemCntrlVal |= 1;
|
|
IRMINI_RawWritePort(comBase+MODEM_CONTROL_REG_OFFSET, modemCntrlVal);
|
|
|
|
/*
|
|
* Set IrDA mode
|
|
*/
|
|
if (!CrystalSetIrDAMode(comBase, &crystalRev)){
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Clear command mode
|
|
*/
|
|
modemCntrlVal &= ~1;
|
|
IRMINI_RawWritePort(comBase+MODEM_CONTROL_REG_OFFSET, modemCntrlVal);
|
|
IRMINI_StallExecution(50000);
|
|
|
|
caps->supportedSpeedsMask = CRYSTAL_IRDA_SPEEDS;
|
|
if (crystalRev == 0x01){
|
|
/*
|
|
* This is rev C, which doesn't support 115.2 Kb.
|
|
*/
|
|
caps->supportedSpeedsMask &= ~NDIS_IRDA_SPEED_115200;
|
|
}
|
|
caps->turnAroundTime_usec = 5000;
|
|
caps->extraBOFsRequired = 0;
|
|
|
|
*context = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* CRYSTAL_Deinit
|
|
*
|
|
* NOTE: This function assumes that the UART speed has been set to 9600.
|
|
*
|
|
*/
|
|
VOID CRYSTAL_Deinit(UINT comBase, UINT context)
|
|
{
|
|
/*
|
|
* Set low-power mode
|
|
*/
|
|
CrystalWrite(comBase, CrystalSetLowPower, sizeof(CrystalSetLowPower));
|
|
|
|
/*
|
|
* Clear command mode
|
|
*/
|
|
IRMINI_RawWritePort(comBase+MODEM_CONTROL_REG_OFFSET, 0);
|
|
IRMINI_StallExecution(50000);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CRYSTAL_SetSpeed
|
|
*
|
|
* This function assumes that the UART speed has been scaled back
|
|
* to 9600 baud for this call.
|
|
*
|
|
*/
|
|
BOOLEAN CRYSTAL_SetSpeed(UINT comBase, UINT bitsPerSec, UINT context)
|
|
{
|
|
UCHAR modemCntrlVal;
|
|
UCHAR *cmdString;
|
|
BOOLEAN result = TRUE;
|
|
|
|
switch (bitsPerSec){
|
|
case 2400: cmdString = CrystalSetSpeed2400; break;
|
|
case 9600: cmdString = CrystalSetSpeed9600; break;
|
|
case 19200: cmdString = CrystalSetSpeed19200; break;
|
|
case 38400: cmdString = CrystalSetSpeed38400; break;
|
|
case 57600: cmdString = CrystalSetSpeed57600; break;
|
|
case 115200: cmdString = CrystalSetSpeed115200; break;
|
|
default: return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Set data-terminal-ready to enter command mode.
|
|
*/
|
|
IRMINI_RawReadPort(comBase+MODEM_CONTROL_REG_OFFSET, &modemCntrlVal);
|
|
modemCntrlVal |= 1;
|
|
IRMINI_RawWritePort(comBase+MODEM_CONTROL_REG_OFFSET, modemCntrlVal);
|
|
IRMINI_StallExecution(50000);
|
|
|
|
/*
|
|
* Send the cmd string to set speed.
|
|
* All the set-speed cmd strings have length 4.
|
|
*/
|
|
if (!CrystalWriteCmdString(comBase, cmdString, 4)){
|
|
UCHAR rev;
|
|
|
|
/*
|
|
* Try one more time, after resetting IrDA mode.
|
|
*/
|
|
if (!(CrystalSetIrDAMode(comBase, &rev) &&
|
|
CrystalWriteCmdString(comBase, cmdString, 4))){
|
|
result = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Clear data-terminal-ready to exit command mode
|
|
* whether or not we succeeded.
|
|
*/
|
|
IRMINI_RawReadPort(comBase+MODEM_CONTROL_REG_OFFSET, &modemCntrlVal);
|
|
modemCntrlVal &= ~1;
|
|
IRMINI_RawWritePort(comBase+MODEM_CONTROL_REG_OFFSET, modemCntrlVal);
|
|
IRMINI_StallExecution(50000);
|
|
|
|
return result;
|
|
}
|
|
|
|
#endif
|