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.

348 lines
8.6 KiB

  1. /*
  2. ************************************************************************
  3. *
  4. * RESOURCE.c
  5. *
  6. *
  7. * Portions Copyright (C) 1996-2001 National Semiconductor Corp.
  8. * All rights reserved.
  9. * Copyright (C) 1996-2001 Microsoft Corporation. All Rights Reserved.
  10. *
  11. *
  12. *
  13. *************************************************************************
  14. */
  15. #include "nsc.h"
  16. /*
  17. *************************************************************************
  18. * MyMemAlloc
  19. *************************************************************************
  20. *
  21. */
  22. PVOID MyMemAlloc(UINT size, BOOLEAN isDmaBuf)
  23. {
  24. NDIS_STATUS stat;
  25. PVOID memptr;
  26. if (isDmaBuf){
  27. NDIS_PHYSICAL_ADDRESS maxAddr = NDIS_PHYSICAL_ADDRESS_CONST(0x0fffff, 0);
  28. stat = NdisAllocateMemory( &memptr,
  29. size,
  30. NDIS_MEMORY_CONTIGUOUS|NDIS_MEMORY_NONCACHED,
  31. maxAddr);
  32. }
  33. else {
  34. stat = NdisAllocateMemoryWithTag(
  35. &memptr,
  36. size,
  37. 'rIsN'
  38. );
  39. }
  40. if (stat == NDIS_STATUS_SUCCESS){
  41. NdisZeroMemory((PVOID)memptr, size);
  42. }
  43. else {
  44. DBGERR(("Memory allocation failed"));
  45. memptr = NULL;
  46. }
  47. return memptr;
  48. }
  49. /*
  50. *************************************************************************
  51. * MyMemFree
  52. *************************************************************************
  53. *
  54. */
  55. VOID MyMemFree(PVOID memptr, UINT size, BOOLEAN isDmaBuf)
  56. {
  57. UINT flags = (isDmaBuf) ? NDIS_MEMORY_CONTIGUOUS|NDIS_MEMORY_NONCACHED : 0;
  58. NdisFreeMemory(memptr, size, flags);
  59. }
  60. /*
  61. *************************************************************************
  62. * NewDevice
  63. *************************************************************************
  64. *
  65. */
  66. IrDevice *NewDevice()
  67. {
  68. IrDevice *newdev;
  69. newdev = MyMemAlloc(sizeof(IrDevice), FALSE);
  70. if (newdev){
  71. InitDevice(newdev);
  72. }
  73. return newdev;
  74. }
  75. /*
  76. *************************************************************************
  77. * FreeDevice
  78. *************************************************************************
  79. *
  80. */
  81. VOID FreeDevice(IrDevice *dev)
  82. {
  83. CloseDevice(dev);
  84. MyMemFree((PVOID)dev, sizeof(IrDevice), FALSE);
  85. }
  86. /*
  87. *************************************************************************
  88. * InitDevice
  89. *************************************************************************
  90. *
  91. * Zero out the device object.
  92. *
  93. * Allocate the device object's spinlock, which will persist while
  94. * the device is opened and closed.
  95. *
  96. */
  97. VOID InitDevice(IrDevice *thisDev)
  98. {
  99. NdisZeroMemory((PVOID)thisDev, sizeof(IrDevice));
  100. NdisInitializeListHead(&thisDev->SendQueue);
  101. NdisAllocateSpinLock(&thisDev->QueueLock);
  102. NdisInitializeTimer(&thisDev->TurnaroundTimer,
  103. DelayedWrite,
  104. thisDev);
  105. NdisInitializeListHead(&thisDev->rcvBufBuf);
  106. NdisInitializeListHead(&thisDev->rcvBufFree);
  107. NdisInitializeListHead(&thisDev->rcvBufFull);
  108. NdisInitializeListHead(&thisDev->rcvBufPend);
  109. }
  110. /*
  111. *************************************************************************
  112. * OpenDevice
  113. *************************************************************************
  114. *
  115. * Allocate resources for a single device object.
  116. *
  117. * This function should be called with device lock already held.
  118. *
  119. */
  120. BOOLEAN OpenDevice(IrDevice *thisDev)
  121. {
  122. BOOLEAN result = FALSE;
  123. NDIS_STATUS stat;
  124. UINT bufIndex;
  125. DBGOUT(("OpenDevice()"));
  126. if (!thisDev){
  127. return FALSE;
  128. }
  129. /*
  130. * Allocate the NDIS packet and NDIS buffer pools
  131. * for this device's RECEIVE buffer queue.
  132. * Our receive packets must only contain one buffer apiece,
  133. * so #buffers == #packets.
  134. */
  135. NdisAllocatePacketPool(&stat, &thisDev->packetPoolHandle, NUM_RCV_BUFS, 24);
  136. if (stat != NDIS_STATUS_SUCCESS){
  137. goto _openDone;
  138. }
  139. NdisAllocateBufferPool(&stat, &thisDev->bufferPoolHandle, NUM_RCV_BUFS);
  140. if (stat != NDIS_STATUS_SUCCESS){
  141. goto _openDone;
  142. }
  143. /*
  144. * Initialize each of the RECEIVE packet objects for this device.
  145. */
  146. for (bufIndex = 0; bufIndex < NUM_RCV_BUFS; bufIndex++){
  147. rcvBuffer *rcvBuf = MyMemAlloc(sizeof(rcvBuffer), FALSE);
  148. PVOID buf;
  149. if (!rcvBuf)
  150. {
  151. goto _openDone;
  152. }
  153. rcvBuf->state = STATE_FREE;
  154. rcvBuf->isDmaBuf = FALSE;
  155. /*
  156. * Allocate a data buffer
  157. *
  158. * This buffer gets swapped with the one on comPortInfo
  159. * and must be the same size.
  160. */
  161. rcvBuf->dataBuf = NULL;
  162. buf = MyMemAlloc(RCV_BUFFER_SIZE, TRUE);
  163. if (!buf){
  164. goto _openDone;
  165. }
  166. // We treat the beginning of the buffer as a LIST_ENTRY.
  167. // Normally we would use NDISSynchronizeInsertHeadList, but the
  168. // Interrupt hasn't been registered yet.
  169. InsertHeadList(&thisDev->rcvBufBuf, (PLIST_ENTRY)buf);
  170. /*
  171. * Allocate the NDIS_PACKET.
  172. */
  173. NdisAllocatePacket(&stat, &rcvBuf->packet, thisDev->packetPoolHandle);
  174. if (stat != NDIS_STATUS_SUCCESS){
  175. goto _openDone;
  176. }
  177. #if 1
  178. /*
  179. * For future convenience, set the MiniportReserved portion of the packet
  180. * to the index of the rcv buffer that contains it.
  181. * This will be used in ReturnPacketHandler.
  182. */
  183. *(ULONG_PTR *)rcvBuf->packet->MiniportReserved = (ULONG_PTR)rcvBuf;
  184. #endif
  185. rcvBuf->dataLen = 0;
  186. InsertHeadList(&thisDev->rcvBufFree, &rcvBuf->listEntry);
  187. }
  188. /*
  189. * Set mediaBusy to TRUE initially. That way, we won't
  190. * IndicateStatus to the protocol in the ISR unless the
  191. * protocol has expressed interest by clearing this flag
  192. * via MiniportSetInformation(OID_IRDA_MEDIA_BUSY).
  193. */
  194. thisDev->mediaBusy = FALSE;
  195. thisDev->haveIndicatedMediaBusy = TRUE;
  196. /*
  197. * Will set speed to 9600 baud initially.
  198. */
  199. thisDev->linkSpeedInfo = &supportedBaudRateTable[BAUDRATE_9600];
  200. thisDev->lastPacketAtOldSpeed = NULL;
  201. thisDev->setSpeedAfterCurrentSendPacket = FALSE;
  202. result = TRUE;
  203. _openDone:
  204. if (!result){
  205. /*
  206. * If we're failing, close the device to free up any resources
  207. * that were allocated for it.
  208. */
  209. CloseDevice(thisDev);
  210. DBGOUT(("OpenDevice() failed"));
  211. }
  212. else {
  213. DBGOUT(("OpenDevice() succeeded"));
  214. }
  215. return result;
  216. }
  217. /*
  218. *************************************************************************
  219. * CloseDevice
  220. *************************************************************************
  221. *
  222. * Free the indicated device's resources.
  223. *
  224. *
  225. * Called for shutdown and reset.
  226. * Don't clear ndisAdapterHandle, since we might just be resetting.
  227. * This function should be called with device lock held.
  228. *
  229. *
  230. */
  231. VOID CloseDevice(IrDevice *thisDev)
  232. {
  233. PLIST_ENTRY ListEntry;
  234. DBGOUT(("CloseDevice()"));
  235. if (!thisDev){
  236. return;
  237. }
  238. /*
  239. * Free all resources for the RECEIVE buffer queue.
  240. */
  241. while (!IsListEmpty(&thisDev->rcvBufFree))
  242. {
  243. rcvBuffer *rcvBuf;
  244. ListEntry = RemoveHeadList(&thisDev->rcvBufFree);
  245. rcvBuf = CONTAINING_RECORD(ListEntry,
  246. rcvBuffer,
  247. listEntry);
  248. if (rcvBuf->packet){
  249. NdisFreePacket(rcvBuf->packet);
  250. rcvBuf->packet = NULL;
  251. }
  252. MyMemFree(rcvBuf, sizeof(rcvBuffer), FALSE);
  253. }
  254. while (!IsListEmpty(&thisDev->rcvBufBuf))
  255. {
  256. ListEntry = RemoveHeadList(&thisDev->rcvBufBuf);
  257. MyMemFree(ListEntry, RCV_BUFFER_SIZE, TRUE);
  258. }
  259. /*
  260. * Free the packet and buffer pool handles for this device.
  261. */
  262. if (thisDev->packetPoolHandle){
  263. NdisFreePacketPool(thisDev->packetPoolHandle);
  264. thisDev->packetPoolHandle = NULL;
  265. }
  266. if (thisDev->bufferPoolHandle){
  267. NdisFreeBufferPool(thisDev->bufferPoolHandle);
  268. thisDev->bufferPoolHandle = NULL;
  269. }
  270. /*
  271. * Free all resources for the SEND buffer queue.
  272. */
  273. while (ListEntry = NdisInterlockedRemoveHeadList(&thisDev->SendQueue, &thisDev->QueueLock)){
  274. // NDIS says we shouldn't try to complete any pending send packets
  275. // because we shouldn't have any packets around to send. If we do,
  276. // it's an NDIS bug.
  277. ASSERT(0);
  278. }
  279. thisDev->mediaBusy = FALSE;
  280. thisDev->haveIndicatedMediaBusy = FALSE;
  281. thisDev->linkSpeedInfo = NULL;
  282. }