mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
6.6 KiB
280 lines
6.6 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
lttimer.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the polling timer processing routines.
|
|
|
|
Author:
|
|
|
|
Stephen Hou ([email protected])
|
|
Nikhil Kamkolkar ([email protected])
|
|
|
|
Revision History:
|
|
19 Jun 1992 Initial Version ([email protected])
|
|
|
|
Notes: Tab stop: 4
|
|
--*/
|
|
|
|
#define LTTIMER_H_LOCALS
|
|
#include "ltmain.h"
|
|
#include "lttimer.h"
|
|
#include "ltreset.h"
|
|
|
|
|
|
// Define file id for errorlogging
|
|
#define FILENUM LTTIMER
|
|
|
|
|
|
VOID
|
|
LtTimerPoll(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID Context,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the polling timer routine. It will receive data from the card
|
|
and process all the queues that are there- send/receive/loopback. NOTE:
|
|
Priority must be given to sends.
|
|
|
|
Arguments:
|
|
|
|
Context : Pointer to the Adapter structure.
|
|
All other parameters as described in NDIS 3.0
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
USHORT ResponseLength;
|
|
UCHAR Data, ResponseType;
|
|
LT_INIT_RESPONSE InitPacket;
|
|
PRECV_DESC RecvDesc;
|
|
PUCHAR RecvPkt;
|
|
NDIS_STATUS Status;
|
|
|
|
BOOLEAN ProcessReset = FALSE;
|
|
|
|
BOOLEAN ClearCardData = FALSE;
|
|
PLT_ADAPTER Adapter = (PLT_ADAPTER)Context;
|
|
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_LOW,
|
|
("LtTimerPoll: Entering...\n"));
|
|
|
|
LtReferenceAdapter(Adapter, &Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
// We are probably shutting down.
|
|
ASSERTMSG("LtTimerPoll: Adapter not closing!\n",
|
|
((Adapter->Flags & ADAPTER_CLOSING) == 0));
|
|
|
|
// Remove the reference we added at timer set.
|
|
LtDeReferenceAdapter(Adapter);
|
|
return;
|
|
}
|
|
|
|
// BUGBUG: Verify reset handling.
|
|
|
|
// !!! Send's get very high priority. In total, the queue is processed
|
|
// !!! three times, twice in the timer and once in LtSend
|
|
LtSendProcessQueue(Adapter);
|
|
|
|
// Check for receive data
|
|
NdisRawReadPortUchar(SC_PORT, &Data);
|
|
|
|
if (Data & RX_READY)
|
|
{
|
|
// Get the length of the response on the card
|
|
NdisRawReadPortUchar(XFER_PORT, &Data);
|
|
|
|
ResponseLength = (USHORT)(Data & 0xFF);
|
|
|
|
NdisRawReadPortUchar(XFER_PORT, &Data);
|
|
|
|
ResponseLength |= (Data << 8);
|
|
|
|
// Now get the IO code.
|
|
NdisRawReadPortUchar(XFER_PORT, &ResponseType);
|
|
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_INFO,
|
|
("LtPoll: RespType = %x, RespLength = %d\n",
|
|
ResponseType, ResponseLength));
|
|
|
|
switch (ResponseType)
|
|
{
|
|
case LT_RSP_LAP_INIT:
|
|
|
|
if (ResponseLength != sizeof(LT_INIT_RESPONSE))
|
|
{
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_ERR,
|
|
("LtTimerPoll: Bad response length %lx! \n", ResponseLength));
|
|
|
|
ClearCardData = TRUE;
|
|
}
|
|
break;
|
|
|
|
case LT_RSP_LAP_FRAME:
|
|
|
|
// Verify the frame is of the maximum packet size possible.
|
|
if (ResponseLength > LT_MAX_PACKET_SIZE)
|
|
{
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_ERR,
|
|
("LtTimerPoll: Bad packet length %lx! \n", ResponseLength));
|
|
|
|
// Keep track of number of bad receives
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
++Adapter->GeneralMandatory[GM_RECEIVE_BAD];
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
ClearCardData = TRUE;
|
|
break;
|
|
}
|
|
|
|
// Allocate a receive buffer descriptor for the packet.
|
|
NdisAllocateMemory(
|
|
&RecvDesc,
|
|
(UINT)(sizeof(RECV_DESC)+ResponseLength),
|
|
0,
|
|
LtNdisPhyAddr);
|
|
|
|
if (RecvDesc == NULL)
|
|
{
|
|
// Keep track of the number of times we couldnt get a buffer.
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
++Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER];
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
ClearCardData = TRUE;
|
|
break;
|
|
}
|
|
|
|
|
|
// Get a pointer to the receive packet storage.
|
|
RecvPkt = (PUCHAR)((PUCHAR)RecvDesc + sizeof(RECV_DESC));
|
|
|
|
NdisRawReadPortBufferUchar(XFER_PORT,
|
|
RecvPkt,
|
|
ResponseLength);
|
|
|
|
RecvDesc->Broadcast = IS_PACKET_BROADCAST(RecvPkt);
|
|
RecvDesc->BufferLength = ResponseLength;
|
|
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_INFO,
|
|
("LtTimerPoll: Recd Pkt Desc %lx Pkt %lx! \n",
|
|
RecvDesc, RecvPkt));
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
++Adapter->GeneralMandatory[GM_RECEIVE_GOOD];
|
|
if (RecvDesc->Broadcast)
|
|
{
|
|
++Adapter->GeneralOptionalFrameCount[GO_BROADCAST_RECEIVES];
|
|
LtAddLongToLargeInteger(
|
|
Adapter->GeneralOptionalByteCount[GO_BROADCAST_RECEIVES],
|
|
RecvDesc->BufferLength);
|
|
|
|
Adapter->MediaMandatory[MM_IN_BROADCASTS]++;
|
|
|
|
}
|
|
else
|
|
{
|
|
++Adapter->GeneralOptionalFrameCount[GO_DIRECTED_RECEIVES];
|
|
LtAddLongToLargeInteger(
|
|
Adapter->GeneralOptionalByteCount[GO_DIRECTED_RECEIVES],
|
|
RecvDesc->BufferLength);
|
|
}
|
|
|
|
InsertTailList(
|
|
&Adapter->Receive,
|
|
&RecvDesc->Linkage);
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
break;
|
|
|
|
case LT_RSP_STATUS:
|
|
|
|
if (ResponseLength != sizeof(LT_STATUS_RESPONSE))
|
|
{
|
|
ClearCardData = TRUE;
|
|
break;
|
|
}
|
|
|
|
NdisRawReadPortBufferUchar(XFER_PORT,
|
|
(PUCHAR)&Adapter->LastCardStatusResponse,
|
|
ResponseLength);
|
|
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_INFO,
|
|
("Node ID = %lx, Rom Ver = %lx, FirmWare Ver %lx\n",
|
|
Adapter->LastCardStatusResponse.NodeId,
|
|
Adapter->LastCardStatusResponse.RomVer,
|
|
Adapter->LastCardStatusResponse.SwVer));
|
|
|
|
break;
|
|
|
|
default:
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_ERR,
|
|
("LtTimerPoll: Unknown response type %lx\n", ResponseType));
|
|
|
|
ClearCardData = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ClearCardData)
|
|
{
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_WARN,
|
|
("LtTimerPoll: Clearing Card of response %d\n", ResponseLength));
|
|
|
|
while (ResponseLength-- > 0 )
|
|
{
|
|
NdisRawReadPortUchar(XFER_PORT, &Data);
|
|
}
|
|
}
|
|
|
|
// Call all the processing routines if their respective queues are
|
|
// not empty!
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
ASSERT (Adapter->Flags & ADAPTER_NODE_ID_VALID);
|
|
|
|
if (Adapter->Flags & ADAPTER_RESET_IN_PROGRESS)
|
|
{
|
|
ProcessReset = TRUE;
|
|
}
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
if (ProcessReset)
|
|
{
|
|
LtResetComplete(Adapter);
|
|
}
|
|
|
|
// Process our receive queue.
|
|
LtRecvProcessQueue(Adapter);
|
|
|
|
// Process send queue as processing receives would have entailed
|
|
// some sends.
|
|
// NOTE: Process LoopQueue after SendQueue as the Send Packet
|
|
// goes into the loop queue if it is a broadcast, after
|
|
// being sent out on the net.
|
|
LtSendProcessQueue(Adapter);
|
|
LtLoopProcessQueue(Adapter);
|
|
|
|
DBGPRINT(DBG_COMP_TIMER, DBG_LEVEL_LOW,
|
|
("LtTimerPoll: Setting timer and Leaving...\n"));
|
|
|
|
// Re-arm the timer
|
|
NdisSetTimer(&Adapter->PollingTimer, LT_POLLING_TIME);
|
|
|
|
// Remove the reference we added at the beginning of this routine.
|
|
LtDeReferenceAdapter(Adapter);
|
|
}
|