⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isr.c

📁 PXA255/270平台的 CS8900网卡驱动程序
💻 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 + -