Windows NT 4.0 source code leak
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

/*++
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);
}