Leaked source code of windows server 2003
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.

2674 lines
86 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. mp_req.c
  5. Abstract:
  6. This module contains miniport OID related handlers
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. DChen 11-01-99 created
  11. Notes:
  12. --*/
  13. #include "precomp.h"
  14. #include "e100_wmi.h"
  15. #if DBG
  16. #define _FILENUMBER 'QERM'
  17. #endif
  18. #if OFFLOAD
  19. //
  20. // This miniport only supports one Encapsultion type: IEEE_802_3_Encapsulation
  21. // one task version: NDIS_TASK_OFFLOAD_VERSION. Modify the code below OID_TCP_
  22. // TASK_OFFLOAD in query and setting information functions to make it support
  23. // more than one encapsulation type and task version
  24. //
  25. // Define the task offload the miniport currently supports.
  26. // This miniport only supports two kinds of offload tasks:
  27. // TCP/IP checksum offload and Segmentation large TCP packet offload
  28. // Later if it can supports more tasks, just redefine this task array
  29. //
  30. NDIS_TASK_OFFLOAD OffloadTasks[] = {
  31. {
  32. NDIS_TASK_OFFLOAD_VERSION,
  33. sizeof(NDIS_TASK_OFFLOAD),
  34. TcpIpChecksumNdisTask,
  35. 0,
  36. sizeof(NDIS_TASK_TCP_IP_CHECKSUM)
  37. },
  38. {
  39. NDIS_TASK_OFFLOAD_VERSION,
  40. sizeof(NDIS_TASK_OFFLOAD),
  41. TcpLargeSendNdisTask,
  42. 0,
  43. sizeof(NDIS_TASK_TCP_LARGE_SEND)
  44. }
  45. };
  46. //
  47. // Get the number of offload tasks this miniport supports
  48. //
  49. ULONG OffloadTasksCount = sizeof(OffloadTasks) / sizeof(OffloadTasks[0]);
  50. //
  51. // Specify TCP/IP checksum offload task, the miniport can only supports, for now,
  52. // TCP checksum and IP checksum on the sending side, also it supports TCP and IP
  53. // options
  54. //
  55. NDIS_TASK_TCP_IP_CHECKSUM TcpIpChecksumTask = {
  56. {1, 1, 1, 0, 1},
  57. {0, 0, 0, 0, 0},
  58. {0, 0, 0, 0},
  59. {0, 0, 0, 0}
  60. };
  61. //
  62. // Specify Large Send offload task, the miniport supports TCP options and IP options,
  63. // and the minimum segment count the protocol can offload is 1. At this point, we
  64. // cannot specify the maximum offload size(here is 0), because it depends on the size
  65. // of shared memory and the number of TCB used by the driver.
  66. //
  67. NDIS_TASK_TCP_LARGE_SEND TcpLargeSendTask = {
  68. 0, //Currently the version is set to 0, later it may change
  69. 0,
  70. 1,
  71. TRUE,
  72. TRUE
  73. };
  74. #endif // OFFLOAD
  75. ULONG VendorDriverVersion = NIC_VENDOR_DRIVER_VERSION;
  76. NDIS_OID NICSupportedOids[] =
  77. {
  78. OID_GEN_SUPPORTED_LIST,
  79. OID_GEN_HARDWARE_STATUS,
  80. OID_GEN_MEDIA_SUPPORTED,
  81. OID_GEN_MEDIA_IN_USE,
  82. OID_GEN_MAXIMUM_LOOKAHEAD,
  83. OID_GEN_MAXIMUM_FRAME_SIZE,
  84. OID_GEN_LINK_SPEED,
  85. OID_GEN_TRANSMIT_BUFFER_SPACE,
  86. OID_GEN_RECEIVE_BUFFER_SPACE,
  87. OID_GEN_TRANSMIT_BLOCK_SIZE,
  88. OID_GEN_RECEIVE_BLOCK_SIZE,
  89. OID_GEN_VENDOR_ID,
  90. OID_GEN_VENDOR_DESCRIPTION,
  91. OID_GEN_VENDOR_DRIVER_VERSION,
  92. OID_GEN_CURRENT_PACKET_FILTER,
  93. OID_GEN_CURRENT_LOOKAHEAD,
  94. OID_GEN_DRIVER_VERSION,
  95. OID_GEN_MAXIMUM_TOTAL_SIZE,
  96. OID_GEN_MAC_OPTIONS,
  97. OID_GEN_MEDIA_CONNECT_STATUS,
  98. OID_GEN_MAXIMUM_SEND_PACKETS,
  99. OID_GEN_SUPPORTED_GUIDS,
  100. OID_GEN_XMIT_OK,
  101. OID_GEN_RCV_OK,
  102. OID_GEN_XMIT_ERROR,
  103. OID_GEN_RCV_ERROR,
  104. OID_GEN_RCV_NO_BUFFER,
  105. OID_GEN_RCV_CRC_ERROR,
  106. OID_GEN_TRANSMIT_QUEUE_LENGTH,
  107. OID_802_3_PERMANENT_ADDRESS,
  108. OID_802_3_CURRENT_ADDRESS,
  109. OID_802_3_MULTICAST_LIST,
  110. OID_802_3_MAXIMUM_LIST_SIZE,
  111. OID_802_3_RCV_ERROR_ALIGNMENT,
  112. OID_802_3_XMIT_ONE_COLLISION,
  113. OID_802_3_XMIT_MORE_COLLISIONS,
  114. OID_802_3_XMIT_DEFERRED,
  115. OID_802_3_XMIT_MAX_COLLISIONS,
  116. OID_802_3_RCV_OVERRUN,
  117. OID_802_3_XMIT_UNDERRUN,
  118. OID_802_3_XMIT_HEARTBEAT_FAILURE,
  119. OID_802_3_XMIT_TIMES_CRS_LOST,
  120. OID_802_3_XMIT_LATE_COLLISIONS,
  121. #if !BUILD_W2K
  122. OID_GEN_PHYSICAL_MEDIUM,
  123. #endif
  124. #if OFFLOAD
  125. OID_TCP_TASK_OFFLOAD,
  126. #endif
  127. /* powermanagement */
  128. OID_PNP_CAPABILITIES,
  129. OID_PNP_SET_POWER,
  130. OID_PNP_QUERY_POWER,
  131. OID_PNP_ADD_WAKE_UP_PATTERN,
  132. OID_PNP_REMOVE_WAKE_UP_PATTERN,
  133. OID_PNP_ENABLE_WAKE_UP,
  134. /* custom oid WMI support */
  135. OID_CUSTOM_DRIVER_SET,
  136. OID_CUSTOM_DRIVER_QUERY,
  137. OID_CUSTOM_ARRAY,
  138. OID_CUSTOM_STRING
  139. };
  140. //
  141. // WMI support
  142. // check out the e100.mof file for examples of how the below
  143. // maps into a .mof file for external advertisement of GUIDs
  144. //
  145. #define NIC_NUM_CUSTOM_GUIDS 4
  146. //
  147. // Define the following values to demonstrate that the driver should
  148. // always validat the content in the information buffer whether the OID
  149. // is for set or query
  150. //
  151. #define CUSTOM_DRIVER_SET_MIN 0x1
  152. #define CUSTOM_DRIVER_SET_MAX 0xFFFFFF
  153. #if BUILD_W2K
  154. static const NDIS_GUID NICGuidList[NIC_NUM_CUSTOM_GUIDS] = {
  155. { // {F4A80276-23B7-11d1-9ED9-00A0C9010057} example of a uint set
  156. E100BExampleSetUINT_OIDGuid,
  157. OID_CUSTOM_DRIVER_SET,
  158. sizeof(ULONG),
  159. (fNDIS_GUID_TO_OID )
  160. },
  161. { // {F4A80277-23B7-11d1-9ED9-00A0C9010057} example of a uint query
  162. E100BExampleQueryUINT_OIDGuid,
  163. OID_CUSTOM_DRIVER_QUERY,
  164. sizeof(ULONG),
  165. (fNDIS_GUID_TO_OID)
  166. },
  167. { // {F4A80278-23B7-11d1-9ED9-00A0C9010057} example of an array query
  168. E100BExampleQueryArrayOIDGuid,
  169. OID_CUSTOM_ARRAY,
  170. sizeof(UCHAR), // size is size of each element in the array
  171. (fNDIS_GUID_TO_OID|fNDIS_GUID_ARRAY )
  172. },
  173. { // {F4A80279-23B7-11d1-9ED9-00A0C9010057} example of a string query
  174. E100BExampleQueryStringOIDGuid,
  175. OID_CUSTOM_STRING,
  176. (ULONG) -1, // size is -1 for ANSI or NDIS_STRING string types
  177. (fNDIS_GUID_TO_OID|fNDIS_GUID_ANSI_STRING)
  178. }
  179. };
  180. #else
  181. //
  182. // Support for the fNDIS_GUID_ALLOW_READ flag has been added in WinXP for
  183. // both 5.0 and 5.1 miniports
  184. //
  185. static const NDIS_GUID NICGuidList[NIC_NUM_CUSTOM_GUIDS] = {
  186. { // {F4A80276-23B7-11d1-9ED9-00A0C9010057} example of a uint set
  187. E100BExampleSetUINT_OIDGuid,
  188. OID_CUSTOM_DRIVER_SET,
  189. sizeof(ULONG),
  190. // Not setting fNDIS_GUID_ALLOW_WRITE flag means that we don't allow
  191. // users without administrator privilege to set this value, but we do
  192. // allow any user to query this value
  193. (fNDIS_GUID_TO_OID | fNDIS_GUID_ALLOW_READ)
  194. },
  195. { // {F4A80277-23B7-11d1-9ED9-00A0C9010057} example of a uint query
  196. E100BExampleQueryUINT_OIDGuid,
  197. OID_CUSTOM_DRIVER_QUERY,
  198. sizeof(ULONG),
  199. // setting fNDIS_GUID_ALLOW_READ flag means that we allow any
  200. // user to query this value.
  201. (fNDIS_GUID_TO_OID | fNDIS_GUID_ALLOW_READ)
  202. },
  203. { // {F4A80278-23B7-11d1-9ED9-00A0C9010057} example of an array query
  204. E100BExampleQueryArrayOIDGuid,
  205. OID_CUSTOM_ARRAY,
  206. sizeof(UCHAR), // size is size of each element in the array
  207. // setting fNDIS_GUID_ALLOW_READ flag means that we allow any
  208. // user to query this value.
  209. (fNDIS_GUID_TO_OID|fNDIS_GUID_ARRAY | fNDIS_GUID_ALLOW_READ)
  210. },
  211. { // {F4A80279-23B7-11d1-9ED9-00A0C9010057} example of a string query
  212. E100BExampleQueryStringOIDGuid,
  213. OID_CUSTOM_STRING,
  214. (ULONG) -1, // size is -1 for ANSI or NDIS_STRING string types
  215. // setting fNDIS_GUID_ALLOW_READ flag means that we allow any
  216. // user to query this value.
  217. (fNDIS_GUID_TO_OID|fNDIS_GUID_ANSI_STRING | fNDIS_GUID_ALLOW_READ)
  218. }
  219. };
  220. #endif
  221. /**
  222. Local Prototypes
  223. **/
  224. NDIS_STATUS
  225. MPSetPower(
  226. PMP_ADAPTER Adapter,
  227. NDIS_DEVICE_POWER_STATE PowerState
  228. );
  229. VOID
  230. MPFillPoMgmtCaps (
  231. IN PMP_ADAPTER Adapter,
  232. IN OUT PNDIS_PNP_CAPABILITIES pPower_Management_Capabilities,
  233. IN OUT PNDIS_STATUS pStatus,
  234. IN OUT PULONG pulInfoLen
  235. );
  236. NDIS_STATUS
  237. MPAddWakeUpPattern(
  238. IN PMP_ADAPTER pAdapter,
  239. IN PVOID InformationBuffer,
  240. IN UINT InformationBufferLength,
  241. IN OUT PULONG BytesRead,
  242. IN OUT PULONG BytesNeeded
  243. );
  244. NDIS_STATUS
  245. MPRemoveWakeUpPattern(
  246. IN PMP_ADAPTER pAdapter,
  247. IN PVOID InformationBuffer,
  248. IN UINT InformationBufferLength,
  249. OUT PULONG BytesRead,
  250. OUT PULONG BytesNeeded
  251. );
  252. BOOLEAN
  253. MPAreTwoPatternsEqual(
  254. IN PNDIS_PM_PACKET_PATTERN pNdisPattern1,
  255. IN PNDIS_PM_PACKET_PATTERN pNdisPattern2
  256. );
  257. //
  258. // Macros used to walk a doubly linked list. Only macros that are not defined in ndis.h
  259. // The List Next macro will work on Single and Doubly linked list as Flink is a common
  260. // field name in both
  261. //
  262. /*
  263. PLIST_ENTRY
  264. ListNext (
  265. IN PLIST_ENTRY
  266. );
  267. PSINGLE_LIST_ENTRY
  268. ListNext (
  269. IN PSINGLE_LIST_ENTRY
  270. );
  271. */
  272. #define ListNext(_pL) (_pL)->Flink
  273. /*
  274. PLIST_ENTRY
  275. ListPrev (
  276. IN LIST_ENTRY *
  277. );
  278. */
  279. #define ListPrev(_pL) (_pL)->Blink
  280. __inline
  281. BOOLEAN
  282. MPIsPoMgmtSupported(
  283. IN PMP_ADAPTER pAdapter
  284. )
  285. {
  286. if (pAdapter->RevsionID >= E100_82559_A_STEP &&
  287. pAdapter->RevsionID <= E100_82559_C_STEP )
  288. {
  289. return TRUE;
  290. }
  291. else
  292. {
  293. return FALSE;
  294. }
  295. }
  296. NDIS_STATUS MPQueryInformation(
  297. IN NDIS_HANDLE MiniportAdapterContext,
  298. IN NDIS_OID Oid,
  299. IN PVOID InformationBuffer,
  300. IN ULONG InformationBufferLength,
  301. OUT PULONG BytesWritten,
  302. OUT PULONG BytesNeeded
  303. )
  304. /*++
  305. Routine Description:
  306. MiniportQueryInformation handler
  307. Arguments:
  308. MiniportAdapterContext Pointer to the adapter structure
  309. Oid Oid for this query
  310. InformationBuffer Buffer for information
  311. InformationBufferLength Size of this buffer
  312. BytesWritten Specifies how much info is written
  313. BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
  314. Return Value:
  315. NDIS_STATUS_SUCCESS
  316. NDIS_STATUS_NOT_SUPPORTED
  317. NDIS_STATUS_BUFFER_TOO_SHORT
  318. --*/
  319. {
  320. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  321. PMP_ADAPTER Adapter;
  322. NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  323. NDIS_MEDIUM Medium = NIC_MEDIA_TYPE;
  324. UCHAR VendorDesc[] = NIC_VENDOR_DESC;
  325. NDIS_PNP_CAPABILITIES Power_Management_Capabilities;
  326. ULONG ulInfo = 0;
  327. ULONG64 ul64Info = 0;
  328. USHORT usInfo = 0;
  329. PVOID pInfo = (PVOID) &ulInfo;
  330. ULONG ulInfoLen = sizeof(ulInfo);
  331. ULONG ulBytesAvailable = ulInfoLen;
  332. PNDIS_TASK_OFFLOAD_HEADER pNdisTaskOffloadHdr;
  333. NDIS_MEDIA_STATE CurrMediaState;
  334. NDIS_STATUS IndicateStatus;
  335. #if OFFLOAD
  336. PNDIS_TASK_OFFLOAD pTaskOffload;
  337. PNDIS_TASK_TCP_IP_CHECKSUM pTcpIpChecksumTask;
  338. PNDIS_TASK_TCP_LARGE_SEND pTcpLargeSendTask;
  339. ULONG ulHeadersLen;
  340. ULONG ulMaxOffloadSize;
  341. UINT i;
  342. #endif
  343. #if !BUILD_W2K
  344. NDIS_PHYSICAL_MEDIUM PhysMedium = NdisPhysicalMediumUnspecified;
  345. #endif
  346. DBGPRINT(MP_TRACE, ("====> MPQueryInformation\n"));
  347. Adapter = (PMP_ADAPTER) MiniportAdapterContext;
  348. //
  349. // Initialize the result
  350. //
  351. *BytesWritten = 0;
  352. *BytesNeeded = 0;
  353. //
  354. // Process different type of requests
  355. //
  356. switch(Oid)
  357. {
  358. case OID_GEN_SUPPORTED_LIST:
  359. pInfo = (PVOID) NICSupportedOids;
  360. ulBytesAvailable = ulInfoLen = sizeof(NICSupportedOids);
  361. break;
  362. case OID_GEN_HARDWARE_STATUS:
  363. pInfo = (PVOID) &HardwareStatus;
  364. ulBytesAvailable = ulInfoLen = sizeof(NDIS_HARDWARE_STATUS);
  365. break;
  366. case OID_GEN_MEDIA_SUPPORTED:
  367. case OID_GEN_MEDIA_IN_USE:
  368. pInfo = (PVOID) &Medium;
  369. ulBytesAvailable = ulInfoLen = sizeof(NDIS_MEDIUM);
  370. break;
  371. #if !BUILD_W2K
  372. case OID_GEN_PHYSICAL_MEDIUM:
  373. pInfo = (PVOID) &PhysMedium;
  374. ulBytesAvailable = ulInfoLen = sizeof(NDIS_PHYSICAL_MEDIUM);
  375. break;
  376. #endif
  377. case OID_GEN_CURRENT_LOOKAHEAD:
  378. case OID_GEN_MAXIMUM_LOOKAHEAD:
  379. if (Adapter->ulLookAhead == 0)
  380. {
  381. Adapter->ulLookAhead = NIC_MAX_PACKET_SIZE - NIC_HEADER_SIZE;
  382. }
  383. ulInfo = Adapter->ulLookAhead;
  384. break;
  385. case OID_GEN_MAXIMUM_FRAME_SIZE:
  386. ulInfo = NIC_MAX_PACKET_SIZE - NIC_HEADER_SIZE;
  387. break;
  388. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  389. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  390. case OID_GEN_RECEIVE_BLOCK_SIZE:
  391. ulInfo = (ULONG) NIC_MAX_PACKET_SIZE;
  392. break;
  393. case OID_GEN_MAC_OPTIONS:
  394. // Notes:
  395. // The protocol driver is free to access indicated data by any means.
  396. // Some fast-copy functions have trouble accessing on-board device
  397. // memory. NIC drivers that indicate data out of mapped device memory
  398. // should never set this flag. If a NIC driver does set this flag, it
  399. // relaxes the restriction on fast-copy functions.
  400. // This miniport indicates receive with NdisMIndicateReceivePacket
  401. // function. It has no MiniportTransferData function. Such a driver
  402. // should set this flag.
  403. ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
  404. NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
  405. NDIS_MAC_OPTION_NO_LOOPBACK;
  406. break;
  407. case OID_GEN_LINK_SPEED:
  408. case OID_GEN_MEDIA_CONNECT_STATUS:
  409. if (InformationBufferLength < ulInfoLen)
  410. {
  411. break;
  412. }
  413. NdisAcquireSpinLock(&Adapter->Lock);
  414. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
  415. {
  416. ASSERT(!Adapter->bQueryPending);
  417. Adapter->bQueryPending = TRUE;
  418. Adapter->QueryRequest.Oid = Oid;
  419. Adapter->QueryRequest.InformationBuffer = InformationBuffer;
  420. Adapter->QueryRequest.InformationBufferLength = InformationBufferLength;
  421. Adapter->QueryRequest.BytesWritten = BytesWritten;
  422. Adapter->QueryRequest.BytesNeeded = BytesNeeded;
  423. NdisReleaseSpinLock(&Adapter->Lock);
  424. DBGPRINT(MP_WARN, ("MPQueryInformation: OID 0x%08x is pended\n", Oid));
  425. Status = NDIS_STATUS_PENDING;
  426. break;
  427. }
  428. else
  429. {
  430. NdisReleaseSpinLock(&Adapter->Lock);
  431. if (Oid == OID_GEN_LINK_SPEED)
  432. {
  433. ulInfo = Adapter->usLinkSpeed * 10000;
  434. }
  435. else // OID_GEN_MEDIA_CONNECT_STATUS
  436. {
  437. CurrMediaState = NICGetMediaState(Adapter);
  438. NdisAcquireSpinLock(&Adapter->Lock);
  439. if (Adapter->MediaState != CurrMediaState)
  440. {
  441. Adapter->MediaState = CurrMediaState;
  442. DBGPRINT(MP_WARN, ("Media state changed to %s\n",
  443. ((CurrMediaState == NdisMediaStateConnected)?
  444. "Connected": "Disconnected")));
  445. IndicateStatus = (CurrMediaState == NdisMediaStateConnected) ?
  446. NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT;
  447. if (IndicateStatus == NDIS_STATUS_MEDIA_CONNECT)
  448. {
  449. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
  450. }
  451. else
  452. {
  453. MP_SET_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
  454. }
  455. NdisReleaseSpinLock(&Adapter->Lock);
  456. // Indicate the media event
  457. NdisMIndicateStatus(Adapter->AdapterHandle, IndicateStatus, (PVOID)0, 0);
  458. NdisMIndicateStatusComplete(Adapter->AdapterHandle);
  459. }
  460. else
  461. {
  462. NdisReleaseSpinLock(&Adapter->Lock);
  463. }
  464. ulInfo = CurrMediaState;
  465. }
  466. }
  467. break;
  468. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  469. ulInfo = NIC_MAX_PACKET_SIZE * Adapter->NumTcb;
  470. break;
  471. case OID_GEN_RECEIVE_BUFFER_SPACE:
  472. ulInfo = NIC_MAX_PACKET_SIZE * Adapter->CurrNumRfd;
  473. break;
  474. case OID_GEN_VENDOR_ID:
  475. NdisMoveMemory(&ulInfo, Adapter->PermanentAddress, 3);
  476. break;
  477. case OID_GEN_VENDOR_DESCRIPTION:
  478. pInfo = VendorDesc;
  479. ulBytesAvailable = ulInfoLen = sizeof(VendorDesc);
  480. break;
  481. case OID_GEN_VENDOR_DRIVER_VERSION:
  482. ulInfo = VendorDriverVersion;
  483. break;
  484. case OID_GEN_DRIVER_VERSION:
  485. usInfo = (USHORT) NIC_DRIVER_VERSION;
  486. pInfo = (PVOID) &usInfo;
  487. ulBytesAvailable = ulInfoLen = sizeof(USHORT);
  488. break;
  489. // WMI support
  490. case OID_GEN_SUPPORTED_GUIDS:
  491. pInfo = (PUCHAR) &NICGuidList;
  492. ulBytesAvailable = ulInfoLen = sizeof(NICGuidList);
  493. break;
  494. #if OFFLOAD
  495. // Task Offload
  496. case OID_TCP_TASK_OFFLOAD:
  497. DBGPRINT(MP_WARN, ("Query Offloading.\n"));
  498. //
  499. // If the miniport supports LBFO, it can't support task offload
  500. //
  501. #if LBFO
  502. return NDIS_STATUS_NOT_SUPPORTED;
  503. #endif
  504. //
  505. // Because this miniport uses shared memory to do the offload tasks, if
  506. // allocation of memory is failed, then the miniport can't do the offloading
  507. //
  508. if (Adapter->OffloadEnable == FALSE)
  509. {
  510. Status = NDIS_STATUS_NOT_SUPPORTED;
  511. break;
  512. }
  513. //
  514. // Calculate the information buffer length we need to write the offload
  515. // capabilities
  516. //
  517. ulInfoLen = sizeof(NDIS_TASK_OFFLOAD_HEADER) +
  518. FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
  519. sizeof(NDIS_TASK_TCP_IP_CHECKSUM) +
  520. FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
  521. sizeof(NDIS_TASK_TCP_LARGE_SEND);
  522. if (ulInfoLen > InformationBufferLength)
  523. {
  524. *BytesNeeded = ulInfoLen;
  525. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  526. break;
  527. }
  528. //
  529. // check version and Encapsulation Type
  530. //
  531. pNdisTaskOffloadHdr = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
  532. //
  533. // Assume the miniport only supports IEEE_802_3_Encapsulation type
  534. //
  535. if (pNdisTaskOffloadHdr->EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation)
  536. {
  537. DBGPRINT(MP_WARN, ("Encapsulation type is not supported.\n"));
  538. pNdisTaskOffloadHdr->OffsetFirstTask = 0;
  539. Status = NDIS_STATUS_NOT_SUPPORTED;
  540. break;
  541. }
  542. //
  543. // Assume the miniport only supports task version of NDIS_TASK_OFFLOAD_VERSION
  544. //
  545. if (pNdisTaskOffloadHdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER)
  546. || pNdisTaskOffloadHdr->Version != NDIS_TASK_OFFLOAD_VERSION)
  547. {
  548. DBGPRINT(MP_WARN, ("Size or Version is not correct.\n"));
  549. pNdisTaskOffloadHdr->OffsetFirstTask = 0;
  550. Status = NDIS_STATUS_NOT_SUPPORTED;
  551. break;
  552. }
  553. //
  554. // If no capabilities supported, OffsetFirstTask should be set to 0
  555. // Currently we support TCP/IP checksum and TCP large send, so set
  556. // OffsetFirstTask to indicate the offset of the first offload task
  557. //
  558. pNdisTaskOffloadHdr->OffsetFirstTask = pNdisTaskOffloadHdr->Size;
  559. //
  560. // Fill TCP/IP checksum and TCP large send task offload structures
  561. //
  562. pTaskOffload = (PNDIS_TASK_OFFLOAD)((PUCHAR)(InformationBuffer) +
  563. pNdisTaskOffloadHdr->Size);
  564. //
  565. // Fill all the offload capabilities the miniport supports.
  566. //
  567. for (i = 0; i < OffloadTasksCount; i++)
  568. {
  569. pTaskOffload->Size = OffloadTasks[i].Size;
  570. pTaskOffload->Version = OffloadTasks[i].Version;
  571. pTaskOffload->Task = OffloadTasks[i].Task;
  572. pTaskOffload->TaskBufferLength = OffloadTasks[i].TaskBufferLength;
  573. //
  574. // Not the last task
  575. //
  576. if (i != OffloadTasksCount - 1)
  577. {
  578. pTaskOffload->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
  579. pTaskOffload->TaskBufferLength;
  580. }
  581. else
  582. {
  583. pTaskOffload->OffsetNextTask = 0;
  584. }
  585. switch (OffloadTasks[i].Task)
  586. {
  587. //
  588. // TCP/IP checksum task offload
  589. //
  590. case TcpIpChecksumNdisTask:
  591. pTcpIpChecksumTask = (PNDIS_TASK_TCP_IP_CHECKSUM) pTaskOffload->TaskBuffer;
  592. NdisMoveMemory(pTcpIpChecksumTask,
  593. &TcpIpChecksumTask,
  594. sizeof(TcpIpChecksumTask));
  595. break;
  596. //
  597. // TCP large send task offload
  598. //
  599. case TcpLargeSendNdisTask:
  600. pTcpLargeSendTask = (PNDIS_TASK_TCP_LARGE_SEND) pTaskOffload->TaskBuffer;
  601. NdisMoveMemory(pTcpLargeSendTask,
  602. &TcpLargeSendTask,
  603. sizeof(TcpLargeSendTask));
  604. ulHeadersLen = TCP_IP_MAX_HEADER_SIZE +
  605. pNdisTaskOffloadHdr->EncapsulationFormat.EncapsulationHeaderSize;
  606. ulMaxOffloadSize = (NIC_MAX_PACKET_SIZE - ulHeadersLen) * (ULONG)(Adapter->NumTcb);
  607. //
  608. // The maximum offload size depends on the size of allocated shared memory
  609. // and the number of TCB available, because this driver doesn't use a queue
  610. // to store the small packets splited from the large packet, so the number
  611. // of small packets must be less than or equal to the number of TCB the
  612. // miniport has, so all the small packets can be sent out at one time.
  613. //
  614. pTcpLargeSendTask->MaxOffLoadSize = (ulMaxOffloadSize > Adapter->OffloadSharedMemSize) ?
  615. Adapter->OffloadSharedMemSize: ulMaxOffloadSize;
  616. //
  617. // Store the maximum offload size
  618. //
  619. TcpLargeSendTask.MaxOffLoadSize = pTcpLargeSendTask->MaxOffLoadSize;
  620. break;
  621. }
  622. //
  623. // Points to the next task offload
  624. //
  625. if (i != OffloadTasksCount)
  626. {
  627. pTaskOffload = (PNDIS_TASK_OFFLOAD)
  628. ((PUCHAR)pTaskOffload + pTaskOffload->OffsetNextTask);
  629. }
  630. }
  631. //
  632. // So far, everything is setup, so return to the caller
  633. //
  634. *BytesWritten = ulInfoLen;
  635. *BytesNeeded = 0;
  636. DBGPRINT (MP_WARN, ("Offloading is set.\n"));
  637. return NDIS_STATUS_SUCCESS;
  638. #endif //OFFLOAD
  639. case OID_802_3_PERMANENT_ADDRESS:
  640. pInfo = Adapter->PermanentAddress;
  641. ulBytesAvailable = ulInfoLen = ETH_LENGTH_OF_ADDRESS;
  642. break;
  643. case OID_802_3_CURRENT_ADDRESS:
  644. pInfo = Adapter->CurrentAddress;
  645. ulBytesAvailable = ulInfoLen = ETH_LENGTH_OF_ADDRESS;
  646. break;
  647. case OID_802_3_MAXIMUM_LIST_SIZE:
  648. ulInfo = NIC_MAX_MCAST_LIST;
  649. break;
  650. case OID_GEN_MAXIMUM_SEND_PACKETS:
  651. ulInfo = NIC_MAX_SEND_PACKETS;
  652. break;
  653. case OID_PNP_CAPABILITIES:
  654. MPFillPoMgmtCaps (Adapter,
  655. &Power_Management_Capabilities,
  656. &Status,
  657. &ulInfoLen);
  658. if (Status == NDIS_STATUS_SUCCESS)
  659. {
  660. pInfo = (PVOID) &Power_Management_Capabilities;
  661. }
  662. else
  663. {
  664. pInfo = NULL;
  665. }
  666. break;
  667. case OID_PNP_QUERY_POWER:
  668. // Status is pre-set in this routine to Success
  669. Status = NDIS_STATUS_SUCCESS;
  670. break;
  671. // WMI support
  672. case OID_CUSTOM_DRIVER_QUERY:
  673. // this is the uint case
  674. DBGPRINT(MP_INFO,("CUSTOM_DRIVER_QUERY got a QUERY\n"));
  675. ulInfo = ++Adapter->CustomDriverSet;
  676. break;
  677. case OID_CUSTOM_DRIVER_SET:
  678. DBGPRINT(MP_INFO,("CUSTOM_DRIVER_SET got a QUERY\n"));
  679. ulInfo = Adapter->CustomDriverSet;
  680. break;
  681. // this is the array case
  682. case OID_CUSTOM_ARRAY:
  683. DBGPRINT(MP_INFO,("CUSTOM_ARRAY got a QUERY\n"));
  684. NdisMoveMemory(&ulInfo, Adapter->PermanentAddress, 4);
  685. break;
  686. // this is the string case
  687. case OID_CUSTOM_STRING:
  688. DBGPRINT(MP_INFO, ("CUSTOM_STRING got a QUERY\n"));
  689. pInfo = (PVOID) VendorDesc;
  690. ulBytesAvailable = ulInfoLen = sizeof(VendorDesc);
  691. break;
  692. case OID_GEN_XMIT_OK:
  693. case OID_GEN_RCV_OK:
  694. case OID_GEN_XMIT_ERROR:
  695. case OID_GEN_RCV_ERROR:
  696. case OID_GEN_RCV_NO_BUFFER:
  697. case OID_GEN_RCV_CRC_ERROR:
  698. case OID_GEN_TRANSMIT_QUEUE_LENGTH:
  699. case OID_802_3_RCV_ERROR_ALIGNMENT:
  700. case OID_802_3_XMIT_ONE_COLLISION:
  701. case OID_802_3_XMIT_MORE_COLLISIONS:
  702. case OID_802_3_XMIT_DEFERRED:
  703. case OID_802_3_XMIT_MAX_COLLISIONS:
  704. case OID_802_3_RCV_OVERRUN:
  705. case OID_802_3_XMIT_UNDERRUN:
  706. case OID_802_3_XMIT_HEARTBEAT_FAILURE:
  707. case OID_802_3_XMIT_TIMES_CRS_LOST:
  708. case OID_802_3_XMIT_LATE_COLLISIONS:
  709. Status = NICGetStatsCounters(Adapter, Oid, &ul64Info);
  710. ulBytesAvailable = ulInfoLen = sizeof(ul64Info);
  711. if (Status == NDIS_STATUS_SUCCESS)
  712. {
  713. if (InformationBufferLength < sizeof(ULONG))
  714. {
  715. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  716. *BytesNeeded = ulBytesAvailable;
  717. break;
  718. }
  719. ulInfoLen = MIN(InformationBufferLength, ulBytesAvailable);
  720. pInfo = &ul64Info;
  721. }
  722. break;
  723. default:
  724. Status = NDIS_STATUS_NOT_SUPPORTED;
  725. break;
  726. }
  727. if (Status == NDIS_STATUS_SUCCESS)
  728. {
  729. *BytesNeeded = ulBytesAvailable;
  730. if (ulInfoLen <= InformationBufferLength)
  731. {
  732. //
  733. // Copy result into InformationBuffer
  734. //
  735. *BytesWritten = ulInfoLen;
  736. if (ulInfoLen)
  737. {
  738. NdisMoveMemory(InformationBuffer, pInfo, ulInfoLen);
  739. }
  740. }
  741. else
  742. {
  743. //
  744. // too short
  745. //
  746. *BytesNeeded = ulInfoLen;
  747. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  748. }
  749. }
  750. DBGPRINT(MP_TRACE, ("<==== MPQueryInformation, OID=0x%08x, Status=%x\n", Oid, Status));
  751. return(Status);
  752. }
  753. NDIS_STATUS NICGetStatsCounters(
  754. IN PMP_ADAPTER Adapter,
  755. IN NDIS_OID Oid,
  756. OUT PULONG64 pCounter
  757. )
  758. /*++
  759. Routine Description:
  760. Get the value for a statistics OID
  761. Arguments:
  762. Adapter Pointer to our adapter
  763. Oid Self-explanatory
  764. pCounter Pointer to receive the value
  765. Return Value:
  766. NDIS_STATUS_SUCCESS
  767. NDIS_STATUS_NOT_SUPPORTED
  768. --*/
  769. {
  770. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  771. DBGPRINT(MP_TRACE, ("--> NICGetStatsCounters\n"));
  772. *pCounter = 0;
  773. DumpStatsCounters(Adapter);
  774. switch(Oid)
  775. {
  776. case OID_GEN_XMIT_OK:
  777. *pCounter = Adapter->GoodTransmits;
  778. break;
  779. case OID_GEN_RCV_OK:
  780. *pCounter = Adapter->GoodReceives;
  781. break;
  782. case OID_GEN_XMIT_ERROR:
  783. *pCounter = Adapter->TxAbortExcessCollisions +
  784. Adapter->TxDmaUnderrun +
  785. Adapter->TxLostCRS +
  786. Adapter->TxLateCollisions;
  787. break;
  788. case OID_GEN_RCV_ERROR:
  789. *pCounter = Adapter->RcvCrcErrors +
  790. Adapter->RcvAlignmentErrors +
  791. Adapter->RcvResourceErrors +
  792. Adapter->RcvDmaOverrunErrors +
  793. Adapter->RcvRuntErrors;
  794. break;
  795. case OID_GEN_RCV_NO_BUFFER:
  796. *pCounter = Adapter->RcvResourceErrors;
  797. break;
  798. case OID_GEN_RCV_CRC_ERROR:
  799. *pCounter = Adapter->RcvCrcErrors;
  800. break;
  801. case OID_GEN_TRANSMIT_QUEUE_LENGTH:
  802. *pCounter = Adapter->nWaitSend;
  803. break;
  804. case OID_802_3_RCV_ERROR_ALIGNMENT:
  805. *pCounter = Adapter->RcvAlignmentErrors;
  806. break;
  807. case OID_802_3_XMIT_ONE_COLLISION:
  808. *pCounter = Adapter->OneRetry;
  809. break;
  810. case OID_802_3_XMIT_MORE_COLLISIONS:
  811. *pCounter = Adapter->MoreThanOneRetry;
  812. break;
  813. case OID_802_3_XMIT_DEFERRED:
  814. *pCounter = Adapter->TxOKButDeferred;
  815. break;
  816. case OID_802_3_XMIT_MAX_COLLISIONS:
  817. *pCounter = Adapter->TxAbortExcessCollisions;
  818. break;
  819. case OID_802_3_RCV_OVERRUN:
  820. *pCounter = Adapter->RcvDmaOverrunErrors;
  821. break;
  822. case OID_802_3_XMIT_UNDERRUN:
  823. *pCounter = Adapter->TxDmaUnderrun;
  824. break;
  825. case OID_802_3_XMIT_HEARTBEAT_FAILURE:
  826. *pCounter = Adapter->TxLostCRS;
  827. break;
  828. case OID_802_3_XMIT_TIMES_CRS_LOST:
  829. *pCounter = Adapter->TxLostCRS;
  830. break;
  831. case OID_802_3_XMIT_LATE_COLLISIONS:
  832. *pCounter = Adapter->TxLateCollisions;
  833. break;
  834. default:
  835. Status = NDIS_STATUS_NOT_SUPPORTED;
  836. break;
  837. }
  838. DBGPRINT(MP_TRACE, ("<-- NICGetStatsCounters\n"));
  839. return(Status);
  840. }
  841. NDIS_STATUS NICSetPacketFilter(
  842. IN PMP_ADAPTER Adapter,
  843. IN ULONG PacketFilter
  844. )
  845. /*++
  846. Routine Description:
  847. This routine will set up the adapter so that it accepts packets
  848. that match the specified packet filter. The only filter bits
  849. that can truly be toggled are for broadcast and promiscuous
  850. Arguments:
  851. Adapter Pointer to our adapter
  852. PacketFilter The new packet filter
  853. Return Value:
  854. NDIS_STATUS_SUCCESS
  855. NDIS_STATUS_NOT_SUPPORTED
  856. --*/
  857. {
  858. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  859. UCHAR NewParameterField;
  860. UINT i;
  861. BOOLEAN bResult;
  862. DBGPRINT(MP_TRACE, ("--> NICSetPacketFilter, PacketFilter=%08x\n", PacketFilter));
  863. //
  864. // Need to enable or disable broadcast and promiscuous support depending
  865. // on the new filter
  866. //
  867. NewParameterField = CB_557_CFIG_DEFAULT_PARM15;
  868. if (PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
  869. {
  870. NewParameterField &= ~CB_CFIG_BROADCAST_DIS;
  871. }
  872. else
  873. {
  874. NewParameterField |= CB_CFIG_BROADCAST_DIS;
  875. }
  876. if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
  877. {
  878. NewParameterField |= CB_CFIG_PROMISCUOUS;
  879. }
  880. else
  881. {
  882. NewParameterField &= ~CB_CFIG_PROMISCUOUS;
  883. }
  884. do
  885. {
  886. if ((Adapter->OldParameterField == NewParameterField ) &&
  887. !(PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST))
  888. {
  889. break;
  890. }
  891. //
  892. // Only need to do something to the HW if the filter bits have changed.
  893. //
  894. Adapter->OldParameterField = NewParameterField;
  895. ((PCB_HEADER_STRUC)Adapter->NonTxCmdBlock)->CbCommand = CB_CONFIGURE;
  896. ((PCB_HEADER_STRUC)Adapter->NonTxCmdBlock)->CbStatus = 0;
  897. ((PCB_HEADER_STRUC)Adapter->NonTxCmdBlock)->CbLinkPointer = DRIVER_NULL;
  898. //
  899. // First fill in the static (end user can't change) config bytes
  900. //
  901. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[0] = CB_557_CFIG_DEFAULT_PARM0;
  902. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[2] = CB_557_CFIG_DEFAULT_PARM2;
  903. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] = CB_557_CFIG_DEFAULT_PARM3;
  904. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[6] = CB_557_CFIG_DEFAULT_PARM6;
  905. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[9] = CB_557_CFIG_DEFAULT_PARM9;
  906. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[10] = CB_557_CFIG_DEFAULT_PARM10;
  907. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[11] = CB_557_CFIG_DEFAULT_PARM11;
  908. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[12] = CB_557_CFIG_DEFAULT_PARM12;
  909. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[13] = CB_557_CFIG_DEFAULT_PARM13;
  910. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[14] = CB_557_CFIG_DEFAULT_PARM14;
  911. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[16] = CB_557_CFIG_DEFAULT_PARM16;
  912. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[17] = CB_557_CFIG_DEFAULT_PARM17;
  913. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[18] = CB_557_CFIG_DEFAULT_PARM18;
  914. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[20] = CB_557_CFIG_DEFAULT_PARM20;
  915. //
  916. // Set the Tx underrun retries
  917. //
  918. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[7] =
  919. (UCHAR) (CB_557_CFIG_DEFAULT_PARM7 | (Adapter->AiUnderrunRetry << 1));
  920. //
  921. // Set the Tx and Rx Fifo limits
  922. //
  923. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[1] =
  924. (UCHAR) ((Adapter->AiTxFifo << 4) | Adapter->AiRxFifo);
  925. //
  926. // set the MWI enable bit if needed
  927. //
  928. if (Adapter->MWIEnable)
  929. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] |= CB_CFIG_B3_MWI_ENABLE;
  930. //
  931. // Set the Tx and Rx DMA maximum byte count fields.
  932. //
  933. if ((Adapter->AiRxDmaCount) || (Adapter->AiTxDmaCount))
  934. {
  935. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] =
  936. Adapter->AiRxDmaCount;
  937. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] =
  938. (UCHAR) (Adapter->AiTxDmaCount | CB_CFIG_DMBC_EN);
  939. }
  940. else
  941. {
  942. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] =
  943. CB_557_CFIG_DEFAULT_PARM4;
  944. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] =
  945. CB_557_CFIG_DEFAULT_PARM5;
  946. }
  947. //
  948. // Setup for MII or 503 operation. The CRS+CDT bit should only be
  949. // set when operating in 503 mode.
  950. //
  951. if (Adapter->PhyAddress == 32)
  952. {
  953. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
  954. (CB_557_CFIG_DEFAULT_PARM8 & (~CB_CFIG_503_MII));
  955. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
  956. (UCHAR) (NewParameterField | CB_CFIG_CRS_OR_CDT);
  957. }
  958. else
  959. {
  960. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
  961. (CB_557_CFIG_DEFAULT_PARM8 | CB_CFIG_503_MII);
  962. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
  963. (UCHAR) (NewParameterField & (~CB_CFIG_CRS_OR_CDT));
  964. }
  965. //
  966. // Setup Full duplex stuff
  967. //
  968. //
  969. // If forced to half duplex
  970. //
  971. if (Adapter->AiForceDpx == 1)
  972. {
  973. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
  974. (CB_557_CFIG_DEFAULT_PARM19 &
  975. (~(CB_CFIG_FORCE_FDX| CB_CFIG_FDX_ENABLE)));
  976. }
  977. //
  978. // If forced to full duplex
  979. //
  980. else if (Adapter->AiForceDpx == 2)
  981. {
  982. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
  983. (CB_557_CFIG_DEFAULT_PARM19 | CB_CFIG_FORCE_FDX);
  984. }
  985. //
  986. // If auto-duplex
  987. //
  988. else
  989. {
  990. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
  991. CB_557_CFIG_DEFAULT_PARM19;
  992. }
  993. //
  994. // if multicast all is being turned on, set the bit
  995. //
  996. if (PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
  997. {
  998. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[21] =
  999. (CB_557_CFIG_DEFAULT_PARM21 | CB_CFIG_MULTICAST_ALL);
  1000. }
  1001. else
  1002. {
  1003. Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[21] =
  1004. CB_557_CFIG_DEFAULT_PARM21;
  1005. }
  1006. //
  1007. // Wait for the SCB to clear before we check the CU status.
  1008. //
  1009. if (!WaitScb(Adapter))
  1010. {
  1011. Status = NDIS_STATUS_HARD_ERRORS;
  1012. break;
  1013. }
  1014. //
  1015. // If we have issued any transmits, then the CU will either be active,
  1016. // or in the suspended state. If the CU is active, then we wait for
  1017. // it to be suspended.
  1018. //
  1019. if (Adapter->TransmitIdle == FALSE)
  1020. {
  1021. //
  1022. // Wait for suspended state
  1023. //
  1024. MP_STALL_AND_WAIT((Adapter->CSRAddress->ScbStatus & SCB_CUS_MASK) != SCB_CUS_ACTIVE, 5000, bResult);
  1025. if (!bResult)
  1026. {
  1027. MP_SET_HARDWARE_ERROR(Adapter);
  1028. Status = NDIS_STATUS_HARD_ERRORS;
  1029. break;
  1030. }
  1031. //
  1032. // Check the current status of the receive unit
  1033. //
  1034. if ((Adapter->CSRAddress->ScbStatus & SCB_RUS_MASK) != SCB_RUS_IDLE)
  1035. {
  1036. // Issue an RU abort. Since an interrupt will be issued, the
  1037. // RU will be started by the DPC.
  1038. Status = D100IssueScbCommand(Adapter, SCB_RUC_ABORT, TRUE);
  1039. if (Status != NDIS_STATUS_SUCCESS)
  1040. {
  1041. break;
  1042. }
  1043. }
  1044. if (!WaitScb(Adapter))
  1045. {
  1046. Status = NDIS_STATUS_HARD_ERRORS;
  1047. break;
  1048. }
  1049. //
  1050. // Restore the transmit software flags. After the multicast
  1051. // command is issued, the command unit will be idle, because the
  1052. // EL bit will be set in the multicast commmand block.
  1053. //
  1054. Adapter->TransmitIdle = TRUE;
  1055. Adapter->ResumeWait = TRUE;
  1056. }
  1057. //
  1058. // Display config info
  1059. //
  1060. DBGPRINT(MP_INFO, ("Re-Issuing Configure command for filter change\n"));
  1061. DBGPRINT(MP_INFO, ("Config Block at virt addr "PTR_FORMAT", phys address %x\n",
  1062. &((PCB_HEADER_STRUC)Adapter->NonTxCmdBlock)->CbStatus, Adapter->NonTxCmdBlockPhys));
  1063. for (i = 0; i < CB_CFIG_BYTE_COUNT; i++)
  1064. DBGPRINT(MP_INFO, (" Config byte %x = %.2x\n", i, Adapter->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[i]));
  1065. //
  1066. // Submit the configure command to the chip, and wait for it to complete.
  1067. //
  1068. Adapter->CSRAddress->ScbGeneralPointer = Adapter->NonTxCmdBlockPhys;
  1069. Status = D100SubmitCommandBlockAndWait(Adapter);
  1070. if (Status != NDIS_STATUS_SUCCESS)
  1071. {
  1072. Status = NDIS_STATUS_NOT_ACCEPTED;
  1073. }
  1074. } while (FALSE);
  1075. DBGPRINT_S(Status, ("<-- NICSetPacketFilter, Status=%x\n", Status));
  1076. return(Status);
  1077. }
  1078. NDIS_STATUS NICSetMulticastList(
  1079. IN PMP_ADAPTER Adapter
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. This routine will set up the adapter for a specified multicast address list
  1084. Arguments:
  1085. Adapter Pointer to our adapter
  1086. Return Value:
  1087. NDIS_STATUS_SUCCESS
  1088. NDIS_STATUS_NOT_ACCEPTED
  1089. --*/
  1090. {
  1091. NDIS_STATUS Status;
  1092. PUCHAR McAddress;
  1093. UINT i, j;
  1094. BOOLEAN bResult;
  1095. DBGPRINT(MP_TRACE, ("--> NICSetMulticastList\n"));
  1096. //
  1097. // Setup the command block for the multicast command.
  1098. //
  1099. for (i = 0; i < Adapter->MCAddressCount; i++)
  1100. {
  1101. DBGPRINT(MP_INFO, ("MC(%d) = %02x-%02x-%02x-%02x-%02x-%02x\n",
  1102. i,
  1103. Adapter->MCList[i][0],
  1104. Adapter->MCList[i][1],
  1105. Adapter->MCList[i][2],
  1106. Adapter->MCList[i][3],
  1107. Adapter->MCList[i][4],
  1108. Adapter->MCList[i][5]));
  1109. McAddress = &Adapter->NonTxCmdBlock->NonTxCb.Multicast.McAddress[i*ETHERNET_ADDRESS_LENGTH];
  1110. for (j = 0; j < ETH_LENGTH_OF_ADDRESS; j++)
  1111. *(McAddress++) = Adapter->MCList[i][j];
  1112. }
  1113. Adapter->NonTxCmdBlock->NonTxCb.Multicast.McCount =
  1114. (USHORT)(Adapter->MCAddressCount * ETH_LENGTH_OF_ADDRESS);
  1115. ((PCB_HEADER_STRUC)Adapter->NonTxCmdBlock)->CbStatus = 0;
  1116. ((PCB_HEADER_STRUC)Adapter->NonTxCmdBlock)->CbCommand = CB_MULTICAST;
  1117. //
  1118. // Wait for the SCB to clear before we check the CU status.
  1119. //
  1120. if (!WaitScb(Adapter))
  1121. {
  1122. Status = NDIS_STATUS_HARD_ERRORS;
  1123. MP_EXIT;
  1124. }
  1125. //
  1126. // If we have issued any transmits, then the CU will either be active, or
  1127. // in the suspended state. If the CU is active, then we wait for it to be
  1128. // suspended.
  1129. //
  1130. if (Adapter->TransmitIdle == FALSE)
  1131. {
  1132. //
  1133. // Wait for suspended state
  1134. //
  1135. MP_STALL_AND_WAIT((Adapter->CSRAddress->ScbStatus & SCB_CUS_MASK) != SCB_CUS_ACTIVE, 5000, bResult);
  1136. if (!bResult)
  1137. {
  1138. MP_SET_HARDWARE_ERROR(Adapter);
  1139. Status = NDIS_STATUS_HARD_ERRORS;
  1140. }
  1141. //
  1142. // Restore the transmit software flags. After the multicast command is
  1143. // issued, the command unit will be idle, because the EL bit will be
  1144. // set in the multicast commmand block.
  1145. //
  1146. Adapter->TransmitIdle = TRUE;
  1147. Adapter->ResumeWait = TRUE;
  1148. }
  1149. //
  1150. // Update the command list pointer.
  1151. //
  1152. Adapter->CSRAddress->ScbGeneralPointer = Adapter->NonTxCmdBlockPhys;
  1153. //
  1154. // Submit the multicast command to the adapter and wait for it to complete.
  1155. //
  1156. Status = D100SubmitCommandBlockAndWait(Adapter);
  1157. if (Status != NDIS_STATUS_SUCCESS)
  1158. {
  1159. Status = NDIS_STATUS_NOT_ACCEPTED;
  1160. }
  1161. exit:
  1162. DBGPRINT_S(Status, ("<-- NICSetMulticastList, Status=%x\n", Status));
  1163. return(Status);
  1164. }
  1165. NDIS_STATUS MPSetInformation(
  1166. IN NDIS_HANDLE MiniportAdapterContext,
  1167. IN NDIS_OID Oid,
  1168. IN PVOID InformationBuffer,
  1169. IN ULONG InformationBufferLength,
  1170. OUT PULONG BytesRead,
  1171. OUT PULONG BytesNeeded
  1172. )
  1173. /*++
  1174. Routine Description:
  1175. This is the handler for an OID set operation.
  1176. The only operations that really change the configuration of the adapter are
  1177. set PACKET_FILTER, and SET_MULTICAST.
  1178. Arguments:
  1179. MiniportAdapterContext Pointer to the adapter structure
  1180. Oid Oid for this query
  1181. InformationBuffer Buffer for information
  1182. InformationBufferLength Size of this buffer
  1183. BytesRead Specifies how much info is read
  1184. BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
  1185. Return Value:
  1186. NDIS_STATUS_SUCCESS
  1187. NDIS_STATUS_INVALID_LENGTH
  1188. NDIS_STATUS_INVALID_OID
  1189. NDIS_STATUS_NOT_SUPPORTED
  1190. NDIS_STATUS_NOT_ACCEPTED
  1191. --*/
  1192. {
  1193. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1194. PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
  1195. ULONG PacketFilter;
  1196. NDIS_DEVICE_POWER_STATE NewPowerState;
  1197. ULONG CustomDriverSet;
  1198. #if OFFLOAD
  1199. PNDIS_TASK_OFFLOAD_HEADER pNdisTaskOffloadHdr;
  1200. PNDIS_TASK_OFFLOAD TaskOffload;
  1201. PNDIS_TASK_OFFLOAD TmpOffload;
  1202. PNDIS_TASK_TCP_IP_CHECKSUM pTcpIpChecksumTask;
  1203. PNDIS_TASK_TCP_LARGE_SEND pNdisTaskTcpLargeSend;
  1204. UINT i;
  1205. #endif
  1206. DBGPRINT(MP_TRACE, ("====> MPSetInformation\n"));
  1207. *BytesRead = 0;
  1208. *BytesNeeded = 0;
  1209. switch(Oid)
  1210. {
  1211. case OID_802_3_MULTICAST_LIST:
  1212. //
  1213. // Verify the length
  1214. //
  1215. if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS != 0)
  1216. {
  1217. return(NDIS_STATUS_INVALID_LENGTH);
  1218. }
  1219. //
  1220. // Save the number of MC list size
  1221. //
  1222. Adapter->MCAddressCount = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
  1223. ASSERT(Adapter->MCAddressCount <= NIC_MAX_MCAST_LIST);
  1224. //
  1225. // Save the MC list
  1226. //
  1227. NdisMoveMemory(
  1228. Adapter->MCList,
  1229. InformationBuffer,
  1230. InformationBufferLength);
  1231. *BytesRead = InformationBufferLength;
  1232. NdisDprAcquireSpinLock(&Adapter->Lock);
  1233. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  1234. Status = NICSetMulticastList(Adapter);
  1235. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1236. NdisDprReleaseSpinLock(&Adapter->Lock);
  1237. break;
  1238. case OID_GEN_CURRENT_PACKET_FILTER:
  1239. //
  1240. // Verify the Length
  1241. //
  1242. if (InformationBufferLength != sizeof(ULONG))
  1243. {
  1244. return(NDIS_STATUS_INVALID_LENGTH);
  1245. }
  1246. *BytesRead = InformationBufferLength;
  1247. NdisMoveMemory(&PacketFilter, InformationBuffer, sizeof(ULONG));
  1248. //
  1249. // any bits not supported?
  1250. //
  1251. if (PacketFilter & ~NIC_SUPPORTED_FILTERS)
  1252. {
  1253. return(NDIS_STATUS_NOT_SUPPORTED);
  1254. }
  1255. //
  1256. // any filtering changes?
  1257. //
  1258. if (PacketFilter == Adapter->PacketFilter)
  1259. {
  1260. return(NDIS_STATUS_SUCCESS);
  1261. }
  1262. NdisDprAcquireSpinLock(&Adapter->Lock);
  1263. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  1264. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
  1265. {
  1266. ASSERT(!Adapter->bSetPending);
  1267. Adapter->bSetPending = TRUE;
  1268. Adapter->SetRequest.Oid = Oid;
  1269. Adapter->SetRequest.InformationBuffer = InformationBuffer;
  1270. Adapter->SetRequest.InformationBufferLength = InformationBufferLength;
  1271. Adapter->SetRequest.BytesRead = BytesRead;
  1272. Adapter->SetRequest.BytesNeeded = BytesNeeded;
  1273. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1274. NdisDprReleaseSpinLock(&Adapter->Lock);
  1275. Status = NDIS_STATUS_PENDING;
  1276. break;
  1277. }
  1278. Status = NICSetPacketFilter(
  1279. Adapter,
  1280. PacketFilter);
  1281. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1282. NdisDprReleaseSpinLock(&Adapter->Lock);
  1283. if (Status == NDIS_STATUS_SUCCESS)
  1284. {
  1285. Adapter->PacketFilter = PacketFilter;
  1286. }
  1287. break;
  1288. case OID_GEN_CURRENT_LOOKAHEAD:
  1289. //
  1290. // Verify the Length
  1291. //
  1292. if (InformationBufferLength < sizeof(ULONG))
  1293. {
  1294. *BytesNeeded = sizeof(ULONG);
  1295. return(NDIS_STATUS_INVALID_LENGTH);
  1296. }
  1297. NdisMoveMemory(&Adapter->ulLookAhead, InformationBuffer, sizeof(ULONG));
  1298. *BytesRead = sizeof(ULONG);
  1299. Status = NDIS_STATUS_SUCCESS;
  1300. break;
  1301. case OID_PNP_SET_POWER:
  1302. DBGPRINT(MP_LOUD, ("SET: Power State change, "PTR_FORMAT"!!!\n", InformationBuffer));
  1303. if (InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE ))
  1304. {
  1305. return(NDIS_STATUS_INVALID_LENGTH);
  1306. }
  1307. NewPowerState = *(PNDIS_DEVICE_POWER_STATE UNALIGNED)InformationBuffer;
  1308. //
  1309. // Set the power state - Cannot fail this request
  1310. //
  1311. Status = MPSetPower(Adapter ,NewPowerState );
  1312. if (Status == NDIS_STATUS_PENDING)
  1313. {
  1314. Adapter->bSetPending = TRUE;
  1315. Adapter->SetRequest.Oid = OID_PNP_SET_POWER;
  1316. Adapter->SetRequest.BytesRead = BytesRead;
  1317. break;
  1318. }
  1319. if (Status != NDIS_STATUS_SUCCESS)
  1320. {
  1321. DBGPRINT(MP_ERROR, ("SET Power: Hardware error !!!\n"));
  1322. break;
  1323. }
  1324. *BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
  1325. Status = NDIS_STATUS_SUCCESS;
  1326. break;
  1327. case OID_PNP_ADD_WAKE_UP_PATTERN:
  1328. //
  1329. // call a function that would program the adapter's wake
  1330. // up pattern, return success
  1331. //
  1332. DBGPRINT(MP_LOUD, ("SET: Add Wake Up Pattern, !!!\n"));
  1333. if (MPIsPoMgmtSupported(Adapter) )
  1334. {
  1335. Status = MPAddWakeUpPattern(Adapter,
  1336. InformationBuffer,
  1337. InformationBufferLength,
  1338. BytesRead,
  1339. BytesNeeded);
  1340. }
  1341. else
  1342. {
  1343. Status = NDIS_STATUS_NOT_SUPPORTED;
  1344. }
  1345. break;
  1346. case OID_PNP_REMOVE_WAKE_UP_PATTERN:
  1347. DBGPRINT(MP_LOUD, ("SET: Got a WakeUpPattern REMOVE Call\n"));
  1348. //
  1349. // call a function that would remove the adapter's wake
  1350. // up pattern, return success
  1351. //
  1352. if (MPIsPoMgmtSupported(Adapter) )
  1353. {
  1354. Status = MPRemoveWakeUpPattern(Adapter,
  1355. InformationBuffer,
  1356. InformationBufferLength,
  1357. BytesRead,
  1358. BytesNeeded);
  1359. }
  1360. else
  1361. {
  1362. Status = NDIS_STATUS_NOT_SUPPORTED;
  1363. }
  1364. break;
  1365. case OID_PNP_ENABLE_WAKE_UP:
  1366. DBGPRINT(MP_LOUD, ("SET: Got a EnableWakeUp Call, "PTR_FORMAT"\n",InformationBuffer));
  1367. //
  1368. // call a function that would enable wake up on the adapter
  1369. // return success
  1370. //
  1371. if (MPIsPoMgmtSupported(Adapter) )
  1372. {
  1373. ULONG WakeUpEnable;
  1374. NdisMoveMemory(&WakeUpEnable, InformationBuffer,sizeof(ULONG));
  1375. //
  1376. // The WakeUpEable can only be 0, or NDIS_PNP_WAKE_UP_PATTERN_MATCH since the driver only
  1377. // supports wake up pattern match
  1378. //
  1379. if ((WakeUpEnable != 0)
  1380. && ((WakeUpEnable & NDIS_PNP_WAKE_UP_PATTERN_MATCH) != NDIS_PNP_WAKE_UP_PATTERN_MATCH ))
  1381. {
  1382. Status = NDIS_STATUS_NOT_SUPPORTED;
  1383. Adapter->WakeUpEnable = 0;
  1384. break;
  1385. }
  1386. //
  1387. // When the driver goes to low power state, it would check WakeUpEnable to decide
  1388. // which wake up methed it should use to wake up the machine. If WakeUpEnable is 0,
  1389. // no wake up method is enabled.
  1390. //
  1391. Adapter->WakeUpEnable = WakeUpEnable;
  1392. *BytesRead = sizeof(ULONG);
  1393. Status = NDIS_STATUS_SUCCESS;
  1394. }
  1395. else
  1396. {
  1397. Status = NDIS_STATUS_NOT_SUPPORTED;
  1398. }
  1399. break;
  1400. //
  1401. // this OID is for showing how to work with driver specific (custom)
  1402. // OIDs and the NDIS 5 WMI interface using GUIDs
  1403. //
  1404. case OID_CUSTOM_DRIVER_SET:
  1405. DBGPRINT(MP_INFO, ("OID_CUSTOM_DRIVER_SET got a set\n"));
  1406. if (InformationBufferLength < sizeof(ULONG))
  1407. {
  1408. *BytesNeeded = sizeof(ULONG);
  1409. Status = NDIS_STATUS_INVALID_LENGTH;
  1410. break;
  1411. }
  1412. //
  1413. // The driver need to validate the set data in the buffer
  1414. //
  1415. NdisMoveMemory(&CustomDriverSet, InformationBuffer, sizeof(ULONG));
  1416. if ((CustomDriverSet < CUSTOM_DRIVER_SET_MIN)
  1417. || (CustomDriverSet > CUSTOM_DRIVER_SET_MAX))
  1418. {
  1419. Status = NDIS_STATUS_INVALID_DATA;
  1420. break;
  1421. }
  1422. *BytesRead = sizeof(ULONG);
  1423. Adapter->CustomDriverSet = CustomDriverSet;
  1424. //
  1425. // Validate the content of the data
  1426. //
  1427. // Adapter->CustomDriverSet = (ULONG) *(PULONG)(InformationBuffer);
  1428. break;
  1429. #if OFFLOAD
  1430. case OID_TCP_TASK_OFFLOAD:
  1431. //
  1432. // Disable all the existing capabilities whenever task offload is updated
  1433. //
  1434. DisableOffload(Adapter);
  1435. if (InformationBufferLength < sizeof(NDIS_TASK_OFFLOAD_HEADER))
  1436. {
  1437. return NDIS_STATUS_INVALID_LENGTH;
  1438. }
  1439. *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  1440. //
  1441. // Assume miniport only supports IEEE_802_3_Encapsulation
  1442. // Check to make sure that TCP/IP passed down the correct encapsulation type
  1443. //
  1444. pNdisTaskOffloadHdr = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
  1445. if (pNdisTaskOffloadHdr->EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation)
  1446. {
  1447. pNdisTaskOffloadHdr->OffsetFirstTask = 0;
  1448. return NDIS_STATUS_INVALID_DATA;
  1449. }
  1450. //
  1451. // No offload task to be set
  1452. //
  1453. if (pNdisTaskOffloadHdr->OffsetFirstTask == 0)
  1454. {
  1455. DBGPRINT(MP_WARN, ("No offload task is set!!\n"));
  1456. return NDIS_STATUS_SUCCESS;
  1457. }
  1458. //
  1459. // OffsetFirstTask is not valid
  1460. //
  1461. if (pNdisTaskOffloadHdr->OffsetFirstTask < pNdisTaskOffloadHdr->Size)
  1462. {
  1463. pNdisTaskOffloadHdr->OffsetFirstTask = 0;
  1464. return NDIS_STATUS_FAILURE;
  1465. }
  1466. //
  1467. // The length can't hold one task
  1468. //
  1469. if (InformationBufferLength <
  1470. (pNdisTaskOffloadHdr->OffsetFirstTask + sizeof(NDIS_TASK_OFFLOAD)))
  1471. {
  1472. DBGPRINT(MP_WARN, ("response of task offload does not have sufficient space even for 1 offload task!!\n"));
  1473. Status = NDIS_STATUS_INVALID_LENGTH;
  1474. break;
  1475. }
  1476. //
  1477. // Copy Encapsulation format into adapter, later the miniport may use it
  1478. // to get Encapsulation header size
  1479. //
  1480. NdisMoveMemory(&(Adapter->EncapsulationFormat),
  1481. &(pNdisTaskOffloadHdr->EncapsulationFormat),
  1482. sizeof(NDIS_ENCAPSULATION_FORMAT));
  1483. ASSERT(pNdisTaskOffloadHdr->EncapsulationFormat.Flags.FixedHeaderSize == 1);
  1484. //
  1485. // Check to make sure we support the task offload requested
  1486. //
  1487. TaskOffload = (NDIS_TASK_OFFLOAD *)
  1488. ( (PUCHAR)pNdisTaskOffloadHdr + pNdisTaskOffloadHdr->OffsetFirstTask);
  1489. TmpOffload = TaskOffload;
  1490. //
  1491. // Check the task in the buffer and enable the offload capabilities
  1492. //
  1493. while (TmpOffload)
  1494. {
  1495. *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
  1496. switch (TmpOffload->Task)
  1497. {
  1498. case TcpIpChecksumNdisTask:
  1499. //
  1500. // Invalid information buffer length
  1501. //
  1502. if (InformationBufferLength < *BytesRead + sizeof(NDIS_TASK_TCP_IP_CHECKSUM))
  1503. {
  1504. *BytesNeeded = *BytesRead + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  1505. return NDIS_STATUS_INVALID_LENGTH;
  1506. }
  1507. //
  1508. //Check version
  1509. //
  1510. for (i = 0; i < OffloadTasksCount; i++)
  1511. {
  1512. if (OffloadTasks[i].Task == TmpOffload->Task &&
  1513. OffloadTasks[i].Version == TmpOffload->Version )
  1514. {
  1515. break;
  1516. }
  1517. }
  1518. //
  1519. // Version is mismatched
  1520. //
  1521. if (i == OffloadTasksCount)
  1522. {
  1523. return NDIS_STATUS_NOT_SUPPORTED;
  1524. }
  1525. //
  1526. // This miniport support TCP/IP checksum offload only with sending TCP
  1527. // and IP checksum with TCP/IP options.
  1528. // check if the fields in NDIS_TASK_TCP_IP_CHECKSUM is set correctly
  1529. //
  1530. Adapter->NicTaskOffload.ChecksumOffload = 1;
  1531. pTcpIpChecksumTask = (PNDIS_TASK_TCP_IP_CHECKSUM) TmpOffload->TaskBuffer;
  1532. if (pTcpIpChecksumTask->V4Transmit.TcpChecksum)
  1533. {
  1534. //
  1535. // If miniport doesn't support sending TCP checksum, we can't enable
  1536. // this capability
  1537. //
  1538. if (TcpIpChecksumTask.V4Transmit.TcpChecksum == 0 )
  1539. {
  1540. return NDIS_STATUS_NOT_SUPPORTED;
  1541. }
  1542. DBGPRINT (MP_WARN, ("Set Sending TCP offloading.\n"));
  1543. //
  1544. // Enable sending TCP checksum
  1545. //
  1546. Adapter->NicChecksumOffload.DoXmitTcpChecksum = 1;
  1547. }
  1548. //
  1549. // left for recieve and other IP and UDP checksum offload
  1550. //
  1551. if (pTcpIpChecksumTask->V4Transmit.IpChecksum)
  1552. {
  1553. //
  1554. // If the miniport doesn't support sending IP checksum, we can't enable
  1555. // this capabilities
  1556. //
  1557. if (TcpIpChecksumTask.V4Transmit.IpChecksum == 0)
  1558. {
  1559. return NDIS_STATUS_NOT_SUPPORTED;
  1560. }
  1561. DBGPRINT (MP_WARN, ("Set Sending IP offloading.\n"));
  1562. //
  1563. // Enable sending IP checksum
  1564. //
  1565. Adapter->NicChecksumOffload.DoXmitIpChecksum = 1;
  1566. }
  1567. if (pTcpIpChecksumTask->V4Receive.TcpChecksum)
  1568. {
  1569. //
  1570. // If the miniport doesn't support receiving TCP checksum, we can't
  1571. // enable this capability
  1572. //
  1573. if (TcpIpChecksumTask.V4Receive.TcpChecksum == 0)
  1574. {
  1575. return NDIS_STATUS_NOT_SUPPORTED;
  1576. }
  1577. DBGPRINT (MP_WARN, ("Set recieve TCP offloading.\n"));
  1578. //
  1579. // Enable recieving TCP checksum
  1580. //
  1581. Adapter->NicChecksumOffload.DoRcvTcpChecksum = 1;
  1582. }
  1583. if (pTcpIpChecksumTask->V4Receive.IpChecksum)
  1584. {
  1585. //
  1586. // If the miniport doesn't support receiving IP checksum, we can't
  1587. // enable this capability
  1588. //
  1589. if (TcpIpChecksumTask.V4Receive.IpChecksum == 0)
  1590. {
  1591. return NDIS_STATUS_NOT_SUPPORTED;
  1592. }
  1593. DBGPRINT (MP_WARN, ("Set Recieve IP offloading.\n"));
  1594. //
  1595. // Enable recieving IP checksum
  1596. //
  1597. Adapter->NicChecksumOffload.DoRcvIpChecksum = 1;
  1598. }
  1599. if (pTcpIpChecksumTask->V4Transmit.UdpChecksum)
  1600. {
  1601. //
  1602. // If the miniport doesn't support sending UDP checksum, we can't
  1603. // enable this capability
  1604. //
  1605. if (TcpIpChecksumTask.V4Transmit.UdpChecksum == 0)
  1606. {
  1607. return NDIS_STATUS_NOT_SUPPORTED;
  1608. }
  1609. DBGPRINT (MP_WARN, ("Set Sending UDP offloading.\n"));
  1610. //
  1611. // Enable sending UDP checksum
  1612. //
  1613. Adapter->NicChecksumOffload.DoXmitUdpChecksum = 1;
  1614. }
  1615. if (pTcpIpChecksumTask->V4Receive.UdpChecksum)
  1616. {
  1617. //
  1618. // IF the miniport doesn't support receiving UDP checksum, we can't
  1619. // enable this capability
  1620. //
  1621. if (TcpIpChecksumTask.V4Receive.UdpChecksum == 0)
  1622. {
  1623. return NDIS_STATUS_NOT_SUPPORTED;
  1624. }
  1625. DBGPRINT (MP_WARN, ("Set recieve UDP offloading.\n"));
  1626. //
  1627. // Enable receiving UDP checksum
  1628. //
  1629. Adapter->NicChecksumOffload.DoRcvUdpChecksum = 1;
  1630. }
  1631. //
  1632. // check for V6 setting, because this miniport doesn't support any of
  1633. // checksum offload for V6, so we just return NDIS_STATUS_NOT_SUPPORTED
  1634. // if the protocol tries to set these capabilities
  1635. //
  1636. if (pTcpIpChecksumTask->V6Transmit.TcpChecksum
  1637. || pTcpIpChecksumTask->V6Transmit.UdpChecksum
  1638. || pTcpIpChecksumTask->V6Receive.TcpChecksum
  1639. || pTcpIpChecksumTask->V6Receive.UdpChecksum)
  1640. {
  1641. return NDIS_STATUS_NOT_SUPPORTED;
  1642. }
  1643. *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  1644. break;
  1645. case TcpLargeSendNdisTask:
  1646. //
  1647. // Invalid information buffer length
  1648. //
  1649. if (InformationBufferLength < *BytesRead + sizeof(NDIS_TASK_TCP_LARGE_SEND))
  1650. {
  1651. *BytesNeeded = *BytesRead + sizeof(NDIS_TASK_TCP_LARGE_SEND);
  1652. return NDIS_STATUS_INVALID_LENGTH;
  1653. }
  1654. //
  1655. // Check version
  1656. //
  1657. for (i = 0; i < OffloadTasksCount; i++)
  1658. {
  1659. if (OffloadTasks[i].Task == TmpOffload->Task &&
  1660. OffloadTasks[i].Version == TmpOffload->Version )
  1661. {
  1662. break;
  1663. }
  1664. }
  1665. if (i == OffloadTasksCount)
  1666. {
  1667. return NDIS_STATUS_NOT_SUPPORTED;
  1668. }
  1669. pNdisTaskTcpLargeSend = (PNDIS_TASK_TCP_LARGE_SEND) TmpOffload->TaskBuffer;
  1670. //
  1671. // Check maximum offload size, if the size is greater than the maximum
  1672. // size of the miniport can handle, return NDIS_STATUS_NOT_SUPPORTED.
  1673. //
  1674. if (pNdisTaskTcpLargeSend->MaxOffLoadSize > TcpLargeSendTask.MaxOffLoadSize
  1675. || pNdisTaskTcpLargeSend->MinSegmentCount < TcpLargeSendTask.MinSegmentCount)
  1676. {
  1677. return NDIS_STATUS_NOT_SUPPORTED;
  1678. }
  1679. //
  1680. // If the miniport doesn't support TCP or IP options, but the protocol
  1681. // is setting such information, return NDIS_STATUS_NOT_SUPPORTED.
  1682. //
  1683. if ((pNdisTaskTcpLargeSend->TcpOptions && !TcpLargeSendTask.TcpOptions)
  1684. || (pNdisTaskTcpLargeSend->IpOptions && !TcpLargeSendTask.IpOptions))
  1685. {
  1686. return NDIS_STATUS_NOT_SUPPORTED;
  1687. }
  1688. //
  1689. // Store the valid setting information into adapter
  1690. //
  1691. Adapter->LargeSendInfo.MaxOffLoadSize = pNdisTaskTcpLargeSend->MaxOffLoadSize;
  1692. Adapter->LargeSendInfo.MinSegmentCount = pNdisTaskTcpLargeSend->MinSegmentCount;
  1693. Adapter->LargeSendInfo.TcpOptions = pNdisTaskTcpLargeSend->TcpOptions;
  1694. Adapter->LargeSendInfo.IpOptions = pNdisTaskTcpLargeSend->IpOptions;
  1695. //
  1696. // Everythins is OK, enable large send offload capabilities
  1697. //
  1698. Adapter->NicTaskOffload.LargeSendOffload = 1;
  1699. *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND);
  1700. break;
  1701. default:
  1702. //
  1703. // Because this miniport doesn't implement IPSec offload, so it doesn't
  1704. // support IPSec offload. Tasks other then these 3 task are not supported
  1705. //
  1706. return NDIS_STATUS_NOT_SUPPORTED;
  1707. }
  1708. //
  1709. // Go on to the next offload structure
  1710. //
  1711. if (TmpOffload->OffsetNextTask)
  1712. {
  1713. TmpOffload = (PNDIS_TASK_OFFLOAD)
  1714. ((PUCHAR) TmpOffload + TmpOffload->OffsetNextTask);
  1715. }
  1716. else
  1717. {
  1718. TmpOffload = NULL;
  1719. }
  1720. } // while
  1721. break;
  1722. #endif
  1723. default:
  1724. Status = NDIS_STATUS_NOT_SUPPORTED;
  1725. break;
  1726. }
  1727. DBGPRINT(MP_TRACE, ("<==== MPSetInformationSet, OID=0x%08x, Status=%x\n", Oid, Status));
  1728. return(Status);
  1729. }
  1730. VOID
  1731. MPSetPowerD0(
  1732. PMP_ADAPTER Adapter
  1733. )
  1734. /*++
  1735. Routine Description:
  1736. This routine is called when the adapter receives a SetPower
  1737. to D0.
  1738. Arguments:
  1739. Adapter Pointer to the adapter structure
  1740. PowerState NewPowerState
  1741. Return Value:
  1742. --*/
  1743. {
  1744. NDIS_STATUS Status;
  1745. //
  1746. // MPSetPowerD0Private Initializes the adapte, issues a selective reset.
  1747. //
  1748. MPSetPowerD0Private (Adapter);
  1749. Adapter->CurrentPowerState = NdisDeviceStateD0;
  1750. //
  1751. // Set up the packet filter
  1752. //
  1753. NdisDprAcquireSpinLock(&Adapter->Lock);
  1754. Status = NICSetPacketFilter(
  1755. Adapter,
  1756. Adapter->OldPacketFilter);
  1757. //
  1758. // If Set Packet Filter succeeds, restore the old packet filter
  1759. //
  1760. if (Status == NDIS_STATUS_SUCCESS)
  1761. {
  1762. Adapter->PacketFilter = Adapter->OldPacketFilter;
  1763. }
  1764. //
  1765. // Set up the multicast list address
  1766. //
  1767. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  1768. Status = NICSetMulticastList(Adapter);
  1769. NICStartRecv(Adapter);
  1770. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1771. NdisDprReleaseSpinLock(&Adapter->Lock);
  1772. //
  1773. // Enable the interrup, so the driver can send/receive packets
  1774. //
  1775. NICEnableInterrupt(Adapter);
  1776. }
  1777. NDIS_STATUS
  1778. MPSetPowerLow(
  1779. PMP_ADAPTER Adapter ,
  1780. NDIS_DEVICE_POWER_STATE PowerState
  1781. )
  1782. /*++
  1783. Routine Description:
  1784. This routine is called when the adapter receives a SetPower
  1785. to a PowerState > D0
  1786. Arguments:
  1787. Adapter Pointer to the adapter structure
  1788. PowerState NewPowerState
  1789. Return Value:
  1790. NDIS_STATUS_SUCCESS
  1791. NDIS_STATUS_PENDING
  1792. NDIS_STATUS_HARD_ERRORS
  1793. --*/
  1794. {
  1795. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1796. do
  1797. {
  1798. Adapter->NextPowerState = PowerState;
  1799. //
  1800. // Stop sending packets. Create a new flag and make it part
  1801. // of the Send Fail Mask
  1802. //
  1803. //
  1804. // Stop hardware from receiving packets - Set the RU to idle
  1805. //
  1806. //
  1807. // Check the current status of the receive unit
  1808. //
  1809. if ((Adapter->CSRAddress->ScbStatus & SCB_RUS_MASK) != SCB_RUS_IDLE)
  1810. {
  1811. //
  1812. // Issue an RU abort. Since an interrupt will be issued, the
  1813. // RU will be started by the DPC.
  1814. //
  1815. Status = D100IssueScbCommand(Adapter, SCB_RUC_ABORT, TRUE);
  1816. }
  1817. if (Status != NDIS_STATUS_SUCCESS)
  1818. {
  1819. break;
  1820. }
  1821. //
  1822. // If there are any outstanding Receive packets, return NDIS_STATUS_PENDING,
  1823. // When all the packets are returned later, the driver will complete the request
  1824. //
  1825. if (Adapter->PoMgmt.OutstandingRecv != 0)
  1826. {
  1827. Status = NDIS_STATUS_PENDING;
  1828. break;
  1829. }
  1830. //
  1831. // Wait for all incoming sends to complete
  1832. //
  1833. //
  1834. // MPSetPowerLowPrivate first disables the interrupt, acknowledges all the pending
  1835. // interrupts and sets pAdapter->CurrentPowerState to the given low power state
  1836. // then starts Hardware specific part of the transition to low power state
  1837. // Setting up wake-up patterns, filters, wake-up events etc
  1838. //
  1839. NdisMSynchronizeWithInterrupt(
  1840. &Adapter->Interrupt,
  1841. (PVOID)MPSetPowerLowPrivate,
  1842. Adapter);
  1843. Status = NDIS_STATUS_SUCCESS;
  1844. } while (FALSE);
  1845. return Status;
  1846. }
  1847. VOID
  1848. MpSetPowerLowComplete(
  1849. IN PMP_ADAPTER Adapter
  1850. )
  1851. /*++
  1852. Routine Description:
  1853. This routine when all the packets are returned to the driver and the driver has a pending OID to
  1854. set it to lower power state
  1855. Arguments:
  1856. Adapter Pointer to the adapter structure
  1857. Return Value:
  1858. NOTE: this function is called with RcvLock held
  1859. --*/
  1860. {
  1861. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1862. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1863. //
  1864. // MPSetPowerLowPrivate first disables the interrupt, acknowledges all the pending
  1865. // interrupts and sets pAdapter->CurrentPowerState to the given low power state
  1866. // then starts Hardware specific part of the transition to low power state
  1867. // Setting up wake-up patterns, filters, wake-up events etc
  1868. //
  1869. NdisMSynchronizeWithInterrupt(
  1870. &Adapter->Interrupt,
  1871. (PVOID)MPSetPowerLowPrivate,
  1872. Adapter);
  1873. Adapter->bSetPending = FALSE;
  1874. *Adapter->SetRequest.BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
  1875. NdisMSetInformationComplete(Adapter->AdapterHandle, Status);
  1876. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  1877. }
  1878. NDIS_STATUS
  1879. MPSetPower(
  1880. PMP_ADAPTER Adapter ,
  1881. NDIS_DEVICE_POWER_STATE PowerState
  1882. )
  1883. /*++
  1884. Routine Description:
  1885. This routine is called when the adapter receives a SetPower
  1886. request. It redirects the call to an appropriate routine to
  1887. Set the New PowerState
  1888. Arguments:
  1889. Adapter Pointer to the adapter structure
  1890. PowerState NewPowerState
  1891. Return Value:
  1892. NDIS_STATUS_SUCCESS
  1893. NDIS_STATUS_PENDING
  1894. NDIS_STATUS_HARDWARE_ERROR
  1895. --*/
  1896. {
  1897. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1898. if (PowerState == NdisDeviceStateD0)
  1899. {
  1900. MPSetPowerD0 (Adapter);
  1901. }
  1902. else
  1903. {
  1904. Status = MPSetPowerLow (Adapter, PowerState);
  1905. }
  1906. return Status;
  1907. }
  1908. VOID
  1909. MPFillPoMgmtCaps (
  1910. IN PMP_ADAPTER pAdapter,
  1911. IN OUT PNDIS_PNP_CAPABILITIES pPower_Management_Capabilities,
  1912. IN OUT PNDIS_STATUS pStatus,
  1913. IN OUT PULONG pulInfoLen
  1914. )
  1915. /*++
  1916. Routine Description:
  1917. Fills in the Power Managment structure depending the capabilities of
  1918. the software driver and the card.
  1919. Currently this is only supported on 82559 Version of the driver
  1920. Arguments:
  1921. Adapter Pointer to the adapter structure
  1922. pPower_Management_Capabilities - Power management struct as defined in the DDK,
  1923. pStatus Status to be returned by the request,
  1924. pulInfoLen Length of the pPowerManagmentCapabilites
  1925. Return Value:
  1926. Success or failure depending on the type of card
  1927. --*/
  1928. {
  1929. BOOLEAN bIsPoMgmtSupported;
  1930. bIsPoMgmtSupported = MPIsPoMgmtSupported(pAdapter);
  1931. if (bIsPoMgmtSupported == TRUE)
  1932. {
  1933. pPower_Management_Capabilities->Flags = NDIS_DEVICE_WAKE_UP_ENABLE ;
  1934. pPower_Management_Capabilities->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
  1935. pPower_Management_Capabilities->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateD3;
  1936. pPower_Management_Capabilities->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
  1937. *pulInfoLen = sizeof (*pPower_Management_Capabilities);
  1938. *pStatus = NDIS_STATUS_SUCCESS;
  1939. }
  1940. else
  1941. {
  1942. NdisZeroMemory (pPower_Management_Capabilities, sizeof(*pPower_Management_Capabilities));
  1943. *pStatus = NDIS_STATUS_NOT_SUPPORTED;
  1944. *pulInfoLen = 0;
  1945. }
  1946. }
  1947. NDIS_STATUS
  1948. MPAddWakeUpPattern(
  1949. IN PMP_ADAPTER pAdapter,
  1950. IN PVOID InformationBuffer,
  1951. IN UINT InformationBufferLength,
  1952. OUT PULONG BytesRead,
  1953. OUT PULONG BytesNeeded
  1954. )
  1955. /*++
  1956. Routine Description:
  1957. This routine will allocate a local memory structure, copy the pattern,
  1958. insert the pattern into a linked list and return success
  1959. We are gauranteed that we wll get only one request at a time, so this is implemented
  1960. without locks.
  1961. Arguments:
  1962. Adapter Adapter structure
  1963. InformationBuffer Wake up Pattern
  1964. InformationBufferLength Wake Up Pattern Length
  1965. Return Value:
  1966. Success - if successful.
  1967. NDIS_STATUS_FAILURE - if memory allocation fails.
  1968. --*/
  1969. {
  1970. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1971. PMP_WAKE_PATTERN pWakeUpPattern = NULL;
  1972. UINT AllocationLength = 0;
  1973. PNDIS_PM_PACKET_PATTERN pPmPattern = NULL;
  1974. ULONG Signature = 0;
  1975. ULONG CopyLength = 0;
  1976. do
  1977. {
  1978. pPmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer;
  1979. if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
  1980. {
  1981. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  1982. *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
  1983. break;
  1984. }
  1985. if (InformationBufferLength < pPmPattern->PatternOffset + pPmPattern->PatternSize)
  1986. {
  1987. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  1988. *BytesNeeded = pPmPattern->PatternOffset + pPmPattern->PatternSize;
  1989. break;
  1990. }
  1991. *BytesRead = pPmPattern->PatternOffset + pPmPattern->PatternSize;
  1992. //
  1993. // Calculate the e100 signature
  1994. //
  1995. Status = MPCalculateE100PatternForFilter (
  1996. (PUCHAR)pPmPattern+ pPmPattern->PatternOffset,
  1997. pPmPattern->PatternSize,
  1998. (PUCHAR)pPmPattern +sizeof(NDIS_PM_PACKET_PATTERN),
  1999. pPmPattern->MaskSize,
  2000. &Signature );
  2001. if ( Status != NDIS_STATUS_SUCCESS)
  2002. {
  2003. break;
  2004. }
  2005. CopyLength = pPmPattern->PatternOffset + pPmPattern->PatternSize;
  2006. //
  2007. // Allocate the memory to hold the WakeUp Pattern
  2008. //
  2009. AllocationLength = sizeof (MP_WAKE_PATTERN) + CopyLength;
  2010. Status = MP_ALLOCMEMTAG (&pWakeUpPattern, AllocationLength);
  2011. if (Status != NDIS_STATUS_SUCCESS)
  2012. {
  2013. pWakeUpPattern = NULL;
  2014. break;
  2015. }
  2016. //
  2017. // Initialize pWakeUpPattern
  2018. //
  2019. NdisZeroMemory (pWakeUpPattern, AllocationLength);
  2020. pWakeUpPattern->AllocationSize = AllocationLength;
  2021. pWakeUpPattern->Signature = Signature;
  2022. //
  2023. // Copy the pattern into local memory
  2024. //
  2025. NdisMoveMemory (&pWakeUpPattern->Pattern[0], InformationBuffer, CopyLength);
  2026. //
  2027. // Insert the pattern into the list
  2028. //
  2029. NdisInterlockedInsertHeadList (&pAdapter->PoMgmt.PatternList,
  2030. &pWakeUpPattern->linkListEntry,
  2031. &pAdapter->Lock);
  2032. Status = NDIS_STATUS_SUCCESS;
  2033. } while (FALSE);
  2034. return Status;
  2035. }
  2036. NDIS_STATUS
  2037. MPRemoveWakeUpPattern(
  2038. IN PMP_ADAPTER pAdapter,
  2039. IN PVOID InformationBuffer,
  2040. IN UINT InformationBufferLength,
  2041. OUT PULONG BytesRead,
  2042. OUT PULONG BytesNeeded
  2043. )
  2044. /*++
  2045. Routine Description:
  2046. This routine will walk the list of wake up pattern and attempt to match the wake up pattern.
  2047. If it finds a copy , it will remove that WakeUpPattern
  2048. Arguments:
  2049. Adapter Adapter structure
  2050. InformationBuffer Wake up Pattern
  2051. InformationBufferLength Wake Up Pattern Length
  2052. Return Value:
  2053. Success - if successful.
  2054. NDIS_STATUS_FAILURE - if memory allocation fails.
  2055. --*/
  2056. {
  2057. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2058. PNDIS_PM_PACKET_PATTERN pReqPattern = (PNDIS_PM_PACKET_PATTERN)InformationBuffer;
  2059. PLIST_ENTRY pPatternEntry = ListNext(&pAdapter->PoMgmt.PatternList) ;
  2060. do
  2061. {
  2062. if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
  2063. {
  2064. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  2065. *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
  2066. break;
  2067. }
  2068. if (InformationBufferLength < pReqPattern->PatternOffset + pReqPattern->PatternSize)
  2069. {
  2070. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  2071. *BytesNeeded = pReqPattern->PatternOffset + pReqPattern->PatternSize;
  2072. break;
  2073. }
  2074. *BytesRead = pReqPattern->PatternOffset + pReqPattern->PatternSize;
  2075. while (pPatternEntry != (&pAdapter->PoMgmt.PatternList))
  2076. {
  2077. BOOLEAN bIsThisThePattern = FALSE;
  2078. PMP_WAKE_PATTERN pWakeUpPattern = NULL;
  2079. PNDIS_PM_PACKET_PATTERN pCurrPattern = NULL;;
  2080. //
  2081. // initialize local variables
  2082. //
  2083. pWakeUpPattern = CONTAINING_RECORD(pPatternEntry, MP_WAKE_PATTERN, linkListEntry);
  2084. pCurrPattern = (PNDIS_PM_PACKET_PATTERN)&pWakeUpPattern->Pattern[0];
  2085. //
  2086. // increment the iterator
  2087. //
  2088. pPatternEntry = ListNext (pPatternEntry);
  2089. //
  2090. // Begin Check : Is (pCurrPattern == pReqPattern)
  2091. //
  2092. bIsThisThePattern = MPAreTwoPatternsEqual(pReqPattern, pCurrPattern);
  2093. if (bIsThisThePattern == TRUE)
  2094. {
  2095. //
  2096. // we have a match - remove the entry
  2097. //
  2098. RemoveEntryList (&pWakeUpPattern->linkListEntry);
  2099. //
  2100. // Free the entry
  2101. //
  2102. MP_FREEMEM (pWakeUpPattern, pWakeUpPattern->AllocationSize, 0);
  2103. Status = NDIS_STATUS_SUCCESS;
  2104. break;
  2105. }
  2106. }
  2107. }
  2108. while (FALSE);
  2109. return Status;
  2110. }
  2111. VOID
  2112. MPRemoveAllWakeUpPatterns(
  2113. PMP_ADAPTER pAdapter
  2114. )
  2115. /*++
  2116. Routine Description:
  2117. This routine will walk the list of wake up pattern and free it
  2118. Arguments:
  2119. Adapter Adapter structure
  2120. Return Value:
  2121. Success - if successful.
  2122. --*/
  2123. {
  2124. PLIST_ENTRY pPatternEntry = ListNext(&pAdapter->PoMgmt.PatternList) ;
  2125. while (pPatternEntry != (&pAdapter->PoMgmt.PatternList))
  2126. {
  2127. PMP_WAKE_PATTERN pWakeUpPattern = NULL;
  2128. //
  2129. // initialize local variables
  2130. //
  2131. pWakeUpPattern = CONTAINING_RECORD(pPatternEntry, MP_WAKE_PATTERN,linkListEntry);
  2132. //
  2133. // increment the iterator
  2134. //
  2135. pPatternEntry = ListNext (pPatternEntry);
  2136. //
  2137. // Remove the entry from the list
  2138. //
  2139. RemoveEntryList (&pWakeUpPattern->linkListEntry);
  2140. //
  2141. // Free the memory
  2142. //
  2143. MP_FREEMEM(pWakeUpPattern, pWakeUpPattern->AllocationSize, 0);
  2144. }
  2145. }
  2146. BOOLEAN
  2147. MPAreTwoPatternsEqual(
  2148. IN PNDIS_PM_PACKET_PATTERN pNdisPattern1,
  2149. IN PNDIS_PM_PACKET_PATTERN pNdisPattern2
  2150. )
  2151. /*++
  2152. Routine Description:
  2153. This routine will compare two wake up patterns to see if they are equal
  2154. Arguments:
  2155. pNdisPattern1 - Pattern1
  2156. pNdisPattern2 - Pattern 2
  2157. Return Value:
  2158. True - if patterns are equal
  2159. False - Otherwise
  2160. --*/
  2161. {
  2162. BOOLEAN bEqual = FALSE;
  2163. // Local variables used later in the compare section of this function
  2164. PUCHAR pMask1, pMask2;
  2165. PUCHAR pPattern1, pPattern2;
  2166. UINT MaskSize, PatternSize;
  2167. do
  2168. {
  2169. bEqual = (BOOLEAN)(pNdisPattern1->Priority == pNdisPattern2->Priority);
  2170. if (bEqual == FALSE)
  2171. {
  2172. break;
  2173. }
  2174. bEqual = (BOOLEAN)(pNdisPattern1->MaskSize == pNdisPattern2->MaskSize);
  2175. if (bEqual == FALSE)
  2176. {
  2177. break;
  2178. }
  2179. //
  2180. // Verify the Mask
  2181. //
  2182. MaskSize = pNdisPattern1->MaskSize ;
  2183. pMask1 = (PUCHAR) pNdisPattern1 + sizeof (NDIS_PM_PACKET_PATTERN);
  2184. pMask2 = (PUCHAR) pNdisPattern2 + sizeof (NDIS_PM_PACKET_PATTERN);
  2185. bEqual = (BOOLEAN)NdisEqualMemory (pMask1, pMask2, MaskSize);
  2186. if (bEqual == FALSE)
  2187. {
  2188. break;
  2189. }
  2190. //
  2191. // Verify the Pattern
  2192. //
  2193. bEqual = (BOOLEAN)(pNdisPattern1->PatternSize == pNdisPattern2->PatternSize);
  2194. if (bEqual == FALSE)
  2195. {
  2196. break;
  2197. }
  2198. PatternSize = pNdisPattern2->PatternSize;
  2199. pPattern1 = (PUCHAR) pNdisPattern1 + pNdisPattern1->PatternOffset;
  2200. pPattern2 = (PUCHAR) pNdisPattern2 + pNdisPattern2->PatternOffset;
  2201. bEqual = (BOOLEAN)NdisEqualMemory (pPattern1, pPattern2, PatternSize );
  2202. if (bEqual == FALSE)
  2203. {
  2204. break;
  2205. }
  2206. } while (FALSE);
  2207. return bEqual;
  2208. }