415 lines
11 KiB
C
415 lines
11 KiB
C
/*****************************************************************************
|
|
*
|
|
* Copyright (c) 1998-1999 Microsoft Corporation
|
|
*
|
|
* @doc
|
|
* @module crystal.c | IrSIR NDIS Miniport Driver
|
|
* @comm
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* Author: Stan Adermann (stana)
|
|
*
|
|
* Date: 10/30/1997 (created)
|
|
*
|
|
* Contents: Crystal (AMP dongle specific code for initialization,
|
|
* deinit, and setting the baud rate of the device.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "irsir.h"
|
|
#include "dongle.h"
|
|
|
|
ULONG 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
|
|
);
|
|
|
|
#define MS(d) ((d)*1000)
|
|
|
|
/*
|
|
** 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 };
|
|
|
|
#if 1
|
|
static BOOLEAN
|
|
CrystalWriteCommand(IN PDEVICE_OBJECT pSerialDevObj,
|
|
IN PUCHAR pCommand, UINT Length)
|
|
{
|
|
SerialSetTimeouts(pSerialDevObj, &SerialTimeoutsInit);
|
|
while (Length--)
|
|
{
|
|
UCHAR Response;
|
|
ULONG BytesRead;
|
|
ULONG BytesWritten = 0;
|
|
NTSTATUS Status;
|
|
|
|
(void)SerialSynchronousWrite(pSerialDevObj,
|
|
pCommand,
|
|
1,
|
|
&BytesWritten);
|
|
|
|
if (BytesWritten!=1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
Status = SerialSynchronousRead(pSerialDevObj,
|
|
&Response,
|
|
1,
|
|
&BytesRead);
|
|
if (Status!=STATUS_SUCCESS || Response!=*pCommand)
|
|
{
|
|
if (BytesRead)
|
|
{
|
|
DEBUGMSG(DBG_ERROR, ("Expected: %02X Got: %02X\n", *pCommand, Response));
|
|
}
|
|
return FALSE;
|
|
}
|
|
pCommand++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
#else
|
|
BOOLEAN CrystalWriteCmd(IN PDEVICE_OBJECT pSerialDevObj, IN PUCHAR pCmd, IN ULONG Len)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG BytesWritten, BytesRead, i, j;
|
|
UCHAR c;
|
|
|
|
SerialSetTimeouts(pSerialDevObj, &SerialTimeoutsInit);
|
|
|
|
for (i=0;
|
|
i<20000;
|
|
i++)
|
|
{
|
|
if (SerialSynchronousRead(pSerialDevObj, &c, 1, &BytesRead)!=STATUS_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i=0; i<Len; i++)
|
|
{
|
|
Status = SerialSynchronousWrite(pSerialDevObj, &pCmd[i], 1, &BytesWritten);
|
|
|
|
if (Status!=STATUS_SUCCESS || BytesWritten!=1)
|
|
return FALSE;
|
|
|
|
// The dongle is not particularly responsive, so we need to give it some time.
|
|
j = 0;
|
|
do
|
|
{
|
|
Status = SerialSynchronousRead(pSerialDevObj, &c, 1, &BytesRead);
|
|
if (BytesRead==0)
|
|
{
|
|
NdisMSleep(MS(10));
|
|
}
|
|
} while ( BytesRead==0 && j++<3);
|
|
|
|
if (Status!=STATUS_SUCCESS || c!=pCmd[i])
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
BOOLEAN CrystalReadRev(IN PDEVICE_OBJECT pSerialDevObj, OUT PUCHAR pRev)
|
|
{
|
|
UCHAR readval, writeval = 0xC0;
|
|
ULONG BytesWritten, BytesRead;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
/*
|
|
** Set secondary register set
|
|
*/
|
|
|
|
if (!CrystalWriteCommand(pSerialDevObj,
|
|
CrystalSetSecondaryRegisterSet,
|
|
sizeof(CrystalSetSecondaryRegisterSet)))
|
|
{
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
if (Status==STATUS_SUCCESS)
|
|
{
|
|
Status = SerialSynchronousWrite(pSerialDevObj, &writeval, 1, &BytesWritten);
|
|
}
|
|
|
|
if (Status==STATUS_SUCCESS && BytesWritten==1)
|
|
{
|
|
NdisMSleep(MS(10));
|
|
Status = SerialSynchronousRead(pSerialDevObj, &readval, 1, &BytesRead);
|
|
}
|
|
|
|
if (Status==STATUS_SUCCESS && BytesRead==1)
|
|
{
|
|
if ((readval & 0xF0) != writeval){
|
|
return FALSE;
|
|
}
|
|
|
|
*pRev = (readval & 0x0F);
|
|
|
|
/*
|
|
** Switch back to primary register set
|
|
*/
|
|
CrystalWriteCommand(pSerialDevObj,
|
|
CrystalSetPrimaryRegisterSet,
|
|
sizeof(CrystalSetPrimaryRegisterSet));
|
|
}
|
|
|
|
#if DBG
|
|
if (Status!=STATUS_SUCCESS)
|
|
{
|
|
DEBUGMSG(DBG_ERR, ("CrystalReadRev failed 0x%08X\n", Status));
|
|
}
|
|
#endif
|
|
|
|
return ((Status==STATUS_SUCCESS) ? TRUE : FALSE);
|
|
}
|
|
|
|
static BOOLEAN CrystalSetIrDAMode(IN PDEVICE_OBJECT pSerialDevObj, OUT PUCHAR pRev)
|
|
{
|
|
UINT i;
|
|
ULONG BytesWritten;
|
|
NTSTATUS Status;
|
|
ULONG Speed9600 = 9600;
|
|
|
|
//(void)SerialSetBaudRate(pSerialDevObj, &Speed9600);
|
|
(void)SerialPurge(pSerialDevObj);
|
|
|
|
for (i=0; i<5; i++)
|
|
{
|
|
(void)SerialSetDTR(pSerialDevObj);
|
|
(void)SerialSetRTS(pSerialDevObj);
|
|
NdisMSleep(MS(50));
|
|
(void)SerialClrRTS(pSerialDevObj);
|
|
NdisMSleep(MS(50));
|
|
|
|
if (!CrystalWriteCommand(pSerialDevObj,
|
|
CrystalSetIrdaMode,
|
|
sizeof(CrystalSetIrdaMode)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (CrystalReadRev(pSerialDevObj, pRev))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
DEBUGMSG(DBG_ERR, ("IRSIR: Failed to set CrystalIrDAMode\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
Crystal_QueryCaps(
|
|
OUT PDONGLE_CAPABILITIES pDongleCaps
|
|
)
|
|
{
|
|
pDongleCaps->supportedSpeedsMask = CRYSTAL_IRDA_SPEEDS;
|
|
pDongleCaps->turnAroundTime_usec = 100;
|
|
pDongleCaps->extraBOFsRequired = 0;
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Function: Crystal_Init
|
|
*
|
|
* Synopsis: Initialize the Crystal dongle.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* Returns: NDIS_STATUS_SUCCESS
|
|
* DONGLE_CAPABILITIES
|
|
*
|
|
* Algorithm:
|
|
*
|
|
* History: dd-mm-yyyy Author Comment
|
|
* 03-04-1998 stana author
|
|
*
|
|
* Notes:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
NDIS_STATUS
|
|
Crystal_Init(
|
|
IN PDEVICE_OBJECT pSerialDevObj
|
|
)
|
|
{
|
|
ULONG BytesRead, BytesWritten;
|
|
UCHAR Response, Revision;
|
|
BOOLEAN Reset = FALSE;
|
|
UINT i;
|
|
|
|
DEBUGMSG(DBG_FUNC, ("+Crystal_Init\n"));
|
|
|
|
if (!CrystalSetIrDAMode(pSerialDevObj, &Revision))
|
|
{
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
//
|
|
// Clear command mode
|
|
//
|
|
(void)SerialClrDTR(pSerialDevObj);
|
|
NdisMSleep(MS(50));
|
|
|
|
if (Revision==0x1)
|
|
{
|
|
// This is Rev C, which doesn't support 115200
|
|
|
|
CRYSTAL_IRDA_SPEEDS &= ~NDIS_IRDA_SPEED_115200;
|
|
}
|
|
else
|
|
{
|
|
CRYSTAL_IRDA_SPEEDS |= NDIS_IRDA_SPEED_115200;
|
|
}
|
|
|
|
|
|
DEBUGMSG(DBG_FUNC, ("-Crystal_Init\n"));
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Function: Crystal_Deinit
|
|
*
|
|
* Synopsis: The Crystal dongle doesn't require any special deinit, but for
|
|
* purposes of being symmetrical with other dongles...
|
|
*
|
|
* Arguments:
|
|
*
|
|
* Returns:
|
|
*
|
|
* Algorithm:
|
|
*
|
|
* History: dd-mm-yyyy Author Comment
|
|
* 03-04-1998 stana author
|
|
*
|
|
* Notes:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
VOID
|
|
Crystal_Deinit(
|
|
IN PDEVICE_OBJECT pSerialDevObj
|
|
)
|
|
{
|
|
DEBUGMSG(DBG_FUNC, ("+Crystal_Deinit\n"));
|
|
|
|
(void)SerialClrDTR(pSerialDevObj);
|
|
(void)SerialClrRTS(pSerialDevObj);
|
|
|
|
DEBUGMSG(DBG_FUNC, ("-Crystal_Deinit\n"));
|
|
return;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Function: Crystal_SetSpeed
|
|
*
|
|
* Synopsis: set the baud rate of the Crystal dongle
|
|
*
|
|
* Arguments:
|
|
*
|
|
* Returns: NDIS_STATUS_SUCCESS if bitsPerSec = 9600 || 19200 || 115200
|
|
* NDIS_STATUS_FAILURE otherwise
|
|
*
|
|
* Algorithm:
|
|
*
|
|
* History: dd-mm-yyyy Author Comment
|
|
* 10/2/1996 stana author
|
|
*
|
|
* Notes:
|
|
* The caller of this function should set the baud rate of the
|
|
* serial driver (UART) to 9600 first to ensure that dongle
|
|
* receives the commands.
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
NDIS_STATUS
|
|
Crystal_SetSpeed(
|
|
IN PDEVICE_OBJECT pSerialDevObj,
|
|
IN UINT bitsPerSec,
|
|
IN UINT currentSpeed
|
|
)
|
|
{
|
|
ULONG WaitMask = SERIAL_EV_TXEMPTY;
|
|
UCHAR *SetSpeedString, Revision;
|
|
ULONG SetSpeedStringLength, BytesWritten;
|
|
ULONG Speed9600 = 9600;
|
|
BOOLEAN Result;
|
|
|
|
|
|
DEBUGMSG(DBG_FUNC, ("+Crystal_SetSpeed\n"));
|
|
|
|
switch (bitsPerSec)
|
|
{
|
|
#define MAKECASE(speed) \
|
|
case speed: SetSpeedString = CrystalSetSpeed##speed; SetSpeedStringLength = sizeof(CrystalSetSpeed##speed); break;
|
|
|
|
MAKECASE(2400)
|
|
MAKECASE(9600)
|
|
MAKECASE(19200)
|
|
MAKECASE(38400)
|
|
MAKECASE(57600)
|
|
MAKECASE(115200)
|
|
default:
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
(void)SerialSetBaudRate(pSerialDevObj, &Speed9600);
|
|
(void)SerialPurge(pSerialDevObj);
|
|
|
|
NdisMSleep(MS(20));
|
|
(void)SerialSetDTR(pSerialDevObj);
|
|
NdisMSleep(MS(50));
|
|
|
|
if (!CrystalWriteCommand(pSerialDevObj,
|
|
SetSpeedString,
|
|
SetSpeedStringLength))
|
|
{
|
|
if (!CrystalSetIrDAMode(pSerialDevObj, &Revision) ||
|
|
!CrystalWriteCommand(pSerialDevObj, SetSpeedString, SetSpeedStringLength))
|
|
{
|
|
// Always clear DTR to get out of command mode.
|
|
(void)SerialClrDTR(pSerialDevObj);
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
(void)SerialClrDTR(pSerialDevObj);
|
|
NdisMSleep(MS(50));
|
|
|
|
DEBUGMSG(DBG_FUNC, ("-Crystal_SetSpeed\n"));
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|