firda.c

来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 2,000 行 · 第 1/5 页

C
2,000
字号
 *************************************************************************
 *  MiniportSend
 *************************************************************************
 *
 *
 *  Transmits a packet through the network interface card onto the medium.
 *
 *
 *
 */
NDIS_STATUS MiniportSend(
                        IN NDIS_HANDLE MiniportAdapterContext,
                        IN PNDIS_PACKET Packet,
                        IN UINT Flags
                        )
{
    NDIS_STATUS stat;
    BOOLEAN TxWasActive;

    IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);

    LOG(TEXT("==> MiniportSend"), 0);
    DBGOUT((TEXT("==> MiniportSend(0x%x, packet = 0x%x)"), 
            (UINT)MiniportAdapterContext, Packet));

    DEBUGMSG(DBG_TX | DBG_TRACE_TX, 
        (TEXT("+MiniportSend(pkt = 0x%x)\r\n"), Packet));

    //
    //  If we have temporarily lost access to the hardware, don't queue up any sends.
    //  return failure until we regain access to the hw.
    //

    NdisAcquireSpinLock(&thisDev->Lock);

    if (thisDev->resourcesReleased){
	   	DEBUGMSG(DBGIRDA, (TEXT("Resource Released\r\n")));
        NdisReleaseSpinLock(&thisDev->Lock);
        ASSERT(FALSE);
        return (NDIS_STATUS_FAILURE);
    }

    IRFIR_LOG_NDIS_PACKET(LOG_TXFRAME, Packet);

    if (thisDev->currentSpeed > MAX_SIR_SPEED)
    {
       DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend => MIR | FIR\r\n")));

       TxWasActive = (thisDev->AdapterState==ADAPTER_TX);
       thisDev->AdapterState = ADAPTER_TX;
       NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_PENDING);
	   InsertTailList(&thisDev->SendQueue,
            (PLIST_ENTRY)Packet->MiniportReserved);

      if (!TxWasActive)
      {
            DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend => TX idle, do work...\r\n")));
            //
            // Complete the Receive DMA before starting the next
            // set of transmits.
            // 
         NdisMCompleteDmaTransfer(&stat, thisDev->DmaHandle,
                                     thisDev->rcvDmaBuffer, 
                                     thisDev->rcvDmaOffset,
                                     thisDev->rcvDmaSize, FALSE);

            DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend: CompleteDma returned 0x%x\r\n"),
                                    stat));

         if (!RegStats.RxWindow) {
                LOG(TEXT("SendPacketsHandler - RxWindow has zero value"), 0);
                DBGOUT((TEXT("SendPacketsHandler - RxWindow has zero value")));
         }
    
         if (RegStats.RxDPC_Window > 1) {
	      RegStats.RxDPC_G1_Count++;
         }
    
         RegStats.RxWindowMax = MAX(RegStats.RxWindowMax, RegStats.RxWindow);
         RegStats.RxWindow = 0;
         RegStats.RxDPC_WindowMax = MAX(RegStats.RxDPC_WindowMax, RegStats.RxDPC_Window);
         RegStats.RxDPC_Window = 0;

       //
       // Use DMA swap bit to switch to DMA to Transmit.
       //

    
       //
       // Kick off the first transmit.
       //
       FIR_Send(thisDev);
     }
    else {
         DEBUGFIR(DBGIRDA, (TEXT("MSend: TX active, queue packet\r\n")));
    }
     stat = NDIS_STATUS_PENDING;
    }
    else
    {
        stat = SendCommPacket(thisDev, Packet);
        DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend: SendCommPacket returned 0x%x\r\n"),
                                stat));
    }
	NdisReleaseSpinLock(&thisDev->Lock);
    LOG(TEXT("<== MiniportSend"), 1);
    DBGOUT((TEXT("<== MiniportSend [%s]"), DBG_NDIS_RESULT_STR(stat)));
    DEBUGMSG(DBG_TX | DBG_TRACE_TX, (TEXT("-MiniportSend [0x%x]\r\n"), stat));

    return (stat);
}



/*
 *************************************************************************
 *  MiniportTransferData
 *************************************************************************
 *
 *
 *  Copies the contents of the received packet to a specified packet buffer.
 *
 *
 *
 */
NDIS_STATUS MiniportTransferData(
                                    OUT PNDIS_PACKET   Packet,
                                    OUT PUINT          BytesTransferred,
                                    IN NDIS_HANDLE     MiniportAdapterContext,
                                    IN NDIS_HANDLE     MiniportReceiveContext,
                                    IN UINT            ByteOffset,
                                    IN UINT            BytesToTransfer
                                    )
{

    RETAILMSG(DBGIRDA, (TEXT("MiniportTransferData - should not get called.")));

    /*
     *  We always pass the entire packet up in the indicate-receive call,
     *  so we will never get this callback.
     *  (We can't do anything but return failure anyway,  
     *   since NdisMIndicateReceivePacket does not pass up a packet context).
     */

    ASSERT(FALSE);
    *BytesTransferred = 0;
    return NDIS_STATUS_FAILURE;
}

/*
 *************************************************************************
 *  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;

    DBGOUT((TEXT("ReturnPacketHandler(0x%x, packet = 0x%x)"), 
            (UINT)MiniportAdapterContext, Packet));

    NdisAcquireSpinLock(&thisDev->Lock);

    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((TEXT("Reclaimed rcv packet 0x%x."), (UINT)Packet));

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

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

        rcvBuf->state = STATE_FREE;

        LOG_RemoveEntryList(thisDev, rcvBuf);
        RemoveEntryList(&rcvBuf->listEntry);
        VerifyNdisPacket(rcvBuf->packet, 0);
        InsertHeadList(&thisDev->rcvBufFree, &rcvBuf->listEntry);
    }
    else {
        LOG(TEXT("Error: Packet in ReturnPacketHandler was not PENDING"), 0);
        DBGERR((TEXT("Packet in ReturnPacketHandler was not PENDING.")));
    }
    VerifyNdisPacket(rcvBuf->packet, 1);
    

    NdisReleaseSpinLock(&thisDev->Lock);

}



/*
 *************************************************************************
 *  AllocateCompleteHandler
 *************************************************************************
 *
 *  Indicate completion of an NdisMAllocateSharedMemoryAsync call.
 *  We never call that function, so we should never get entered here.
 *
 */
VOID AllocateCompleteHandler(   NDIS_HANDLE MiniportAdapterContext,
                                PVOID VirtualAddress,
                                PNDIS_PHYSICAL_ADDRESS  PhysicalAddress,
                                ULONG Length,
                                PVOID Context)
{
    DBGERR((TEXT("AllocateCompleteHandler - should not get called")));
}




/*
 *************************************************************************
 *  PortReadyForWrite
 *************************************************************************
 *
 *  Called when COM port is ready for another write packet.  
 *  Send the first frame in the send queue.
 *
 *  Return TRUE iff send succeeded.
 *
 *  NOTE: Do not call inside of interrupt context.
 *
 */
NDIS_STATUS PortReadyForWrite(IrDevice *thisDev, BOOLEAN firstBufIsPending)
{
    NDIS_STATUS Result = NDIS_STATUS_FAILURE;
    BOOLEAN sendSucceeded;
    PLIST_ENTRY ListEntry;

#if 0
    DEBUGMSG(DBG_TX, (TEXT("prfw\r\n")));

    DBGOUT((TEXT("PortReadyForWrite(dev=0x%x, %xh, %hs)"),    
        (UINT)thisDev, 
        thisDev->portInfo.ioBase, 
        (CHAR *)(firstBufIsPending ? "pend" : "not pend")));
#endif
    ListEntry = MyRemoveHeadList(&thisDev->SendQueue);
    if (ListEntry){

        PNDIS_PACKET packetToSend = CONTAINING_RECORD(ListEntry,
                                                      NDIS_PACKET,
                                                      MiniportReserved);
        PNDIS_IRDA_PACKET_INFO packetInfo;


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

        //
        // NOTE: Don't use NdisStallExecution for turnaround delay since
        //       you shouldn't stall for more than 60 us. Calling
        //       NdisStallExecution for large times will degrade system
        //       performance.
        //

        if (packetInfo->MinTurnAroundTime){

            UINT usecToWait = packetInfo->MinTurnAroundTime;
            UINT msecToWait;

            packetInfo->MinTurnAroundTime = 0;

            InsertHeadList(&thisDev->SendQueue, (PLIST_ENTRY)packetToSend->MiniportReserved);

            // Ndis timer has a 1ms granularity (in theory).  Let's round off.
            msecToWait = (usecToWait<1000) ? 1 : (usecToWait+500)/1000;
        #ifdef UNDER_CE
            NdisMSetTimer(&thisDev->TurnaroundTimer, msecToWait);
        #else // UNDER_CE
            NdisSetTimer(&thisDev->TurnaroundTimer, msecToWait);
        #endif //!UNDER_CE
            return NDIS_STATUS_PENDING; // Say we're successful.  We'll come back here.
        }

        /*
         * See if this was the last packet before we need to change
         * speed.
         */
        if (packetToSend == thisDev->lastPacketAtOldSpeed){
            thisDev->lastPacketAtOldSpeed = NULL;
            thisDev->setSpeedAfterCurrentSendPacket = TRUE;
        }

        /*
         *  Send one packet to the COMM port.
         */
        DBGPKT((TEXT("Sending packet 0x%x (0x%x)."), 
            thisDev->packetsSent++, (UINT)packetToSend));
        sendSucceeded = DoSend(thisDev, packetToSend);

        /*
         *  If the buffer we just sent was pending 
         *  (i.e. we returned NDIS_STATUS_PENDING for it in MiniportSend),
         *  then hand the sent packet back to the protocol.
         *  Otherwise, we're just delivering it synchronously from MiniportSend.
         */
        if (firstBufIsPending){
            DBGOUT((TEXT("Calling NdisMSendComplete")));
            NdisMSendComplete(thisDev->ndisAdapterHandle, packetToSend, 
                              (NDIS_STATUS)(sendSucceeded ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE));

            // If the packet was pended, it means this packet was not just
            // received in MiniportSend.  If we're being called from there,
            // we want them to pend the packet they just did receive, so we
            // return PENDING.
            Result = NDIS_STATUS_PENDING;
        }
        else
        {
            Result = sendSucceeded ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
        }

    }


    DBGOUT((TEXT("PortReadyForWrite done.")));

    return Result;
}

/*
 *************************************************************************
 *  DriverEntry
 *************************************************************************
 *
 *  Only include if IRMINI is a stand-alone driver.
 *
 */
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
#pragma NDIS_INIT_FUNCTION(DriverEntry)

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    NTSTATUS result = STATUS_SUCCESS, stat;
    NDIS_HANDLE wrapperHandle;
    NDIS40_MINIPORT_CHARACTERISTICS info;

    RETAILMSG(DBGIRDA, (TEXT("==> DriverEntry(0x%x, 0x%x\r\n)"), DriverObject, RegistryPath));

	

#ifndef UNDER_CE
    if (AbortLoad)
    {
        return STATUS_CANCELLED;
    }
#endif // !UNDER_CE

    NdisMInitializeWrapper( (PNDIS_HANDLE)&wrapperHandle,
                            DriverObject,
                            RegistryPath,
                            NULL
                          );
    DEBUGFIR(DBGIRDA, (TEXT("NDIS wrapper handle is 0x%xh\r\n"), wrapperHandle));

	memset(&info, 0, sizeof(info));

    info.MajorNdisVersion           =   (UCHAR)NDIS_MAJOR_VERSION;      
    info.MinorNdisVersion           =   (UCHAR)NDIS_MINOR_VERSION;  
    info.CheckForHangHandler        =   MiniportCheckForHang;   
    info.HaltHandler                =   MiniportHalt;   
    info.InitializeHandler          =   MiniportInitialize;  
    info.QueryInformationHandler    =   MiniportQueryInformation; 
    info.ReconfigureHandler         =   MiniportReconfigure;  
    info.ResetHandler               =   MiniportReset; 
    info.SendHandler                =   MiniportSend;  
    info.SetInformationHandler      =   

⌨️ 快捷键说明

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