?? irdahw.cpp
字號:
//**********************************************************************
//
// Filename: irdahw.cpp
//
// Description: Controls the IRDA hardware.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// Copyright(c) Cirrus Logic Corporation 2001, All Rights Reserved
//
//**********************************************************************
#include <windows.h>
extern "C"
{
#include <ndis.h>
#include <ntddndis.h>
}
#include <linklist.h>
#include <ceddk.h>
#include <hwdefs.h>
#include <clocks.h>
#include <nkintr.h>
#include <oalintr.h>
#include "settings.h"
#include "debugzone.h"
#include "recvlist.h"
#include "sendlist.h"
#include "sirstate.h"
#include "irdahw.h"
#include "miniport.h"
#include "irmacutl.h"
//
// v_rgSupportedBaudRates - Maps speed masks to real value.
// NOTE: The entries in the table must align with the enum BAUDRATES.
//
const BAUDRATE_INFO v_rgSupportedBaudRates[] =
{
// bps Serial bit mask
// ------ ---------------
{2400, BAUD_2400 , TEXT("2400 "), 0 },
{9600, BAUD_9600 , TEXT("9600 "), 1 },
{19200, BAUD_19200 , TEXT("19200 "), 2 },
{38400, BAUD_38400 , TEXT("38400 "), 4 },
{57600, BAUD_57600 , TEXT("57600 "), 12 },
{115200, BAUD_115200 , TEXT("115200 "), 24 },
// {576000, BAUD_USER },
// {1152000, BAUD_USER },
// {4000000, BAUD_USER }
};
//****************************************************************************
// IrdaHW::IrdaHW
//****************************************************************************
// Constructor for IrdaHW.
//
//
IrdaHW::IrdaHW():
m_SirState(),
m_bSirExiting(FALSE),
eIrdaMode(MODE_SIR),
m_ulBaudRate(9600),
m_fMinTATRequired(TRUE),
m_hSirEvent(0),
m_hSirInterruptThread(0),
m_pSIRTransmitNDisPacket(0),
m_pSendBuf(0),
m_ulSendCurPos(0),
m_ulSendBufSize(0),
m_ulPacketsTxDropped(0),
m_ulPacketsTx(0)
{
}
//****************************************************************************
// IrdaHW::InitializeIRDA
//****************************************************************************
// Initializes the IRDA interface.
//
//
NDIS_STATUS IrdaHW::InitializeIrdaHW()
{
DEBUGMSG(ZONE_IRDAHW, (TEXT("+IrdaHW::InitializeIrdaHW")));
NDIS_STATUS ulStatus;
BOOL b;
ulStatus = SetHWBaudRate(9600);
//
// Create the Sir Event.
//
if(ulStatus == NDIS_STATUS_SUCCESS)
{
m_hSirEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
ulStatus = m_hSirEvent? NDIS_STATUS_SUCCESS: NDIS_STATUS_RESOURCES;
}
//
// Hook the SIR interrupt.
//
if(ulStatus == NDIS_STATUS_SUCCESS)
{
b=InterruptInitialize(SYSINTR_UART2, m_hSirEvent, NULL, 0);
ASSERT(b);
ulStatus = b? NDIS_STATUS_SUCCESS: NDIS_STATUS_RESOURCES;
}
//
// Create the SIR interrupt thread.
//
if(ulStatus == NDIS_STATUS_SUCCESS)
{
m_hSirInterruptThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)SIRInterruptHandler,
(PVOID)this,
0,
NULL);
ASSERT( m_hSirInterruptThread);
ulStatus = m_hSirInterruptThread? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES;
}
if( ulStatus == NDIS_STATUS_SUCCESS)
{
//
// Set the thread priority for the SIR Interrupt handler.
// 148 should be fine.
//
b = CeSetThreadPriority( m_hSirInterruptThread, 148);
ASSERT( b);
ulStatus = b? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES;
}
//
// Allocate memory for the buffer.
//
if(ulStatus == NDIS_STATUS_SUCCESS)
{
m_pSendBuf = (PUCHAR) LocalAlloc
(
LMEM_FIXED | LMEM_ZEROINIT,
MAX_IRDA_DATA_SIZE
);
ASSERT(m_pSendBuf);
}
DEBUGMSG(ZONE_IRDAHW, (TEXT("-IrdaHW::InitializeIrdaHW")));
return(ulStatus);
}
//****************************************************************************
// IrdaHW::~IrdaHW
//****************************************************************************
// Destructor
//
//
IrdaHW::~IrdaHW()
{
DEBUGMSG(ZONE_IRDAHW, (TEXT("+IrdaHW::~IrdaHW")));
//
// Delete the Send buffer memory.
//
if(m_pSendBuf)
{
LocalFree(m_pSendBuf);
}
//
// Delete the event
//
if(m_hSirEvent)
{
CloseHandle(m_hSirEvent);
}
DEBUGMSG(ZONE_IRDAHW, (TEXT("-IrdaHW::~IrdaHW")));
}
//****************************************************************************
// IrdaHW::BaudRateSupported
//****************************************************************************
// Check to see if the baud rate is supported.
//
//
NDIS_STATUS IrdaHW::BaudRateSupported( ULONG ulBaudRate)
{
DEBUGMSG(ZONE_IRDAHW, (TEXT("+IrdaHW::BaudRateSupported")));
ULONG ulStatus = NDIS_STATUS_FAILURE;
ULONG ulCount;
//
// Check to see if it is one of the baud rates
//
for(ulCount =0; ulCount <= NUM_BAUDRATES; ulCount++)
{
if(v_rgSupportedBaudRates[ulCount].dwBPS == ulBaudRate)
{
ulStatus = NDIS_STATUS_SUCCESS;
break;
}
}
DEBUGMSG(ZONE_IRDAHW, (TEXT("-IrdaHW::BaudRateSupported")));
return (ulStatus);
}
//****************************************************************************
// IrdaHW::SetBaudRate
//****************************************************************************
// Sets the IRDA baud rate for SIR, MIR and FIR.
//
//
NDIS_STATUS IrdaHW::SetHWBaudRate( ULONG ulBaudRate)
{
DEBUGMSG(ZONE_IRDAHW, (TEXT("+IrdaHW::SetHWBaudRate")));
ULONG ulCount;
ULONG ulStatus = NDIS_STATUS_SUCCESS;
ULONG ulDivisor;
//
// Check to make sure that the
//
ulStatus = BaudRateSupported(ulBaudRate);
if(ulStatus == NDIS_STATUS_SUCCESS)
{
if(ulBaudRate <= 115200)
{
//
// The Transmit and recieve bits in the IRCON register
// must be disabled before disable IRDA in the IRENABLE
// register.
//
*IRDA_IRCON &= ~(IRCON_TXE | IRCON_RXE);
//
// Disable IRDA.
//
*IRDA_IRENABLE = IRENABLE_DISABLE;
//
// Disable the UART 2.
//
*UART2_CR = 0;
//
// Calculate the divisor.
//
ulDivisor = (UART_CLOCK / (16 * ulBaudRate)) - 1;
//
// Program the baud rate into the baud rate registers.
//
*UART2_LCR_M = (ulDivisor >> 8) & 0x0FF;
*UART2_LCR_L = (ulDivisor & 0x0FF);
//
// The documentation is not very clear on this register.
// It says that this is a divisor of the UART clock rate.
// The divided frequency should be between 1.42 and 2.12 Mhz
//
// If this register is not programmed, UART recieve will not
// work.
//
*UART2_ILPR = 2;
//
// Enable Uart for 8bits No parity, one stop bit.
//
*UART2_LCR_H = LCR_H_DATABITS_8 | LCR_H_FIFO_ENABLE;
//
// Enable SIR in the UART 2 register. Also Enable
// the interrupts.
//
*UART2_CR = CR_UARTE | CR_SIREN | CR_RIE ;
//
// Enable SIR.
//
*IRDA_IRENABLE = IRENABLE_SIR;
//
// The Transmit and recieve bits in the IRCON register
// must be enabled after the IRDA is enabled in the IRENABLE
// register.
//
*IRDA_IRCON |= IRCON_TXE | IRCON_RXE;
//
// Set the mode to SIR.
//
eIrdaMode = MODE_SIR;
}
//
// Check to see if it is MIR baud rate.
//
else if( ulBaudRate == 576000 || ulBaudRate == 1152000)
{
//
// Disable IRDA.
//
*IRDA_IRENABLE = IRENABLE_DISABLE;
//
// Disable the UART 2.
//
*UART2_CR = 0;
*IRDA_IRCON = 0; //~(IRCON_TXE | IRCON_RXE);
//
// Enable MIR.
//
*IRDA_IRENABLE = IRENABLE_MIR;
//
// Check to see which baud rate it is.
//
if( ulBaudRate == 1152000)
{
*IRDA_IRCON = IRCON_MIR_FAST;
}
else
{
*IRDA_IRCON = 0;
}
//
// Set the mode to MIR.
//
eIrdaMode = MODE_MIR;
}
//
// Check to see if it is FIR baud rate.
//
else if( ulBaudRate == 4000000)
{
//
// Disable IRDA.
//
*IRDA_IRENABLE = IRENABLE_DISABLE;
//
// Disable the UART 2.
//
*UART2_CR = 0;
*IRDA_IRCON = ~(IRCON_TXE | IRCON_RXE);
//
// Enable MIR.
//
*IRDA_IRENABLE = IRENABLE_FIR;
//
// Set the mode to FIR.
//
eIrdaMode = MODE_FIR;
}
else
{
ulStatus = NDIS_STATUS_FAILURE;
}
}
//
// Change the baud rate
//
if(ulStatus == NDIS_STATUS_SUCCESS)
{
m_ulBaudRate = ulBaudRate;
}
DEBUGMSG(ZONE_IRDAHW, (TEXT("-IrdaHW::SetHWBaudRate")));
return(ulStatus);
}
//****************************************************************************
// IrdaHW::IirTransmit
//****************************************************************************
// Only have to change if we are not in SIR mode.
//
//
void IrdaHW::IirTransmit( )
{
ULONG ulIRCON;
if(eIrdaMode != MODE_SIR)
{
ulIRCON = *IRDA_IRCON;
*IRDA_IRCON = (ulIRCON & IRCON_MIR_FAST) | IRCON_TXE;
}
}
//****************************************************************************
// IrdaHW::IirRecieve
//****************************************************************************
// Only have to change if we are not in SIR mode.
//
//
void IrdaHW::IirRecieve()
{
ULONG ulIRCON;
if(eIrdaMode != MODE_SIR)
{
ulIRCON = *IRDA_IRCON;
*IRDA_IRCON = (ulIRCON & IRCON_MIR_FAST) | IRCON_RXE;
}
}
//****************************************************************************
// IrdaHW::ClearStatistics
//****************************************************************************
// Clears the statitistics.
//
//
void IrdaHW::ClearStatistics()
{
//
// Clear the statistics.
//
m_SirState.ClearStats();
m_ulPacketsTxDropped = 0;
m_ulPacketsTx = 0;
}
#define MAX_TX_WAIT 400
//****************************************************************************
// SIRInterruptHandler
//****************************************************************************
// SIR Interrupt Handler.
//
// Performs the following:
//
// 1. Checks to see if we are exiting from the interrupt handler.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -