|
|
/*****************************************************************************
* * Copyright (c) 1996-1999 Microsoft Corporation * * @doc * @module resource.c | IrSIR NDIS Miniport Driver * @comm * *----------------------------------------------------------------------------- * * Author: Scott Holden (sholden) * * Date: 10/3/1996 (created) * * Contents: initialize and allocate resources * *****************************************************************************/
#include "irsir.h"
#if MEM_CHECKING
typedef struct MEM_HDR { LIST_ENTRY ListEntry; ULONG Size; CHAR File[12]; ULONG Line; } MEM_HDR;
LIST_ENTRY leAlloc; NDIS_SPIN_LOCK slAlloc;
VOID InitMemory() { NdisAllocateSpinLock(&slAlloc); NdisInitializeListHead(&leAlloc); }
VOID DeinitMemory() { PLIST_ENTRY ListEntry;
NdisAcquireSpinLock(&slAlloc); for (ListEntry=leAlloc.Flink; ListEntry!=&leAlloc; ListEntry = ListEntry->Flink) { MEM_HDR *Hdr = (MEM_HDR*)ListEntry; DbgPrint("IRSIR: Unfreed Memory:%08x size:%4x <%s:%d>\n", &Hdr[1], Hdr->Size, Hdr->File, Hdr->Line);
} NdisReleaseSpinLock(&slAlloc); } #endif
/*****************************************************************************
* * Function: MyMemAlloc * * Synopsis: allocates a block of memory using NdisAllocateMemory * * Arguments: size - size of the block to allocate * * Returns: a pointer to the allocated block of memory * * Algorithm: * * History: dd-mm-yyyy Author Comment * 10/3/1996 sholden author * * Notes: * * *****************************************************************************/
#if MEM_CHECKING
PVOID _MyMemAlloc(UINT size, PUCHAR file, UINT line) #else
PVOID MyMemAlloc(UINT size) #endif
{ PVOID memptr; NDIS_PHYSICAL_ADDRESS noMaxAddr = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1); NDIS_STATUS status;
#if MEM_CHECKING
status = NdisAllocateMemoryWithTag(&memptr, size+sizeof(MEM_HDR), IRSIR_TAG); #else
status = NdisAllocateMemoryWithTag(&memptr, size, IRSIR_TAG); #endif
if (status != NDIS_STATUS_SUCCESS) { DEBUGMSG(DBG_ERR, ("Memory allocation failed\n")); memptr = NULL; } #if MEM_CHECKING
else { MEM_HDR *Hdr = memptr; UINT FileNameLen = strlen(file);
Hdr->Line = line; if (FileNameLen>sizeof(Hdr->File)-1) strcpy(Hdr->File, &file[FileNameLen-sizeof(Hdr->File)+1]); else strcpy(Hdr->File, file); MyInterlockedInsertHeadList(&leAlloc, &Hdr->ListEntry, &slAlloc); memptr = &Hdr[1]; } #endif
return memptr; }
/*****************************************************************************
* * Function: MyMemFree * * Synopsis: frees a block of memory allocated by MyMemAlloc * * Arguments: memptr - memory to free * size - size of the block to free * * Returns: none * * Algorithm: * * History: dd-mm-yyyy Author Comment * 10/3/1996 sholden author * * Notes: * * *****************************************************************************/
VOID MyMemFree( PVOID memptr, UINT size ) { #if MEM_CHECKING
PLIST_ENTRY ListEntry; MEM_HDR *Hdr = (MEM_HDR*)((PUCHAR)memptr-sizeof(MEM_HDR));
NdisAcquireSpinLock(&slAlloc); for (ListEntry = leAlloc.Flink; ListEntry != &leAlloc; ListEntry = ListEntry->Flink) { if (ListEntry==&Hdr->ListEntry) { RemoveEntryList(&Hdr->ListEntry); break; } } if (ListEntry==&leAlloc) { DEBUGMSG(DBG_ERR, ("IRSIR: Freeing memory not owned %x\n", memptr)); } NdisReleaseSpinLock(&slAlloc);
NdisFreeMemory(Hdr, size+sizeof(MEM_HDR), 0); #else
NdisFreeMemory(memptr, size, 0); #endif
}
#if LIST_CHECKING
VOID FASTCALL CheckList(PLIST_ENTRY ListHead) { PLIST_ENTRY ListEntry, PrevListEntry;
if (ListHead->Flink==ListHead) { if (ListHead->Flink!=ListHead || ListHead->Blink!=ListHead) { DbgPrint("IRSIR: Corrupt list head:%x Flink:%x Blink:%x\n", ListHead, ListHead->Flink, ListHead->Blink); DbgBreakPoint(); } } else { ListEntry = ListHead;
do { PrevListEntry = ListEntry; ListEntry = ListEntry->Flink;
if (ListEntry->Blink!=PrevListEntry) { DbgPrint("IRSIR: Corrupt LIST_ENTRY Head:%08x %08x->Flink==%08x %08x->Blink==%08x\n", ListHead, PrevListEntry, PrevListEntry->Flink, ListEntry, ListEntry->Blink); DbgBreakPoint(); } } while (ListEntry!=ListHead); } }
PLIST_ENTRY FASTCALL MyInterlockedInsertHeadList(PLIST_ENTRY Head, PLIST_ENTRY Entry, PNDIS_SPIN_LOCK SpinLock) { PLIST_ENTRY RetVal;
NdisAcquireSpinLock(SpinLock); if (IsListEmpty(Head)) RetVal = NULL; else RetVal = Head->Flink; CheckedInsertHeadList(Head, Entry); NdisReleaseSpinLock(SpinLock);
return RetVal; }
PLIST_ENTRY FASTCALL MyInterlockedInsertTailList(PLIST_ENTRY Head, PLIST_ENTRY Entry, PNDIS_SPIN_LOCK SpinLock) { PLIST_ENTRY RetVal;
NdisAcquireSpinLock(SpinLock); if (IsListEmpty(Head)) RetVal = NULL; else RetVal = Head->Blink; CheckedInsertTailList(Head, Entry); NdisReleaseSpinLock(SpinLock);
return RetVal; }
PLIST_ENTRY FASTCALL MyInterlockedRemoveHeadList(PLIST_ENTRY Head, PNDIS_SPIN_LOCK SpinLock) { PLIST_ENTRY RetVal; NdisAcquireSpinLock(SpinLock); //RemoveHeadList uses RemoveEntryList, which is redefined to call CheckList in DEBUG.H
RetVal = RemoveHeadList(Head); if (RetVal==Head) RetVal = NULL; else RetVal->Flink = RetVal->Blink = NULL; NdisReleaseSpinLock(SpinLock);
return RetVal; } #endif
/*****************************************************************************
* * Function: NewDevice * * Synopsis: allocates an IR_DEVICE and inits the device * * Arguments: none * * Returns: initialized IR_DEVICE or NULL (if alloc failed) * * Algorithm: * * History: dd-mm-yyyy Author Comment * 10/3/1996 sholden author * * Notes: * * *****************************************************************************/
PIR_DEVICE NewDevice() { PIR_DEVICE pNewDev;
pNewDev = MyMemAlloc(sizeof(IR_DEVICE));
if (pNewDev != NULL) { NdisZeroMemory((PVOID)pNewDev, sizeof(IR_DEVICE)); }
return pNewDev; }
/*****************************************************************************
* * Function: FreeDevice * * Synopsis: frees an IR_DEVICE allocated by NewDevice * * Arguments: dev - pointer to device to free * * Returns: none * * Algorithm: * * History: dd-mm-yyyy Author Comment * 10/3/1996 sholden author * * Notes: * * *****************************************************************************/
VOID FreeDevice( PIR_DEVICE pDev ) { MyMemFree((PVOID)pDev, sizeof(IR_DEVICE)); }
/*****************************************************************************
* * Function: IrBuildIrp * * Synopsis: Builds an I/O request packet for either a read or a write * request to the serial device object. * Supports the following request codes: * IOCTL_MJ_READ * IOCTL_MJ_WRITE * * Arguments: * * Returns: * * Algorithm: * * History: dd-mm-yyyy Author Comment * 10/14/1996 sholden author * * Notes: * * *****************************************************************************/
PIRP SerialBuildReadWriteIrp( IN PDEVICE_OBJECT pSerialDevObj, IN ULONG MajorFunction, IN OUT PVOID pBuffer, IN ULONG BufferLength, IN PIO_STATUS_BLOCK pIosb ) { PIRP pIrp; PIO_STACK_LOCATION irpSp;
// DEBUGMSG(DBG_FUNC, ("+SerialBuildReadWriteIrp\n"));
if (pSerialDevObj == NULL) { DEBUGMSG(DBG_ERR, (" SerialBuildReadWriteIrp:pSerialDevObj==NULL\n"));
return NULL; } //
// Allocate the irp.
//
pIrp = IoAllocateIrp( pSerialDevObj->StackSize, FALSE );
if (pIrp == NULL) { DEBUGMSG(DBG_ERR, (" IoAllocateIrp failed.\n"));
return pIrp; }
//
// Set current thread for IoSetHardErrorOrVerifyDevice.
//
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
//
// Get a pointer to the stack location of the first driver which will be
// invoked. This is where the function codes and the parameters are set.
//
irpSp = IoGetNextIrpStackLocation(pIrp);
//
// Set the major function code.
//
irpSp->MajorFunction = (UCHAR)MajorFunction;
pIrp->AssociatedIrp.SystemBuffer = pBuffer;
if (MajorFunction == IRP_MJ_READ) { pIrp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; irpSp->Parameters.Read.Length = BufferLength; } else // MajorFunction == IRP_MJ_WRITE
{ pIrp->Flags = IRP_BUFFERED_IO; irpSp->Parameters.Write.Length = BufferLength; }
pIrp->UserIosb = pIosb;
// DEBUGMSG(DBG_FUNC, ("-SerialBuildReadWriteIrp\n"));
return pIrp; }
NDIS_STATUS ScheduleWorkItem(PASSIVE_PRIMITIVE Prim, PIR_DEVICE pDevice, WORK_PROC Callback, PVOID InfoBuf, ULONG InfoBufLen) { PIR_WORK_ITEM pWorkItem; NDIS_STATUS Status = NDIS_STATUS_FAILURE;
DEBUGMSG(DBG_FUNC, ("+ScheduleWorkItem\n"));
pWorkItem = MyMemAlloc(sizeof(IR_WORK_ITEM));
if (pWorkItem != NULL) { pWorkItem->Prim = Prim; pWorkItem->pIrDevice = pDevice; pWorkItem->InfoBuf = InfoBuf; pWorkItem->InfoBufLen = InfoBufLen;
/*
** This interface was designed to use NdisScheduleWorkItem(), which ** would be good except that we're really only supposed to use that ** interface during startup and shutdown, due to the limited pool of ** threads available to service NdisScheduleWorkItem(). Therefore, ** instead of scheduling real work items, we simulate them, and use ** our own thread to process the calls. This also makes it easy to ** expand the size of our own thread pool, if we wish. ** ** Our version is slightly different from actual NDIS_WORK_ITEMs, ** because that is an NDIS 5.0 structure, and we want people to ** (at least temporarily) build this with NDIS 4.0 headers. */
pWorkItem->Callback = Callback;
/*
** Our worker thread checks this list for new jobs, whenever its event ** is signalled. */
MyInterlockedInsertTailList(&pDevice->leWorkItems, &pWorkItem->ListEntry, &pDevice->slWorkItem);
// Wake up our thread.
KeSetEvent(&pDevice->eventPassiveThread, 0, FALSE);
Status = NDIS_STATUS_SUCCESS; }
return Status; }
VOID FreeWorkItem( PIR_WORK_ITEM pItem ) { MyMemFree((PVOID)pItem, sizeof(IR_WORK_ITEM)); }
|