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.

873 lines
32 KiB

  1. /*
  2. (C) Copyright 1998
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995, 1999 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the terms outlined in
  7. the TriplePoint Software Services Agreement.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL Request Request_c
  12. @module Request.c |
  13. This module implements the NDIS request routines for the Miniport.
  14. @head3 Contents |
  15. @index class,mfunc,func,msg,mdata,struct,enum | Request_c
  16. @end
  17. */
  18. /* @doc EXTERNAL INTERNAL
  19. @topic 3.2 Query/Set Request Processing |
  20. For querying and setting network interface card binding information, the
  21. NDIS library calls <f MiniportQueryInformation> or <f MiniportSetInformation>.
  22. The upper layers place an object identifier (OID) in the structure for
  23. an object in the miniport NIC driver MIB that it wants to query or set.
  24. The <f MiniportQueryInformation> function fills in results and returns an
  25. appropriate status code to the NDIS library. See Part I of the Network
  26. Driver Reference for more information on OIDs.
  27. These two functions are potentially asynchronous. If they behave
  28. synchronously, they return immediately with a status code other than
  29. NDIS_STATUS_PENDING. If asynchronous, the function returns
  30. NDIS_STATUS_PENDING; and the miniport NIC driver later completes the
  31. request operation by a call to NdisMQueryInformationComplete for the
  32. query function or NdisMSetInformationComplete for the set function.
  33. The NDIS library guarantees that the miniport NIC driver will have only
  34. one outstanding request at a time so there is no need for the miniport
  35. NIC driver to queue requests.
  36. @end
  37. */
  38. #define __FILEID__ REQUEST_OBJECT_TYPE
  39. // Unique file ID for error logging
  40. #include "Miniport.h" // Defines all the miniport objects
  41. #if defined(NDIS_LCODE)
  42. # pragma NDIS_LCODE // Windows 95 wants this code locked down!
  43. # pragma NDIS_LDATA
  44. #endif
  45. /*
  46. // The following is a list of all the possible NDIS QuereyInformation requests
  47. // that might be directed to the miniport.
  48. // Comment out any that are not supported by this driver.
  49. */
  50. static const NDIS_OID g_SupportedOidArray[] =
  51. {
  52. OID_GEN_SUPPORTED_LIST,
  53. OID_GEN_HARDWARE_STATUS,
  54. OID_GEN_MEDIA_SUPPORTED,
  55. OID_GEN_MEDIA_IN_USE,
  56. OID_GEN_MAXIMUM_LOOKAHEAD,
  57. OID_GEN_MAC_OPTIONS,
  58. OID_GEN_VENDOR_ID,
  59. OID_GEN_VENDOR_DESCRIPTION,
  60. OID_GEN_DRIVER_VERSION,
  61. OID_GEN_CURRENT_LOOKAHEAD,
  62. OID_WAN_PERMANENT_ADDRESS,
  63. OID_WAN_CURRENT_ADDRESS,
  64. OID_WAN_MEDIUM_SUBTYPE,
  65. OID_WAN_GET_INFO,
  66. OID_WAN_SET_LINK_INFO,
  67. OID_WAN_GET_LINK_INFO,
  68. #if defined(NDIS50_MINIPORT)
  69. OID_WAN_LINE_COUNT,
  70. OID_PNP_CAPABILITIES,
  71. OID_PNP_SET_POWER,
  72. OID_PNP_QUERY_POWER,
  73. #endif // NDIS50_MINIPORT
  74. 0
  75. };
  76. #if DBG
  77. /*
  78. // Make sure the following list is in the same order as the list above!
  79. */
  80. static char *g_SupportedOidNames[] =
  81. {
  82. "OID_GEN_SUPPORTED_LIST",
  83. "OID_GEN_HARDWARE_STATUS",
  84. "OID_GEN_MEDIA_SUPPORTED",
  85. "OID_GEN_MEDIA_IN_USE",
  86. "OID_GEN_MAXIMUM_LOOKAHEAD",
  87. "OID_GEN_MAC_OPTIONS",
  88. "OID_GEN_VENDOR_ID",
  89. "OID_GEN_VENDOR_DESCRIPTION",
  90. "OID_GEN_DRIVER_VERSION",
  91. "OID_GEN_CURRENT_LOOKAHEAD",
  92. "OID_WAN_PERMANENT_ADDRESS",
  93. "OID_WAN_CURRENT_ADDRESS",
  94. "OID_WAN_MEDIUM_SUBTYPE",
  95. "OID_WAN_GET_INFO",
  96. "OID_WAN_SET_LINK_INFO",
  97. "OID_WAN_GET_LINK_INFO",
  98. #if defined(NDIS50_MINIPORT)
  99. "OID_WAN_LINE_COUNT",
  100. "OID_PNP_CAPABILITIES",
  101. "OID_PNP_SET_POWER",
  102. "OID_PNP_QUERY_POWER",
  103. #endif // NDIS50_MINIPORT
  104. "OID_UNKNOWN"
  105. };
  106. #define NUM_OID_ENTRIES (sizeof(g_SupportedOidArray) / sizeof(g_SupportedOidArray[0]))
  107. /*
  108. // This debug routine will lookup the printable name for the selected OID.
  109. */
  110. static char * DbgGetOidString(NDIS_OID Oid)
  111. {
  112. UINT i;
  113. for (i = 0; i < NUM_OID_ENTRIES-1; i++)
  114. {
  115. if (g_SupportedOidArray[i] == Oid)
  116. {
  117. break;
  118. }
  119. }
  120. return(g_SupportedOidNames[i]);
  121. }
  122. #endif // DBG
  123. /*
  124. // Returned from an OID_WAN_PERMANENT_ADDRESS MiniportQueryInformation request.
  125. // The WAN wrapper wants the miniport to return a unique address for this
  126. // adapter. This is used as an ethernet address presented to the protocols.
  127. // The least significant bit of the first byte must not be a 1, or it could
  128. // be interpreted as an ethernet multicast address. If the vendor has an
  129. // assigned ethernet vendor code (the first 3 bytes), they should be used
  130. // to assure that the address does not conflict with another vendor's address.
  131. // The last digit is replaced during the call with the adapter instance number.
  132. */
  133. static UCHAR g_PermanentWanAddress[6] = VER_VENDOR_ID;
  134. /*
  135. // Returned from an OID_GEN_VENDOR_ID MiniportQueryInformation request.
  136. // Again, the vendor's assigned ethernet vendor code should be used if possible.
  137. */
  138. static UCHAR g_Vendor3ByteID[4] = VER_VENDOR_ID;
  139. /*
  140. // Returned from an OID_GEN_VENDOR_DESCRIPTION MiniportQueryInformation request.
  141. // This is an arbitrary string which may be used by upper layers to present
  142. // a user friendly description of the adapter.
  143. */
  144. static NDIS_STRING g_VendorDescriptionString = INIT_STRING_CONST(VER_PRODUCT_NAME_STR);
  145. /* @doc INTERNAL Request Request_c MiniportQueryInformation
  146. @func
  147. <f MiniportQueryInformation> is a required function that
  148. returns information about the capabilities and status of
  149. the driver and/or its NIC.
  150. @comm
  151. NDIS calls the <f MiniportQueryInformation> function either
  152. on its own behalf, such as to determine which options the
  153. driver supports or to manage binding-specific information
  154. for the miniport, or when a bound protocol driver calls
  155. <f NdisRequest>.
  156. NDIS makes one or more calls to <f MiniportQueryInformation>
  157. just after a driver's <f MiniportInitialize> function returns
  158. NDIS_STATUS_SUCCESS. NDIS supplies the following OIDs in
  159. its initialization-time calls to the driver's
  160. <f MiniportQueryInformation> function:
  161. <f OID_GEN_MAXIMUM_LOOKAHEAD><nl>
  162. <f MiniportQueryInformation> must return how many bytes of lookahead
  163. data the NIC can provide, that is, the initial transfer capacity
  164. of the NIC.<nl>
  165. Even if a driver supports multipacket receives and, therefore,
  166. will indicate an array of pointers to fully set up packets,
  167. MiniportQueryInformation must supply this information. Such a
  168. driver should return the maximum packet size it can indicate.
  169. <f OID_GEN_MAC_OPTIONS><nl>
  170. <f MiniportQueryInformation> must return a bitmask set with the
  171. appropriate NDIS_MAC_OPTION_XXX flags indicating which options
  172. it (or its NIC) supports, or it can return zero at InformationBuffer
  173. if the driver supports none of the options designated by these flags.
  174. For example, a NIC driver always sets the
  175. NDIS_MAC_OPTION_NO_LOOPBACK flag if its NIC has no
  176. internal hardware support for loopback. This tells
  177. NDIS to manage loopback for the driver, which cannot
  178. provide software loopback code as efficient as the NDIS
  179. library's because NDIS manages all binding-specific
  180. information for miniports. Any miniport that tries to provide
  181. software loopback must check the destination address of every
  182. send packet against the currently set filter addresses to
  183. determine whether to loop back each packet. WAN NIC drivers
  184. must set this flag.
  185. If the NIC driver sets the NDIS_MAC_OPTION_FULL_DUPLEX flag,
  186. the NDIS library serializes calls to the MiniportSendPackets
  187. or <f MiniportWanSend> function separately from its serialized
  188. calls to other MiniportXxx functions in SMP machines. However,
  189. NDIS returns incoming send packets to protocols while such a
  190. driver's <f MiniportReset> function is executing: that is, NDIS
  191. never calls a full-duplex miniport to transmit a packet until
  192. its reset operation is completed. The designer of any full-duplex
  193. driver can expect that driver to achieve significantly higher
  194. performance in SMP machines, but the driver must synchronize
  195. its accesses to shared resources carefully to prevent race
  196. conditions or deadlocks from occurring. NDIS assumes that
  197. all intermediate drivers are full-duplex drivers.
  198. Depending on the NdisMediumXxx that <f MiniportInitialize> selected,
  199. NDIS submits additional intialization-time requests to
  200. <f MiniportQueryInformation>, such as the following:
  201. <f OID_XXX_CURRENT_ADDRESS><nl>
  202. If the driver's <f MiniportInitialize> function selected an NdisMediumXxx
  203. for which the system supplies a filter, NDIS calls
  204. <f MiniportQueryInformation> to return the NIC's current
  205. address in medium-specific format. For FDDI drivers, NDIS
  206. requests both long and short current addresses.
  207. <f OID_802_3_MAXIMUM_LIST_SIZE><nl>
  208. For Ethernet drivers, NDIS requests the multicast list size.
  209. <f OID_FDDI_LONG>/<f SHORT_MAX_LIST_SIZE><nl>
  210. For FDDI drivers, NDIS requests the multicast list sizes.
  211. If possible, <f MiniportQueryInformation> should not return
  212. <f NDIS_STATUS_PENDING> for initialization-time requests.
  213. Until NDIS has sufficient information to set up bindings
  214. to the miniport, such requests should be handled synchronously.
  215. If the Miniport does not complete the call immediately (by returning
  216. <f NDIS_STATUS_PENDING>), it must call NdisMQueryInformationComplete to
  217. complete the call. The Miniport controls the buffers pointed to by
  218. InformationBuffer, BytesWritten, and BytesNeeded until the request
  219. completes.
  220. No other requests will be submitted to the Miniport until
  221. this request has been completed.
  222. <f Note>: that the wrapper will intercept all queries of the following OIDs:
  223. OID_GEN_CURRENT_PACKET_FILTER,
  224. OID_GEN_PROTOCOL_OPTIONS,
  225. OID_802_5_CURRENT_FUNCTIONAL,
  226. OID_802_3_MULTICAST_LIST,
  227. OID_FDDI_LONG_MULTICAST_LIST,
  228. OID_FDDI_SHORT_MULTICAST_LIST.
  229. <f Note>: Interrupts will be in any state when called.
  230. @rdesc
  231. <f MiniportQueryInformation> can return one of the following:
  232. @flag NDIS_STATUS_SUCCESS |
  233. <f MiniportQueryInformation> returned the requested information at
  234. InformationBuffer and set the variable at BytesWritten to the amount
  235. of information it returned.
  236. @flag NDIS_STATUS_PENDING |
  237. The driver will complete the request asynchronously with a call to
  238. NdisMQueryInformationComplete when it has gathered the requested
  239. information.
  240. @flag NDIS_STATUS_INVALID_OID |
  241. <f MiniportQueryInformation> does not recognize the Oid.
  242. @flag NDIS_STATUS_INVALID_LENGTH |
  243. The InformationBufferLength does not match the length required
  244. by the given Oid. <f MiniportQueryInformation> returned how many
  245. bytes the buffer should be at BytesNeeded.
  246. @flag NDIS_STATUS_NOT_ACCEPTED |
  247. <f MiniportQueryInformation> attempted to gather the requested
  248. information from the NIC but was unsuccessful.
  249. @flag NDIS_STATUS_NOT_SUPPORTED |
  250. <f MiniportQueryInformation> does not support the Oid, which
  251. is optional.
  252. @flag NDIS_STATUS_RESOURCES |
  253. <f MiniportQueryInformation> could not allocate sufficient
  254. resources to return the requested information. This return
  255. value does not necessarily mean that the same request,
  256. submitted at a later time, will be failed for the same
  257. reason.
  258. @xref
  259. <f MiniportInitialize>
  260. <f MiniportSetInformation>
  261. */
  262. NDIS_STATUS MiniportQueryInformation(
  263. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  264. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  265. IN NDIS_OID Oid, // @parm
  266. // The OID. (See section 7.4 of the NDIS 3.0 specification for a complete
  267. // description of OIDs.)
  268. IN PVOID InformationBuffer, // @parm
  269. // The buffer that will receive the information. (See section 7.4 of the
  270. // NDIS 3.0 specification for a description of the length required for
  271. // each OID.)
  272. IN ULONG InformationBufferLength, // @parm
  273. // The length in bytes of InformationBuffer.
  274. OUT PULONG BytesWritten, // @parm
  275. // Returns the number of bytes written into InformationBuffer.
  276. OUT PULONG BytesNeeded // @parm
  277. // Returns the number of additional bytes needed to satisfy the OID.
  278. )
  279. {
  280. DBG_FUNC("MiniportQueryInformation")
  281. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  282. // Holds the status result returned by this function.
  283. PVOID SourceBuffer;
  284. // Pointer to driver data to be copied back to caller's InformationBuffer
  285. ULONG SourceBufferLength;
  286. // Number of bytes to be copied from driver.
  287. ULONG GenericULong = 0;
  288. // Most return values are long integers, so this is used to hold the
  289. // return value of a constant or computed result.
  290. UCHAR VendorId[4];
  291. // Used to store vendor ID string.
  292. #if defined(NDIS50_MINIPORT)
  293. NDIS_PNP_CAPABILITIES PnpCapabilities;
  294. // Used to return our PNP capabilities.
  295. #endif // NDIS50_MINIPORT
  296. /*
  297. // If this is a TAPI OID, pass it on over.
  298. */
  299. if ((Oid & 0xFFFFFF00L) == (OID_TAPI_ACCEPT & 0xFFFFFF00L))
  300. {
  301. Status = TspiRequestHandler(pAdapter,
  302. Oid,
  303. InformationBuffer,
  304. InformationBufferLength,
  305. BytesWritten,
  306. BytesNeeded
  307. );
  308. return (Status);
  309. }
  310. DBG_ENTER(pAdapter);
  311. DBG_REQUEST(pAdapter,
  312. ("(OID=0x%08X %s)\n\t\tInfoLength=%d InfoBuffer=0x%X\n",
  313. Oid, DbgGetOidString(Oid),
  314. InformationBufferLength,
  315. InformationBuffer
  316. ));
  317. /*
  318. // Initialize these once, since this is the majority of cases.
  319. */
  320. SourceBuffer = &GenericULong;
  321. SourceBufferLength = sizeof(ULONG);
  322. /*
  323. // Determine which OID is being requested and do the right thing.
  324. // Refer to section 7.4 of the NDIS 3.0 specification for a complete
  325. // description of OIDs and their return values.
  326. */
  327. switch (Oid)
  328. {
  329. case OID_GEN_SUPPORTED_LIST:
  330. /*
  331. // NDIS wants to know which OID's to pass down to us.
  332. // So we report back these new IOCTL's in addition to any NDIS OID's.
  333. */
  334. SourceBuffer = (PVOID)g_SupportedOidArray;
  335. SourceBufferLength = sizeof(g_SupportedOidArray);
  336. break;
  337. case OID_GEN_HARDWARE_STATUS:
  338. GenericULong = NdisHardwareStatusReady;
  339. break;
  340. case OID_GEN_MEDIA_SUPPORTED:
  341. GenericULong = NdisMediumWan;
  342. break;
  343. case OID_GEN_MEDIA_IN_USE:
  344. GenericULong = NdisMediumWan;
  345. break;
  346. case OID_GEN_VENDOR_ID:
  347. NdisMoveMemory((PVOID)VendorId, (PVOID)g_PermanentWanAddress, 3);
  348. VendorId[3] = 0x0;
  349. SourceBuffer = &g_PermanentWanAddress[0];
  350. SourceBufferLength = sizeof(VendorId);
  351. break;
  352. case OID_GEN_VENDOR_DESCRIPTION:
  353. SourceBuffer = (PUCHAR) g_VendorDescriptionString.Buffer;
  354. SourceBufferLength = g_VendorDescriptionString.MaximumLength;
  355. break;
  356. case OID_GEN_MAXIMUM_LOOKAHEAD:
  357. GenericULong = CARD_MAX_LOOKAHEAD;
  358. break;
  359. case OID_GEN_CURRENT_LOOKAHEAD:
  360. GenericULong = CARD_MAX_LOOKAHEAD;
  361. break;
  362. case OID_GEN_MAC_OPTIONS:
  363. GenericULong = NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
  364. NDIS_MAC_OPTION_NO_LOOPBACK |
  365. NDIS_MAC_OPTION_TRANSFERS_NOT_PEND;
  366. break;
  367. case OID_WAN_PERMANENT_ADDRESS:
  368. case OID_WAN_CURRENT_ADDRESS:
  369. g_PermanentWanAddress[5] = (UCHAR) ((pAdapter->ObjectID & 0xFF) + '0');
  370. SourceBuffer = g_PermanentWanAddress;
  371. SourceBufferLength = sizeof(g_PermanentWanAddress);
  372. break;
  373. case OID_WAN_MEDIUM_SUBTYPE:
  374. GenericULong = NdisWanMediumIsdn;
  375. break;
  376. case OID_WAN_GET_INFO:
  377. SourceBuffer = &pAdapter->WanInfo;
  378. SourceBufferLength = sizeof(NDIS_WAN_INFO);
  379. break;
  380. case OID_WAN_GET_LINK_INFO:
  381. {
  382. PNDIS_WAN_GET_LINK_INFO pGetWanLinkInfo;
  383. PBCHANNEL_OBJECT pBChannel;
  384. // A Pointer to one of our <t BCHANNEL_OBJECT>'s.
  385. /*
  386. // The InformationBuffer really points to a NDIS_WAN_GET_LINK_INFO
  387. // which contains a pointer to one of our BCHANNEL_OBJECT's in the
  388. // NdisLinkHandle field.
  389. */
  390. pGetWanLinkInfo = (PNDIS_WAN_GET_LINK_INFO)InformationBuffer;
  391. pBChannel = (PBCHANNEL_OBJECT) pGetWanLinkInfo->NdisLinkHandle;
  392. /*
  393. // Make sure what I just said is true.
  394. */
  395. if (!IS_VALID_BCHANNEL(pAdapter, pBChannel))
  396. {
  397. SourceBufferLength = 0;
  398. Status = NDIS_STATUS_INVALID_DATA;
  399. break;
  400. }
  401. DBG_PARAMS(pAdapter,
  402. ("Returning:\n"
  403. "NdisLinkHandle = %08lX\n"
  404. "MaxSendFrameSize = %08lX\n"
  405. "MaxRecvFrameSize = %08lX\n"
  406. "SendFramingBits = %08lX\n"
  407. "RecvFramingBits = %08lX\n"
  408. "SendACCM = %08lX\n"
  409. "RecvACCM = %08lX\n",
  410. pBChannel->WanLinkInfo.NdisLinkHandle,
  411. pBChannel->WanLinkInfo.MaxSendFrameSize ,
  412. pBChannel->WanLinkInfo.MaxRecvFrameSize ,
  413. pBChannel->WanLinkInfo.SendFramingBits ,
  414. pBChannel->WanLinkInfo.RecvFramingBits ,
  415. pBChannel->WanLinkInfo.SendACCM ,
  416. pBChannel->WanLinkInfo.RecvACCM ));
  417. SourceBuffer = &(pBChannel->WanLinkInfo);
  418. SourceBufferLength = sizeof(NDIS_WAN_GET_LINK_INFO);
  419. }
  420. break;
  421. #if defined(NDIS50_MINIPORT)
  422. case OID_WAN_LINE_COUNT:
  423. GenericULong = pAdapter->NumBChannels;
  424. break;
  425. case OID_PNP_CAPABILITIES:
  426. // The sample just returns success for all PM events even though we
  427. // don't really do anything with them.
  428. PnpCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp =
  429. NdisDeviceStateUnspecified;
  430. PnpCapabilities.WakeUpCapabilities.MinPatternWakeUp =
  431. NdisDeviceStateUnspecified;
  432. PnpCapabilities.WakeUpCapabilities.MinLinkChangeWakeUp =
  433. NdisDeviceStateUnspecified;
  434. SourceBuffer = &PnpCapabilities;
  435. SourceBufferLength = sizeof(PnpCapabilities);
  436. break;
  437. case OID_PNP_QUERY_POWER:
  438. // The sample just returns success for all PM events even though we
  439. // don't really do anything with them.
  440. break;
  441. #endif // NDIS50_MINIPORT
  442. default:
  443. /*
  444. // Unknown OID
  445. */
  446. Status = NDIS_STATUS_INVALID_OID;
  447. SourceBufferLength = 0;
  448. DBG_WARNING(pAdapter,("UNSUPPORTED Oid=0x%08x\n", Oid));
  449. break;
  450. }
  451. /*
  452. // Now we copy the data into the caller's buffer if there's enough room,
  453. // otherwise, we report the error and tell em how much we need.
  454. */
  455. if (SourceBufferLength > InformationBufferLength)
  456. {
  457. *BytesNeeded = SourceBufferLength;
  458. *BytesWritten = 0;
  459. Status = NDIS_STATUS_INVALID_LENGTH;
  460. }
  461. else if (SourceBufferLength)
  462. {
  463. NdisMoveMemory(InformationBuffer,
  464. SourceBuffer,
  465. SourceBufferLength
  466. );
  467. *BytesNeeded = *BytesWritten = SourceBufferLength;
  468. }
  469. else
  470. {
  471. *BytesNeeded = *BytesWritten = 0;
  472. }
  473. DBG_REQUEST(pAdapter,
  474. ("RETURN: Status=0x%X Needed=%d Written=%d\n",
  475. Status, *BytesNeeded, *BytesWritten));
  476. DBG_RETURN(pAdapter, Status);
  477. return (Status);
  478. }
  479. /* @doc INTERNAL Request Request_c MiniportSetInformation
  480. @func
  481. <f MiniportSetInformation> is a required function that allows
  482. bound protocol drivers (or NDIS) to request changes in the
  483. state information that the miniport maintains for
  484. particular OIDs, such as changes in multicast addresses.
  485. @comm
  486. NDIS calls <f MiniportSetInformation> either on its own
  487. behalf, such as to manage bindings to the miniport, or
  488. when a bound protocol driver calls <f NdisRequest>.
  489. If <f MiniportSetInformation> returns NDIS_STATUS_PENDING, the
  490. driver must complete the request later by calling
  491. NdisMSetInformationComplete. Until it completes any request,
  492. the miniport can safely access the memory at InformationBuffer,
  493. BytesRead, and BytesNeeded. After the miniport completes any set
  494. request, ownership of these variables and the buffer reverts to
  495. NDIS or the caller of <f NdisRequest>, whichever allocated the memory.
  496. No other requests will be submitted to the WAN driver until the
  497. current set request is complete. If the WAN driver does not complete
  498. the call immediately (by returning NDIS_STATUS_PENDING), it must call
  499. NdisMSetInformationComplete to complete the call.
  500. Any of the settable NDIS global OIDs can be used, although a WAN
  501. miniport cannot set the <f NDIS_MAC_OPTION_FULL_DUPLEX> flag in
  502. response to an <f OID_GEN_MAC_OPTIONS> request. The following
  503. WAN-specific OID is passed to MiniportSetInformation.
  504. <f OID_WAN_SET_LINK_INFO><nl>
  505. This OID is used to set the link characteristics.
  506. The parameters in the structure passed for this OID
  507. are described previously for OID_WAN_GET_LINK_INFO.
  508. For more information about the system-defined OIDs, see Part 2 of the
  509. Network Drivers Network Reference document.
  510. <f MiniportSetInformation> can be pre-empted by an interrupt.
  511. By default, <f MiniportSetInformation> runs at IRQL DISPATCH_LEVEL.
  512. Calls to MiniportSetInformation changes information maintained by
  513. the miniport. This function definition and operation is the same
  514. as in a LAN miniport NIC driver except that certain WAN-specific
  515. OIDs must be recognized.
  516. @rdesc
  517. <f MiniportSetInformation> can return one of the following:
  518. @flag NDIS_STATUS_SUCCESS |
  519. MiniportSetInformation used the data at InformationBuffer to
  520. set itself or its NIC to the state required by the given Oid,
  521. and it set the variable at BytesRead to the amount of supplied
  522. data it used.
  523. @flag NDIS_STATUS_PENDING |
  524. The driver will complete the request asynchronously with a call
  525. to NdisMSetInformationComplete when it has set itself or its NIC
  526. to the state requested.
  527. @flag NDIS_STATUS_INVALID_OID |
  528. MiniportSetInformation did not recognize the Oid.
  529. @flag NDIS_STATUS_INVALID_LENGTH |
  530. The InformationBufferLength does not match the length required
  531. by the given Oid. MiniportSetInformation returned how many bytes
  532. the buffer should be at BytesNeeded.
  533. @flag NDIS_STATUS_INVALID_DATA |
  534. The data supplied at InformationBuffer was invalid for the given Oid.
  535. @flag NDIS_STATUS_NOT_ACCEPTED |
  536. MiniportSetInformation attempted the requested set operation on
  537. the NIC but was unsuccessful.
  538. @flag NDIS_STATUS_NOT_SUPPORTED |
  539. MiniportSetInformation does not support the Oid, which is optional.
  540. @flag NDIS_STATUS_RESOURCES |
  541. MiniportSetInformation could not carry out the requested operation
  542. due to resource constraints. This return value does not necessarily
  543. mean that the same request, submitted at a later time, will be
  544. failed for the same reason.
  545. @xref
  546. <f MiniportInitialize>
  547. <f MiniportQueryInformation>
  548. */
  549. NDIS_STATUS MiniportSetInformation(
  550. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  551. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  552. IN NDIS_OID Oid, // @parm
  553. // The OID. (See section 7.4 of the NDIS 3.0 specification for a complete
  554. // description of OIDs.)
  555. IN PVOID InformationBuffer, // @parm
  556. // The buffer that will receive the information. (See section 7.4 of the
  557. // NDIS 3.0 specification for a description of the length required for
  558. // each OID.)
  559. IN ULONG InformationBufferLength, // @parm
  560. // The length in bytes of InformationBuffer.
  561. OUT PULONG BytesRead, // @parm
  562. // Returns the number of bytes read from InformationBuffer.
  563. OUT PULONG BytesNeeded // @parm
  564. // Returns the number of additional bytes needed to satisfy the OID.
  565. )
  566. {
  567. DBG_FUNC("MiniportSetInformation")
  568. NDIS_STATUS Status;
  569. // Holds the status result returned by this function.
  570. /*
  571. // If this is a TAPI OID, pass it on over.
  572. */
  573. if ((Oid & 0xFFFFFF00L) == (OID_TAPI_ACCEPT & 0xFFFFFF00L))
  574. {
  575. Status = TspiRequestHandler(pAdapter,
  576. Oid,
  577. InformationBuffer,
  578. InformationBufferLength,
  579. BytesRead,
  580. BytesNeeded
  581. );
  582. return (Status);
  583. }
  584. DBG_ENTER(pAdapter);
  585. DBG_REQUEST(pAdapter,
  586. ("(OID=0x%08X %s)\n\t\tInfoLength=%d InfoBuffer=0x%X\n",
  587. Oid, DbgGetOidString(Oid),
  588. InformationBufferLength,
  589. InformationBuffer
  590. ));
  591. /*
  592. // Assume no extra bytes are needed.
  593. */
  594. ASSERT(BytesRead && BytesNeeded);
  595. *BytesRead = 0;
  596. *BytesNeeded = 0;
  597. /*
  598. // Determine which OID is being requested and do the right thing.
  599. */
  600. switch (Oid)
  601. {
  602. case OID_GEN_CURRENT_LOOKAHEAD:
  603. /*
  604. // WAN drivers always indicate the entire packet regardless of the
  605. // lookahead size. So this request should be politely ignored.
  606. */
  607. DBG_NOTICE(pAdapter,("OID_GEN_CURRENT_LOOKAHEAD: set=%d expected=%d\n",
  608. *(PULONG) InformationBuffer, CARD_MAX_LOOKAHEAD));
  609. ASSERT(InformationBufferLength == sizeof(ULONG));
  610. *BytesNeeded = *BytesRead = sizeof(ULONG);
  611. Status = NDIS_STATUS_SUCCESS;
  612. break;
  613. case OID_WAN_SET_LINK_INFO:
  614. if (InformationBufferLength == sizeof(NDIS_WAN_SET_LINK_INFO))
  615. {
  616. PNDIS_WAN_SET_LINK_INFO pSetWanLinkInfo;
  617. PBCHANNEL_OBJECT pBChannel;
  618. // A Pointer to one of our <t BCHANNEL_OBJECT>'s.
  619. /*
  620. // The InformationBuffer really points to a NDIS_WAN_SET_LINK_INFO
  621. // which contains a pointer to one of our BCHANNEL_OBJECT's in the
  622. // NdisLinkHandle field.
  623. */
  624. pSetWanLinkInfo = (PNDIS_WAN_SET_LINK_INFO)InformationBuffer;
  625. pBChannel = (PBCHANNEL_OBJECT) pSetWanLinkInfo->NdisLinkHandle;
  626. /*
  627. // Make sure what I just said is true.
  628. */
  629. if (!IS_VALID_BCHANNEL(pAdapter, pBChannel))
  630. {
  631. Status = NDIS_STATUS_INVALID_DATA;
  632. break;
  633. }
  634. ASSERT(pBChannel->WanLinkInfo.NdisLinkHandle == pBChannel);
  635. ASSERT(!(pBChannel->WanLinkInfo.SendFramingBits & ~pAdapter->WanInfo.FramingBits));
  636. ASSERT(!(pBChannel->WanLinkInfo.RecvFramingBits & ~pAdapter->WanInfo.FramingBits));
  637. /*
  638. // Copy the data into our WanLinkInfo sturcture.
  639. */
  640. NdisMoveMemory(&(pBChannel->WanLinkInfo),
  641. InformationBuffer,
  642. InformationBufferLength
  643. );
  644. *BytesRead = sizeof(NDIS_WAN_SET_LINK_INFO);
  645. Status = NDIS_STATUS_SUCCESS;
  646. if (pBChannel->WanLinkInfo.MaxSendFrameSize != pAdapter->WanInfo.MaxFrameSize ||
  647. pBChannel->WanLinkInfo.MaxRecvFrameSize != pAdapter->WanInfo.MaxFrameSize)
  648. {
  649. DBG_NOTICE(pAdapter,("Line=%d - "
  650. "NdisLinkHandle=%08lX - "
  651. "SendFrameSize=%08lX - "
  652. "RecvFrameSize=%08lX\n",
  653. pBChannel->BChannelIndex,
  654. pBChannel->WanLinkInfo.NdisLinkHandle,
  655. pBChannel->WanLinkInfo.MaxSendFrameSize,
  656. pBChannel->WanLinkInfo.MaxRecvFrameSize));
  657. }
  658. DBG_PARAMS(pAdapter,
  659. ("\n setting expected\n"
  660. "NdisLinkHandle = %08lX=?=%08lX\n"
  661. "MaxSendFrameSize = %08lX=?=%08lX\n"
  662. "MaxRecvFrameSize = %08lX=?=%08lX\n"
  663. "SendFramingBits = %08lX=?=%08lX\n"
  664. "RecvFramingBits = %08lX=?=%08lX\n"
  665. "SendACCM = %08lX=?=%08lX\n"
  666. "RecvACCM = %08lX=?=%08lX\n",
  667. pBChannel->WanLinkInfo.NdisLinkHandle , pBChannel,
  668. pBChannel->WanLinkInfo.MaxSendFrameSize , pAdapter->WanInfo.MaxFrameSize,
  669. pBChannel->WanLinkInfo.MaxRecvFrameSize , pAdapter->WanInfo.MaxFrameSize,
  670. pBChannel->WanLinkInfo.SendFramingBits , pAdapter->WanInfo.FramingBits,
  671. pBChannel->WanLinkInfo.RecvFramingBits , pAdapter->WanInfo.FramingBits,
  672. pBChannel->WanLinkInfo.SendACCM , pAdapter->WanInfo.DesiredACCM,
  673. pBChannel->WanLinkInfo.RecvACCM , pAdapter->WanInfo.DesiredACCM));
  674. }
  675. else
  676. {
  677. DBG_WARNING(pAdapter, ("OID_WAN_SET_LINK_INFO: Invalid size:%d expected:%d\n",
  678. InformationBufferLength, sizeof(NDIS_WAN_SET_LINK_INFO)));
  679. Status = NDIS_STATUS_INVALID_LENGTH;
  680. }
  681. *BytesNeeded = sizeof(NDIS_WAN_SET_LINK_INFO);
  682. break;
  683. #if defined(NDIS50_MINIPORT)
  684. case OID_PNP_SET_POWER:
  685. // The sample just returns success for all PM events even though we
  686. // don't really do anything with them.
  687. break;
  688. #endif // NDIS50_MINIPORT
  689. default:
  690. /*
  691. // Unknown OID
  692. */
  693. Status = NDIS_STATUS_INVALID_OID;
  694. DBG_WARNING(pAdapter,("UNSUPPORTED Oid=0x%08x\n", Oid));
  695. break;
  696. }
  697. DBG_REQUEST(pAdapter,
  698. ("RETURN: Status=0x%X Needed=%d Read=%d\n",
  699. Status, *BytesNeeded, *BytesRead));
  700. DBG_RETURN(pAdapter, Status);
  701. return (Status);
  702. }