resource.c

来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 396 行

C
396
字号
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//

#include "firda.h"

/*
 *************************************************************************
 *  MyMemAlloc -  Allocates memory
 *************************************************************************
 *
 */
PVOID MyMemAlloc(UINT size, BOOLEAN isDmaBuf)
{
    NDIS_STATUS stat;
    PVOID memptr;

#ifdef UNDER_CE
    // For Windows CE, we allocate our contiguous memory for DMA from
    // a block of physical memory reserved in the memory map. See externs.h
    // for more details.
    ASSERT(isDmaBuf == FALSE);
#endif 

    if (isDmaBuf){
        NDIS_PHYSICAL_ADDRESS maxAddr = NDIS_PHYSICAL_ADDRESS_CONST(0x0fffff, 0); 
        stat = NdisAllocateMemory(  &memptr, 
                                    size, 
                                    NDIS_MEMORY_CONTIGUOUS|NDIS_MEMORY_NONCACHED, 
                                    maxAddr); 
    }
    else {
        NDIS_PHYSICAL_ADDRESS noMaxAddr = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
        stat = NdisAllocateMemory(  &memptr, 
                                    size, 
                                    0, 
                                    noMaxAddr); 
    }

    if (stat == NDIS_STATUS_SUCCESS){
        NdisZeroMemory((PVOID)memptr, size);
    }
    else {
        DBGERR((TEXT("Memory allocation failed")));
        memptr = NULL;
    }

    return memptr;
}


/*
 *************************************************************************
 *  MyMemFree
 *************************************************************************
 *
 */
VOID MyMemFree(PVOID memptr, UINT size, BOOLEAN isDmaBuf)
{
    UINT flags = (isDmaBuf) ? NDIS_MEMORY_CONTIGUOUS|NDIS_MEMORY_NONCACHED : 0;
#ifdef UNDER_CE    
    ASSERT(isDmaBuf == FALSE);
#endif // UNDER_CE
    NdisFreeMemory(memptr, size, flags);

}


/*
 *************************************************************************
 *  NewDevice
 *************************************************************************
 *
 */
IrDevice *NewDevice()
{
    IrDevice *newdev;

	RETAILMSG(DBGIRDA, (TEXT("NewDevice -->\r\n")));

    newdev = MyMemAlloc(sizeof(IrDevice), FALSE);
    if (newdev){
        InitDevice(newdev);
    }

	RETAILMSG(DBGIRDA, (TEXT("NewDevice <--\r\n")));
    return newdev;
}


/*
 *************************************************************************
 *  FreeDevice
 *************************************************************************
 *
 */
VOID FreeDevice(IrDevice *dev)
{
    CloseDevice(dev);   
    NdisReleaseSpinLock(&dev->Lock);
    NdisFreeSpinLock(&dev->Lock);
    MyMemFree((PVOID)dev, sizeof(IrDevice), FALSE);
}



/*
 *************************************************************************
 *  InitDevice
 *************************************************************************
 *
 *  Zero out the device object.
 *
 *  Allocate the device object's spinlock, which will persist while
 *  the device is opened and closed.
 *
 */
VOID InitDevice(IrDevice *thisDev)
{
    NdisZeroMemory((PVOID)thisDev, sizeof(IrDevice));
    NdisInitializeListHead(&thisDev->SendQueue);
    NdisAllocateSpinLock(&thisDev->Lock);
#ifdef UNDER_CE
    // CE - calls NdisMInitializeTimer instead of NdisInitializeTimer. This
    //      requires the NdisAdapterHandle passed into MiniportInitialize.
    //      Therefore CE initializes the timer after the call to
    //      NewDevice in MiniportInitialize.
#else // UNDER_CE
        NdisInitializeTimer(&thisDev->TurnaroundTimer,
                        DelayedWrite,
                        thisDev);
#endif // !UNDER_CE
    NdisInitializeListHead(&thisDev->rcvBufBuf);
    NdisInitializeListHead(&thisDev->rcvBufFree);
    NdisInitializeListHead(&thisDev->rcvBufFull);
    NdisInitializeListHead(&thisDev->rcvBufPend);

    
	RETAILMSG(DBGIRDA, (TEXT("InitDevice <--\r\n")));
}




/*
 *************************************************************************
 *  OpenDevice
 *************************************************************************
 *
 *  Allocate resources for a single device object.
 *
 *  This function should be called with device lock already held.
 *
 */
BOOLEAN OpenDevice(IrDevice *thisDev)
{
    BOOLEAN result = FALSE;
    NDIS_STATUS stat;
    UINT bufIndex;
#ifdef UNDER_CE
    PVOID  pvRcvPkt;
#endif // UNDER_CE

    DBGOUT((TEXT("OpenDevice()")));

    if (!thisDev){ 
        return FALSE;
    }


    /*
     *  Allocate the NDIS packet and NDIS buffer pools 
     *  for this device's RECEIVE buffer queue.
     *  Our receive packets must only contain one buffer apiece,
     *  so #buffers == #packets.
     */

    NdisAllocatePacketPool(&stat, &thisDev->packetPoolHandle, NUM_RCV_BUFS, 24);
    if (stat != NDIS_STATUS_SUCCESS){
        goto _openDone;
    }
    NdisAllocateBufferPool(&stat, &thisDev->bufferPoolHandle, NUM_RCV_BUFS);
    if (stat != NDIS_STATUS_SUCCESS){
        goto _openDone;
    }

#ifdef UNDER_CE    
    // Windows CE. We get a chunk of memory from our contiguous physical
    // buffer. See externs.h for detailed information.

    pvRcvPkt = (PUCHAR)g_pvDmaVirtualBase + RCVPACKETS_OFFSET;
#endif // UNDER_CE

     //  Initialize each of the RECEIVE packet objects for this device.
     //
     RETAILMSG(DBGIRDA, (TEXT("OpenDevice: Value of NUM_RCV_BUFS - %d === sizeof(rcvBuffer) - %d\r\n"), NUM_RCV_BUFS, sizeof(rcvBuffer)));
     for (bufIndex = 0; bufIndex < NUM_RCV_BUFS; bufIndex++){

        rcvBuffer *rcvBuf = MyMemAlloc(sizeof(rcvBuffer), FALSE);
        PVOID buf;

        if (!rcvBuf)
        {
            goto _openDone;
        }

        rcvBuf->state = STATE_FREE;
        rcvBuf->isDmaBuf = FALSE;

        /*
         *  Allocate a data buffer
         *
         *  This buffer gets swapped with the one on comPortInfo
         *  and must be the same size.
         */
        rcvBuf->dataBuf = NULL;
        
    #ifdef UNDER_CE
        buf = pvRcvPkt;
        pvRcvPkt = (PUCHAR)pvRcvPkt + RCV_BUFFER_SIZE;
    #else // UNDER_CE
        buf = MyMemAlloc(RCV_BUFFER_SIZE, TRUE);
        if (!buf){
            goto _openDone;
        }
    #endif //!UNDER_CE

        // We treat the beginning of the buffer as a LIST_ENTRY.

        // Normally we would use NDISSynchronizeInsertHeadList, but the 
        // Interrupt hasn't been registered yet.
        InsertHeadList(&thisDev->rcvBufBuf, (PLIST_ENTRY)buf);

        /*
         *  Allocate the NDIS_PACKET.
         */
        NdisAllocatePacket(&stat, &rcvBuf->packet, thisDev->packetPoolHandle);
        if (stat != NDIS_STATUS_SUCCESS){
            goto _openDone;
        }
#if 1
        /*
         *  For future convenience, set the MiniportReserved portion of the packet
         *  to the index of the rcv buffer that contains it.
         *  This will be used in ReturnPacketHandler.
         */
        *(ULONG *)rcvBuf->packet->MiniportReserved = (ULONG)rcvBuf;
#endif
                                                            
        rcvBuf->dataLen = 0;

        InsertHeadList(&thisDev->rcvBufFree, &rcvBuf->listEntry);

    }


    /*
     *  Set mediaBusy to TRUE initially.  That way, we won't
     *  IndicateStatus to the protocol in the ISR unless the
     *  protocol has expressed interest by clearing this flag
     *  via MiniportSetInformation(OID_IRDA_MEDIA_BUSY).
     */
    thisDev->mediaBusy = FALSE;  
    thisDev->haveIndicatedMediaBusy = FALSE;

    /*
     *  Will set speed to 9600 baud initially.
     */
    thisDev->linkSpeedInfo = &supportedBaudRateTable[BAUDRATE_9600];

    thisDev->lastPacketAtOldSpeed = NULL;       
    thisDev->setSpeedAfterCurrentSendPacket = FALSE;

    result = TRUE;

    _openDone:
    if (!result){
        /*
         *  If we're failing, close the device to free up any resources
         *  that were allocated for it.  
         */
        CloseDevice(thisDev);
        DBGOUT((TEXT("OpenDevice() failed")));
    }
    else {
        DBGOUT((TEXT("OpenDevice() succeeded")));
    }
	RETAILMSG(DBGIRDA, (TEXT("OpenDevice <--\r\n")));
    return result;

}



/*
 *************************************************************************
 *  CloseDevice
 *************************************************************************
 *
 *  Free the indicated device's resources.  
 *
 *
 *  Called for shutdown and reset.  
 *  Don't clear ndisAdapterHandle, since we might just be resetting.
 *  This function should be called with device lock held.
 *
 *
 */
VOID CloseDevice(IrDevice *thisDev)
{
    PLIST_ENTRY ListEntry;

    DBGOUT((TEXT("CloseDevice()")));

    if (!thisDev){
        return;
    }

    /*
     *  Free all resources for the RECEIVE buffer queue.
     */

    while (!IsListEmpty(&thisDev->rcvBufFree))
    {
        rcvBuffer *rcvBuf;
        RETAILMSG(DBGIRDA, (TEXT("Calling RemoveHeadList \r\n")));
        ListEntry = RemoveHeadList(&thisDev->rcvBufFree);
        rcvBuf = CONTAINING_RECORD(ListEntry,
                                   rcvBuffer,
                                   listEntry);

        if (rcvBuf->packet){
	     RETAILMSG(DBGIRDA, (TEXT("Calling NdisFreePacket first time \r\n")));
            NdisFreePacket(rcvBuf->packet);
            rcvBuf->packet = NULL;
        }
	 RETAILMSG(DBGIRDA, (TEXT("Calling MyMemFree first time \r\n")));
        MyMemFree(rcvBuf, sizeof(rcvBuffer), FALSE);
    }


    while (!IsListEmpty(&thisDev->rcvBufBuf))
    {
        ListEntry = RemoveHeadList(&thisDev->rcvBufBuf);
    #ifdef UNDER_CE
        // Windows CE. Don't need to free since it is just a pointer in our
        // reserved physical memory.
    #else
        MyMemFree(ListEntry, RCV_BUFFER_SIZE, TRUE);
    #endif // !UNDER_CE
    }

    /*
     *  Free the packet and buffer pool handles for this device.
     */
    if (thisDev->packetPoolHandle){
        RETAILMSG(DBGIRDA, (TEXT("Calling NdisFreePacketPool \r\n")));
        NdisFreePacketPool(thisDev->packetPoolHandle);
        thisDev->packetPoolHandle = NULL;
    }
    if (thisDev->bufferPoolHandle){
        RETAILMSG(DBGIRDA, (TEXT("Calling NdisFreeBufferPool \r\n")));	 
        NdisFreeBufferPool(thisDev->bufferPoolHandle);
        thisDev->bufferPoolHandle = NULL;
    }


    /*
     *  Free all resources for the SEND buffer queue.
     */
    while (ListEntry = MyRemoveHeadList(&thisDev->SendQueue)){
        PNDIS_PACKET Packet = CONTAINING_RECORD(ListEntry,
                                                NDIS_PACKET,
                                                MiniportReserved);
        NdisReleaseSpinLock(&thisDev->Lock);
        NdisMSendComplete(thisDev->ndisAdapterHandle, Packet, NDIS_STATUS_FAILURE);
        NdisAcquireSpinLock(&thisDev->Lock);
    }


    thisDev->mediaBusy = FALSE;
    thisDev->haveIndicatedMediaBusy = FALSE;

    thisDev->linkSpeedInfo = NULL;

}


⌨️ 快捷键说明

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