📄 nsc.c
字号:
/*
************************************************************************
*
* NSC.c
*
*
* Portions Copyright (C) 1996-2001 National Semiconductor Corp.
* All rights reserved.
* Copyright (C) 1996-2001 Microsoft Corporation. All Rights Reserved.
*
*
*
*************************************************************************
*/
#include "nsc.h"
#include "nsc.tmh"
/*
* We keep a linked list of device objects
*/
/* This fuction sets up the device for Recv */
void SetupRecv(IrDevice *thisDev);
//
// Debug Counters
//
DebugCounters RegStats = {0,0,0,0,0,0,0,0,0};
ULONG DebugSpeed=0;
#ifdef RECEIVE_PACKET_LOGGING
typedef struct {
UCHAR Data[12];
} DATA_BITS;
typedef struct {
USHORT Tag;
USHORT Line;
union {
struct {
PNDIS_PACKET Packet;
PVOID DmaBuffer;
ULONG Length;
} Packet;
struct {
PLIST_ENTRY Head;
PLIST_ENTRY Entry;
} List;
struct {
PVOID Start;
ULONG Offset;
ULONG Length;
} Dma;
struct {
ULONG Length;
} Discard;
DATA_BITS Data;
};
} RCV_LOG;
#define CHAIN_PACKET_TAG 'CP'
#define UNCHAIN_PACKET_TAG 'UP'
#define ADD_HEAD_LIST_TAG 'HA'
#define ADD_TAIL_LIST_TAG 'TA'
#define REMOVE_HEAD_LIST_TAG 'HR'
#define REMOVE_ENTRY_TAG 'ER'
#define DMA_TAG 'MD'
#define DATA_TAG 'AD'
#define DATA2_TAG '2D'
#define DISCARD_TAG 'XX'
#define NUM_RCV_LOG 256
ULONG RcvLogIndex = 0;
RCV_LOG RcvLog[NUM_RCV_LOG];
BOOLEAN SyncGetRcvLogEntry(PVOID Context)
{
*(ULONG*)Context = RcvLogIndex++;
RcvLogIndex &= NUM_RCV_LOG-1;
return TRUE;
}
ULONG GetRcvLogEntry(IrDevice *thisDev)
{
ULONG Entry;
NdisAcquireSpinLock(&thisDev->QueueLock);
NdisMSynchronizeWithInterrupt(&thisDev->interruptObj, SyncGetRcvLogEntry, &Entry);
NdisReleaseSpinLock(&thisDev->QueueLock);
return Entry;
}
#define LOG_InsertHeadList(d, h, e) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = ADD_HEAD_LIST_TAG; \
RcvLog[i].Line = __LINE__; \
RcvLog[i].List.Head = (h); \
RcvLog[i].List.Entry = (PLIST_ENTRY)(e); \
}
#define LOG_InsertTailList(d, h, e) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = ADD_TAIL_LIST_TAG; \
RcvLog[i].Line = __LINE__; \
RcvLog[i].List.Head = (h); \
RcvLog[i].List.Entry = (PLIST_ENTRY)(e); \
}
#define LOG_RemoveHeadList(d, h, e) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = REMOVE_HEAD_LIST_TAG; \
RcvLog[i].Line = __LINE__; \
RcvLog[i].List.Head = (h); \
RcvLog[i].List.Entry = (PLIST_ENTRY)(e); \
}
#define LOG_RemoveEntryList(d, e) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = REMOVE_ENTRY_TAG; \
RcvLog[i].Line = __LINE__; \
RcvLog[i].List.Head = NULL; \
RcvLog[i].List.Entry = (PLIST_ENTRY)(e); \
}
#define LOG_PacketChain(d, p) \
{ \
PNDIS_BUFFER NdisBuffer; \
PVOID Address; \
ULONG Len; \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = CHAIN_PACKET_TAG; \
RcvLog[i].Line = __LINE__; \
NdisQueryPacket((p), NULL, NULL, &NdisBuffer, NULL); \
NdisQueryBufferSafe(NdisBuffer, &Address, &Len,NormalPagePriority); \
RcvLog[i].Packet.Packet = (p); \
RcvLog[i].Packet.DmaBuffer = Address; \
RcvLog[i].Packet.Length = Len; \
}
#define LOG_PacketUnchain(d, p) \
{ \
PNDIS_BUFFER NdisBuffer; \
PVOID Address; \
ULONG Len; \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = UNCHAIN_PACKET_TAG; \
RcvLog[i].Line = __LINE__; \
NdisQueryPacket((p), NULL, NULL, &NdisBuffer, NULL); \
NdisQueryBufferSafe(NdisBuffer, &Address, &Len,NormalPagePriority); \
RcvLog[i].Packet.Packet = (p); \
RcvLog[i].Packet.DmaBuffer = Address; \
RcvLog[i].Packet.Length = Len; \
}
#define LOG_Dma(d) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = DMA_TAG; \
RcvLog[i].Line = __LINE__; \
RcvLog[i].Dma.Start = (d)->rcvDmaBuffer; \
RcvLog[i].Dma.Offset = (d)->rcvDmaOffset; \
RcvLog[i].Dma.Length = (d)->rcvDmaSize; \
}
#define LOG_Data(d,s) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = DATA_TAG; \
RcvLog[i].Line = ((USHORT)(s))&0xffff; \
RcvLog[i].Data = *(DATA_BITS*)(s); \
}
#define LOG_Data2(d,s) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = DATA2_TAG; \
RcvLog[i].Line = ((USHORT)(s))&0xffff; \
RcvLog[i].Data = *(DATA_BITS*)(s); \
}
#define LOG_Discard(d,s) \
{ \
ULONG i = GetRcvLogEntry(d); \
RcvLog[i].Tag = DISCARD_TAG; \
RcvLog[i].Line = __LINE__; \
RcvLog[i].Discard.Length = (s); \
}
void DumpNdisPacket(PNDIS_PACKET Packet, UINT Line)
{
UINT PhysBufCnt, BufCnt, TotLen, Len;
PNDIS_BUFFER NdisBuffer;
PVOID Address;
DbgPrint("Badly formed NDIS packet at line %d\n", Line);
NdisQueryPacket(Packet, &PhysBufCnt, &BufCnt, &NdisBuffer, &TotLen);
DbgPrint("Packet:%08X PhysBufCnt:%d BufCnt:%d TotLen:%d\n",
Packet, PhysBufCnt, BufCnt, TotLen);
while (NdisBuffer)
{
NdisQueryBufferSafe(NdisBuffer, &Address, &Len,NormalPagePriority);
DbgPrint(" Buffer:%08X Address:%08X Length:%d\n",
NdisBuffer, Address, Len);
NdisGetNextBuffer(NdisBuffer, &NdisBuffer);
}
ASSERT(0);
}
#define VerifyNdisPacket(p, b) \
{ \
UINT BufCnt; \
\
NdisQueryPacket((p), NULL, &BufCnt, NULL, NULL); \
if (BufCnt>(b)) \
{ \
DumpNdisPacket((p), __LINE__); \
} \
}
#else
#define VerifyNdisPacket(p,b)
#define LOG_InsertHeadList(d, h, e)
#define LOG_InsertTailList(d, h, e)
#define LOG_RemoveHeadList(d, h, e)
#define LOG_RemoveEntryList(d, e)
#define LOG_PacketChain(d, p)
#define LOG_PacketUnchain(d, p)
#define LOG_Dma(d)
#define LOG_Data(d,s)
#define LOG_Data2(d,s)
#define LOG_Discard(d,s)
#endif
BOOLEAN
VerifyHardware(
IrDevice *thisDev
);
/*
*************************************************************************
* MiniportCheckForHang
*************************************************************************
*
* Reports the state of the network interface card.
*
*/
BOOLEAN MiniportCheckForHang(NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
// LOG("==> MiniportCheckForHang");
DBGOUT(("==> MiniportCheckForHang(0x%x)", MiniportAdapterContext));
// We have seen cases where we hang sending at high speeds. This occurs only
// on very old revisions of the NSC hardware.
// This is an attempt to kick us off again.
NdisDprAcquireSpinLock(&thisDev->QueueLock);
if (thisDev->FirTransmitPending) {
switch (thisDev->HangChk)
{
case 0:
break;
default:
DBGERR(("NSCIRDA: CheckForHang--we appear hung\n"));
LOG_ERROR("CheckForHang--we appear hung\n");
// Issue a soft reset to the transmitter & receiver.
SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, 2, 0x06);
//
// turn the timer on and let it gnerate an interrupt
//
thisDev->FirIntMask = 0x90;
SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 4, 2, 0x01);
SyncSetInterruptMask(thisDev, TRUE);
break;
}
thisDev->HangChk++;
}
NdisDprReleaseSpinLock(&thisDev->QueueLock);
// LOG("<== MiniportCheckForHang");
DBGOUT(("<== MiniportCheckForHang(0x%x)", MiniportAdapterContext));
return FALSE;
}
/*
*************************************************************************
* MiniportHalt
*************************************************************************
*
* Halts the network interface card.
*
*/
VOID MiniportHalt(IN NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
LOG("==> MiniportHalt");
DBGOUT(("==> MiniportHalt(0x%x)", MiniportAdapterContext));
thisDev->hardwareStatus = NdisHardwareStatusClosing;
NdisAcquireSpinLock(&thisDev->QueueLock);
thisDev->Halting=TRUE;
if (thisDev->PacketsSentToProtocol > 0) {
//
// wait for all the packets to come back from the protocol
//
NdisReleaseSpinLock(&thisDev->QueueLock);
NdisWaitEvent(&thisDev->ReceiveStopped, 1*60*1000);
NdisAcquireSpinLock(&thisDev->QueueLock);
}
if (!thisDev->TransmitIsIdle) {
//
// wait for all the packets to be transmitted
//
NdisReleaseSpinLock(&thisDev->QueueLock);
NdisWaitEvent(&thisDev->SendStoppedOnHalt,1*60*1000);
NdisAcquireSpinLock(&thisDev->QueueLock);
}
if (thisDev->FirReceiveDmaActive) {
thisDev->FirReceiveDmaActive=FALSE;
//
// receive dma is running, stop it
//
CompleteDmaTransferFromDevice(
&thisDev->DmaUtil
);
}
//
// which back to SIR mode
//
CloseCOM(thisDev);
SyncSetInterruptMask(thisDev, FALSE);
NdisReleaseSpinLock(&thisDev->QueueLock);
//
// release the interrupt
//
NdisMDeregisterInterrupt(&thisDev->interruptObj);
#if DBG
NdisZeroMemory(&thisDev->interruptObj,sizeof(thisDev->interruptObj));
#endif
//
// release fir related resources including dma channel
//
NSC_Shutdown(thisDev);
//
// release sir related buffers
//
DoClose(thisDev);
if (thisDev->portInfo.ConfigIoBasePhysAddr) {
NdisMDeregisterIoPortRange(thisDev->ndisAdapterHandle,
thisDev->portInfo.ConfigIoBasePhysAddr,
2,
(PVOID)thisDev->portInfo.ConfigIoBaseAddr);
}
NdisMDeregisterIoPortRange(thisDev->ndisAdapterHandle,
thisDev->portInfo.ioBasePhys,
((thisDev->CardType==PUMA108)?16:8),
(PVOID)thisDev->portInfo.ioBase);
//
// free the device block
//
FreeDevice(thisDev);
LOG("<== MiniportHalt");
DBGOUT(("<== MiniportHalt(0x%x)", MiniportAdapterContext));
}
void InterlockedInsertBufferSorted(PLIST_ENTRY Head,
rcvBuffer *rcvBuf,
PNDIS_SPIN_LOCK Lock)
{
PLIST_ENTRY ListEntry;
NdisAcquireSpinLock(Lock);
if (IsListEmpty(Head))
{
InsertHeadList(Head, &rcvBuf->listEntry);
}
else
{
BOOLEAN EntryInserted = FALSE;
for (ListEntry = Head->Flink;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -