Windows NT 4.0 source code leak
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.

681 lines
18 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. wrapper.h
  5. Abstract:
  6. NDIS wrapper definitions
  7. Author:
  8. Environment:
  9. Kernel mode, FSD
  10. Revision History:
  11. Jun-95 Jameel Hyder Split up from a monolithic file
  12. --*/
  13. #ifndef _WRAPPPER_
  14. #define _WRAPPPER_
  15. #include <ntos.h>
  16. #include <ndismain.h>
  17. #include <ndisprot.h>
  18. #include <ndismac.h>
  19. #include <ndismini.h>
  20. #include <ndisco.h>
  21. #include <zwapi.h>
  22. #include <ndisdbg.h>
  23. #include <ndistags.h>
  24. extern UCHAR ndisValidProcessors[];
  25. extern ULONG ndisMaximumProcessor;
  26. extern ULONG ndisCurrentProcessor;
  27. extern UCHAR ndisInternalEaName[4];
  28. extern UCHAR ndisInternalEaValue[8];
  29. extern TDI_REGISTER_CALLBACK ndisTdiRegisterCallback;
  30. extern BOOLEAN ndisSkipProcessorAffinity;
  31. extern BOOLEAN ndisMediaTypeCl[NdisMediumMax];
  32. #define BYTE_SWAP(_word) ((USHORT) (((_word) >> 8) | ((_word) << 8)))
  33. #define LOW_WORD(_dword) ((USHORT) ((_dword) & 0x0000FFFF))
  34. #define HIGH_WORD(_dword) ((USHORT) (((_dword) >> 16) & 0x0000FFFF))
  35. #define BYTE_SWAP_ULONG(_ulong) ((ULONG)((ULONG)(BYTE_SWAP(LOW_WORD(_ulong)) << 16) + \
  36. BYTE_SWAP(HIGH_WORD(_ulong))))
  37. //
  38. // A set of macros to manipulate bitmasks.
  39. //
  40. //VOID
  41. //CLEAR_BIT_IN_MASK(
  42. // IN UINT Offset,
  43. // IN OUT PMASK MaskToClear
  44. // )
  45. //
  46. ///*++
  47. //
  48. //Routine Description:
  49. //
  50. // Clear a bit in the bitmask pointed to by the parameter.
  51. //
  52. //Arguments:
  53. //
  54. // Offset - The offset (from 0) of the bit to altered.
  55. //
  56. // MaskToClear - Pointer to the mask to be adjusted.
  57. //
  58. //Return Value:
  59. //
  60. // None.
  61. //
  62. //--*/
  63. //
  64. #define CLEAR_BIT_IN_MASK(Offset, MaskToClear) *(MaskToClear) &= (~(1 << Offset))
  65. //VOID
  66. //SET_BIT_IN_MASK(
  67. // IN UINT Offset,
  68. // IN OUT PMASK MaskToSet
  69. // )
  70. //
  71. ///*++
  72. //
  73. //Routine Description:
  74. //
  75. // Set a bit in the bitmask pointed to by the parameter.
  76. //
  77. //Arguments:
  78. //
  79. // Offset - The offset (from 0) of the bit to altered.
  80. //
  81. // MaskToSet - Pointer to the mask to be adjusted.
  82. //
  83. //Return Value:
  84. //
  85. // None.
  86. //
  87. //--*/
  88. #define SET_BIT_IN_MASK(Offset, MaskToSet) *(MaskToSet) |= (1 << Offset)
  89. //BOOLEAN
  90. //IS_BIT_SET_IN_MASK(
  91. // IN UINT Offset,
  92. // IN MASK MaskToTest
  93. // )
  94. //
  95. ///*++
  96. //
  97. //Routine Description:
  98. //
  99. // Tests if a particular bit in the bitmask pointed to by the parameter is
  100. // set.
  101. //
  102. //Arguments:
  103. //
  104. // Offset - The offset (from 0) of the bit to test.
  105. //
  106. // MaskToTest - The mask to be tested.
  107. //
  108. //Return Value:
  109. //
  110. // Returns TRUE if the bit is set.
  111. //
  112. //--*/
  113. #define IS_BIT_SET_IN_MASK(Offset, MaskToTest) ((MaskToTest & (1 << Offset)) ? TRUE : FALSE)
  114. //BOOLEAN
  115. //IS_MASK_CLEAR(
  116. // IN MASK MaskToTest
  117. // )
  118. //
  119. ///*++
  120. //
  121. //Routine Description:
  122. //
  123. // Tests whether there are *any* bits enabled in the mask.
  124. //
  125. //Arguments:
  126. //
  127. // MaskToTest - The bit mask to test for all clear.
  128. //
  129. //Return Value:
  130. //
  131. // Will return TRUE if no bits are set in the mask.
  132. //
  133. //--*/
  134. #define IS_MASK_CLEAR(MaskToTest) ((MaskToTest) ? FALSE : TRUE)
  135. //VOID
  136. //CLEAR_MASK(
  137. // IN OUT PMASK MaskToClear
  138. // );
  139. //
  140. ///*++
  141. //
  142. //Routine Description:
  143. //
  144. // Clears a mask.
  145. //
  146. //Arguments:
  147. //
  148. // MaskToClear - The bit mask to adjust.
  149. //
  150. //Return Value:
  151. //
  152. // None.
  153. //
  154. //--*/
  155. #define CLEAR_MASK(MaskToClear) *(MaskToClear) = 0
  156. //
  157. // This constant is used for places where NdisAllocateMemory
  158. // needs to be called and the HighestAcceptableAddress does
  159. // not matter.
  160. //
  161. #define RetrieveUlong(Destination, Source) \
  162. { \
  163. PUCHAR _S = (Source); \
  164. *(Destination) = ((ULONG)(*_S) << 24) | \
  165. ((ULONG)(*(_S+1)) << 16) | \
  166. ((ULONG)(*(_S+2)) << 8) | \
  167. ((ULONG)(*(_S+3))); \
  168. }
  169. //
  170. // This is the number of extra OIDs that ARCnet with Ethernet encapsulation
  171. // supports.
  172. //
  173. #define ARC_NUMBER_OF_EXTRA_OIDS 2
  174. //
  175. // ZZZ NonPortable definitions.
  176. //
  177. #define AllocPhys(s, l) NdisAllocateMemory((PVOID *)(s), (l), 0, HighestAcceptableMax)
  178. #define FreePhys(s, l) NdisFreeMemory((PVOID)(s), (l), 0)
  179. //
  180. // Internal wrapper data structures.
  181. //
  182. //
  183. // NDIS_WRAPPER_CONTEXT
  184. //
  185. // This data structure contains internal data items for use by the wrapper.
  186. //
  187. typedef struct _NDIS_WRAPPER_CONTEXT
  188. {
  189. //
  190. // Mac/miniport defined shutdown context.
  191. //
  192. PVOID ShutdownContext;
  193. //
  194. // Mac/miniport registered shutdown handler.
  195. //
  196. ADAPTER_SHUTDOWN_HANDLER ShutdownHandler;
  197. //
  198. // Kernel bugcheck record for bugcheck handling.
  199. //
  200. KBUGCHECK_CALLBACK_RECORD BugcheckCallbackRecord;
  201. //
  202. // Miniport assigned resources for PCI, PCMCIA, EISA, etc.
  203. //
  204. PCM_RESOURCE_LIST AssignedSlotResources;
  205. //
  206. // HAL common buffer cache.
  207. //
  208. PVOID SharedMemoryPage[2];
  209. ULONG SharedMemoryLeft[2];
  210. NDIS_PHYSICAL_ADDRESS SharedMemoryAddress[2];
  211. } NDIS_WRAPPER_CONTEXT, *PNDIS_WRAPPER_CONTEXT;
  212. //
  213. // Arcnet specific stuff
  214. //
  215. #define WRAPPER_ARC_BUFFERS 8
  216. #define WRAPPER_ARC_HEADER_SIZE 4
  217. //
  218. // Define constants used internally to identify regular opens from
  219. // query global statistics ones.
  220. //
  221. #define NDIS_OPEN_INTERNAL 1
  222. #define NDIS_OPEN_QUERY_STATISTICS 2
  223. //
  224. // This is the structure pointed to by the FsContext of an
  225. // open used for query statistics.
  226. //
  227. typedef struct _NDIS_USER_OPEN_CONTEXT
  228. {
  229. PDEVICE_OBJECT DeviceObject;
  230. union
  231. {
  232. PNDIS_MINIPORT_BLOCK MiniportBlock;
  233. PNDIS_ADAPTER_BLOCK AdapterBlock;
  234. };
  235. ULONG OidCount;
  236. PNDIS_OID OidArray;
  237. ULONG FullOidCount;
  238. PNDIS_OID FullOidArray;
  239. } NDIS_USER_OPEN_CONTEXT, *PNDIS_USER_OPEN_CONTEXT;
  240. //
  241. // An active query single statistic request.
  242. //
  243. typedef struct _NDIS_QUERY_GLOBAL_REQUEST
  244. {
  245. PIRP Irp;
  246. NDIS_REQUEST Request;
  247. } NDIS_QUERY_GLOBAL_REQUEST, *PNDIS_QUERY_GLOBAL_REQUEST;
  248. //
  249. // An active query all statistics request.
  250. //
  251. typedef struct _NDIS_QUERY_ALL_REQUEST
  252. {
  253. PIRP Irp;
  254. NDIS_REQUEST Request;
  255. NDIS_STATUS NdisStatus;
  256. KEVENT Event;
  257. } NDIS_QUERY_ALL_REQUEST, *PNDIS_QUERY_ALL_REQUEST;
  258. //
  259. // An temporary request used during an open.
  260. //
  261. typedef struct _NDIS_QUERY_OPEN_REQUEST
  262. {
  263. PIRP Irp;
  264. NDIS_REQUEST Request;
  265. NDIS_STATUS NdisStatus;
  266. KEVENT Event;
  267. } NDIS_QUERY_OPEN_REQUEST, *PNDIS_QUERY_OPEN_REQUEST;
  268. //
  269. // An temporary request used during init
  270. //
  271. typedef struct _NDIS_QS_REQUEST
  272. {
  273. NDIS_REQUEST Request;
  274. NDIS_STATUS NdisStatus;
  275. KEVENT Event;
  276. } NDIS_QS_REQUEST, *PNDIS_QS_REQUEST;
  277. //
  278. // Used to queue configuration parameters
  279. //
  280. typedef struct _NDIS_CONFIGURATION_PARAMETER_QUEUE
  281. {
  282. struct _NDIS_CONFIGURATION_PARAMETER_QUEUE* Next;
  283. NDIS_CONFIGURATION_PARAMETER Parameter;
  284. } NDIS_CONFIGURATION_PARAMETER_QUEUE, *PNDIS_CONFIGURATION_PARAMETER_QUEUE;
  285. //
  286. // Configuration Handle
  287. //
  288. typedef struct _NDIS_CONFIGURATION_HANDLE
  289. {
  290. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable;
  291. PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterList;
  292. } NDIS_CONFIGURATION_HANDLE, *PNDIS_CONFIGURATION_HANDLE;
  293. typedef struct _NDIS_REQUEST_RESERVED
  294. {
  295. PNDIS_REQUEST Next;
  296. struct _NDIS_M_OPEN_BLOCK * Open;
  297. } NDIS_REQUEST_RESERVED, *PNDIS_REQUEST_RESERVED;
  298. #define PNDIS_RESERVED_FROM_PNDIS_REQUEST(_request) ((PNDIS_REQUEST_RESERVED)((_request)->MacReserved))
  299. //
  300. // This is used to keep track of pci/eisa/mca cards in the system so that
  301. // if they move, then the bus#/slot# can be fixed up appropriately.
  302. //
  303. typedef struct _BUS_SLOT_DB
  304. {
  305. struct _BUS_SLOT_DB *Next;
  306. NDIS_INTERFACE_TYPE BusType;
  307. ULONG BusNumber;
  308. ULONG SlotNumber;
  309. ULONG BusId;
  310. } BUS_SLOT_DB, *PBUS_SLOT_DB;
  311. extern PBUS_SLOT_DB ndisGlobalDb;
  312. extern KSPIN_LOCK ndisGlobalDbLock;
  313. //
  314. // This is used during addadapter/miniportinitialize so that when the
  315. // driver calls any NdisImmediatexxx routines we can access its driverobj.
  316. //
  317. typedef struct _NDIS_WRAPPER_CONFIGURATION_HANDLE
  318. {
  319. RTL_QUERY_REGISTRY_TABLE ParametersQueryTable[5];
  320. PDRIVER_OBJECT DriverObject;
  321. PUNICODE_STRING DriverBaseName;
  322. BUS_SLOT_DB Db;
  323. } NDIS_WRAPPER_CONFIGURATION_HANDLE, *PNDIS_WRAPPER_CONFIGURATION_HANDLE;
  324. //
  325. // Describes an open NDIS file
  326. //
  327. //
  328. // Context for Bind Adapter.
  329. //
  330. typedef struct _NDIS_BIND_CONTEXT
  331. {
  332. struct _NDIS_BIND_CONTEXT * Next;
  333. PNDIS_PROTOCOL_BLOCK Protocol;
  334. NDIS_STRING ProtocolSection;
  335. PNDIS_STRING DeviceName;
  336. WORK_QUEUE_ITEM WorkItem;
  337. NDIS_STATUS BindStatus;
  338. KEVENT Event;
  339. KEVENT ThreadDoneEvent;
  340. } NDIS_BIND_CONTEXT, *PNDIS_BIND_CONTEXT;
  341. typedef struct _NDIS_FILE_DESCRIPTOR
  342. {
  343. PVOID Data;
  344. KSPIN_LOCK Lock;
  345. BOOLEAN Mapped;
  346. } NDIS_FILE_DESCRIPTOR, *PNDIS_FILE_DESCRIPTOR;
  347. //
  348. // The following structure is used to queue openadapter/closeadapter calls to
  349. // worker threads so that they can complete at LOW_LEVEL.
  350. //
  351. typedef struct _QUEUED_OPEN_CLOSE
  352. {
  353. PNDIS_OPEN_BLOCK OpenP;
  354. NDIS_STATUS Status;
  355. NDIS_STATUS OpenErrorStatus;
  356. WORK_QUEUE_ITEM WorkItem;
  357. BOOLEAN FreeIt;
  358. } QUEUED_OPEN_CLOSE, *PQUEUED_OPEN_CLOSE;
  359. typedef struct _QueuedProtocolNotification
  360. {
  361. WORK_QUEUE_ITEM WorkItem;
  362. PNDIS_M_DRIVER_BLOCK MiniBlock;
  363. UNICODE_STRING UpCaseDeviceInstance;
  364. WCHAR Buffer[1];
  365. } QUEUED_PROTOCOL_NOTIFICATION, *PQUEUED_PROTOCOL_NOTIFICATION;
  366. #if defined(_ALPHA_)
  367. typedef struct _NDIS_LOOKAHEAD_ELEMENT
  368. {
  369. ULONG Length;
  370. struct _NDIS_LOOKAHEAD_ELEMENT *Next;
  371. } NDIS_LOOKAHEAD_ELEMENT, *PNDIS_LOOKAHEAD_ELEMENT;
  372. #endif
  373. typedef struct _PKG_REF
  374. {
  375. KSPIN_LOCK ReferenceLock;
  376. ULONG ReferenceCount;
  377. PVOID ImageHandle;
  378. KEVENT PagedInEvent;
  379. } PKG_REF, *PPKG_REF;
  380. //
  381. // Structures for dealing with making the module specific routines pagable
  382. //
  383. extern PKG_REF ProtocolPkg;
  384. extern PKG_REF MacPkg;
  385. extern PKG_REF CoPkg;
  386. extern PKG_REF InitPkg;
  387. extern PKG_REF PnPPkg;
  388. extern PKG_REF MiniportPkg;
  389. extern PKG_REF ArcPkg;
  390. extern PKG_REF EthPkg;
  391. extern PKG_REF TrPkg;
  392. extern PKG_REF FddiPkg;
  393. extern PNDIS_PROTOCOL_BLOCK ndisProtocolList;
  394. //
  395. // Work item structure
  396. //
  397. typedef struct _NDIS_MINIPORT_WORK_ITEM
  398. {
  399. //
  400. // Link for the list of work items of this type.
  401. //
  402. SINGLE_LIST_ENTRY Link;
  403. //
  404. // type of work item and context information.
  405. //
  406. NDIS_WORK_ITEM_TYPE WorkItemType;
  407. PVOID WorkItemContext1;
  408. PVOID WorkItemContext2;
  409. } NDIS_MINIPORT_WORK_ITEM, *PNDIS_MINIPORT_WORK_ITEM;
  410. //
  411. // This does most of the work of dequeueing a workitem.
  412. //
  413. #define NDISM_DEQUEUE_WORK_ITEM_MACRO(_M, _WT, _pWC1, _pWC2) \
  414. { \
  415. }
  416. #define NDISM_QUEUE_WORK_ITEM_MACRO(_M, _WT, _WC1, _WC2, _pS) \
  417. { \
  418. PSINGLE_LIST_ENTRY _Link; \
  419. PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
  420. \
  421. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  422. ("==>ndisMQueueWorkItem()\n")); \
  423. \
  424. _Link = PopEntryList(&(_M)->SingleWorkItems[(_WT)]); \
  425. if (NULL != _Link) \
  426. { \
  427. _WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
  428. _WorkItem->WorkItemType = (_WT); \
  429. _WorkItem->WorkItemContext1 = (_WC1); \
  430. _WorkItem->WorkItemContext2 = (_WC2); \
  431. PushEntryList(&(_M)->WorkQueue[(_WT)], _Link); \
  432. *(_pS) = NDIS_STATUS_SUCCESS; \
  433. } \
  434. else \
  435. { \
  436. *(_pS) = NDIS_STATUS_NOT_ACCEPTED; \
  437. } \
  438. \
  439. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  440. ("<==ndisMQueueWorkItem()\n")); \
  441. }
  442. #define NDISM_QUEUE_WORK_ITEM_FULL_DUPLEX_MACRO(_M, _WT, _WC1, _WC2, _pS) \
  443. { \
  444. PSINGLE_LIST_ENTRY _Link; \
  445. PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
  446. \
  447. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  448. ("==>ndisMQueueWorkItemFullDuplex()\n")); \
  449. \
  450. ACQUIRE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
  451. \
  452. _Link = PopEntryList(&(_M)->SingleWorkItems[(_WT)]); \
  453. if (NULL != _Link) \
  454. { \
  455. _WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
  456. _WorkItem->WorkItemType = (_WT); \
  457. _WorkItem->WorkItemContext1 = (_WC1); \
  458. _WorkItem->WorkItemContext2 = (_WC2); \
  459. PushEntryList(&(_M)->WorkQueue[(_WT)], \
  460. _Link); \
  461. \
  462. *(_pS) = NDIS_STATUS_SUCCESS; \
  463. } \
  464. else \
  465. { \
  466. *(_pS) = NDIS_STATUS_NOT_ACCEPTED; \
  467. } \
  468. \
  469. RELEASE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
  470. \
  471. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  472. ("<==ndisMQueueWorkItemFullDuplex()\n")); \
  473. }
  474. #define NDISM_QUEUE_NEW_WORK_ITEM_MACRO(_M, _WT, _WC1, _WC2, _pS) \
  475. { \
  476. PSINGLE_LIST_ENTRY _Link; \
  477. PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
  478. \
  479. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  480. ("==>ndisMQueueNewWorkItem()\n")); \
  481. \
  482. ASSERT(((_WT) < NUMBER_OF_WORK_ITEM_TYPES) && ((_WT) > NUMBER_OF_SINGLE_WORK_ITEMS)); \
  483. \
  484. do \
  485. { \
  486. _Link = PopEntryList(&(_M)->WorkItemFreeQueue); \
  487. if (NULL == _Link) \
  488. { \
  489. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  490. ("Allocate a workitem from the pool.\n")); \
  491. \
  492. _WorkItem = ALLOC_FROM_POOL(sizeof(NDIS_MINIPORT_WORK_ITEM), NDIS_TAG_WORK_ITEM);\
  493. if (NULL == _WorkItem) \
  494. { \
  495. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL, \
  496. ("Failed to allocate a workitem from the pool!\n")); \
  497. DBGBREAK(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL); \
  498. \
  499. *(_pS) = NDIS_STATUS_FAILURE; \
  500. \
  501. break; \
  502. } \
  503. (_M)->NumberOfAllocatedWorkItems++; \
  504. } \
  505. else \
  506. { \
  507. _WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
  508. } \
  509. \
  510. ZeroMemory(_WorkItem, sizeof(NDIS_MINIPORT_WORK_ITEM)); \
  511. _WorkItem->WorkItemType = (_WT); \
  512. _WorkItem->WorkItemContext1 = (_WC1); \
  513. _WorkItem->WorkItemContext2 = (_WC2); \
  514. \
  515. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  516. ("WorkItem 0x%x\n", _WorkItem)); \
  517. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  518. ("WorkItem Type 0x%x\n", (_WT))); \
  519. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  520. ("WorkItem Context2 0x%x\n", (_WC1))); \
  521. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  522. ("WorkItem Context1 0x%x\n", (_WC2))); \
  523. \
  524. PushEntryList(&(_M)->WorkQueue[(_WT)], &_WorkItem->Link); \
  525. \
  526. *(_pS) = NDIS_STATUS_SUCCESS; \
  527. \
  528. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  529. ("<==ndisMQueueNewWorkItem()\n")); \
  530. } while (FALSE); \
  531. }
  532. #define NDISM_QUEUE_NEW_WORK_ITEM_FULL_DUPLEX_MACRO(_M, _WT, _WC1, _WC2, _pS) \
  533. { \
  534. PSINGLE_LIST_ENTRY _Link; \
  535. PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
  536. \
  537. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  538. ("==>ndisMQueueNewWorkItemFullDuplex()\n")); \
  539. \
  540. ASSERT(((_WT) < NUMBER_OF_WORK_ITEM_TYPES) && ((_WT) > NUMBER_OF_SINGLE_WORK_ITEMS)); \
  541. \
  542. ACQUIRE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
  543. \
  544. do \
  545. { \
  546. _Link = PopEntryList(&(_M)->WorkItemFreeQueue); \
  547. if (NULL == _Link) \
  548. { \
  549. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  550. ("Allocate a workitem from the pool.\n")); \
  551. \
  552. _WorkItem = ALLOC_FROM_POOL(sizeof(NDIS_MINIPORT_WORK_ITEM), NDIS_TAG_WORK_ITEM);\
  553. if (NULL == _WorkItem) \
  554. { \
  555. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL, \
  556. ("Failed to allocate a workitem from the pool!\n")); \
  557. DBGBREAK(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL); \
  558. \
  559. *(_pS) = NDIS_STATUS_FAILURE; \
  560. \
  561. break; \
  562. } \
  563. \
  564. (_M)->NumberOfAllocatedWorkItems++; \
  565. } \
  566. else \
  567. { \
  568. _WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
  569. } \
  570. \
  571. ZeroMemory(_WorkItem, sizeof(NDIS_MINIPORT_WORK_ITEM)); \
  572. _WorkItem->WorkItemType = (_WT); \
  573. _WorkItem->WorkItemContext1 = (_WC1); \
  574. _WorkItem->WorkItemContext2 = (_WC2); \
  575. \
  576. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  577. ("WorkItem 0x%x\n", _WorkItem)); \
  578. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  579. ("WorkItem Type 0x%x\n", (_WT))); \
  580. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  581. ("WorkItem Context2 0x%x\n", (_WC1))); \
  582. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  583. ("WorkItem Context1 0x%x\n", (_WC2))); \
  584. \
  585. PushEntryList(&(_M)->WorkQueue[(_WT)], &_WorkItem->Link); \
  586. \
  587. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
  588. ("<==ndisMQueueNewWorkItemFullDuplex()\n")); \
  589. } while (FALSE); \
  590. \
  591. RELEASE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
  592. }
  593. #define NDISM_QUEUE_WORK_ITEM(_M, _WT, _WC1, _WC2) (_M)->QueueWorkItemHandler(_M, _WT, _WC1, _WC2)
  594. #define NDISM_QUEUE_NEW_WORK_ITEM(_M, _WT, _WC1, _WC2) (_M)->QueueNewWorkItemHandler(_M, _WT, _WC1, _WC2)
  595. #define NDISM_DEQUEUE_WORK_ITEM(_M, _WT, _pWC1, _pWC2) (_M)->DeQueueWorkItemHandler(_M, _WT, _pWC1, _pWC2)
  596. #define NDISM_PROCESS_DEFERRED(_M) (_M)->ProcessDeferredHandler((_M))
  597. #endif // _WRAPPPER_