📄 8390.c
字号:
* ARGUMENTS:
* Adapter = Pointer to adapter information
*/
{
BOOLEAN SkipPacket = FALSE;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Get the header of the next packet in the receive ring */
Adapter->PacketOffset = Adapter->NextPacket << 8;
NICReadData(Adapter,
(PUCHAR)&Adapter->PacketHeader,
Adapter->PacketOffset,
sizeof(PACKET_HEADER));
NDIS_DbgPrint(MAX_TRACE, ("HEADER: (Status) (0x%X)\n", Adapter->PacketHeader.Status));
NDIS_DbgPrint(MAX_TRACE, ("HEADER: (NextPacket) (0x%X)\n", Adapter->PacketHeader.NextPacket));
NDIS_DbgPrint(MAX_TRACE, ("HEADER: (PacketLength) (0x%X)\n", Adapter->PacketHeader.PacketLength));
if (Adapter->PacketHeader.PacketLength < 64 ||
Adapter->PacketHeader.PacketLength > 1518) { /* XXX I don't think the CRC will show up... should be 1514 */
NDIS_DbgPrint(MAX_TRACE, ("Bogus packet size (%d).\n",
Adapter->PacketHeader.PacketLength));
SkipPacket = TRUE;
}
if (SkipPacket) {
/* Skip packet */
Adapter->NextPacket = Adapter->CurrentPage;
} else {
NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
Adapter->MiniportAdapterHandle));
NICIndicatePacket(Adapter);
/* Go to the next free buffer in receive ring */
Adapter->NextPacket = Adapter->PacketHeader.NextPacket;
}
/* Update boundary page */
NICSetBoundaryPage(Adapter);
}
static VOID NICWritePacket(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Writes a full packet to the transmit buffer ring
* ARGUMENTS:
* Adapter = Pointer to adapter information
* NOTES:
* There must be enough free buffers available in the transmit buffer ring.
* The packet is taken from the head of the transmit queue and the position
* into the transmit buffer ring is taken from TXNext
*/
{
PNDIS_BUFFER SrcBuffer;
UINT BytesToCopy, SrcSize, DstSize;
PUCHAR SrcData;
ULONG DstData;
UINT TXStart;
UINT TXStop;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
TXStart = Adapter->TXStart * DRIVER_BLOCK_SIZE;
TXStop = (Adapter->TXStart + Adapter->TXCount) * DRIVER_BLOCK_SIZE;
NdisQueryPacket(Adapter->TXQueueHead,
NULL,
NULL,
&SrcBuffer,
&Adapter->TXSize[Adapter->TXNext]);
NDIS_DbgPrint(MID_TRACE, ("Packet (%d) is now size (%d).\n",
Adapter->TXNext,
Adapter->TXSize[Adapter->TXNext]));
NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
DstData = TXStart + Adapter->TXNext * DRIVER_BLOCK_SIZE;
DstSize = TXStop - DstData;
/* Start copying the data */
for (;;) {
BytesToCopy = (SrcSize < DstSize)? SrcSize : DstSize;
NICWriteData(Adapter, DstData, SrcData, BytesToCopy);
SrcData = (PUCHAR)((ULONG_PTR) SrcData + BytesToCopy);
SrcSize -= BytesToCopy;
DstData += BytesToCopy;
DstSize -= BytesToCopy;
if (SrcSize == 0) {
/* No more bytes in source buffer. Proceed to
the next buffer in the source buffer chain */
NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
if (!SrcBuffer)
break;
NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
}
if (DstSize == 0) {
/* Wrap around the end of the transmit buffer ring */
DstData = TXStart;
DstSize = Adapter->TXCount * DRIVER_BLOCK_SIZE;
}
}
}
static BOOLEAN NICPrepareForTransmit(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Prepares a packet for transmission
* ARGUMENTS:
* Adapter = Pointer to adapter information
* NOTES:
* There must be at least one packet in the transmit queue
* RETURNS:
* TRUE if a packet was prepared, FALSE if not
*/
{
UINT Length;
UINT BufferCount;
PNDIS_PACKET Packet;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Calculate number of buffers needed to transmit packet */
NdisQueryPacket(Adapter->TXQueueHead,
NULL,
NULL,
NULL,
&Length);
BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE;
if (BufferCount > Adapter->TXFree) {
NDIS_DbgPrint(MID_TRACE, ("No transmit resources. Have (%d) buffers, need (%d).\n",
Adapter->TXFree, BufferCount));
/* We don't have the resources to transmit this packet right now */
return FALSE;
}
/* Write the packet to the card */
NICWritePacket(Adapter);
/* If the NIC is not transmitting, reset the current transmit pointer */
if (Adapter->TXCurrent == -1)
Adapter->TXCurrent = Adapter->TXNext;
Adapter->TXNext = (Adapter->TXNext + BufferCount) % Adapter->TXCount;
Adapter->TXFree -= BufferCount;
/* Remove the packet from the queue */
Packet = Adapter->TXQueueHead;
Adapter->TXQueueHead = RESERVED(Packet)->Next;
if (Packet == Adapter->TXQueueTail)
Adapter->TXQueueTail = NULL;
/* Assume the transmit went well */
NdisMSendComplete(Adapter->MiniportAdapterHandle,
Packet,
NDIS_STATUS_SUCCESS);
return TRUE;
}
VOID NICTransmit(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Starts transmitting packets in the transmit queue
* ARGUMENTS:
* Adapter = Pointer to adapter information
* NOTES:
* There must be at least one packet in the transmit queue
*/
{
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
if (Adapter->TXCurrent == -1) {
/* NIC is not transmitting, so start transmitting now */
/* Load next packet onto the card, and start transmitting */
if (NICPrepareForTransmit(Adapter))
NICStartTransmit(Adapter);
}
}
static VOID HandleReceive(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Handles reception of a packet
* ARGUMENTS:
* Adapter = Pointer to adapter information
* NOTES:
* Buffer overflows are also handled here
*/
{
UINT i;
UCHAR Tmp;
UINT PacketCount;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
Adapter->DoneIndicating = FALSE;
PacketCount = 0;
NICGetCurrentPage(Adapter);
if (Adapter->BufferOverflow) {
NDIS_DbgPrint(MID_TRACE, ("Receive ring overflow.\n"));
/* Select page 0 and stop the NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
/* Clear RBCR0,RBCR1 - Remote Byte Count Registers */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00);
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
/* Wait for ISR_RST to be set, but timeout after 2ms */
for (i = 0; i < 4; i++) {
NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp);
if (Tmp & ISR_RST)
break;
NdisStallExecution(500);
}
#ifdef DBG
if (i == 4)
NDIS_DbgPrint(MIN_TRACE, ("NIC was not reset after 2ms.\n"));
#endif
if ((Adapter->InterruptStatus & (ISR_PTX | ISR_TXE)) == 0) {
/* We may need to restart the transmitter */
Adapter->TransmitPending = TRUE;
}
/* Initialize TCR - Transmit Configuration Register to loopback mode 1 */
NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);
/* Start NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2);
NICStart(Adapter);
Adapter->BufferOverflow = FALSE;
}
if (Adapter->ReceiveError) {
NDIS_DbgPrint(MID_TRACE, ("Receive error.\n"));
/* Skip this packet */
Adapter->NextPacket = Adapter->CurrentPage;
NICSetBoundaryPage(Adapter);
Adapter->ReceiveError = FALSE;
}
for (;;) {
NICGetCurrentPage(Adapter);
NDIS_DbgPrint(MID_TRACE, ("Current page (0x%X) NextPacket (0x%X).\n",
Adapter->CurrentPage,
Adapter->NextPacket));
if (Adapter->CurrentPage == Adapter->NextPacket) {
NDIS_DbgPrint(MID_TRACE, ("No more packets.\n"));
break;
} else {
NDIS_DbgPrint(MID_TRACE, ("Got a packet in the receive ring.\n"));
NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
Adapter->MiniportAdapterHandle));
/* Read packet from receive buffer ring */
NICReadPacket(Adapter);
Adapter->DoneIndicating = TRUE;
PacketCount++;
if (PacketCount == 10) {
/* Don't starve transmit interrupts */
break;
}
}
}
if ((Adapter->TransmitPending) && (Adapter->TXCurrent != -1)) {
NDIS_DbgPrint(MID_TRACE, ("Retransmitting current packet at (%d).\n", Adapter->TXCurrent));
/* Retransmit packet */
NICStartTransmit(Adapter);
Adapter->TransmitPending = FALSE;
}
if (Adapter->DoneIndicating)
NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
}
static VOID HandleTransmit(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Handles transmission of a packet
* ARGUMENTS:
* Adapter = Pointer to adapter information
*/
{
UINT Length;
UINT BufferCount;
// PIP_PACKET pIPPacket;
// pIPPacket = (PIP_PACKET)
// DisplayIPPacket(pIPPacket);
if (Adapter->TransmitError) {
/* FIXME: Retransmit now or let upper layer protocols handle retransmit? */
Adapter->TransmitError = FALSE;
}
/* Free transmit buffers */
Length = Adapter->TXSize[Adapter->TXCurrent];
BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE;
NDIS_DbgPrint(MID_TRACE, ("Freeing (%d) buffers at (%d).\n",
BufferCount,
Adapter->TXCurrent));
Adapter->TXFree += BufferCount;
Adapter->TXSize[Adapter->TXCurrent] = 0;
Adapter->TXCurrent = (Adapter->TXCurrent + BufferCount) % Adapter->TXCount;
if (Adapter->TXSize[Adapter->TXCurrent] == 0) {
NDIS_DbgPrint(MID_TRACE, ("No more packets in transmit buffer.\n"));
Adapter->TXCurrent = -1;
}
if (Adapter->TXQueueTail) {
if (NICPrepareForTransmit(Adapter))
NICStartTransmit(Adapter);
}
}
VOID STDCALL MiniportHandleInterrupt(
IN NDIS_HANDLE MiniportAdapterContext)
/*
* FUNCTION: Handler for deferred processing of interrupts
* ARGUMENTS:
* MiniportAdapterContext = Pointer to adapter context area
* NOTES:
* Interrupt Service Register is read to determine which interrupts
* are pending. All pending interrupts are handled
*/
{
UCHAR ISRValue;
UCHAR ISRMask;
UCHAR Mask;
PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
ISRMask = Adapter->InterruptMask;
NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue);
NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue));
Adapter->InterruptStatus |= (ISRValue & ISRMask);
if (ISRValue != 0x00)
/* Acknowledge interrupts */
NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue);
Mask = 0x01;
while (Adapter->InterruptStatus != 0x00) {
NDIS_DbgPrint(MID_TRACE, ("Adapter->InterruptStatus (0x%X) Mask (0x%X).\n",
Adapter->InterruptStatus, Mask));
/* Find next interrupt type */
while (((Adapter->InterruptStatus & Mask) == 0) && (Mask < ISRMask))
Mask = (Mask << 1);
switch (Adapter->InterruptStatus & Mask) {
case ISR_OVW:
NDIS_DbgPrint(MID_TRACE, ("Overflow interrupt.\n"));
/* Overflow. Handled almost the same way as a receive interrupt */
Adapter->BufferOverflow = TRUE;
NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
Adapter->MiniportAdapterHandle));
if(Adapter->MiniportAdapterHandle)
HandleReceive(Adapter);
else
NDIS_DbgPrint(MAX_TRACE,("No miniport adapter yet\n"));
Adapter->InterruptStatus &= ~ISR_OVW;
break;
case ISR_RXE:
NDIS_DbgPrint(MID_TRACE, ("Receive error interrupt.\n"));
NICUpdateCounters(Adapter);
Adapter->ReceiveError = TRUE;
case ISR_PRX:
NDIS_DbgPrint(MID_TRACE, ("Receive interrupt.\n"));
NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
Adapter->MiniportAdapterHandle));
if(Adapter->MiniportAdapterHandle)
HandleReceive(Adapter);
else
NDIS_DbgPrint(MAX_TRACE,("No miniport adapter yet\n"));
Adapter->InterruptStatus &= ~(ISR_PRX | ISR_RXE);
break;
case ISR_TXE:
NDIS_DbgPrint(MID_TRACE, ("Transmit error interrupt.\n"));
NICUpdateCounters(Adapter);
Adapter->TransmitError = TRUE;
case ISR_PTX:
NDIS_DbgPrint(MID_TRACE, ("Transmit interrupt.\n"));
HandleTransmit(Adapter);
Adapter->InterruptStatus &= ~(ISR_PTX | ISR_TXE);
break;
case ISR_CNT:
NDIS_DbgPrint(MID_TRACE, ("Counter interrupt.\n"));
/* Counter overflow. Read counters from the NIC */
NICUpdateCounters(Adapter);
Adapter->InterruptStatus &= ~ISR_CNT;
break;
default:
NDIS_DbgPrint(MID_TRACE, ("Unknown interrupt. Adapter->InterruptStatus (0x%X).\n", Adapter->InterruptStatus));
Adapter->InterruptStatus &= ~Mask;
break;
}
Mask = (Mask << 1);
/* Check if new interrupts are generated */
NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue);
NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue));
Adapter->InterruptStatus |= (ISRValue & ISRMask);
if (ISRValue != 0x00) {
/* Acknowledge interrupts */
NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue);
Mask = 0x01;
}
}
NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -