windows-nt/Source/XPSP1/NT/net/irda/irsir/crystal.c

415 lines
11 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*****************************************************************************
*
* 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;
}