📄 isr.c
字号:
//---------------------------------------------------------------------------
//
// Copyright (C) 1996-1997. Unpublished Work of Crystal Semiconductor Corp.
// All Rights Reserved.
//
// THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
// PROPRIETARY AND TRADE SECRET INFORMATION OF CRYSTAL SEMICONDUCTOR.
// ACCESS TO THIS WORK IS RESTRICTED TO (I) CRYSTAL SEMICONDUCTOR EMPLOYEES
// WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR
// ASSIGNMENTS AND (II) ENTITIES OTHER THAN CRYSTAL SEMICONDUCTOR WHO
// HAVE ENTERED INTO APPROPRIATE LICENSE AGREEMENTS. NO PART OF THIS
// WORK MAY BE USED, PRACTICED, PERFORMED, COPIED, DISTRIBUTED, REVISED,
// MODIFIED, TRANSLATED, ABRIDGED, CONDENSED, EXPANDED, COLLECTED,
// COMPILED,LINKED,RECAST, TRANSFORMED, ADAPTED IN ANY FORM OR BY ANY
// MEANS,MANUAL, MECHANICAL, CHEMICAL, ELECTRICAL, ELECTRONIC, OPTICAL,
// BIOLOGICAL, OR OTHERWISE WITHOUT THE PRIOR WRITTEN PERMISSION AND
// CONSENT OF CRYSTAL SEMICONDUCTOR . ANY USE OR EXPLOITATION OF THIS WORK
// WITHOUT THE PRIOR WRITTEN CONSENT OF CRYSTAL SEMICONDUCTOR COULD
// SUBJECT THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
//
//---------------------------------------------------------------------------
#include "cs8900a.h"
#include "cshrd.h"
// External Prototypes
void CopyPacketToChip( IN PCHIP );
WORD BidForTransmit( IN PCHIP );
void PurgeTransmitQueue( IN PCHIP );
void ReceivePacket( IN PCHIP, IN WORD );
void ReceiveEarlyPacket( IN PCHIP, IN WORD );
// Local Prototypes
void ProcessReceiveInterrupts(IN PCHIP, IN WORD );
void ProcessTransmitInterrupts(IN PCHIP, IN WORD );
void ProcessBufferInterrupts(IN PCHIP, IN WORD );
void ProcessRxOverflowInterrupts(IN PCHIP, IN WORD );
void ProcessTxOverflowInterrupts(IN PCHIP, IN WORD );
typedef void (*VC20_ISQHANDLER)(IN PCHIP, IN WORD );
#define MAX_ISQ_EVENTS 5
PVPMINIPDATA gMini_Context = NULL;
CRITICAL_SECTION m_csCS8900ISR;
BOOL bHasInterrupt = FALSE;
VC20_ISQHANDLER IsqEventHandler[MAX_ISQ_EVENTS] = {
ProcessReceiveInterrupts,
ProcessTransmitInterrupts,
ProcessBufferInterrupts,
ProcessRxOverflowInterrupts,
ProcessTxOverflowInterrupts,
};
VOID CrystalDisableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
{
PRINTRETAILMSG(1, (TEXT("==>CS8900:CrystalDisableInterrupt\r\n")));
VchipDisableInterrupts( ((PVPMINIPDATA)MiniportAdapterContext)->pChip );
PRINTRETAILMSG(1, (TEXT("<==CS8900:CrystalDisableInterrupt\r\n")));
return;
}
/*++
Routine Description:
This routine is used to turn on all interrupts from the adapter.
Arguments:
MiniportAdapterContext - A pointer to the VP context
Return Value:
None.
--*/
VOID CrystalEnableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
{
VPM_SetupMiniContext;
PRINTRETAILMSG(1, (TEXT("==>CS8900:CrystalEnableInterrupt\r\n")));
VchipEnableInterrupts( ((PVPMINIPDATA)MiniportAdapterContext)->pChip );
PRINTRETAILMSG(1, (TEXT("<==CS8900:CrystalEnableInterrupt\r\n")));
return;
}
/*++
Routine Description:
Interrupt service routine. This routine only gets
called during initial initialization of the adapter.
Arguments:
InterruptRecognized - Boolean value which returns TRUE if the
ISR recognizes the interrupt as coming from this adapter.
QueueDpc - TRUE if a DPC should be queued.
Context - Really a pointer to the adapter.
Return Value:
Returns true if the card ISR is non-zero.
--*/
extern VOID CrystalInterruptService(OUT PBOOLEAN InterruptRecognized,
OUT PBOOLEAN QueueDpc,
IN PVOID Context)
{
NDIS_HANDLE MiniportAdapterContext = Context;
VPM_SetupMiniContext;
PRINTRETAILMSG(1, (TEXT("==>CS8900:CrystalInterruptService\r\n")));
*InterruptRecognized = TRUE;
*QueueDpc = TRUE;
PRINTRETAILMSG(1, (TEXT("<==CS8900:CrystalInterruptService\r\n")));
return;
}
/*++
Routine Description:
This DPR routine is queued by the wrapper after every interrupt
and also by other routines within the driver that notice that
some deferred processing needs to be done. It's main
job is to call the interrupt processing code.
Arguments:
MiniportAdapterContext - Really a pointer to the adapter.
Return Value:
None.
--*/
VOID CrystalHandleInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
{
VPM_SetupMiniContext;
PRINTRETAILMSG(1, (TEXT("==>Cs8900: HandleInterrupt \r\n")));
if (pvMini_Context->CurrentState == NdisHardwareStatusInitializing)
return;
VchipDisableInterrupts (pvMini_Context->pChip );
/// EnterCriticalSection(&m_csCS8900ISR);
/// bHasInterrupt = TRUE;
while (VchipISR( pvMini_Context->pChip ));
/// LeaveCriticalSection(&m_csCS8900ISR);
VchipEnableInterrupts (pvMini_Context->pChip );
PRINTRETAILMSG(1, (TEXT("<==Cs8900: HandleInterrupt \r\n")));
return;
}
WORD VchipISR( PCHIP pChip )
{
WORD IsqEvent;
WORD EventIndex;
PCD pData = pChip->pData;
WORD BidStatus;
WORD Status=FALSE;
WORD regNum;
PRINTRETAILMSG(1, (TEXT("==>Cs8900: VchipISR \r\n")));
pData->NeedToIssueRcvCmpltFlag = FALSE;
/* Ignore spurrious interrupt that occurs while resetting */
if ( pData->Resetting ) return Status;
do // While ISQ != 0
{
// Read ISQ
IsqEvent = v_pCS8900Regs->ISQ;
if (IsqEvent != 0)
{
Status=TRUE;
regNum = IsqEvent & CRYSTAL_ISQ_EVENT_MASK;
if (regNum == 0x12) //TxCol event
{
// @melody 11/05/2002
// The register number of Tx Collision Counter is not multiple of 4
// so we should calculate it separately.
EventIndex = 5;
}
else
{
EventIndex = regNum/4;
}
if (--EventIndex < MAX_ISQ_EVENTS)
{
IsqEventHandler[EventIndex](pChip, IsqEvent);
} /* endif */
} /* endif */
} while ( IsqEvent != 0 ); /* enddo */
if (pData->NeedToIssueRcvCmpltFlag == TRUE)
{
PVPMINIPDATA pvMini_Context = (PVPMINIPDATA)(pChip->pPSD);
NDIS_HANDLE MiniportAdapterHandle = pvMini_Context->vpMiniportAdapterHandle;
NdisMEthIndicateReceiveComplete( MiniportAdapterHandle );
} /* endif */
// Transmits are handled outside of ISQ Loop to prioritize Receive
if ((pData->StartTX) && (pData->TransmitQueue.Head != NULL))
{
pData->StartTX = FALSE;
if (!pData->TransmitBidPending)
BidStatus = BidForTransmit(pChip);
if ((pData->TransmitBidPending) || // StartTX & TransmitBidPending means ReadyForTX received
(BidStatus == SUCCESS))
{
pData->TransmitBidPending = FALSE;
CopyPacketToChip(pChip);
}
}
else
{
pData->StartTX = FALSE;
} /* endif */
PRINTRETAILMSG(1, (TEXT("<==Cs8900: VchipISR \r\n")));
return Status;
}
void ProcessReceiveInterrupts( PCHIP pChip, WORD IsqEvent )
{
PCD pData = pChip->pData;
WORD Errors = 0;
PRINTRETAILMSG(1, (TEXT("==>CS8900: ProcessReceiveInterrupts \r\n")));
if ( IsqEvent & CRYSTAL_RER_PACKET_RECEIVED_OK)
ReceivePacket( pChip, IsqEvent );
else
{
//
// A receive error occurred
//
if (IsqEvent & CRYSTAL_RER_CRC_ERROR)
{
Errors |= RX_ERR_CRC_ERROR;
if(IsqEvent & CRYSTAL_RER_DRIBBLE)
Errors |= RX_ERR_DRIBBLE;
}
if (IsqEvent & CRYSTAL_RER_EXTRA_DATA)
Errors |= RX_ERR_EXTRA_DATA;
if (IsqEvent & CRYSTAL_RER_RUNT)
Errors |= RX_ERR_RUNT;
VpsRecvError( pChip, Errors );
}
PRINTRETAILMSG(1, (TEXT("<==CS8900: ProcessReceiveInterrupts \r\n")));
};
void ProcessTransmitInterrupts( PCHIP pChip, WORD IsqEvent )
{
PCD pData = pChip->pData;
WORD Errors = 0;
WORD Collisions = 0;
PTRANSMIT_QUEUE_ELEMENT TxPacket;
PNDIS_PACKET Packet;
PVPMINIPDATA pvMini_Context = (PVPMINIPDATA)(pChip->pPSD);
NDIS_HANDLE MiniportAdapterHandle = pvMini_Context->vpMiniportAdapterHandle;
PRINTRETAILMSG(1, (TEXT("==>CS8900: ProcessTransmitInterrupts \r\n")));
//
// We first in any transmit event must decrement the counter of the
// underrun Threshold
//
if ( pData->TransmitThresholdCount != 0)
(pData->TransmitThresholdCount)--;
//
// Check if the packet completed OK, and update statistics.
//
if (IsqEvent & CRYSTAL_TER_EXCESSIVE_COLLISIONS)
Errors |= TX_ERR_EXCESS_COLL;
Collisions = (INT)(IsqEvent & CRYSTAL_TER_COLLISIONS_MASK) >> CRYSTAL_TER_COLLISIONS_SHIFT;
if (IsqEvent & CRYSTAL_TER_JABBER)
Errors |= TX_ERR_JABBER;
if (IsqEvent & CRYSTAL_TER_OUT_OF_WINDOW)
Errors |= TX_ERR_OUT_OF_WIN;
// Dequeue the Packet
DEQ_PACKET(&TxPacket, pData->TransmitQueue);
if (TxPacket != NULL)
{
Packet = CONTAINING_RECORD(TxPacket,NDIS_PACKET,MiniportReserved);
if (IsqEvent & CRYSTAL_TER_LOST_CRS)
Errors |= TX_ERR_LOSS_CRS;
if (IsqEvent & CRYSTAL_TER_SQE_ERROR)
Errors |= TX_ERR_SQE_ERROR;
if (Errors)
VpsSendError( pChip,Errors );
if (Collisions == 1)
pvMini_Context->XmitOneCollisions++;
else if (Collisions > 1)
pvMini_Context->XmitMoreCollisions++;
pvMini_Context->XmitOKs++;
NdisMSendComplete(MiniportAdapterHandle,
Packet,
NDIS_STATUS_SUCCESS);
} /* endif */
//
// If there is a packet in the transmit queue then try
// transmitting it at the end of the ISR
//
if (pData->TransmitQueue.Head != NULL )
pData->StartTX = TRUE;
else
pData->TransmitInProgress = FALSE;
PRINTRETAILMSG(1, (TEXT("<==CS8900: ProcessTransmitInterrupts \r\n")));
};
void ProcessBufferInterrupts( PCHIP pChip, WORD IsqEvent )
{
PCD pData = pChip->pData;
PRINTRETAILMSG(1, (TEXT("==>CS8900: ProcessBufferInterrupts \r\n")));
//
// Then check for READY_FOR_TRANSMIT
//
if (IsqEvent & CRYSTAL_BER_READY_FOR_TRANSMIT)
{
if (pData->TransmitQueue.Head != NULL)
{
pData->TransmitBidPending = FALSE;
pData->StartTX = FALSE;
CopyPacketToChip( pChip );
}
}
//
// If TX_UNDERRUN occured then update counters.
//
if (IsqEvent & CRYSTAL_BER_TX_UNDERRUN)
{
if (pData->TransmitQueue.Head != NULL)
{ // Resend current Frame
VpsSendError( pChip,TX_ERR_UNDERRUN );
pData->StartTX = TRUE;
}
//
// We have a underrun so we see if we have exceeded the threshold
// if so go to next transmit command
//
(pData->TransmitThresholdCount)++;
if( pData->TransmitThresholdCount == UNDERRUN_THRESHOLD)
{
(pData->TransmitThresholdCount)= 0;
if (pData->TransmitCommand < CRYSTAL_TCR_TX_START_ALL_BYTES)
pData->TransmitCommand += CRYSTAL_TCR_TX_START_381_BYTES;
}
}
PRINTRETAILMSG(1, (TEXT("<==CS8900: ProcessBufferInterrupts \r\n")));
};
void ProcessRxOverflowInterrupts( PCHIP pChip, WORD IsqEvent )
{
PCD pData = pChip->pData;
PRINTRETAILMSG(1, (TEXT("==>CS8900: ProcessRxOverflowInterrupts \r\n")));
IsqEvent = IsqEvent >> 6;
do
{
VpsRecvError( pChip, RX_ERR_OVERRUN );
} while (--IsqEvent !=0);
PRINTRETAILMSG(1, (TEXT("<==CS8900: ProcessRxOverflowInterrupts \r\n")));
}
void ProcessTxOverflowInterrupts( PCHIP pChip, WORD IsqEvent )
{
PCD pData = pChip->pData;
PRINTRETAILMSG(1, (TEXT("==>CS8900: ProcessTxOverflowInterrupts \r\n")));
if (pData->TransmitQueue.Head != NULL) // Resend current Frame
VpsSendError( pChip, TX_ERR_FRAME_ABORT ); // May need better RC here
PRINTRETAILMSG(1, (TEXT("<==CS8900: ProcessTxOverflowInterrupts \r\n")));
}
void VchipEnableInterrupts( PCHIP pChip )
{
WORD Data;
PRINTRETAILMSG(1, (TEXT("==>CS8900:VchipEnableInterrupts\r\n")));
if ( ((PCD)(pChip->pData))->Resetting )
{
PRINTRETAILMSG(1, (TEXT("<==CS8900:VchipEnableInterrupts FAILED\r\n")));
return;
}
//
// Enable BUS_CTL register Interrupt Enable.
//
Data = ReadPacketPage(CRYSTAL_BUS_CONTROL_REGISTER);
WritePacketPage(CRYSTAL_BUS_CONTROL_REGISTER, Data | CRYSTAL_BCR_INTERRUPT_ENABLE);
PRINTRETAILMSG(1, (TEXT("<==CS8900:VchipEnableInterrupts SUCCESS\r\n")));
}
void VchipDisableInterrupts( PCHIP pChip )
{
WORD Data;
PRINTRETAILMSG(1, (TEXT("==>CS8900:VchipDisableInterrupts\r\n")));
if ( ((PCD)(pChip->pData))->Resetting )
{
PRINTRETAILMSG(1, (TEXT("<==CS8900:VchipDisableInterrupts FAILED\r\n")));
return;
}
//
// Disable BUS_CTL register Interrupt Enable.
//
Data = ReadPacketPage(CRYSTAL_BUS_CONTROL_REGISTER);
WritePacketPage(CRYSTAL_BUS_CONTROL_REGISTER, Data & (~CRYSTAL_BCR_INTERRUPT_ENABLE));
PRINTRETAILMSG(1, (TEXT("<==CS8900:VchipDisableInterrupts SUCCESS\r\n")));
}
void CS8900DetectThread(void)
{
PVPMINIPDATA pvMini_Context = gMini_Context;
NDIS_HANDLE MiniportAdapterHandle = pvMini_Context->vpMiniportAdapterHandle;
PCHIP pChip = pvMini_Context->pChip;
InitializeCriticalSection(&m_csCS8900ISR) ;
CrystalEnableInterrupt(pvMini_Context);
while(1)
{
Sleep(30);
if(!bHasInterrupt)
{
EnterCriticalSection(&m_csCS8900ISR);
while (VchipISR( pvMini_Context->pChip ));
LeaveCriticalSection(&m_csCS8900ISR);
}
bHasInterrupt = FALSE;
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -