📄 lan91c111_miniport.c
字号:
ULONG IOBase;
UINT PacketLength;
USHORT PacketNumber;
NDIS_STATUS RetVal;
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 ==> Miniport Send\r\n")));
IOBase = Adapter->IOBase;
//Make sure that the packet size is in legal limits.
NdisQueryPacket(pNDISPacket,NULL,NULL,NULL,(PUINT) &PacketLength);
if ((PacketLength > MAX_FRAME_SIZE) || (PacketLength < MIN_FRAME_SIZE))
{
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: Invalid Packet Size\r\n")));
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 <== Miniport Send\r\n")));
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")));
return (NDIS_STATUS_PENDING);
}
/*
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;
PrintDebugMsg(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, *(USHORT*)(&Adapter->HashTable[Counter]));
//Setup Receive control Register
Adapter->RCVAllMulticast = TRUE;
Adapter->RCVBroadcast = TRUE;
Adapter->PromiscuousMode = FALSE;
Adapter->RCR = 0;
Adapter->RCR |= RCR_STRP_CRC;
Adapter->RCR |= RCR_RX_EN;
Adapter->RCR |= RCR_ALL_MUL;
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); Adapter->DelQ = Adapter->AddQ = 0;
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;
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);
}
}
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
if (pCurrentBuffer != NULL)
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);
Packet = (MINIPORT_PACKET *) pNDISPacket->MiniportReserved;
Packet->Next = (MINIPORT_PACKET *) 0;
QuePacket(Adapter->AckPending, Packet); Adapter->AddQ++;
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 <== AdapterWriteData\r\n")));
return (NDIS_STATUS_PENDING);
}
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))
{
//If Nothing in TX and RX
//and atleast one slot is used, then reset.
if (((MIR & 0xFF00) != 0x0400) && (FIFO & 0x8000))
RetVal = TRUE;
}
return RetVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -