⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nsc.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 ************************************************************************
 *
 *	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 + -