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

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