firda.c

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

C
2,000
字号


    NdisAcquireSpinLock(&thisDev->Lock);


    if (thisDev->portInfo.writePending)
    {
        switch (thisDev->HangChk)
        {
            case 0:
                thisDev->HangChk++;
                break;
            default:
                thisDev->HangChk++;
        //        RETAILMSG(DBGIRDA, (TEXT("IRDA: CheckForHang--we appear hung\n")));

                // Issue a soft reset to the transmitter & receiver.

         //       g_pIRDAregs->rIRDA_FCR |= (3 <<1);
                
                NdisReleaseSpinLock(&thisDev->Lock);
                MiniportHandleInterrupt(MiniportAdapterContext);
                NdisAcquireSpinLock(&thisDev->Lock);
                break;
        }
    }

    NdisReleaseSpinLock(&thisDev->Lock);


    return FALSE;
	
}


/*
 *************************************************************************
 *  MiniportDisableInterrupt
 *************************************************************************
 *
 *  Disables the NIC from generating interrupts.
 *
 */
VOID MiniportDisableInterrupt(NDIS_HANDLE MiniportAdapterContext)
{
    IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);

   // RETAILMSG(DBGIRDA,(TEXT("==> MiniportDisableInterrupt\r\n")));
    
    NdisAcquireSpinLock(&thisDev->Lock);

    if (!thisDev->resourcesReleased){
		 SetCOMInterrupts(thisDev, FALSE);
    }

    NdisReleaseSpinLock(&thisDev->Lock);
   
    
}


/*
 *************************************************************************
 *  MiniportEnableInterrupt
 *************************************************************************
 *
 *  Enables the IR card to generate interrupts.
 *
 */
VOID MiniportEnableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
{
    IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);

    //RETAILMSG(DBGIRDA, (TEXT("==> MiniportEnableInterrupt\r\n")));
                       
    NdisAcquireSpinLock(&thisDev->Lock);

    if (!thisDev->resourcesReleased){

		 SetCOMInterrupts(thisDev, TRUE);

    }

    NdisReleaseSpinLock(&thisDev->Lock);

}


/*
 *************************************************************************
 *  MiniportHalt
 *************************************************************************
 *
 *  Halts the network interface card.
 *
 */
VOID MiniportHalt(IN NDIS_HANDLE MiniportAdapterContext)
{
    IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);

    DEBUGFIR(DBGIRDA, (TEXT("==> MiniportHalt\r\n")));
    DEBUGFIR(DBGIRDA, (TEXT("==> MiniportHalt(0x%x)"), (UINT)MiniportAdapterContext));

    /*
     *  Remove this device from our global list
     */

    if (thisDev == firstIrDADevice){
        firstIrDADevice = firstIrDADevice->next;
    }
    else {
        IrDevice *dev;
        for (dev = firstIrDADevice; dev && (dev->next != thisDev);
            dev = dev->next){}
        if (dev) {
            dev->next = dev->next->next;
        }
        else {
            /*
             * Don't omit this error check.  I've seen NDIS call
             * MiniportHalt with a bogus context when the system
             * gets corrupted.
             */
            DBGERR((TEXT("Error: Bad context in MiniportHalt\r\n")));
            return;
        }
    }


    /*
     *  Now destroy the device object.
     */
    NdisAcquireSpinLock(&thisDev->Lock);
    IR24A0_Shutdown(thisDev);
    DoClose(thisDev);
//    NdisMDeregisterIoPortRange(thisDev->ndisAdapterHandle, thisDev->ioBase, 8, (PVOID)thisDev->mappedPortRange);
    FreeDevice(thisDev);
    DEBUGFIR(DBGIRDA, (TEXT("<== MiniportHalt\r\n")));
    DEBUGFIR(DBGIRDA, (TEXT("<== MiniportHalt(0x%x)"), (UINT)MiniportAdapterContext));
}


/*
 *************************************************************************
 *  MiniportSyncHandleInterrupt
 *************************************************************************
 *
 * This function is called from MiniportHandleInterrupt via
 * NdisMSynchronizeWithInterrupt to synchronize with MiniportISR.  This is
 * required because the deferred procedure call (MiniportHandleInterrupt)
 * shares data with MiniportISR but cannot achieve mutual exclusion with a
 * spinlock because ISR's are not allowed to acquire spinlocks.
 * This function should be called WITH DEVICE LOCK HELD, however, to
 * synchronize with the rest of the miniport code (besides the ISR).
 * The device's IRQ is masked out in the PIC while this function executes,
 * so don't make calls up the stack.
 */  
BOOLEAN MiniportSyncHandleInterrupt(PVOID MiniportAdapterContext)
{
    IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);

    // QueueLock should be held.

    DEBUGFIR(DBGIRDA, (TEXT("==> MiniportSyncHandleInterrupt\r\n")));
    DEBUGFIR(DBGIRDA, (TEXT("==> MiniportSyncHandleInterrupt(0x%x)"), (UINT)MiniportAdapterContext));

#if 0 // Since we're using queues, this function doesn't really do anything.
    /*
     *  Update .firstRcvBufIndex and .lastRcvBufIndex.
     */
    while ((thisDev->firstRcvBufIndex != NO_BUF_INDEX) &&
           (thisDev->rcvBufs[thisDev->firstRcvBufIndex].state ==
            STATE_FREE)) {

        if (thisDev->firstRcvBufIndex == thisDev->lastRcvBufIndex) {
            thisDev->firstRcvBufIndex =
            thisDev->lastRcvBufIndex = NO_BUF_INDEX;
        }
        else {
            thisDev->firstRcvBufIndex =
            NEXT_RCV_BUF_INDEX(thisDev->firstRcvBufIndex);
        }
    }
#endif

    DEBUGFIR(DBGIRDA, (TEXT("<== MiniportSyncHandleInterrupt\r\n")));
    DEBUGFIR(DBGIRDA, (TEXT("<== MiniportSyncHandleInterrupt(0x%x)"), (UINT)MiniportAdapterContext));
    
    return TRUE;
}



void
InsertBufferSorted(
    PLIST_ENTRY Head,
    rcvBuffer *rcvBuf
    )
{
    PLIST_ENTRY ListEntry;

    if (IsListEmpty(Head))
    {
        InsertHeadList(Head, &rcvBuf->listEntry);
    }
    else
    {
        BOOLEAN EntryInserted = FALSE;
        for (ListEntry = Head->Flink;
             ListEntry != Head;
             ListEntry = ListEntry->Flink)
        {
            rcvBuffer *temp = CONTAINING_RECORD(ListEntry,
                                                rcvBuffer,
                                                listEntry);
            if (temp->dataBuf > rcvBuf->dataBuf)
            {
                // We found one that comes after ours.  
                // We need to insert before it

                InsertTailList(ListEntry, &rcvBuf->listEntry);
                EntryInserted = TRUE;
                break;
            }
        }
        if (!EntryInserted)
        {
            // We didn't find an entry on the last who's address was later
            // than our buffer.  We go at the end.
            InsertTailList(Head, &rcvBuf->listEntry);
        }
    }
}

/*
 *************************************************************************
 *  DeliverFullBuffers
 *************************************************************************
 *
 *  Deliver received packets to the protocol.
 *  Return TRUE if delivered at least one frame.
 *
 */ 
BOOLEAN DeliverFullBuffers(IrDevice *thisDev)
{
    BOOLEAN result = FALSE;
    PLIST_ENTRY ListEntry;

    LOG(TEXT("==> DeliverFullBuffers"), 0);
    DBGOUT((TEXT("==> DeliverFullBuffers(0x%x)"), (UINT) thisDev));


    /*
     *  Deliver all full rcv buffers
     */

    for (
         ListEntry = MyRemoveHeadList(&thisDev->rcvBufFull);
         ListEntry;
         ListEntry = MyRemoveHeadList(&thisDev->rcvBufFull)
        )
    {
        rcvBuffer *rcvBuf = CONTAINING_RECORD(ListEntry,
                                              rcvBuffer,
                                              listEntry);
        NDIS_STATUS stat;
        PNDIS_BUFFER packetBuf;
        SLOW_IR_FCS_TYPE fcs;
   
        VerifyNdisPacket(rcvBuf->packet, 0);

        if (thisDev->currentSpeed <= MAX_SIR_SPEED) {
        /*
         * The packet we have already has had BOFs,
         * EOF, and * escape-sequences removed.  It
         * contains an FCS code at the end, which we
         * need to verify and then remove before
         * delivering the frame.  We compute the FCS
         * on the packet with the packet FCS attached;
         * this should produce the constant value
         * GOOD_FCS.
         */
            fcs = ComputeFCS(rcvBuf->dataBuf,
                             rcvBuf->dataLen);

            if (fcs != GOOD_FCS) {
            /*
             *  FCS Error.  Drop this frame.
             */
                LOG(TEXT("Error: Bad FCS in DeliverFullBuffers"), fcs);
                DBGERR((TEXT("Bad FCS in DeliverFullBuffers bad != good 0x%x!=0x%x."),
                        (UINT)fcs, (UINT) GOOD_FCS));
                rcvBuf->state = STATE_FREE;

                DBGSTAT((TEXT("Dropped %d/%d pkts; BAD FCS (%xh!=%xh):"),
                         ++thisDev->packetsDropped,
                         thisDev->packetsDropped +
                         thisDev->packetsRcvd, fcs,
                         GOOD_FCS));

                DBGPRINTBUF(rcvBuf->dataBuf,
                            rcvBuf->dataLen);

                if (!rcvBuf->isDmaBuf) {
                    InsertTailList(&thisDev->rcvBufBuf, RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf));
                }
                rcvBuf->dataBuf = NULL;
                rcvBuf->isDmaBuf = FALSE;

                VerifyNdisPacket(rcvBuf->packet, 0);
                InsertHeadList(&thisDev->rcvBufFree, &rcvBuf->listEntry);
                //break;
                continue;
            }

        /* Remove the FCS from the end of the packet. */
            rcvBuf->dataLen -= SLOW_IR_FCS_SIZE;
        }
#ifdef DBG_ADD_PKT_ID
        if (addPktIdOn) {

            /* Remove dbg packet id. */
            USHORT uniqueId;
            rcvBuf->dataLen -= sizeof(USHORT);
            uniqueId = *(USHORT *)(rcvBuf->dataBuf+
                                   rcvBuf->dataLen);
            DBGOUT(("ID: RCVing packet %xh **",
                    (UINT)uniqueId));
            LOG("ID: Rcv Pkt id:", uniqueId);
        }
#endif

    /*
     * The packet array is set up with its NDIS_PACKET.
     * Now we need to allocate a single NDIS_BUFFER for
     * the NDIS_PACKET and set the NDIS_BUFFER to the
     * part of dataBuf that we want to deliver.
     */
        NdisAllocateBuffer(&stat, &packetBuf, 
                           thisDev->bufferPoolHandle,
                           (PVOID)rcvBuf->dataBuf, rcvBuf->dataLen); 

        if (stat != NDIS_STATUS_SUCCESS){
            LOG(TEXT("Error: NdisAllocateBuffer failed"), 0);
            DBGERR((TEXT("NdisAllocateBuffer failed")));
            DbgBreakPoint();
            break;
        }

        VerifyNdisPacket(rcvBuf->packet, 0);
        NdisChainBufferAtFront(rcvBuf->packet, packetBuf);
        LOG_PacketChain(thisDev, rcvBuf->packet);
        VerifyNdisPacket(rcvBuf->packet, 1);

    /*
     *  Fix up some other packet fields.
     */
        NDIS_SET_PACKET_HEADER_SIZE(rcvBuf->packet,
                                    IR_ADDR_SIZE+IR_CONTROL_SIZE);

        DBGPKT((TEXT("Indicating rcv packet 0x%x."),
                (UINT)rcvBuf->packet));
        DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen);

    /*  
     * Indicate to the protocol that another packet is
     * ready.  Set the rcv buffer's state to PENDING first
     * to avoid a race condition with NDIS's call to the
     * return packet handler.
     */
        rcvBuf->state = STATE_PENDING;

        *(rcvBuffer **)rcvBuf->packet->MiniportReserved = rcvBuf;
        InsertBufferSorted(&thisDev->rcvBufPend, rcvBuf);
        VerifyNdisPacket(rcvBuf->packet, 1);
        LOG_Data2(thisDev, rcvBuf->dataBuf);
        
        NdisReleaseSpinLock(&thisDev->Lock);

        NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle, &rcvBuf->packet, 1);

        NdisAcquireSpinLock(&thisDev->Lock);

        IRFIR_LOG_NDIS_PACKET(LOG_RXFRAME, rcvBuf->packet);
        result = TRUE;

        stat = NDIS_GET_PACKET_STATUS(rcvBuf->packet);          
        if (stat == NDIS_STATUS_PENDING) {
        /*
         * The packet is being delivered asynchronously.
         * Leave the rcv buffer's state as PENDING;
         * we'll get a callback when the transfer is
         * complete.  Do NOT step firstRcvBufIndex.
         * We don't really need to break out here, 
         * but we will anyways just to make things
         * simple.  This is ok since we get this
         * deferred interrupt callback for each packet
         * anyway.  It'll give the protocol a chance
         * to catch up.
         */

⌨️ 快捷键说明

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