Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

478 lines
11 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1996-1999 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module resource.c | IrSIR NDIS Miniport Driver
  7. * @comm
  8. *
  9. *-----------------------------------------------------------------------------
  10. *
  11. * Author: Scott Holden (sholden)
  12. *
  13. * Date: 10/3/1996 (created)
  14. *
  15. * Contents: initialize and allocate resources
  16. *
  17. *****************************************************************************/
  18. #include "irsir.h"
  19. #if MEM_CHECKING
  20. typedef struct MEM_HDR {
  21. LIST_ENTRY ListEntry;
  22. ULONG Size;
  23. CHAR File[12];
  24. ULONG Line;
  25. } MEM_HDR;
  26. LIST_ENTRY leAlloc;
  27. NDIS_SPIN_LOCK slAlloc;
  28. VOID InitMemory()
  29. {
  30. NdisAllocateSpinLock(&slAlloc);
  31. NdisInitializeListHead(&leAlloc);
  32. }
  33. VOID DeinitMemory()
  34. {
  35. PLIST_ENTRY ListEntry;
  36. NdisAcquireSpinLock(&slAlloc);
  37. for (ListEntry=leAlloc.Flink;
  38. ListEntry!=&leAlloc;
  39. ListEntry = ListEntry->Flink)
  40. {
  41. MEM_HDR *Hdr = (MEM_HDR*)ListEntry;
  42. DbgPrint("IRSIR: Unfreed Memory:%08x size:%4x <%s:%d>\n",
  43. &Hdr[1], Hdr->Size, Hdr->File, Hdr->Line);
  44. }
  45. NdisReleaseSpinLock(&slAlloc);
  46. }
  47. #endif
  48. /*****************************************************************************
  49. *
  50. * Function: MyMemAlloc
  51. *
  52. * Synopsis: allocates a block of memory using NdisAllocateMemory
  53. *
  54. * Arguments: size - size of the block to allocate
  55. *
  56. * Returns: a pointer to the allocated block of memory
  57. *
  58. * Algorithm:
  59. *
  60. * History: dd-mm-yyyy Author Comment
  61. * 10/3/1996 sholden author
  62. *
  63. * Notes:
  64. *
  65. *
  66. *****************************************************************************/
  67. #if MEM_CHECKING
  68. PVOID
  69. _MyMemAlloc(UINT size, PUCHAR file, UINT line)
  70. #else
  71. PVOID
  72. MyMemAlloc(UINT size)
  73. #endif
  74. {
  75. PVOID memptr;
  76. NDIS_PHYSICAL_ADDRESS noMaxAddr = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
  77. NDIS_STATUS status;
  78. #if MEM_CHECKING
  79. status = NdisAllocateMemoryWithTag(&memptr, size+sizeof(MEM_HDR), IRSIR_TAG);
  80. #else
  81. status = NdisAllocateMemoryWithTag(&memptr, size, IRSIR_TAG);
  82. #endif
  83. if (status != NDIS_STATUS_SUCCESS)
  84. {
  85. DEBUGMSG(DBG_ERR, ("Memory allocation failed\n"));
  86. memptr = NULL;
  87. }
  88. #if MEM_CHECKING
  89. else
  90. {
  91. MEM_HDR *Hdr = memptr;
  92. UINT FileNameLen = strlen(file);
  93. Hdr->Line = line;
  94. if (FileNameLen>sizeof(Hdr->File)-1)
  95. strcpy(Hdr->File, &file[FileNameLen-sizeof(Hdr->File)+1]);
  96. else
  97. strcpy(Hdr->File, file);
  98. MyInterlockedInsertHeadList(&leAlloc, &Hdr->ListEntry, &slAlloc);
  99. memptr = &Hdr[1];
  100. }
  101. #endif
  102. return memptr;
  103. }
  104. /*****************************************************************************
  105. *
  106. * Function: MyMemFree
  107. *
  108. * Synopsis: frees a block of memory allocated by MyMemAlloc
  109. *
  110. * Arguments: memptr - memory to free
  111. * size - size of the block to free
  112. *
  113. * Returns: none
  114. *
  115. * Algorithm:
  116. *
  117. * History: dd-mm-yyyy Author Comment
  118. * 10/3/1996 sholden author
  119. *
  120. * Notes:
  121. *
  122. *
  123. *****************************************************************************/
  124. VOID
  125. MyMemFree(
  126. PVOID memptr,
  127. UINT size
  128. )
  129. {
  130. #if MEM_CHECKING
  131. PLIST_ENTRY ListEntry;
  132. MEM_HDR *Hdr = (MEM_HDR*)((PUCHAR)memptr-sizeof(MEM_HDR));
  133. NdisAcquireSpinLock(&slAlloc);
  134. for (ListEntry = leAlloc.Flink;
  135. ListEntry != &leAlloc;
  136. ListEntry = ListEntry->Flink)
  137. {
  138. if (ListEntry==&Hdr->ListEntry)
  139. {
  140. RemoveEntryList(&Hdr->ListEntry);
  141. break;
  142. }
  143. }
  144. if (ListEntry==&leAlloc)
  145. {
  146. DEBUGMSG(DBG_ERR, ("IRSIR: Freeing memory not owned %x\n", memptr));
  147. }
  148. NdisReleaseSpinLock(&slAlloc);
  149. NdisFreeMemory(Hdr, size+sizeof(MEM_HDR), 0);
  150. #else
  151. NdisFreeMemory(memptr, size, 0);
  152. #endif
  153. }
  154. #if LIST_CHECKING
  155. VOID FASTCALL CheckList(PLIST_ENTRY ListHead)
  156. {
  157. PLIST_ENTRY ListEntry, PrevListEntry;
  158. if (ListHead->Flink==ListHead)
  159. {
  160. if (ListHead->Flink!=ListHead ||
  161. ListHead->Blink!=ListHead)
  162. {
  163. DbgPrint("IRSIR: Corrupt list head:%x Flink:%x Blink:%x\n", ListHead, ListHead->Flink, ListHead->Blink);
  164. DbgBreakPoint();
  165. }
  166. }
  167. else
  168. {
  169. ListEntry = ListHead;
  170. do
  171. {
  172. PrevListEntry = ListEntry;
  173. ListEntry = ListEntry->Flink;
  174. if (ListEntry->Blink!=PrevListEntry)
  175. {
  176. DbgPrint("IRSIR: Corrupt LIST_ENTRY Head:%08x %08x->Flink==%08x %08x->Blink==%08x\n",
  177. ListHead, PrevListEntry, PrevListEntry->Flink, ListEntry, ListEntry->Blink);
  178. DbgBreakPoint();
  179. }
  180. } while (ListEntry!=ListHead);
  181. }
  182. }
  183. PLIST_ENTRY FASTCALL MyInterlockedInsertHeadList(PLIST_ENTRY Head, PLIST_ENTRY Entry, PNDIS_SPIN_LOCK SpinLock)
  184. {
  185. PLIST_ENTRY RetVal;
  186. NdisAcquireSpinLock(SpinLock);
  187. if (IsListEmpty(Head))
  188. RetVal = NULL;
  189. else
  190. RetVal = Head->Flink;
  191. CheckedInsertHeadList(Head, Entry);
  192. NdisReleaseSpinLock(SpinLock);
  193. return RetVal;
  194. }
  195. PLIST_ENTRY FASTCALL MyInterlockedInsertTailList(PLIST_ENTRY Head, PLIST_ENTRY Entry, PNDIS_SPIN_LOCK SpinLock)
  196. {
  197. PLIST_ENTRY RetVal;
  198. NdisAcquireSpinLock(SpinLock);
  199. if (IsListEmpty(Head))
  200. RetVal = NULL;
  201. else
  202. RetVal = Head->Blink;
  203. CheckedInsertTailList(Head, Entry);
  204. NdisReleaseSpinLock(SpinLock);
  205. return RetVal;
  206. }
  207. PLIST_ENTRY FASTCALL MyInterlockedRemoveHeadList(PLIST_ENTRY Head, PNDIS_SPIN_LOCK SpinLock)
  208. {
  209. PLIST_ENTRY RetVal;
  210. NdisAcquireSpinLock(SpinLock);
  211. //RemoveHeadList uses RemoveEntryList, which is redefined to call CheckList in DEBUG.H
  212. RetVal = RemoveHeadList(Head);
  213. if (RetVal==Head)
  214. RetVal = NULL;
  215. else
  216. RetVal->Flink = RetVal->Blink = NULL;
  217. NdisReleaseSpinLock(SpinLock);
  218. return RetVal;
  219. }
  220. #endif
  221. /*****************************************************************************
  222. *
  223. * Function: NewDevice
  224. *
  225. * Synopsis: allocates an IR_DEVICE and inits the device
  226. *
  227. * Arguments: none
  228. *
  229. * Returns: initialized IR_DEVICE or NULL (if alloc failed)
  230. *
  231. * Algorithm:
  232. *
  233. * History: dd-mm-yyyy Author Comment
  234. * 10/3/1996 sholden author
  235. *
  236. * Notes:
  237. *
  238. *
  239. *****************************************************************************/
  240. PIR_DEVICE
  241. NewDevice()
  242. {
  243. PIR_DEVICE pNewDev;
  244. pNewDev = MyMemAlloc(sizeof(IR_DEVICE));
  245. if (pNewDev != NULL)
  246. {
  247. NdisZeroMemory((PVOID)pNewDev, sizeof(IR_DEVICE));
  248. }
  249. return pNewDev;
  250. }
  251. /*****************************************************************************
  252. *
  253. * Function: FreeDevice
  254. *
  255. * Synopsis: frees an IR_DEVICE allocated by NewDevice
  256. *
  257. * Arguments: dev - pointer to device to free
  258. *
  259. * Returns: none
  260. *
  261. * Algorithm:
  262. *
  263. * History: dd-mm-yyyy Author Comment
  264. * 10/3/1996 sholden author
  265. *
  266. * Notes:
  267. *
  268. *
  269. *****************************************************************************/
  270. VOID
  271. FreeDevice(
  272. PIR_DEVICE pDev
  273. )
  274. {
  275. MyMemFree((PVOID)pDev, sizeof(IR_DEVICE));
  276. }
  277. /*****************************************************************************
  278. *
  279. * Function: IrBuildIrp
  280. *
  281. * Synopsis: Builds an I/O request packet for either a read or a write
  282. * request to the serial device object.
  283. * Supports the following request codes:
  284. * IOCTL_MJ_READ
  285. * IOCTL_MJ_WRITE
  286. *
  287. * Arguments:
  288. *
  289. * Returns:
  290. *
  291. * Algorithm:
  292. *
  293. * History: dd-mm-yyyy Author Comment
  294. * 10/14/1996 sholden author
  295. *
  296. * Notes:
  297. *
  298. *
  299. *****************************************************************************/
  300. PIRP
  301. SerialBuildReadWriteIrp(
  302. IN PDEVICE_OBJECT pSerialDevObj,
  303. IN ULONG MajorFunction,
  304. IN OUT PVOID pBuffer,
  305. IN ULONG BufferLength,
  306. IN PIO_STATUS_BLOCK pIosb
  307. )
  308. {
  309. PIRP pIrp;
  310. PIO_STACK_LOCATION irpSp;
  311. // DEBUGMSG(DBG_FUNC, ("+SerialBuildReadWriteIrp\n"));
  312. if (pSerialDevObj == NULL)
  313. {
  314. DEBUGMSG(DBG_ERR, (" SerialBuildReadWriteIrp:pSerialDevObj==NULL\n"));
  315. return NULL;
  316. }
  317. //
  318. // Allocate the irp.
  319. //
  320. pIrp = IoAllocateIrp(
  321. pSerialDevObj->StackSize,
  322. FALSE
  323. );
  324. if (pIrp == NULL)
  325. {
  326. DEBUGMSG(DBG_ERR, (" IoAllocateIrp failed.\n"));
  327. return pIrp;
  328. }
  329. //
  330. // Set current thread for IoSetHardErrorOrVerifyDevice.
  331. //
  332. pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
  333. //
  334. // Get a pointer to the stack location of the first driver which will be
  335. // invoked. This is where the function codes and the parameters are set.
  336. //
  337. irpSp = IoGetNextIrpStackLocation(pIrp);
  338. //
  339. // Set the major function code.
  340. //
  341. irpSp->MajorFunction = (UCHAR)MajorFunction;
  342. pIrp->AssociatedIrp.SystemBuffer = pBuffer;
  343. if (MajorFunction == IRP_MJ_READ)
  344. {
  345. pIrp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
  346. irpSp->Parameters.Read.Length = BufferLength;
  347. }
  348. else // MajorFunction == IRP_MJ_WRITE
  349. {
  350. pIrp->Flags = IRP_BUFFERED_IO;
  351. irpSp->Parameters.Write.Length = BufferLength;
  352. }
  353. pIrp->UserIosb = pIosb;
  354. // DEBUGMSG(DBG_FUNC, ("-SerialBuildReadWriteIrp\n"));
  355. return pIrp;
  356. }
  357. NDIS_STATUS
  358. ScheduleWorkItem(PASSIVE_PRIMITIVE Prim,
  359. PIR_DEVICE pDevice,
  360. WORK_PROC Callback,
  361. PVOID InfoBuf,
  362. ULONG InfoBufLen)
  363. {
  364. PIR_WORK_ITEM pWorkItem;
  365. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  366. DEBUGMSG(DBG_FUNC, ("+ScheduleWorkItem\n"));
  367. pWorkItem = MyMemAlloc(sizeof(IR_WORK_ITEM));
  368. if (pWorkItem != NULL)
  369. {
  370. pWorkItem->Prim = Prim;
  371. pWorkItem->pIrDevice = pDevice;
  372. pWorkItem->InfoBuf = InfoBuf;
  373. pWorkItem->InfoBufLen = InfoBufLen;
  374. /*
  375. ** This interface was designed to use NdisScheduleWorkItem(), which
  376. ** would be good except that we're really only supposed to use that
  377. ** interface during startup and shutdown, due to the limited pool of
  378. ** threads available to service NdisScheduleWorkItem(). Therefore,
  379. ** instead of scheduling real work items, we simulate them, and use
  380. ** our own thread to process the calls. This also makes it easy to
  381. ** expand the size of our own thread pool, if we wish.
  382. **
  383. ** Our version is slightly different from actual NDIS_WORK_ITEMs,
  384. ** because that is an NDIS 5.0 structure, and we want people to
  385. ** (at least temporarily) build this with NDIS 4.0 headers.
  386. */
  387. pWorkItem->Callback = Callback;
  388. /*
  389. ** Our worker thread checks this list for new jobs, whenever its event
  390. ** is signalled.
  391. */
  392. MyInterlockedInsertTailList(&pDevice->leWorkItems,
  393. &pWorkItem->ListEntry,
  394. &pDevice->slWorkItem);
  395. // Wake up our thread.
  396. KeSetEvent(&pDevice->eventPassiveThread, 0, FALSE);
  397. Status = NDIS_STATUS_SUCCESS;
  398. }
  399. return Status;
  400. }
  401. VOID
  402. FreeWorkItem(
  403. PIR_WORK_ITEM pItem
  404. )
  405. {
  406. MyMemFree((PVOID)pItem, sizeof(IR_WORK_ITEM));
  407. }