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.

431 lines
27 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. sendm.h
  5. Abstract:
  6. Author:
  7. Kyle Brandon (KyleB)
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. --*/
  12. #ifndef __SENDM_H
  13. #define __SENDM_H
  14. #define SEND_PACKET_ARRAY 16
  15. //
  16. // The following definitions apply to serialized drivers only. Packets for the deserialized drivers are not queued
  17. // within NDIS
  18. //
  19. #define PACKET_LIST(_P) (PLIST_ENTRY)((_P)->WrapperReserved)
  20. #define GET_FIRST_MINIPORT_PACKET(_M, _P) \
  21. { \
  22. *(_P) = NULL; \
  23. if (!IsListEmpty(&(_M)->PacketList)) \
  24. { \
  25. PLIST_ENTRY _L; \
  26. \
  27. _L = (_M)->PacketList.Flink; \
  28. *(_P) = CONTAINING_RECORD(_L, NDIS_PACKET, WrapperReserved); \
  29. } \
  30. }
  31. //
  32. // Macros used for getting to OOB data and packet extension.
  33. //
  34. #define PNDIS_PACKET_OOB_DATA_FROM_PNDIS_PACKET(_P) \
  35. (PNDIS_PACKET_OOB_DATA)((PUCHAR)(_P) + (_P)->Private.NdisPacketOobOffset)
  36. #define INIT_PACKET_LIST(_P) InitializeListHead(PACKET_LIST(_P))
  37. #define LINK_PACKET(_M, _P, _NSR, _O) \
  38. { \
  39. (_NSR)->Open = _O; \
  40. INIT_PACKET_LIST(_P); \
  41. \
  42. InsertTailList(&(_M)->PacketList, \
  43. PACKET_LIST(_P)); \
  44. }
  45. #define LINK_WAN_PACKET(_M, _P) \
  46. { \
  47. InitializeListHead(&(_P)->WanPacketQueue); \
  48. \
  49. InsertTailList(&(_M)->PacketList, \
  50. &(_P)->WanPacketQueue); \
  51. }
  52. #define UNLINK_PACKET(_M, _P, _NSR) \
  53. { \
  54. ASSERT(_P != (_M)->FirstPendingPacket); \
  55. RemoveEntryList(PACKET_LIST(_P)); \
  56. INIT_PACKET_LIST(_P); \
  57. }
  58. #define UNLINK_WAN_PACKET(_P) \
  59. { \
  60. RemoveEntryList(&(_P)->WanPacketQueue); \
  61. InitializeListHead(&(_P)->WanPacketQueue); \
  62. }
  63. #if DBG
  64. #define VALIDATE_PACKET_OPEN(_P) \
  65. { \
  66. PNDIS_STACK_RESERVED _NSR; \
  67. \
  68. NDIS_STACK_RESERVED_FROM_PACKET(_P, &_NSR); \
  69. ASSERT(VALID_OPEN(_NSR->Open)); \
  70. }
  71. #else
  72. #define VALIDATE_PACKET_OPEN(_P)
  73. #endif
  74. #define NEXT_PACKET_PENDING(_M, _P, _NSR) \
  75. { \
  76. PLIST_ENTRY _List; \
  77. \
  78. _List = PACKET_LIST(_P); \
  79. (_M)->FirstPendingPacket = NULL; \
  80. if (_List->Flink != &(_M)->PacketList) \
  81. { \
  82. (_M)->FirstPendingPacket = \
  83. CONTAINING_RECORD(_List->Flink, \
  84. NDIS_PACKET, \
  85. WrapperReserved); \
  86. VALIDATE_PACKET_OPEN((_M)->FirstPendingPacket); \
  87. } \
  88. }
  89. #if DBG
  90. #define CHECK_FOR_DUPLICATE_PACKET(_M, _P) \
  91. { \
  92. IF_DBG(DBG_COMP_SEND, DBG_LEVEL_FATAL) \
  93. { \
  94. PLIST_ENTRY _List; \
  95. \
  96. if (!IsListEmpty(&(_M)->PacketList)) \
  97. { \
  98. PNDIS_PACKET _Pkt; \
  99. \
  100. for (_List = (_M)->PacketList.Flink; \
  101. _List != &(_M)->PacketList; \
  102. _List = _List->Flink) \
  103. { \
  104. _Pkt = CONTAINING_RECORD(_List, \
  105. NDIS_PACKET, \
  106. WrapperReserved); \
  107. if (_P == _Pkt) \
  108. { \
  109. DBGBREAK(DBG_COMP_SEND, DBG_LEVEL_FATAL); \
  110. } \
  111. } \
  112. } \
  113. } \
  114. }
  115. #else
  116. #define CHECK_FOR_DUPLICATE_PACKET(_M, _P)
  117. #endif
  118. #define ADD_RESOURCE(_M, C) MINIPORT_SET_FLAG(_M, fMINIPORT_RESOURCES_AVAILABLE)
  119. #define CLEAR_RESOURCE(_M, C) MINIPORT_CLEAR_FLAG(_M, fMINIPORT_RESOURCES_AVAILABLE)
  120. #define VALID_OPEN(_O) (((ULONG_PTR)(_O) & 0xFFFFFF00) != MAGIC_OPEN)
  121. #define MAGIC_OPEN 'MOC\00'
  122. #define MAGIC_OPEN_I(x) (PVOID)((MAGIC_OPEN & 0xFFFFFF00) + 0x00000030 + x)
  123. #define CLEAR_WRAPPER_RESERVED(_NSR) (_NSR)->RefUlong = 0
  124. #if ARCNET
  125. #define FREE_ARCNET_BUFFER(_M, _P, _O) \
  126. { \
  127. /* \
  128. * If this is arcnet, then free the appended header. \
  129. */ \
  130. if ((_M)->MediaType == NdisMediumArcnet878_2) \
  131. { \
  132. ndisMFreeArcnetHeader(_M, _P, _O); \
  133. } \
  134. }
  135. #else
  136. #define FREE_ARCNET_BUFFER(_M, _P, _O)
  137. #endif
  138. #define NDISM_COMPLETE_SEND(_M, _P, _NSR, _S, _L, _I) \
  139. { \
  140. PNDIS_OPEN_BLOCK _O; \
  141. \
  142. if (!(_L)) \
  143. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(_M); \
  144. \
  145. _O = (_NSR)->Open; \
  146. \
  147. UNLINK_PACKET(_M, _P, _NSR); \
  148. POP_PACKET_STACK(_P); \
  149. \
  150. ADD_RESOURCE((_M), 'F'); \
  151. \
  152. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, \
  153. ("Completed 0x%x\n", (_S))); \
  154. \
  155. FREE_ARCNET_BUFFER(_M, _P, _O); \
  156. \
  157. (_NSR)->Open = MAGIC_OPEN_I(_I); \
  158. M_OPEN_DECREMENT_REF(_O); \
  159. \
  160. if (!(_L) && (NULL != (_M)->FirstPendingPacket)) \
  161. { \
  162. /* \
  163. * Do we need to queue another workitem to process more sends ? \
  164. */ \
  165. NDISM_QUEUE_WORK_ITEM(_M, NdisWorkItemSend, NULL); \
  166. } \
  167. \
  168. /* \
  169. * Indicate the completion to the protocol. \
  170. */ \
  171. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC((_M)); \
  172. \
  173. /* \
  174. * Make sure that an IM which shares send and receive packets on the same \
  175. * pool works fine with the check in the receive path. \
  176. */ \
  177. (_NSR)->RefCount = 0; \
  178. MINIPORT_CLEAR_PACKET_FLAG(_P, fPACKET_CLEAR_ITEMS); \
  179. CLEAR_WRAPPER_RESERVED(_NSR); \
  180. (_O->SendCompleteHandler)(_O->ProtocolBindingContext, \
  181. (_P), \
  182. (_S)); \
  183. \
  184. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO, \
  185. ("- Open 0x%x Reference 0x%x\n", _O, _O->References)); \
  186. \
  187. if (_O->References == 0) \
  188. { \
  189. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(_M); \
  190. ndisMFinishClose(_O); \
  191. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC((_M)); \
  192. } \
  193. \
  194. if (_L) \
  195. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(_M); \
  196. }
  197. #define NDISM_COMPLETE_SEND_RESOURCES(_M, _NSR, _P) \
  198. { \
  199. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, \
  200. ("Deferring send\n")); \
  201. \
  202. ASSERT(VALID_OPEN((_NSR)->Open)); \
  203. /* \
  204. * Put on pending queue \
  205. */ \
  206. MINIPORT_CLEAR_PACKET_FLAG(_P, fPACKET_PENDING); \
  207. (_M)->FirstPendingPacket = (_P); \
  208. \
  209. /* \
  210. * Mark the miniport as out of send resources. \
  211. */ \
  212. CLEAR_RESOURCE((_M), 'S'); \
  213. }
  214. #define NDISM_SEND_PACKET(_M, _O, _P, _pS) \
  215. { \
  216. UINT _Flags; \
  217. BOOLEAN _SelfDirected; \
  218. \
  219. /* \
  220. * Indicate the packet loopback if necessary. \
  221. */ \
  222. \
  223. if (NDIS_CHECK_FOR_LOOPBACK(_M, _P)) \
  224. { \
  225. _SelfDirected = ndisMLoopbackPacketX(_M, _P); \
  226. } \
  227. else \
  228. { \
  229. _SelfDirected = FALSE; \
  230. } \
  231. \
  232. if (_SelfDirected) \
  233. { \
  234. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, \
  235. ("Packet is self-directed.\n")); \
  236. \
  237. /* \
  238. * Self-directed loopback always succeeds. \
  239. */ \
  240. *(_pS) = NDIS_STATUS_SUCCESS; \
  241. } \
  242. else \
  243. { \
  244. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, \
  245. ("Sending packet 0x%p\n", _P)); \
  246. \
  247. NdisQuerySendFlags((_P), &_Flags); \
  248. \
  249. /* \
  250. * Call down to the driver. \
  251. */ \
  252. MINIPORT_SET_PACKET_FLAG(_P, fPACKET_PENDING); \
  253. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(_M); \
  254. *(_pS) = ((_O)->WSendHandler)((_O)->MiniportAdapterContext, _P, _Flags);\
  255. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(_M); \
  256. } \
  257. }
  258. #define PACKETS_OUT(_M) (_M)->NdisStats.DirectedPacketsOut ++
  259. #define DIRECTED_PACKETS_IN(_M) (_M)->NdisStats.DirectedPacketsIn ++
  260. #if NDIS_STATISTICS_BYTES
  261. #define BYTES_OUT(_M, _B) (_M)->NdisStats.DirectedBytesOut.QuadPart += MDL_SIZE(_B)
  262. #define DIRECTED_BYTES_IN(_M, _S) (_M)->NdisStats.DirectedBytesIn.QuadPart += (_S);
  263. #define DIRECTED_BYTES_IN_PACKET(_M, _P) \
  264. { \
  265. PNDIS_BUFFER p; \
  266. \
  267. for (p = (_P)->Private.Head; p != NULL; p = p->Next) \
  268. { \
  269. DIRECTED_BYTES_IN(_M, MDL_SIZE(p)); \
  270. } \
  271. }
  272. #else // NDIS_STATISTICS_BYTES
  273. #define BYTES_OUT(_M, _B)
  274. #define DIRECTED_BYTES_IN(_M, _S)
  275. #define DIRECTED_BYTES_IN_PACKET(_M, _P)
  276. #endif // NDIS_STATISTICS_BYTES
  277. #define ndisMCheckPacketAndGetStatsOut(_M, _P, _S) \
  278. { \
  279. PNDIS_BUFFER _Buffer; \
  280. \
  281. *(_S) = NDIS_STATUS_SUCCESS; \
  282. PACKETS_OUT(_M); \
  283. _Buffer = (_P)->Private.Head; \
  284. while (_Buffer != NULL) \
  285. { \
  286. if (MDL_ADDRESS_SAFE(_Buffer, HighPagePriority) == NULL) \
  287. { \
  288. *(_S) = NDIS_STATUS_RESOURCES; \
  289. break; \
  290. } \
  291. BYTES_OUT(_M, _Buffer); \
  292. _Buffer = _Buffer->Next; \
  293. } \
  294. }
  295. #define ndisMCheckPacketAndGetStatsOutAlreadyMapped(_M, _P) \
  296. { \
  297. PNDIS_BUFFER _Buffer; \
  298. \
  299. PACKETS_OUT(_M); \
  300. _Buffer = (_P)->Private.Head; \
  301. while (_Buffer != NULL) \
  302. { \
  303. BYTES_OUT(_M, _Buffer); \
  304. _Buffer = _Buffer->Next; \
  305. } \
  306. }
  307. #define NDISM_COMPLETE_SEND_SG(_M, _P, _NSR, _S, _L, _I, _UNLINK) \
  308. { \
  309. PNDIS_OPEN_BLOCK _O; \
  310. \
  311. if (!(_L)) \
  312. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(_M); \
  313. \
  314. _O = (_NSR)->Open; \
  315. \
  316. if (_UNLINK) \
  317. { \
  318. UNLINK_PACKET(_M, _P, _NSR); \
  319. } \
  320. POP_PACKET_STACK(_P); \
  321. \
  322. ADD_RESOURCE((_M), 'F'); \
  323. \
  324. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, \
  325. ("Completed 0x%x\n", (_S))); \
  326. \
  327. (_NSR)->Open = MAGIC_OPEN_I(_I); \
  328. M_OPEN_DECREMENT_REF(_O); \
  329. \
  330. if (!(_L) && (NULL != (_M)->FirstPendingPacket)) \
  331. { \
  332. /* \
  333. * Do we need to queue another workitem to process more sends ? \
  334. */ \
  335. NDISM_QUEUE_WORK_ITEM(_M, NdisWorkItemSend, NULL); \
  336. } \
  337. \
  338. /* \
  339. * Indicate the completion to the protocol. \
  340. */ \
  341. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC((_M)); \
  342. \
  343. if (NDIS_PER_PACKET_INFO_FROM_PACKET(_P, ScatterGatherListPacketInfo) != NULL) \
  344. { \
  345. ndisMFreeSGList(_M, _P); \
  346. } \
  347. /* \
  348. * Make sure that an IM which shares send and receive packets on the same \
  349. * pool works fine with the check in the receive path. \
  350. */ \
  351. (_NSR)->RefCount = 0; \
  352. MINIPORT_CLEAR_PACKET_FLAG(_P, fPACKET_CLEAR_ITEMS); \
  353. CLEAR_WRAPPER_RESERVED(_NSR); \
  354. (_O->SendCompleteHandler)(_O->ProtocolBindingContext, \
  355. (_P), \
  356. (_S)); \
  357. \
  358. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO, \
  359. ("- Open 0x%x Reference 0x%x\n", _O, _O->References)); \
  360. \
  361. if (_O->References == 0) \
  362. { \
  363. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(_M); \
  364. ndisMFinishClose(_O); \
  365. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC((_M)); \
  366. } \
  367. \
  368. if (_L) \
  369. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(_M); \
  370. }
  371. #define LINK_PACKET_SG(_M, _P, _NSR) \
  372. { \
  373. INIT_PACKET_LIST(_P); \
  374. \
  375. InsertTailList(&(_M)->PacketList, \
  376. PACKET_LIST(_P)); \
  377. }
  378. #endif // __SENDM_H