/* ************************************************************************ * * RESOURCE.c * * * Portions Copyright (C) 1996-2001 National Semiconductor Corp. * All rights reserved. * Copyright (C) 1996-2001 Microsoft Corporation. All Rights Reserved. * * * ************************************************************************* */ #include "nsc.h" /* ************************************************************************* * MyMemAlloc ************************************************************************* * */ PVOID MyMemAlloc(UINT size, BOOLEAN isDmaBuf) { NDIS_STATUS stat; PVOID memptr; if (isDmaBuf){ NDIS_PHYSICAL_ADDRESS maxAddr = NDIS_PHYSICAL_ADDRESS_CONST(0x0fffff, 0); stat = NdisAllocateMemory( &memptr, size, NDIS_MEMORY_CONTIGUOUS|NDIS_MEMORY_NONCACHED, maxAddr); } else { stat = NdisAllocateMemoryWithTag( &memptr, size, 'rIsN' ); } if (stat == NDIS_STATUS_SUCCESS){ NdisZeroMemory((PVOID)memptr, size); } else { DBGERR(("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; NdisFreeMemory(memptr, size, flags); } /* ************************************************************************* * NewDevice ************************************************************************* * */ IrDevice *NewDevice() { IrDevice *newdev; newdev = MyMemAlloc(sizeof(IrDevice), FALSE); if (newdev){ InitDevice(newdev); } return newdev; } /* ************************************************************************* * FreeDevice ************************************************************************* * */ VOID FreeDevice(IrDevice *dev) { CloseDevice(dev); 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->QueueLock); NdisInitializeTimer(&thisDev->TurnaroundTimer, DelayedWrite, thisDev); NdisInitializeListHead(&thisDev->rcvBufBuf); NdisInitializeListHead(&thisDev->rcvBufFree); NdisInitializeListHead(&thisDev->rcvBufFull); NdisInitializeListHead(&thisDev->rcvBufPend); } /* ************************************************************************* * 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; DBGOUT(("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; } /* * Initialize each of the RECEIVE packet objects for this device. */ 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; buf = MyMemAlloc(RCV_BUFFER_SIZE, TRUE); if (!buf){ goto _openDone; } // 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_PTR *)rcvBuf->packet->MiniportReserved = (ULONG_PTR)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 = TRUE; /* * 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(("OpenDevice() failed")); } else { DBGOUT(("OpenDevice() succeeded")); } 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(("CloseDevice()")); if (!thisDev){ return; } /* * Free all resources for the RECEIVE buffer queue. */ while (!IsListEmpty(&thisDev->rcvBufFree)) { rcvBuffer *rcvBuf; ListEntry = RemoveHeadList(&thisDev->rcvBufFree); rcvBuf = CONTAINING_RECORD(ListEntry, rcvBuffer, listEntry); if (rcvBuf->packet){ NdisFreePacket(rcvBuf->packet); rcvBuf->packet = NULL; } MyMemFree(rcvBuf, sizeof(rcvBuffer), FALSE); } while (!IsListEmpty(&thisDev->rcvBufBuf)) { ListEntry = RemoveHeadList(&thisDev->rcvBufBuf); MyMemFree(ListEntry, RCV_BUFFER_SIZE, TRUE); } /* * Free the packet and buffer pool handles for this device. */ if (thisDev->packetPoolHandle){ NdisFreePacketPool(thisDev->packetPoolHandle); thisDev->packetPoolHandle = NULL; } if (thisDev->bufferPoolHandle){ NdisFreeBufferPool(thisDev->bufferPoolHandle); thisDev->bufferPoolHandle = NULL; } /* * Free all resources for the SEND buffer queue. */ while (ListEntry = NdisInterlockedRemoveHeadList(&thisDev->SendQueue, &thisDev->QueueLock)){ // NDIS says we shouldn't try to complete any pending send packets // because we shouldn't have any packets around to send. If we do, // it's an NDIS bug. ASSERT(0); } thisDev->mediaBusy = FALSE; thisDev->haveIndicatedMediaBusy = FALSE; thisDev->linkSpeedInfo = NULL; }