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

📄 nsc.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
 */
NDIS_STATUS MiniportReset(PBOOLEAN AddressingReset, NDIS_HANDLE MiniportAdapterContext)
{
    IrDevice    *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
    NDIS_STATUS result = NDIS_STATUS_PENDING;

    LIST_ENTRY          TempList;
    BOOLEAN             SetSpeedNow=FALSE;
    PNDIS_PACKET        Packet;

    DBGERR(("MiniportReset(0x%x)", MiniportAdapterContext));

    InitializeListHead(&TempList);

    NdisAcquireSpinLock(&thisDev->QueueLock);

    thisDev->hardwareStatus = NdisHardwareStatusReset;
    //
    //  un-queue all the send packets and put them on a temp list
    //
    while (!IsListEmpty(&thisDev->SendQueue)) {

        PLIST_ENTRY    ListEntry;

        ListEntry=RemoveHeadList(&thisDev->SendQueue);

        InsertTailList(&TempList,ListEntry);
    }

    //
    //  if there is a current send packet, then request a speed change after it completes
    //
    if (thisDev->CurrentPacket != NULL) {
        //
        //  the current packet is now the last, chage speed after it is done
        //
        thisDev->lastPacketAtOldSpeed=thisDev->CurrentPacket;

    } else {
        //
        //  no current packet, change speed now
        //
        SetSpeedNow=TRUE;

    }


    //
    //  back to 9600
    //
    thisDev->linkSpeedInfo = &supportedBaudRateTable[BAUDRATE_9600];

    if (SetSpeedNow) {
        //
        //  there are no packets being transmitted now, switch speeds now.
        //  otherwise the dpc will do it when the current send completes
        //
        SetSpeed(thisDev);
        thisDev->TransmitIsIdle=FALSE;
    }

    NdisReleaseSpinLock(&thisDev->QueueLock);

    if (SetSpeedNow) {
        //
        //  the transmit was idle, but we change this to get the receive going again
        //
        ProcessSendQueue(thisDev);
    }

    //
    //  return all of these back to the protocol
    //
    while (!IsListEmpty(&TempList)) {

        PLIST_ENTRY    ListEntry;

        ListEntry=RemoveHeadList(&TempList);

        Packet= CONTAINING_RECORD(
                                   ListEntry,
                                   NDIS_PACKET,
                                   MiniportReserved
                                   );
        NdisMSendComplete(thisDev->ndisAdapterHandle, Packet, NDIS_STATUS_RESET_IN_PROGRESS );
    }

    thisDev->hardwareStatus = NdisHardwareStatusReady;

    NdisMResetComplete(thisDev->ndisAdapterHandle,
                       NDIS_STATUS_SUCCESS,
                       TRUE);  // Addressing reset



    *AddressingReset = TRUE;

    DBGOUT(("MiniportReset done."));
    return NDIS_STATUS_PENDING;
}




/*
 *************************************************************************
 *  ReturnPacketHandler
 *************************************************************************
 *
 *  When NdisMIndicateReceivePacket returns asynchronously,
 *  the protocol returns ownership of the packet to the miniport via this function.
 *
 */
VOID ReturnPacketHandler(NDIS_HANDLE MiniportAdapterContext, PNDIS_PACKET Packet)
{
    IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
    rcvBuffer *rcvBuf;
    LONG       PacketsLeft;

    DBGOUT(("ReturnPacketHandler(0x%x)", MiniportAdapterContext));
    RegStats.ReturnPacketHandlerCalled++;

    //
    // MiniportReserved contains the pointer to our rcvBuffer
    //

    rcvBuf = *(rcvBuffer**) Packet->MiniportReserved;

    VerifyNdisPacket(Packet, 1);

    if (rcvBuf->state == STATE_PENDING){
        PNDIS_BUFFER ndisBuf;

        DBGPKT(("Reclaimed rcv packet 0x%x.", Packet));

        LOG_RemoveEntryList(thisDev, rcvBuf);
        NDISSynchronizedRemoveEntryList(&rcvBuf->listEntry, &thisDev->interruptObj);

        LOG_PacketUnchain(thisDev, rcvBuf->packet);
        NdisUnchainBufferAtFront(Packet, &ndisBuf);
        if (ndisBuf){
            NdisFreeBuffer(ndisBuf);
        }

        if (!rcvBuf->isDmaBuf)
        {
            NDISSynchronizedInsertTailList(&thisDev->rcvBufBuf,
                                           RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf),
                                           &thisDev->interruptObj);
            // ASSERT the pointer is actually outside our FIR DMA buffer
            ASSERT(rcvBuf->dataBuf < thisDev->dmaReadBuf ||
                   rcvBuf->dataBuf >= thisDev->dmaReadBuf+RCV_DMA_SIZE);
        }
        rcvBuf->dataBuf = NULL;

        rcvBuf->state = STATE_FREE;

        VerifyNdisPacket(rcvBuf->packet, 0);
        NDISSynchronizedInsertHeadList(&thisDev->rcvBufFree,
                                       &rcvBuf->listEntry,
                                       &thisDev->interruptObj);
    }
    else {
        LOG("Error: Packet in ReturnPacketHandler was not PENDING");

        DBGERR(("Packet in ReturnPacketHandler was not PENDING."));
    }

    NdisAcquireSpinLock(&thisDev->QueueLock);

    PacketsLeft=NdisInterlockedDecrement(&thisDev->PacketsSentToProtocol);

    if (thisDev->Halting && (PacketsLeft == 0)) {

        NdisSetEvent(&thisDev->ReceiveStopped);
    }

    NdisReleaseSpinLock(&thisDev->QueueLock);

    VerifyNdisPacket(rcvBuf->packet, 1);

}


VOID
GivePacketToSirISR(
    IrDevice *thisDev
    )

{

    thisDev->portInfo.writeComBufferPos = 0;
    thisDev->portInfo.SirWritePending = TRUE;
    thisDev->nowReceiving = FALSE;

    SetCOMPort(thisDev->portInfo.ioBase, INT_ENABLE_REG_OFFSET, XMIT_MODE_INTS_ENABLE);

}

VOID
SendCurrentPacket(
    IrDevice *thisDev
    )

{
    BOOLEAN         Result;
    PNDIS_PACKET    FailedPacket=NULL;


    NdisAcquireSpinLock(&thisDev->QueueLock);

    thisDev->TransmitIsIdle=FALSE;

    if (thisDev->CurrentPacket == thisDev->lastPacketAtOldSpeed){
        thisDev->setSpeedAfterCurrentSendPacket = TRUE;
    }


    if (thisDev->currentSpeed > MAX_SIR_SPEED) {
        //
        //  send via FIR
        //
        if (thisDev->FirReceiveDmaActive) {

            thisDev->FirReceiveDmaActive=FALSE;
            //
            //  receive dma is running, stop it
            //
            CompleteDmaTransferFromDevice(
                &thisDev->DmaUtil
                );

        }

        thisDev->HangChk=0;

        thisDev->FirTransmitPending = TRUE;
        //
        // Use DMA swap bit to switch to DMA to Transmit.
        //
        SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 2, 2, 0x0B);

        //
        // Switch on the DMA interrupt to decide when
        // transmission is complete.
        //
        thisDev->FirIntMask = 0x14;

        SyncSetInterruptMask(thisDev, TRUE);
        //
        // Kick off the first transmit.
        //

        NdisToFirPacket(
            thisDev->CurrentPacket,
            (UCHAR *) thisDev->TransmitDmaBuffer,
            MAX_IRDA_DATA_SIZE,
            &thisDev->TransmitDmaLength
            );


        LOG_FIR("Sending packet %d",thisDev->TransmitDmaLength);
        DEBUGFIR(DBG_PKT, ("NSC: Sending packet\n"));
        DBGPRINTBUF(thisDev->TransmitDmaBuffer,thisDev->TransmitDmaLength);

        {
            UCHAR   LsrValue;

            //
            //  make sure the transmitter is empty before starting to send this frame
            //
            LsrValue=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, LSR_OFFSET);

            if ((LsrValue & (LSR_TXRDY | LSR_TXEMP)) != (LSR_TXRDY | LSR_TXEMP)) {

                ULONG   LoopCount=0;

                while (((LsrValue & (LSR_TXRDY | LSR_TXEMP)) != (LSR_TXRDY | LSR_TXEMP)) && (LoopCount < 16)) {

                    LsrValue=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, LSR_OFFSET);
                    LoopCount++;
                }

                LOG_ERROR("SendCurrentPacket: Looped %d times waiting for tx empty",LoopCount);
            }

        }

        /* Setup Transmit DMA. */
        StartDmaTransferToDevice(
                              &thisDev->DmaUtil,
                              thisDev->xmitDmaBuffer,
                              0,
                              thisDev->TransmitDmaLength
                              );
#if 0
        {
            ULONG    CurrentDMACount;

            CurrentDMACount = NdisMReadDmaCounter(thisDev->DmaHandle);

            LOG("SendCurrentPacket: dma count after start %d",CurrentDMACount);
        }
#endif
        SyncSetInterruptMask(thisDev, TRUE);


    } else {
        //
        //  SIR mode transfer
        //
        /*
         * See if this was the last packet before we need to change
         * speed.
         */

        /*
         *  Send one packet to the COMM port.
         */
        DBGPKT(("Sending packet 0x%x (0x%x).", thisDev->packetsSent++, thisDev->CurrentPacket));

    	/*
    	 *  Convert the NDIS packet to an IRDA packet.
    	 */
    	Result = NdisToIrPacket(
                                thisDev->CurrentPacket,
    							(UCHAR *)thisDev->portInfo.writeComBuffer,
    							MAX_IRDA_DATA_SIZE,
    							&thisDev->portInfo.writeComBufferLen
                                );
    	if (Result){

            LOG_SIR("Sending packet %d",thisDev->portInfo.writeComBufferLen);

            NdisMSynchronizeWithInterrupt(
                &thisDev->interruptObj,
                GivePacketToSirISR,
                thisDev
                );

    	} else {

            ASSERT(0);
            FailedPacket=thisDev->CurrentPacket;
            thisDev->CurrentPacket=NULL;

        }
    }


    NdisReleaseSpinLock(&thisDev->QueueLock);

    if (FailedPacket != NULL) {

        NdisMSendComplete(thisDev->ndisAdapterHandle, FailedPacket, NDIS_STATUS_FAILURE );
        ProcessSendQueue(thisDev);
    }

    return;
}

VOID
DelayedWrite(
    IN PVOID SystemSpecific1,
    IN PVOID FunctionContext,
    IN PVOID SystemSpecific2,
    IN PVOID SystemSpecific3
    )
{
    IrDevice *thisDev = FunctionContext;
#if DBG
    ASSERT(thisDev->WaitingForTurnAroundTimer);

    thisDev->WaitingForTurnAroundTimer=FALSE;
#endif

    LOG("Turn around timer expired");
    SendCurrentPacket(thisDev);
}



VOID
ProcessSendQueue(
    IrDevice *thisDev
    )

{

    PNDIS_PACKET    Packet=NULL;
    PLIST_ENTRY     ListEntry;

    NdisAcquireSpinLock(&thisDev->QueueLock);

    if (thisDev->CurrentPacket == NULL) {
        //
        //  not currently processing a send
        //
        if (!IsListEmpty(&thisDev->SendQueue)) {
            //
            //  we have some queue packets to process
            //
            ListEntry=RemoveHeadList(&thisDev->SendQueue);

            Packet=  CONTAINING_RECORD(
                                       ListEntry,
                                       NDIS_PACKET,
                                       MiniportReserved
                                       );

            thisDev->CurrentPacket=Packet;



            NdisReleaseSpinLock(&thisDev->QueueLock);

            {

                PNDIS_IRDA_PACKET_INFO packetInfo;

                /*
                 *  Enforce the minimum turnaround time that must transpire
                 *  after the last receive.
                 */
                packetInfo = GetPacketInfo(Packet);

                //
                //  see if this packet is requesting a turnaround time or not
                //
                if (packetInfo->MinTurnAr

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -