?? 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
VC20_ISQHANDLER IsqEventHandler[MAX_ISQ_EVENTS] = {
ProcessReceiveInterrupts,
ProcessTransmitInterrupts,
ProcessBufferInterrupts,
ProcessRxOverflowInterrupts,
ProcessTxOverflowInterrupts,
};
VOID
CrystalDisableInterrupt(
IN NDIS_HANDLE MiniportAdapterContext
)
{
//QQQQQQQQQQQ Why mark out? VchipDisableInterrupts( ((PVPMINIPDATA)MiniportAdapterContext)->pChip );
VchipDisableInterrupts( ((PVPMINIPDATA)MiniportAdapterContext)->pChip );
// DbgPrint("\nCs8900a(): DisableInterrupt() \n");
return;
}
VOID
CrystalEnableInterrupt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
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.
--*/
{
VPM_SetupMiniContext;
VchipEnableInterrupts( ((PVPMINIPDATA)MiniportAdapterContext)->pChip );
// DbgPrint("\nCs8900a(): EnableInterrupt\n");
return;
}
extern
VOID
CrystalInterruptService(
OUT PBOOLEAN InterruptRecognized,
OUT PBOOLEAN QueueDpc,
IN PVOID Context
)
/*++
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.
--*/
{
NDIS_HANDLE MiniportAdapterContext = Context;
VPM_SetupMiniContext;
// DbgPrint("\nCs8900a(): InterruptService()\n");
*InterruptRecognized = TRUE;
*QueueDpc = TRUE;
return;
}
VOID
CrystalHandleInterrupt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
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.
--*/
{
WORD Result=TRUE;
VPM_SetupMiniContext;
// DbgPrint("\nCs8900a(): HandleInterrupt 1\n");
if (pvMini_Context->CurrentState == NdisHardwareStatusInitializing) {
return;
} /* endif */
while (Result) { // Loop until ISR indicates there was nothing to do
Result = VchipISR( pvMini_Context->pChip );
} /* endwhile */
VchipEnableInterrupts (pvMini_Context->pChip );
// DbgPrint("\nCs8900a(): HandleInterrupt 2\n");
return;
}
WORD VchipISR( PCHIP pChip )
{
WORD IsqEvent;
WORD EventIndex;
PORT IOBase = pChip->Config.IOBase;
PCD pData = pChip->pData;
WORD BidStatus;
WORD Status=FALSE;
WORD regNum;
pData->NeedToIssueRcvCmpltFlag = FALSE;
/* Ignore spurrious interrupt that occurs while resetting */
if ( pData->Resetting ) return Status;
do { // While ISQ != 0
// Read ISQ
NdisRawReadPortUshort((PORT)(IOBase+CRYSTAL_ISQ_PORT), &IsqEvent );
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);
} /* endif */
if ((pData->TransmitBidPending) || // StartTX & TransmitBidPending means ReadyForTX received
(BidStatus == SUCCESS)) {
pData->TransmitBidPending = FALSE;
CopyPacketToChip(pChip);
}
} else {
pData->StartTX = FALSE;
} /* endif */
return Status;
}
void ProcessReceiveInterrupts( PCHIP pChip, WORD IsqEvent )
{
PORT IOBase = pChip->Config.IOBase;
PCD pData = pChip->pData;
WORD Errors = 0;
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 );
}
};
void ProcessTransmitInterrupts( PCHIP pChip, WORD IsqEvent )
{
PORT IOBase = pChip->Config.IOBase;
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;
//
// 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 );
} /* endif */
if (Collisions == 1) {
pvMini_Context->XmitOneCollisions++;
} else if (Collisions > 1) {
pvMini_Context->XmitMoreCollisions++;
} /* endif */
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;
}
};
void ProcessBufferInterrupts( PCHIP pChip, WORD IsqEvent )
{
PORT IOBase = pChip->Config.IOBase;
PCD pData = pChip->pData;
//
// 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;
}
}
}
};
void ProcessRxOverflowInterrupts( PCHIP pChip, WORD IsqEvent )
{
PCD pData = pChip->pData;
IsqEvent = IsqEvent >> 6;
do {
VpsRecvError( pChip, RX_ERR_OVERRUN );
} while (--IsqEvent !=0);
};
void ProcessTxOverflowInterrupts( PCHIP pChip, WORD IsqEvent )
{
PCD pData = pChip->pData;
if (pData->TransmitQueue.Head != NULL) { // Resend current Frame
VpsSendError( pChip, TX_ERR_FRAME_ABORT ); // May need better RC here
}
};
void VchipEnableInterrupts( PCHIP pChip )
{
WORD Data;
PORT IOBase = pChip->Config.IOBase;
if ( ((PCD)(pChip->pData))->Resetting ) return;
//
// Enable BUS_CTL register Interrupt Enable.
//
NdisRawWritePortUshort((PORT)(IOBase+CRYSTAL_ADDRESS_PORT),
CRYSTAL_BUS_CONTROL_REGISTER);
NdisRawReadPortUshort((PORT)(IOBase+CRYSTAL_DATA_PORT), &Data);
NdisRawWritePortUshort((PORT)(IOBase+CRYSTAL_DATA_PORT),
Data | CRYSTAL_BCR_INTERRUPT_ENABLE);
};
void VchipDisableInterrupts( PCHIP pChip )
{
WORD Data;
PORT IOBase = pChip->Config.IOBase;
if ( ((PCD)(pChip->pData))->Resetting ) return;
//
// Disable BUS_CTL register Interrupt Enable.
//
NdisRawWritePortUshort((PORT)(IOBase+CRYSTAL_ADDRESS_PORT),
CRYSTAL_BUS_CONTROL_REGISTER);
NdisRawReadPortUshort((PORT)(IOBase+CRYSTAL_DATA_PORT), &Data);
NdisRawWritePortUshort((PORT)(IOBase+CRYSTAL_DATA_PORT),
Data &(~CRYSTAL_BCR_INTERRUPT_ENABLE) );
};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -