?? lan91c111_intr.c
字號:
/*
*
* Copyright (c) Standard MicroSystems Corporation. All Rights Reserved.
*
* LAN91C111 Driver for Windows CE .NET
*
* Revision History
*_______________________________________________________________________________
* Author Date Version Description
*_______________________________________________________________________________
* Pramod Bhardwaj 6/18/2002 0.1 Beta Release
* Pramod Bhardwaj 1/22/2003 1.1 Removed some platform dependencies
* Pramod Bhardwaj 4/15/2003 2.0 Added support for alloc interrupt
*_______________________________________________________________________________
*
* Description:
* Interrupt Service routines and other required functions for
* processing the interrupts.
*
*
*/
#include <Ndis.h>
#include <PKFuncs.h>
#include "LAN91C111_Adapter.h"
#include "LAN91C111_Proto.h"
#define SMSC_32BIT_RW 1
/*
Function Name : LAN91C111_MiniportISR
Description :
This routine is invoked when an interrupt occurs. If
the interrupting device is identified as ours, then the DPC
is scheduled to complete the processing.
Parameters :
OUT PBOOLEAN InterruptRecognized Is it ours?
OUT PBOOLEAN QueueMiniportHandleInterrupt Run the DPC?
IN NDIS_HANDLE AdapterContext The Adapter structure.
Return Value :
VOID
*/
VOID LAN91C111_MiniportISR (
PBOOLEAN InterruptRecognized,
PBOOLEAN QueueMiniportHandleInterrupt,
NDIS_HANDLE MiniportAdapterContext
)
{
USHORT SavedBS;
ULONG IOBase;
MINIPORT_ADAPTER *Adapter = (MINIPORT_ADAPTER *) MiniportAdapterContext;
IOBase = Adapter->IOBase;
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111:<==> Miniport ISR\r\n")));
NdisRawReadPortUshort(Adapter->IOBase + BANK_SELECT, &SavedBS);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 2);
NdisRawWritePortUshort(Adapter->IOBase + BANK2_INT_STS,0);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, SavedBS);
*InterruptRecognized =
*QueueMiniportHandleInterrupt = TRUE;
return;
}
/*
Function Name : LAN91C111_MiniPortHandleInterrupt
Description :
This routine performs deferred processing for adapter
interrupts. All pending interrupt conditions are
handled before exit.
Parameters :
NDIS_HANDLE AdapterContext - Handle to the adapter structure
Return Value :
VOID
*/
VOID LAN91C111_MiniPortHandleInterrupt (IN NDIS_HANDLE AdapterContext)
{
MINIPORT_ADAPTER *Adapter = (MINIPORT_ADAPTER *) AdapterContext;
USHORT SavedBSel,
SavedPNR,
SavedPTR,
temp;
ULONG IOBase,
IntrPort;
UCHAR IntrSts;
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111:==> Miniport Handler\r\n")));
IOBase = Adapter->IOBase;
IntrPort = IOBase + BANK2_INT_STS;
//Save the Bank Select..
NdisRawReadPortUshort(IOBase + BANK_SELECT, &SavedBSel);
NdisRawWritePortUshort(IOBase + BANK_SELECT, (USHORT) 2);
NdisRawReadPortUshort(IOBase + BANK2_PNR, &SavedPNR);
NdisRawReadPortUshort(IOBase + BANK2_PTR, &SavedPTR);
while(1)
{
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 2);
NdisRawReadPortUshort (IntrPort, &temp);
IntrSts = LOBYTE(temp);
if (Adapter->AllocIntPending)
IntrSts &= (ENABLED_INTS | INT_ALLOC);
else
IntrSts &= ENABLED_INTS;
if(!IntrSts) break;
if (IntrSts & INT_RX_CMP)
RCV_Interrupt_Handler(Adapter);
if (IntrSts & INT_TX_CMP)
TX_Interrupt_Handler(Adapter);
if (IntrSts & INT_RX_OVRN)
RX_OVRN_Interrupt_Handler(Adapter);
if (IntrSts & INT_EPH_INT)
EPH_Interrupt_Handler(Adapter);
if (IntrSts & INT_ALLOC)
ALLOC_Interrupt_Handler(Adapter);
if (IntrSts & INT_MDINT)
MD_Interrupt_Handler(Adapter);
}
//Restore the registers
NdisRawWritePortUshort(IOBase + BANK_SELECT, 2);
NdisRawWritePortUshort(IOBase + BANK2_PNR, SavedPNR);
NdisRawWritePortUshort(IOBase + BANK2_PTR, SavedPTR);
NdisRawWritePortUshort(IOBase + BANK_SELECT, SavedBSel);
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111:<== Miniport Handler\r\n")));
return;
}
VOID LAN91C111_MiniportEnableInterrupt (NDIS_HANDLE MiniportAdapterContext)
{
USHORT SavedBS;
MINIPORT_ADAPTER *Adapter = (MINIPORT_ADAPTER *) MiniportAdapterContext;
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: ==> MiniPort ENABLE Interrupt\r\n")));
NdisRawReadPortUshort(Adapter->IOBase + BANK_SELECT, &SavedBS);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 2);
NdisRawWritePortUshort(Adapter->IOBase + BANK2_INT_STS,(ENABLED_INTS << 8));
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, SavedBS);
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: <== MiniPort ENABLE Interrupt\r\n")));
return;
}
VOID LAN91C111_MiniportDisableInterrupt (NDIS_HANDLE MiniportAdapterContext)
{
USHORT SavedBS;
MINIPORT_ADAPTER *Adapter = (MINIPORT_ADAPTER *) MiniportAdapterContext;
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: ==> MiniPort DISABLE Interrupt\r\n")));
NdisRawReadPortUshort(Adapter->IOBase + BANK_SELECT, &SavedBS);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 2);
NdisRawWritePortUshort(Adapter->IOBase + BANK2_INT_STS,0);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, SavedBS);
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: <== MiniPort DISABLE Interrupt\r\n")));
return;
}
VOID MD_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: ==> MDINT Interrupt Handler\r\n")));
//Acknowledge the interrupt
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,2);
NdisRawWritePortUshort(Adapter->IOBase + BANK2_INT_STS,INT_MDINT);
//Acknowledge the PHY interrupt
ReadPhyRegister(Adapter->IOBase, 18);
//Indicate to the change to the higher layer.
if (Adapter->LinkStatus == MEDIA_CONNECTED)
{
NdisMIndicateStatus(Adapter->AdapterHandle,NDIS_STATUS_MEDIA_DISCONNECT,NULL,0);
Adapter->LinkStatus = MEDIA_DISCONNECTED;
}
else
{
//Re-Negotiate the Link..
EstablishLink(Adapter);
//Setup Transmit Control Register
Adapter->TCR = (USHORT)(TCR_TX_ENA | TCR_PAD_EN | TCR_MON_CSN);
if (Adapter->Duplex == FULL_DUPLEX)
Adapter->TCR |= TCR_SWFDUP;
else
Adapter->TCR &= (~TCR_SWFDUP);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, (USHORT) 0);
NdisRawWritePortUshort(Adapter->IOBase + BANK0_TCR, Adapter->TCR);
NdisMIndicateStatus(Adapter->AdapterHandle,NDIS_STATUS_MEDIA_CONNECT,NULL,0);
Adapter->LinkStatus = MEDIA_CONNECTED;
}
NdisMIndicateStatusComplete(Adapter->AdapterHandle);
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111<== MDINT Interrupt\r\n")));
return;
}
VOID EPH_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
USHORT EPHStatus;
USHORT temp, TempWord, PacketNumber;
ULONG IOBase;
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: ==> EPH Interrupt Handler\r\n")));
IOBase = Adapter->IOBase;
//Read the EPH Status register
NdisRawWritePortUshort(IOBase + BANK_SELECT, (USHORT) 0);
NdisRawReadPortUshort(IOBase + BANK0_STS, &EPHStatus);
//Check for errors
if (EPHStatus & TFS_LINKERROR)
{
//Acked by clearing the LE_ENABLE bit in the Control Register
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111: LINK_OK\r\n")));
}
if (EPHStatus & TFS_COUNTER)
{
//This is cleared by reading the ECR
NdisRawReadPortUshort(IOBase + BANK0_CTR, &temp);
}
//Check if ths TXEnable bit has been cleared.
//If cleared, indicates a critical TX error, so we will have to clear
//the buffer space. Currently the buffer is free up. If required the
//packet can be requeued.
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)0);
NdisRawReadPortUshort(IOBase + BANK0_TCR, &TempWord);
if (!(TempWord & TCR_TX_ENA))
{
//Error encountered in TX Clear the packet and set the TXENA
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)2);
//Read TXDONE Pkt# from FIFO Port Register
NdisRawReadPortUshort(IOBase + BANK2_FIFOS, &PacketNumber);
PacketNumber &= 0x007F;
//Write to Packet Number Register
NdisRawWritePortUshort(IOBase + BANK2_PNR,(USHORT) PacketNumber);
NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD,(USHORT) CMD_REL_SPEC);
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
while (TempWord & MMUCMD_BUSY)
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)0);
NdisRawWritePortUshort(IOBase + BANK0_TCR, Adapter->TCR);
}
//Renable the Transmitter..
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, (USHORT) 0);
NdisRawWritePortUshort(Adapter->IOBase + BANK0_TCR, Adapter->TCR);
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: <== EPH Interrupt Handler\r\n")));
}
VOID RX_OVRN_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
USHORT FIFO, MIR;
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: ==> RX OVRN Interrupt Handler\r\n")));
//Ack the interrupt
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,2);
NdisRawWritePortUshort(Adapter->IOBase + BANK2_INT_STS,INT_RX_OVRN);
//Update the counter
Adapter->Stat_RxOvrn++;
NdisRawReadPortUshort(Adapter->IOBase + BANK2_FIFOS, &FIFO);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 0);
NdisRawReadPortUshort(Adapter->IOBase + BANK0_MIR, &MIR);
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: MIR=%04X, FIFO=%04X\r\n"), MIR,FIFO));
//Make sure the RCR is ok.
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 0);
NdisRawWritePortUshort(Adapter->IOBase + BANK0_RCR, Adapter->RCR);
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: <== RX OVRN Interrupt Handler\r\n")));
return;
}
VOID ALLOC_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
USHORT PacketNumber;
MINIPORT_PACKET *Packet;
PNDIS_PACKET pNDISPacket;
ULONG IOBase;
NDIS_STATUS RetVal;
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: ==> Alloc Interrupt Handler\r\n")));
IOBase = Adapter->IOBase;
Adapter->AllocIntPending = FALSE;
//Get the allocated packet
NdisRawReadPortUshort(IOBase + BANK2_PNR, (PUSHORT)&PacketNumber);
PacketNumber = PacketNumber >> 8; //allocated packet number in higher byte
//Write the allocated packet no. to PNR
NdisRawWritePortUshort(IOBase + BANK2_PNR, PacketNumber);
NdisStallExecution(1);
if (Adapter->AllocPending.First)
{
//Send the packet in the Queue
DequePacket(Adapter->AllocPending, Packet);
pNDISPacket = CONTAINING_RECORD(Packet,NDIS_PACKET,MiniportReserved[0]);
LAN91C111_AdapterWriteData(Adapter, pNDISPacket, PacketNumber);
}
else
{
//Well there is nothing to send, so free this slot
DebugBreak();
NdisRawWritePortUshort(IOBase + BANK2_PNR, PacketNumber);
NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD,(USHORT) CMD_REL_SPEC);
}
//Now check if there are any other packets to send, in the AllocPending queue
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -