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

📄 isr.c

📁 CS8900 for windows ce 4.2 驱动程序源码
💻 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 + -