674 lines
18 KiB
C
674 lines
18 KiB
C
|
/*****************************************************************************
|
||
|
** **
|
||
|
** COPYRIGHT (C) 2000, 2001 MKNET CORPORATION **
|
||
|
** DEVELOPED FOR THE MK7100-BASED VFIR PCI CONTROLLER. **
|
||
|
** **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/**********************************************************************
|
||
|
|
||
|
Module Name:
|
||
|
INTERRUP.C
|
||
|
|
||
|
Procedures:
|
||
|
MKMiniportIsr
|
||
|
MKMiniportHandleInterrupt
|
||
|
ProcessRXComp
|
||
|
ProcessTXComp
|
||
|
ProcessRXCompIsr
|
||
|
ProcessTXCompIsr
|
||
|
|
||
|
Comments:
|
||
|
|
||
|
|
||
|
|
||
|
**********************************************************************/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
#include "protot.h"
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Procedure: [MKMiniportIsr] (miniport)
|
||
|
//
|
||
|
// Description: This is the interrupt service routine running at interrupt level.
|
||
|
// It checks to see if there is an interrupt pending. If yes, it
|
||
|
// disables board interrupts and schedules HandleInterrupt callback.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// MiniportAdapterContext - The context value returned by the Miniport
|
||
|
// when the adapter was initialized (see the call
|
||
|
// NdisMSetAttributes). In reality, it is a pointer to MK7_ADAPTER.
|
||
|
//
|
||
|
// Returns:
|
||
|
// InterruptRecognized - Returns True if the interrupt belonges to this
|
||
|
// adapter, and false otherwise.
|
||
|
// QueueMiniportHandleInterrupt - Returns True if we want a callback to
|
||
|
// HandleInterrupt.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
MKMiniportIsr( OUT PBOOLEAN InterruptRecognized,
|
||
|
OUT PBOOLEAN QueueMiniportHandleInterrupt,
|
||
|
IN NDIS_HANDLE MiniportAdapterContext )
|
||
|
{
|
||
|
MK7REG mk7reg, ReadInt;
|
||
|
|
||
|
|
||
|
PMK7_ADAPTER Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
||
|
|
||
|
|
||
|
DBGLOG("=> INT", 0);
|
||
|
|
||
|
//****************************************
|
||
|
// Read the Interrupt Event Reg and save to context area for
|
||
|
// DPC processing.
|
||
|
//
|
||
|
// IMPORTANT NOTE: The ISR runs at DIRQL level and is, thus, higher
|
||
|
// proiority than other miniport routines. We need to be careful
|
||
|
// about shared resources. Example: If our multi-pkt send is running
|
||
|
// when an int occurs, the send routine can be preempted. If the ISR
|
||
|
// and the send routine access shared resource then we have problems.
|
||
|
//
|
||
|
// We save the interrupt in recentInt because the interrupt event
|
||
|
// register may be cleared upon a Read. (This has been verified.)
|
||
|
//****************************************
|
||
|
//MK7Reg_Read(Adapter, R_INTS, &Adapter->recentInt);
|
||
|
MK7Reg_Read(Adapter, R_INTS, &ReadInt);
|
||
|
if (MK7OurInterrupt(ReadInt)) {
|
||
|
|
||
|
// Int enable should happen only after DPC is done.
|
||
|
// Also disabling interrupt clears Interrupt Status.
|
||
|
MK7DisableInterrupt(Adapter);
|
||
|
|
||
|
Adapter->recentInt = ReadInt;
|
||
|
|
||
|
MK7Reg_Read(Adapter, R_CFG3, &mk7reg);
|
||
|
if ((mk7reg & 0x1000) != 0){
|
||
|
mk7reg &= 0xEFFF;
|
||
|
MK7Reg_Write(Adapter, R_CFG3, mk7reg);
|
||
|
mk7reg |= 0x1000;
|
||
|
MK7Reg_Write(Adapter, R_CFG3, mk7reg);
|
||
|
// mk7reg = mk7reg; //For Debugging
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
GDbgStat.isrCnt++;
|
||
|
DBGLOG(" INT status", Adapter->recentInt);
|
||
|
#endif
|
||
|
|
||
|
// Don't do TX processing in ISR. I saw a condition where SetSpeed()
|
||
|
// was called while tcbused = 1. I set the change-speed flags correctly.
|
||
|
// But the TX processing in ISR cleared tcbused resulting in the code
|
||
|
// not chaning speed in DPC.
|
||
|
// ProcessTXCompIsr(Adapter);
|
||
|
|
||
|
ProcessRXCompIsr(Adapter);
|
||
|
|
||
|
*InterruptRecognized = TRUE;
|
||
|
*QueueMiniportHandleInterrupt = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
*InterruptRecognized = FALSE;
|
||
|
*QueueMiniportHandleInterrupt = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Procedure: [MKMiniportHandleInterrupt]
|
||
|
//
|
||
|
// Description: This is the DPC for the ISR. It goes on to do RX & TX
|
||
|
// completion processing.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// MiniportAdapterContext (miniport) - The context value returned by the
|
||
|
// Miniport when the adapter was initialized (see the call
|
||
|
// NdisMSetAttributes). In reality, it is a pointer to MK7_ADAPTER.
|
||
|
//
|
||
|
// Returns: (none)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID
|
||
|
MKMiniportHandleInterrupt(NDIS_HANDLE MiniportAdapterContext)
|
||
|
{
|
||
|
MK7REG mk7reg;
|
||
|
PMK7_ADAPTER Adapter = PMK7_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
||
|
|
||
|
|
||
|
NdisAcquireSpinLock(&Adapter->Lock);
|
||
|
|
||
|
DBGLOG("=> MKMiniportHandleInterrupt", Adapter->recentInt);
|
||
|
|
||
|
//****************************************
|
||
|
// DPC runs at Dispatch Level IRQL (just below ISR's DIRQL in proiority).
|
||
|
// Note that recentInt can be modified in the ISR routine, which is
|
||
|
// higher IRQL. But since this is DPC w/ int disabled, recentInt can
|
||
|
// be safely queried.
|
||
|
//****************************************
|
||
|
ProcessTXComp(Adapter);
|
||
|
ProcessRXComp(Adapter);
|
||
|
|
||
|
Adapter->recentInt = 0; // clear the saved int
|
||
|
|
||
|
NdisReleaseSpinLock(&Adapter->Lock);
|
||
|
MK7EnableInterrupt(Adapter);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Procedure: [ProcessRXComp]
|
||
|
//
|
||
|
// Description: This is the DPC for RX completions.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// Adapter - ptr to Adapter object instance
|
||
|
//
|
||
|
// Returns: (none)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
VOID ProcessRXComp(PMK7_ADAPTER Adapter)
|
||
|
{
|
||
|
UINT PacketArrayCount, i;
|
||
|
// 4.0.1 BOC
|
||
|
UINT PacketFreeCount;
|
||
|
// 4.0.1 EOC
|
||
|
PNDIS_PACKET PacketArray[MAX_ARRAY_RECEIVE_PACKETS];
|
||
|
PRCB rcb;
|
||
|
PRRD rrd;
|
||
|
PRPD rpd;
|
||
|
UINT rrdstatus;
|
||
|
BOOLEAN done=FALSE;
|
||
|
BOOLEAN gotdata=FALSE;
|
||
|
MK7REG intereg;
|
||
|
UINT rcvcnt;
|
||
|
// 4.0.1 BOC
|
||
|
BOOLEAN LowResource;
|
||
|
// 4.0.1 EOC
|
||
|
|
||
|
|
||
|
// Process only if we get the corresponding int.
|
||
|
if (!(Adapter->recentInt & B_RX_INTS)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DBGLOG("=> RX comp", 0);
|
||
|
|
||
|
#if DBG
|
||
|
GDbgStat.rxIsrCnt++;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// 1.0.0
|
||
|
// If we have just started receiving a packet, indicate media-busy
|
||
|
// to the protocol.
|
||
|
// if (Adapter->mediaBusy && !Adapter->haveIndicatedMediaBusy) {
|
||
|
// if (Adapter->CurrentSpeed > MAX_SIR_SPEED) {
|
||
|
//#if DBG
|
||
|
// DBGLOG("Error: MKMiniportHandleInterrupt is in wrong state",
|
||
|
// Adapter->CurrentSpeed);
|
||
|
//#endif
|
||
|
// ASSERT(0);
|
||
|
// }
|
||
|
// NdisMIndicateStatus(Adapter->MK7AdapterHandle,
|
||
|
// NDIS_STATUS_MEDIA_BUSY, NULL, 0);
|
||
|
// NdisMIndicateStatusComplete(Adapter->MK7AdapterHandle);
|
||
|
// RYM-5+
|
||
|
// May need to protect this because ISR also writes to this?
|
||
|
// Adapter->haveIndicatedMediaBusy = TRUE;
|
||
|
// }
|
||
|
|
||
|
|
||
|
|
||
|
rcb = Adapter->pRcbArray[Adapter->nextRxRcbIdx];
|
||
|
rrd = rcb->rrd;
|
||
|
rrdstatus = rrd->status; // for debug
|
||
|
|
||
|
do {
|
||
|
PacketArrayCount = 0;
|
||
|
// 4.0.1 BOC
|
||
|
LowResource = FALSE;
|
||
|
// 4.0.1 EOC.
|
||
|
|
||
|
|
||
|
// 4.0.1 BOC
|
||
|
PacketFreeCount = 0;
|
||
|
// 4.0.1 EOC.
|
||
|
// inner loop
|
||
|
while ( !HwOwnsRrd(rrd) &&
|
||
|
(PacketArrayCount < MAX_ARRAY_RECEIVE_PACKETS) ) {
|
||
|
// 4.0.1 BOC
|
||
|
if (QueueEmpty(&Adapter->FreeRpdList))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
// 4.0.1 EOC.
|
||
|
|
||
|
#if DBG
|
||
|
// DBG_STAT
|
||
|
if (RrdAnyError(rrd)) {
|
||
|
GDbgStat.rxErrCnt++;
|
||
|
GDbgStat.rxErr |= rrd->status;
|
||
|
DBGSTATUS1(" RX err: %x \n\r", rrd->status);
|
||
|
}
|
||
|
if (Adapter->recentInt & B_RX_INTS)
|
||
|
GDbgStat.rxComp++;
|
||
|
else
|
||
|
GDbgStat.rxCompNoInt++;
|
||
|
#endif
|
||
|
|
||
|
if (RrdError(rrd)) {
|
||
|
// If error just give RRD back to hw and continue.
|
||
|
// (NOTE: This may indicate errors for MIR & FIR only.
|
||
|
// The sw does the FCS for SIR.)
|
||
|
// (Note that hw may not detect all SIR errors.)
|
||
|
rrd->count = 0;
|
||
|
GrantRrdToHw(rrd);
|
||
|
// Next receive to read from
|
||
|
Adapter->nextRxRcbIdx++;
|
||
|
Adapter->nextRxRcbIdx %= Adapter->NumRcb;
|
||
|
rcb = Adapter->pRcbArray[Adapter->nextRxRcbIdx];
|
||
|
rrd = rcb->rrd;
|
||
|
rrdstatus = rrd->status; // for debug
|
||
|
// break; // this to do 1 rx per int
|
||
|
|
||
|
DBGLOG(" RX err", 0);
|
||
|
|
||
|
continue; // this to do > 1 rx per int
|
||
|
}
|
||
|
|
||
|
|
||
|
// Additional software processing for SIR frames
|
||
|
if (Adapter->CurrentSpeed <= MAX_SIR_SPEED) {
|
||
|
if (!ProcRXSir(rcb->rpd->databuff, (UINT)rrd->count)) {
|
||
|
// If error just give RRD back to hw and continue.
|
||
|
rrd->count = 0;
|
||
|
GrantRrdToHw(rrd);
|
||
|
// Next receive to read from
|
||
|
Adapter->nextRxRcbIdx++;
|
||
|
Adapter->nextRxRcbIdx %= Adapter->NumRcb;
|
||
|
rcb = Adapter->pRcbArray[Adapter->nextRxRcbIdx];
|
||
|
rrd = rcb->rrd;
|
||
|
rrdstatus = rrd->status; // for debug
|
||
|
#if DBG
|
||
|
GDbgStat.rxErrCnt++;
|
||
|
GDbgStat.rxErrSirCrc++;
|
||
|
#endif
|
||
|
// break; // this to do 1 rx per int
|
||
|
|
||
|
DBGLOG(" RX err", 0);
|
||
|
|
||
|
continue; // this to do > 1 rx per int
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Remove count of FCS bytes:
|
||
|
// SIR/MIR = 2 (16 bits)
|
||
|
// FIR/VFIR = 4 (32 bits)
|
||
|
if (Adapter->CurrentSpeed < MIN_FIR_SPEED) {
|
||
|
rcvcnt = (UINT) rrd->count - SIR_FCS_SIZE;
|
||
|
DBGLOG(" RX comp (slow)", 0);
|
||
|
}
|
||
|
else {
|
||
|
rcvcnt = (UINT) rrd->count - FASTIR_FCS_SIZE;
|
||
|
DBGLOG(" RX comp (fast)", 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
NdisAdjustBufferLength(rcb->rpd->ReceiveBuffer, rcvcnt);
|
||
|
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
if (rcvcnt > GDbgStat.rxLargestPkt) {
|
||
|
GDbgStat.rxLargestPkt = rcvcnt;
|
||
|
}
|
||
|
|
||
|
// NdisGetCurrentSystemTime((PLARGE_INTEGER)&GDbgTARspTime[GDbgTATimeIdx]);
|
||
|
// GDbgTATime[GDbgTATimeIdx] = GDbgTARspTime[GDbgTATimeIdx] -
|
||
|
// GDbgTACmdTime[GDbgTATimeIdx];
|
||
|
// GDbgTATimeIdx++;
|
||
|
// GDbgTATimeIdx %= 1000; // wrap around
|
||
|
#endif
|
||
|
|
||
|
|
||
|
PacketArray[PacketArrayCount] = rcb->rpd->ReceivePacket;
|
||
|
// 4.0.1 BOC
|
||
|
if (((Adapter->NumRpd - Adapter->UsedRpdCount-Adapter->NumRcb) <= 4)|| LowResource==TRUE) {
|
||
|
NDIS_SET_PACKET_STATUS(PacketArray[PacketArrayCount], NDIS_STATUS_RESOURCES);
|
||
|
LowResource = TRUE;
|
||
|
PacketFreeCount++;
|
||
|
}
|
||
|
else {
|
||
|
// NDIS_SET_PACKET_STATUS(PacketArray[PacketArrayCount], NDIS_STATUS_SUCCESS);
|
||
|
NDIS_SET_PACKET_STATUS(PacketArray[PacketArrayCount], NDIS_STATUS_SUCCESS);
|
||
|
}
|
||
|
// 4.0.1 EOC
|
||
|
|
||
|
PacketArrayCount++;
|
||
|
|
||
|
// 4.0.1 BOC
|
||
|
Adapter->UsedRpdCount++;
|
||
|
// 4.0.1 EOC
|
||
|
|
||
|
// unbind the one we just indicated to upper layer
|
||
|
rcb->rpd = (PRPD)NULL;
|
||
|
rcb->rrd->addr = 0;
|
||
|
|
||
|
|
||
|
// get a new one for the next rx
|
||
|
rpd = (PRPD) QueuePopHead(&Adapter->FreeRpdList);
|
||
|
|
||
|
// 4.0.1 BOC
|
||
|
ASSERT(!(rpd == (PRPD)NULL));
|
||
|
// if (rpd == (PRPD)NULL) {
|
||
|
|
||
|
//****************************************
|
||
|
// If there's no existing RCB that's waiting for a
|
||
|
// RPD, set the start of waiting RCBs to this one.
|
||
|
//****************************************
|
||
|
// if (Adapter->rcbPendRpdCnt == 0) {
|
||
|
// Adapter->rcbPendRpdIdx = Adapter->nextRxRcbIdx;
|
||
|
// }
|
||
|
// Adapter->rcbPendRpdCnt++;
|
||
|
//
|
||
|
//#if DBG
|
||
|
// GDbgStat.rxNoRpd++;
|
||
|
//#endif
|
||
|
// }
|
||
|
// else {
|
||
|
// 4.0.1 EOC
|
||
|
// bind new RDP-Packet to RCB-RRD
|
||
|
rcb->rpd = rpd;
|
||
|
rcb->rrd->addr = rpd->databuffphys;
|
||
|
rcb->rrd->count = 0;
|
||
|
GrantRrdToHw(rcb->rrd);
|
||
|
// 4.0.1 BOC
|
||
|
// }
|
||
|
// 4.0.1 EOC.
|
||
|
|
||
|
// Next receive to read from
|
||
|
Adapter->nextRxRcbIdx++;
|
||
|
Adapter->nextRxRcbIdx %= Adapter->NumRcb;
|
||
|
|
||
|
|
||
|
rcb = Adapter->pRcbArray[Adapter->nextRxRcbIdx];
|
||
|
rrd = rcb->rrd;
|
||
|
rrdstatus = rrd->status; // for debug
|
||
|
|
||
|
} // while
|
||
|
|
||
|
|
||
|
if (PacketArrayCount >= MAX_ARRAY_RECEIVE_PACKETS) {
|
||
|
DBGLOG(" RX max indicate", 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
//****************************************
|
||
|
// RYM-5+
|
||
|
// NOTE: This controls whether we poll the next ring buffers
|
||
|
// for data after serviceing the current ring buffer that
|
||
|
// caused the original RX int. The current int scheme
|
||
|
// is to get 1 rx buffer per int. So the following lines
|
||
|
// are replaced with a 1 rx per int logic.
|
||
|
// **We're done when we run into the 1st Ring entry that
|
||
|
// **we have no ownership.
|
||
|
//****************************************
|
||
|
if (HwOwnsRrd(rrd))
|
||
|
done = TRUE;
|
||
|
// done = TRUE;
|
||
|
|
||
|
// Indicate away
|
||
|
if(PacketArrayCount) {
|
||
|
NdisReleaseSpinLock(&Adapter->Lock);
|
||
|
NdisMIndicateReceivePacket(Adapter->MK7AdapterHandle,
|
||
|
PacketArray,
|
||
|
PacketArrayCount);
|
||
|
#if DBG
|
||
|
GDbgStat.rxPktsInd += PacketArrayCount;
|
||
|
#endif
|
||
|
gotdata = TRUE;
|
||
|
|
||
|
NdisAcquireSpinLock(&Adapter->Lock);
|
||
|
//DBGLOG(" ProcessRXInterrupt: indicated Packet(s)", PacketArrayCount);
|
||
|
}
|
||
|
|
||
|
|
||
|
//****************************************
|
||
|
// Check Packet status on return from Indicate. Pending means
|
||
|
// NDIS-upper layer still holds it, else it's ours.
|
||
|
//****************************************
|
||
|
// Don't do this for deserialized driver.
|
||
|
// for (i=0; i<PacketArrayCount; i++ ) {
|
||
|
// NDIS_STATUS ReturnStatus;
|
||
|
//
|
||
|
// ReturnStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
|
||
|
//
|
||
|
// recover the RPD
|
||
|
// rpd = *(PRPD *)(PacketArray[i]->MiniportReserved);
|
||
|
//
|
||
|
// if (ReturnStatus != NDIS_STATUS_PENDING) {
|
||
|
// ProcReturnedRpd(Adapter, rpd);
|
||
|
// }
|
||
|
// }
|
||
|
// 4.0.1 BOC
|
||
|
for (i=PacketArrayCount-PacketFreeCount; i<PacketArrayCount; i++){
|
||
|
rpd = *(PRPD *)(PacketArray[i]->MiniportReserved);
|
||
|
ProcReturnedRpd(Adapter, rpd);
|
||
|
Adapter->UsedRpdCount--;
|
||
|
}
|
||
|
// 4.0.1 EOC.
|
||
|
|
||
|
} while (!done);
|
||
|
|
||
|
Adapter->nowReceiving = FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Procedure: [ProcessTXComp]
|
||
|
//
|
||
|
// Description: TX complete processing in DPC. This is very similar to
|
||
|
// ProcessTXCompIsr(), the main difference being we also process the TX
|
||
|
// queue here and perform TXs as necessary.
|
||
|
//
|
||
|
// Arguements: Adapter.
|
||
|
//
|
||
|
// Result: (none)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID ProcessTXComp(PMK7_ADAPTER Adapter)
|
||
|
{
|
||
|
PTCB tcb;
|
||
|
MK7REG mk7reg;
|
||
|
NDIS_STATUS SendStatus;
|
||
|
PNDIS_PACKET QueuePacket;
|
||
|
|
||
|
|
||
|
// Process only if we get the corresponding int.
|
||
|
if (!(Adapter->recentInt & B_TX_INTS)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
DBGLOG("=> TX comp", 0);
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
GDbgStat.txIsrCnt++;
|
||
|
#endif
|
||
|
|
||
|
// Debug
|
||
|
if (Adapter->CurrentSpeed > MAX_SIR_SPEED) {
|
||
|
DBGLOG(" TX comp (fast)", 0);
|
||
|
}
|
||
|
else {
|
||
|
DBGLOG(" TX comp (slow)", 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Simplified change speed
|
||
|
if (Adapter->changeSpeedPending == CHANGESPEED_ON_DONE) {
|
||
|
// Note: We're changing speed in TX mode.
|
||
|
MK7ChangeSpeedNow(Adapter);
|
||
|
Adapter->changeSpeedPending = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
while (Adapter->tcbUsed > 0) {
|
||
|
tcb = Adapter->pTcbArray[Adapter->nextReturnTcbIdx];
|
||
|
|
||
|
if ( !HwOwnsTrd(tcb->trd) ) {
|
||
|
#if DBG
|
||
|
if (TrdAnyError(tcb->trd)) {
|
||
|
GDbgStat.txErrCnt++;
|
||
|
GDbgStat.txErr |= tcb->trd->status;
|
||
|
DBGSTATUS1(" TX err: %x \n\r", tcb->trd->status);
|
||
|
}
|
||
|
if (Adapter->recentInt & B_TX_INTS)
|
||
|
GDbgStat.txComp++;
|
||
|
else
|
||
|
GDbgStat.txCompNoInt++;
|
||
|
#endif
|
||
|
tcb->trd->count = 0;
|
||
|
|
||
|
|
||
|
// For each completing TX there's a corresponding q'd pkt.
|
||
|
// We release it here.
|
||
|
QueuePacket = Adapter->FirstTxQueue;
|
||
|
DequeuePacket(Adapter->FirstTxQueue, Adapter->LastTxQueue);
|
||
|
Adapter->NumPacketsQueued--;
|
||
|
NDIS_SET_PACKET_STATUS(QueuePacket, NDIS_STATUS_SUCCESS);
|
||
|
NdisMSendComplete( Adapter->MK7AdapterHandle,
|
||
|
QueuePacket,
|
||
|
NDIS_STATUS_SUCCESS);
|
||
|
Adapter->HangCheck = 0; // 1.0.0
|
||
|
Adapter->nextReturnTcbIdx++;
|
||
|
Adapter->nextReturnTcbIdx %= Adapter->NumTcb;
|
||
|
Adapter->tcbUsed--;
|
||
|
}
|
||
|
else {
|
||
|
DBGLOG(" Not our TCB; but tcbUsed>0", 0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// No resource even if we have more to send. Return now & let subsequent
|
||
|
// TX completes keep the ball rolling.
|
||
|
if (Adapter->tcbUsed >= Adapter->NumTcb) {
|
||
|
// NdisReleaseSpinLock(&Adapter->Lock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// If no TXs queued and all TXs are done, then switch to RX mode.
|
||
|
if ( (!Adapter->FirstTxQueue) && (Adapter->tcbUsed == 0) ) {
|
||
|
MK7SwitchToRXMode(Adapter);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Send the q'd pkts until all done or until all TX ring buffers are used up.
|
||
|
//while(Adapter->FirstTxQueue) {
|
||
|
if (Adapter->FirstTxQueue) {
|
||
|
|
||
|
#if DBG
|
||
|
GDbgStat.txProcQ++;
|
||
|
#endif
|
||
|
|
||
|
DBGLOG(" Proc Q", 0);
|
||
|
|
||
|
QueuePacket = Adapter->FirstTxQueue;
|
||
|
SendStatus = SendPkt(Adapter, QueuePacket);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Procedure: [ProcessRXCompIsr]
|
||
|
//
|
||
|
// Description: Some RX complete processing in ISR.
|
||
|
//
|
||
|
// Arguements: Adapter.
|
||
|
//
|
||
|
// Result: (none)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID ProcessRXCompIsr(PMK7_ADAPTER Adapter)
|
||
|
{
|
||
|
|
||
|
// 4.1.0 Back for HW_VER_1 support
|
||
|
if (Adapter->recentInt & B_RX_INTS) {
|
||
|
Adapter->nowReceiving=TRUE;
|
||
|
// if (!Adapter->mediaBusy) {
|
||
|
// mediaBusy: IrLAP clears mediaBusy (via OID) to indicate
|
||
|
// it wants to be notified when media becomes busy. Here
|
||
|
// we detect it is cleared. We then set it and clear
|
||
|
// haveIndicatedMediaBusy so we do notify later in DPC.
|
||
|
// Adapter->mediaBusy = TRUE;
|
||
|
// Adapter->haveIndicatedMediaBusy = FALSE;
|
||
|
// Adapter->nowReceiving = TRUE;
|
||
|
// }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Procedure: [ProcessTXCompIsr]
|
||
|
//
|
||
|
// Description: TX complete processing in ISR. This is very similar to
|
||
|
// ProcessTXComp() except we don't start any TX's here.
|
||
|
//
|
||
|
// Arguements: Adapter.
|
||
|
//
|
||
|
// Result: (none)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID ProcessTXCompIsr(PMK7_ADAPTER Adapter)
|
||
|
{
|
||
|
PTCB tcb;
|
||
|
MK7REG mk7reg;
|
||
|
|
||
|
//******************************
|
||
|
// Whether or not there was a TX-completion interrupt, we do some
|
||
|
// processing here in case ever the driver or hw missed an
|
||
|
// interrupt previously.
|
||
|
//
|
||
|
// We loop until all tcb's are returned (tcbUsed == 0) or we run into
|
||
|
// a TX ring buff that the hw still owns (HwOwnsTrd()). When we leave
|
||
|
// here, we should have processed all current TX completions based on
|
||
|
// the TX ownership bit. We switch to RX mode ONLY after all TX are
|
||
|
// completed (either here in the ISR or in DPC).
|
||
|
//******************************
|
||
|
|
||
|
|
||
|
while (Adapter->tcbUsed > 0) {
|
||
|
tcb = Adapter->pTcbArray[Adapter->nextReturnTcbIdx];
|
||
|
|
||
|
if ( !HwOwnsTrd(tcb->trd) ) {
|
||
|
#if DBG
|
||
|
if (TrdAnyError(tcb->trd)) {
|
||
|
GDbgStat.txErrCnt++;
|
||
|
GDbgStat.txErr |= tcb->trd->status;
|
||
|
DBGSTATUS1(" TX err: %x \n\r", tcb->trd->status);
|
||
|
}
|
||
|
if (Adapter->recentInt & B_TX_INTS)
|
||
|
GDbgStat.txComp++;
|
||
|
else
|
||
|
GDbgStat.txCompNoInt++;
|
||
|
#endif
|
||
|
tcb->trd->count = 0;
|
||
|
Adapter->nextReturnTcbIdx++;
|
||
|
Adapter->nextReturnTcbIdx %= Adapter->NumTcb;
|
||
|
Adapter->tcbUsed--;
|
||
|
}
|
||
|
else {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|