📄 lan91c111_miniport.c
字号:
return (NDIS_STATUS_FAILURE);
}
if (Adapter->AllocIntPending)
{
PrintDebugMsg(1, (TEXT("LAN91C111: Allocation in process\r\n")));
PrintDebugMsg(1, (TEXT("LAN91C111: <== Miniport Send\r\n")));
Packet = (MINIPORT_PACKET *) pNDISPacket->MiniportReserved;
Packet->Next = (MINIPORT_PACKET *) 0;
QuePacket(Adapter->AllocPending, Packet);
Adapter->AllocIntPending = TRUE;
NdisMSynchronizeWithInterrupt((PNDIS_MINIPORT_INTERRUPT)&Adapter->InterruptInfo, (PVOID)AllocIntEnabler, (PVOID)Adapter);
return (NDIS_STATUS_PENDING);
}
RetVal = LAN91C111_AdapterAllocBuffer(Adapter, &PacketNumber);
if (RetVal == NDIS_STATUS_SUCCESS)
LAN91C111_AdapterWriteData(Adapter, pNDISPacket, PacketNumber);
else
{
Packet = (MINIPORT_PACKET *) pNDISPacket->MiniportReserved;
Packet->Next = (MINIPORT_PACKET *) 0;
QuePacket(Adapter->AllocPending, Packet);
Adapter->AllocIntPending = TRUE;
NdisMSynchronizeWithInterrupt((PNDIS_MINIPORT_INTERRUPT)&Adapter->InterruptInfo, (PVOID)AllocIntEnabler, (PVOID)Adapter);
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: Allocation FAILED - Packet Queued\r\n")));
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: <== Miniport Send\r\n")));
return (NDIS_STATUS_PENDING);
}
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 <== Miniport Send\r\n")));
#ifdef SMSC_AUTO_RELEASE
return (NDIS_STATUS_SUCCESS);
#else
return (NDIS_STATUS_PENDING);
#endif
}
/*
Function Name : LAN91C111_MiniportReset
Description : This function is a required function that issues a hardware reset
to the network adapter and/or resets the driver抯 software state.
Parameters :
PBOOLEAN AddressingReset -Points to a variable that MiniportReset
sets to TRUE if the NDIS library should call
MiniportSetInformation to restore addressing information
to the current values.
NDIS_HANDLE AdapterContext - Handle to the adapter structure
Return Value :
NDIS_STATUS Status
*/
NDIS_STATUS LAN91C111_MiniportReset (
PBOOLEAN AddressingReset,
NDIS_HANDLE AdapterContext
)
{
NDIS_STATUS Status=NDIS_STATUS_SUCCESS;
MINIPORT_ADAPTER *Adapter = (MINIPORT_ADAPTER *) AdapterContext;
USHORT TempWord;
ULONG IOBase;
INT Counter;
RETAILMSG(1, (TEXT("LAN91C111 ==> Miniport Reset\r\n")));
IOBase = Adapter->IOBase;
//Clear the card's interrupt mask register
NdisRawWritePortUshort( IOBase + BANK_SELECT, 2 );
NdisRawWritePortUshort( IOBase + BANK2_INT_STS, (USHORT)0 );
//Just Reset the MMU and clear the Statistics...
NdisRawWritePortUshort( IOBase + BANK2_MMU_CMD, CMD_RIS);
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
while (TempWord & MMUCMD_BUSY)
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) TempWord);
Adapter->State = RESET_STATE;
//Restore Multicast Hash Table.
NdisRawWritePortUshort(IOBase + BANK_SELECT, (USHORT) 3 );
for(Counter = 0;Counter < 8;Counter += 2)
NdisRawWritePortUshort(IOBase + BANK3_MT01 + Counter, *(&Adapter->HashTable[Counter]));
//Setup Receive control Register
Adapter->RCVAllMulticast = TRUE;
Adapter->RCVBroadcast = TRUE;
Adapter->PromiscuousMode = FALSE;
Adapter->RCR = RCR_RX_EN;
Adapter->RCR |= RCR_STRP_CRC;
NdisRawWritePortUshort( IOBase + BANK_SELECT, (USHORT) 0);
NdisRawWritePortUshort(IOBase + BANK0_RCR, Adapter->RCR);
//Clear all the statistic counter
Adapter->Stat_RxError =
Adapter->Stat_RxOK =
Adapter->Stat_RxOvrn =
Adapter->Stat_TxError =
Adapter->Stat_TxOK =
Adapter->Stat_AlignError =
Adapter->Stat_MultiColl =
Adapter->Stat_SingleColl = 0;
//Initialize Queues.
ClearPacketQue(Adapter->AckPending);
ClearPacketQue(Adapter->AllocPending);
Adapter->AllocIntPending = FALSE;
//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(IOBase+BANK_SELECT, (USHORT) 0);
NdisRawWritePortUshort( IOBase + BANK0_TCR, Adapter->TCR);
//Enable the interrupts !!
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 2);
NdisRawWritePortUshort( Adapter->IOBase + BANK2_INT_STS,(USHORT)(ENABLED_INTS << 8));
Adapter->State = NORMAL_STATE;
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111 <== Miniport Reset\r\n")));
return Status;
}
/*
Function Name : LAN91C111_AdapterAllocBuffer
Description : Allocates a buffer for TX pacet. The PacketNumber holds the packet allocated.
Return Value : NDIS_STAUS_SUCCESS if allocation is success
NDIS_STATUS_FAILURE if allocation failed, in this case PacketNumber is invalid
*/
NDIS_STATUS LAN91C111_AdapterAllocBuffer(MINIPORT_ADAPTER *Adapter, USHORT *PacketNumber)
{
ULONG IOBase;
UINT AllocateOk;
USHORT AllocSts;
*PacketNumber = -1;
IOBase = Adapter->IOBase;
//Allocate memory
NdisRawWritePortUshort(IOBase + BANK_SELECT,2);
NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD,(USHORT)(CMD_ALLOC));
AllocateOk = MMU_WAIT;
while(AllocateOk)
{
NdisRawReadPortUshort(IOBase + BANK2_INT_STS, (PUSHORT) &AllocSts);
if(AllocSts & INT_ALLOC) break;
AllocateOk--;
}
if (!(AllocSts & INT_ALLOC))
return (NDIS_STATUS_FAILURE);
else
{
NdisRawReadPortUshort(IOBase + BANK2_PNR, PacketNumber);
*PacketNumber = *PacketNumber >> 8; //allocated packet number in higher byte
PrintDebugMsg(ZONE_TX, (TEXT("\tLAN91C111: Packet #%d Allocated\r\n"), *PacketNumber));
return (NDIS_STATUS_SUCCESS);
}
}
/*
Function Name : LAN91C111_AdapterWriteData
Description : Write the packet data to the packet specified int he PacketNumber parameter.
Return Value : NDIS_STAUS_SUCCESS
*/
NDIS_STATUS LAN91C111_AdapterWriteData(
MINIPORT_ADAPTER *Adapter,
PNDIS_PACKET pNDISPacket,
UINT PacketNumber
)
{
PNDIS_BUFFER pCurrentBuffer;
ULONG IOBase;
UINT PacketLength,
CurrentBufferLength;
PUCHAR pCurrentBufferAddr,
ptemp;
UCHAR OddByte=0;
MINIPORT_PACKET *Packet;
USHORT ControlWord;
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 ==> AdapterWriteData\r\n")));
IOBase = Adapter->IOBase;
//Make sure that the packet size is in legal limits.
NdisQueryPacket(pNDISPacket,NULL,NULL,&pCurrentBuffer,(PUINT) &PacketLength);
NdisRawWritePortUshort(IOBase + BANK_SELECT,2);
//Write the allocated packet no. to PNR
NdisRawWritePortUshort(IOBase + BANK2_PNR, PacketNumber);
NdisStallExecution(1);
//Set the pointer register to TX + AUTO_INCR + WRITE
NdisRawWritePortUshort(IOBase + BANK2_PTR, PTR_AUTO);
NdisStallExecution(1); //Wait for 1us (as per the Data sheet atleast 370ns)
//Write the status word (placeholder)
NdisRawWritePortUshort(IOBase + BANK2_DATA1, (USHORT) 0);
//Write the byte count + packet overhead
NdisRawWritePortUshort(IOBase + BANK2_DATA1, (USHORT)(PacketLength+FRAME_OVERHEAD));
//Query for the first non-zero buffer
NdisQueryPacket(pNDISPacket,NULL,NULL,&pCurrentBuffer,(PUINT) &PacketLength);
NdisQueryBuffer(pCurrentBuffer, (PVOID*)&pCurrentBufferAddr, &CurrentBufferLength);
while ((pCurrentBuffer) && (CurrentBufferLength == 0))
{
NdisGetNextBuffer(pCurrentBuffer, (PNDIS_BUFFER *)&pCurrentBuffer);
NdisQueryBuffer(pCurrentBuffer, (PVOID*)&pCurrentBufferAddr, &CurrentBufferLength);
}
//Copy the data to the TxBuffer
ptemp = Adapter->TxBuffer;
do
{
NdisMoveMemory(ptemp, pCurrentBufferAddr, (ULONG)CurrentBufferLength);
(ULONG)ptemp += CurrentBufferLength;
NdisGetNextBuffer (pCurrentBuffer, (PNDIS_BUFFER *)&pCurrentBuffer); //Get the next buffer
NdisQueryBuffer (pCurrentBuffer, (PVOID*)&pCurrentBufferAddr, &CurrentBufferLength);
}
while(pCurrentBuffer);
#ifdef SMSC_32BIT_RW
{
NdisRawWritePortBufferUlong(IOBase + BANK2_DATA1, Adapter->TxBuffer, PacketLength>>2);
if ((PacketLength & 0xFFFE) % 4)
{
USHORT LastWord;
if (PacketLength & 1)
LastWord = *((PUSHORT)(Adapter->TxBuffer+PacketLength-3));
else
LastWord = *((PUSHORT)(Adapter->TxBuffer+PacketLength-2));
NdisRawWritePortUshort(IOBase + BANK2_DATA1, LastWord);
}
}
#else
//Write the data to the chip
NdisRawWritePortBufferUshort(IOBase + BANK2_DATA1, Adapter->TxBuffer, PacketLength>>1);
#endif
//If odd length packet
if (PacketLength & 1)
{
ptemp = Adapter->TxBuffer;
OddByte = ptemp[PacketLength-1];
ControlWord = ((CTL_BYTE_ODD | CTL_BYTE_CRC) << 8)| OddByte;
}
else
ControlWord = (CTL_BYTE_CRC<< 8);
//Write the control word to the chip
NdisRawWritePortUshort(IOBase+BANK2_DATA1, (USHORT)ControlWord);
//Now enque the packet for transmission..
NdisRawWritePortUshort( IOBase + BANK_SELECT, (USHORT) 2);
NdisRawWritePortUshort (IOBase+BANK2_MMU_CMD, CMD_ENQ_TX);
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 <== AdapterWriteData\r\n")));
#ifdef SMSC_AUTO_RELEASE
return (NDIS_STATUS_SUCCESS);
#else
Packet = (MINIPORT_PACKET *) pNDISPacket->MiniportReserved;
Packet->Next = (MINIPORT_PACKET *) 0;
QuePacket(Adapter->AckPending, Packet);
return (NDIS_STATUS_PENDING);
#endif
}
/*
Function Name : LAN91C111_MiniportCheckforHang
Description : This function checks for the internal state of the chip. If one or more onchip buffers
are unaccounted, it returns TRUE indicatin to the NDIS layer to call the AdapterReset
function. Generally this funciton is called every 2 seconds, by the NDIS layer.
This is an optional miniport functions. If not used, the NDIS layer judges the drivers
unresponsivenss to call the AdapterReset function.
Basically this functions checks if there are any TX or RX packets are pending. If pending
it returns FALSE, else it checks for the empty buffer space. If the buffer space is less than
4, then it returns TRUE.
Return Value : TRUE - If the chip needs to be reset, else FALSE
*/
BOOLEAN LAN91C111_MiniportCheckforHang(
NDIS_HANDLE AdapterContext
)
{
MINIPORT_ADAPTER *Adapter = (MINIPORT_ADAPTER *) AdapterContext;
ULONG IOBase;
USHORT FIFO, MIR;
BOOLEAN RetVal = FALSE;
IOBase = Adapter->IOBase;
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,2);
NdisRawReadPortUshort(Adapter->IOBase + BANK2_FIFOS, &FIFO);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 0);
NdisRawReadPortUshort(Adapter->IOBase + BANK0_MIR, &MIR);
if ((!(Adapter->AckPending.First)) && (Adapter->AllocIntPending == FALSE))
{
//Nothing in TX and RX
//And atleast one slot is full, then reset.
if (((MIR & 0xFF00) != 0x0400) && (FIFO & 0x8000))
RetVal = TRUE;
}
return RetVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -