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.

1051 lines
39 KiB

  1. /*
  2. (C) Copyright 1999
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the same terms
  7. outlined in the Microsoft Windows Device Driver Development Kit.
  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 NDIS Request Processing |
  20. A connection-oriented client or call manager calls NdisCoRequest to query or
  21. set information maintained by another protocol driver on a binding or by the
  22. underlying miniport.
  23. Before it calls NdisCoRequest, a client or call manager allocates a buffer
  24. for its request and initializes an NDIS_REQUEST structure. This structure
  25. specifies the type of request (query or set), identifies the information
  26. (OID) being queried or set, and points to buffers used for passing OID data.
  27. If the connection-oriented client or call manager passes a valid
  28. NdisAfHandle (see Section 1.2.1), NDIS calls the <f ProtocolCoRequest>
  29. function of each protocol driver on the binding.
  30. If the connection-oriented client or call manager passes a NULL address
  31. family handle, NDIS calls the <f MiniportCoRequest> function of the
  32. underlying miniport or MCM.
  33. The caller of NdisCoRequest or NdisMCmRequest can narrow the scope of the
  34. request by specifying a VC handle that identifies a VC, or a party handle
  35. that identifies a party on a multipoint VC. Passing a NULL NdisVcHandle
  36. makes such a request global in nature, whether the request is directed to
  37. the client, call manager, miniport, or MCM.
  38. <f ProtocolCoRequest> or <f MiniportCoRequest> can complete synchronously,
  39. or these functions can complete asynchronously with NdisCoRequestComplete.
  40. The call to NdisCoRequestComplete causes NDIS to call the
  41. <f ProtocolCoRequestComplete> function of the driver that called
  42. NdisCoRequest.
  43. @comm
  44. Since only one NDIS request can be outstanding at a time, this mechanism
  45. should not be used for requests that need to be pended indefintely. For
  46. such long term requests, you should use a system event mechanism such as
  47. NdisSetEvent to trigger the request.
  48. @end
  49. */
  50. #define __FILEID__ REQUEST_OBJECT_TYPE
  51. // Unique file ID for error logging
  52. #include "Miniport.h" // Defines all the miniport objects
  53. #if defined(NDIS_LCODE)
  54. # pragma NDIS_LCODE // Windows 9x wants this code locked down!
  55. # pragma NDIS_LDATA
  56. #endif
  57. /*
  58. // The following is a list of all the possible NDIS QuereyInformation requests
  59. // that might be directed to the miniport.
  60. // Comment out any that are not supported by this driver.
  61. */
  62. DBG_STATIC const NDIS_OID g_SupportedOidArray[] =
  63. {
  64. OID_GEN_CO_SUPPORTED_LIST,
  65. OID_GEN_CO_HARDWARE_STATUS,
  66. OID_GEN_CO_MEDIA_SUPPORTED,
  67. OID_GEN_CO_MEDIA_IN_USE,
  68. OID_GEN_CO_LINK_SPEED,
  69. OID_GEN_CO_VENDOR_ID,
  70. OID_GEN_CO_VENDOR_DESCRIPTION,
  71. OID_GEN_CO_DRIVER_VERSION,
  72. OID_GEN_CO_PROTOCOL_OPTIONS,
  73. OID_GEN_CO_MAC_OPTIONS,
  74. OID_GEN_CO_MEDIA_CONNECT_STATUS,
  75. OID_GEN_CO_VENDOR_DRIVER_VERSION,
  76. OID_GEN_CO_SUPPORTED_GUIDS,
  77. OID_CO_TAPI_CM_CAPS,
  78. OID_CO_TAPI_LINE_CAPS,
  79. OID_CO_TAPI_ADDRESS_CAPS,
  80. OID_802_3_PERMANENT_ADDRESS,
  81. OID_802_3_CURRENT_ADDRESS,
  82. OID_WAN_PERMANENT_ADDRESS,
  83. OID_WAN_CURRENT_ADDRESS,
  84. OID_WAN_MEDIUM_SUBTYPE,
  85. OID_WAN_CO_GET_INFO,
  86. OID_WAN_CO_SET_LINK_INFO,
  87. OID_WAN_CO_GET_LINK_INFO,
  88. OID_WAN_LINE_COUNT,
  89. OID_PNP_CAPABILITIES,
  90. OID_PNP_SET_POWER,
  91. OID_PNP_QUERY_POWER,
  92. 0
  93. };
  94. DBG_STATIC const NDIS_GUID g_SupportedGuidArray[] =
  95. {
  96. 0
  97. };
  98. #if DBG
  99. /*
  100. // Make sure the following list is in the same order as the list above!
  101. */
  102. DBG_STATIC char * g_SupportedOidNames[] =
  103. {
  104. "OID_GEN_CO_SUPPORTED_LIST",
  105. "OID_GEN_CO_HARDWARE_STATUS",
  106. "OID_GEN_CO_MEDIA_SUPPORTED",
  107. "OID_GEN_CO_MEDIA_IN_USE",
  108. "OID_GEN_CO_LINK_SPEED",
  109. "OID_GEN_CO_VENDOR_ID",
  110. "OID_GEN_CO_VENDOR_DESCRIPTION",
  111. "OID_GEN_CO_DRIVER_VERSION",
  112. "OID_GEN_CO_PROTOCOL_OPTIONS",
  113. "OID_GEN_CO_MAC_OPTIONS",
  114. "OID_GEN_CO_MEDIA_CONNECT_STATUS",
  115. "OID_GEN_CO_VENDOR_DRIVER_VERSION",
  116. "OID_GEN_CO_SUPPORTED_GUIDS",
  117. "OID_CO_TAPI_CM_CAPS",
  118. "OID_CO_TAPI_LINE_CAPS",
  119. "OID_CO_TAPI_ADDRESS_CAPS",
  120. "OID_802_3_PERMANENT_ADDRESS",
  121. "OID_802_3_CURRENT_ADDRESS",
  122. "OID_WAN_PERMANENT_ADDRESS",
  123. "OID_WAN_CURRENT_ADDRESS",
  124. "OID_WAN_MEDIUM_SUBTYPE",
  125. "OID_WAN_CO_GET_INFO",
  126. "OID_WAN_CO_SET_LINK_INFO",
  127. "OID_WAN_CO_GET_LINK_INFO",
  128. "OID_WAN_LINE_COUNT",
  129. "OID_PNP_CAPABILITIES",
  130. "OID_PNP_SET_POWER",
  131. "OID_PNP_QUERY_POWER",
  132. "OID_UNKNOWN"
  133. };
  134. #define NUM_OID_ENTRIES (sizeof(g_SupportedOidArray) / sizeof(g_SupportedOidArray[0]))
  135. /*
  136. // This debug routine will lookup the printable name for the selected OID.
  137. */
  138. DBG_STATIC char * DbgGetOidString(
  139. IN NDIS_OID Oid
  140. )
  141. {
  142. UINT i;
  143. for (i = 0; i < NUM_OID_ENTRIES-1; i++)
  144. {
  145. if (g_SupportedOidArray[i] == Oid)
  146. {
  147. break;
  148. }
  149. }
  150. return(g_SupportedOidNames[i]);
  151. }
  152. #endif // DBG
  153. DBG_STATIC UCHAR g_PermanentWanAddress[6] // @globalv
  154. // Returned from an OID_WAN_PERMANENT_ADDRESS MiniportCoQueryInformation
  155. // request. The WAN wrapper wants the miniport to return a unique address
  156. // for this adapter. This is used as an ethernet address presented to the
  157. // protocols. The least significant bit of the first byte must not be a 1,
  158. // or it could be interpreted as an ethernet multicast address. If the
  159. // vendor has an assigned ethernet vendor code (the first 3 bytes), they
  160. // should be used to assure that the address does not conflict with another
  161. // vendor's address. The last digit is replaced during the call with the
  162. // adapter instance number. Usually defined as VER_VENDOR_ID.
  163. // See also <f g_Vendor3ByteID>.
  164. = VER_VENDOR_ID;
  165. DBG_STATIC UCHAR g_Vendor3ByteID[4] // @globalv
  166. // Returned from an OID_GEN_CO_VENDOR_ID MiniportCoQueryInformation request.
  167. // Again, the vendor's assigned ethernet vendor code should be used if possible.
  168. // Usually defined as VER_VENDOR_ID. See also <f g_PermanentWanAddress>.
  169. = VER_VENDOR_ID;
  170. DBG_STATIC NDIS_STRING g_VendorDescriptionString // @globalv
  171. // Returned from an OID_GEN_CO_VENDOR_DESCRIPTION MiniportCoQueryInformation
  172. // request. This is an arbitrary string which may be used by upper layers to
  173. // present a user friendly description of the adapter.
  174. // Usually defined as VER_PRODUCT_NAME_STR.
  175. = INIT_STRING_CONST(VER_PRODUCT_NAME_STR);
  176. /* @doc INTERNAL Request Request_c MiniportCoQueryInformation
  177. @func
  178. <f MiniportCoQueryInformation> allows the inspection of the Miniport's
  179. capabilities and current status.
  180. If the Miniport does not complete the call immediately (by returning
  181. NDIS_STATUS_PENDING), it must call NdisMQueryInformationComplete to
  182. complete the call. The Miniport controls the buffers pointed to by
  183. InformationBuffer, BytesWritten, and BytesNeeded until the request
  184. completes.
  185. No other requests will be submitted to the Miniport until this request
  186. has been completed.
  187. <f Note>: that the wrapper will intercept all queries of the following OIDs:
  188. OID_GEN_CURRENT_PACKET_FILTER,
  189. OID_GEN_PROTOCOL_OPTIONS,
  190. OID_802_5_CURRENT_FUNCTIONAL,
  191. OID_802_3_MULTICAST_LIST,
  192. OID_FDDI_LONG_MULTICAST_LIST,
  193. OID_FDDI_SHORT_MULTICAST_LIST.
  194. <f Note>: Interrupts will be in any state when called.
  195. @rdesc
  196. <f MiniportCoQueryInformation> returns zero if it is successful.<nl>
  197. Otherwise, a non-zero return value indicates an error condition.
  198. */
  199. DBG_STATIC NDIS_STATUS MiniportCoQueryInformation(
  200. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  201. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  202. IN PBCHANNEL_OBJECT pBChannel, // @parm
  203. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  204. IN NDIS_OID Oid, // @parm
  205. // The OID. (See section 7.4 of the NDIS 3.0 specification for a complete
  206. // description of OIDs.)
  207. IN PVOID InformationBuffer, // @parm
  208. // The buffer that will receive the information. (See section 7.4 of the
  209. // NDIS 3.0 specification for a description of the length required for
  210. // each OID.)
  211. IN ULONG InformationBufferLength, // @parm
  212. // The length in bytes of InformationBuffer.
  213. OUT PULONG BytesWritten, // @parm
  214. // Returns the number of bytes written into InformationBuffer.
  215. OUT PULONG BytesNeeded // @parm
  216. // Returns the number of additional bytes needed to satisfy the OID.
  217. )
  218. {
  219. DBG_FUNC("MiniportCoQueryInformation")
  220. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  221. // Holds the status result returned by this function.
  222. PVOID SourceBuffer;
  223. // Pointer to driver data to be copied back to caller's InformationBuffer
  224. ULONG SourceBufferLength;
  225. // Number of bytes to be copied from driver.
  226. ULONG GenericULong = 0;
  227. // Most return values are long integers, so this is used to hold the
  228. // return value of a constant or computed result.
  229. UCHAR VendorId[4];
  230. // Used to store vendor ID string.
  231. NDIS_PNP_CAPABILITIES PnpCapabilities;
  232. // Used to return our PNP capabilities.
  233. NDIS_CO_LINK_SPEED LinkSpeed;
  234. // Used to return our link speed.
  235. UINT InfoOffset;
  236. // Offset from the start of the buffer to the various information
  237. // fields we fill in and return to the caller.
  238. UINT InfoLength;
  239. // Length of the information being copied.
  240. DBG_STATIC WCHAR LineSwitchName[] =
  241. INIT_WIDE_STRING(VER_DEVICE_STR) DECLARE_WIDE_STRING(" Switch");
  242. // TODO: Replace with unicode string to identify the ISDN switch.
  243. DBG_STATIC WCHAR LineAddressName[] =
  244. INIT_WIDE_STRING(VER_DEVICE_STR) DECLARE_WIDE_STRING(" Address 00");
  245. // TODO: The SAMPLE_DRIVER only handles 1 address per line. You may want
  246. // to modify the driver to present multiple addresses per line.
  247. DBG_ENTER(pAdapter);
  248. DBG_REQUEST(pAdapter,
  249. ("(OID=0x%08X %s)\n\t\tInfoLength=%d InfoBuffer=0x%X\n",
  250. Oid, DbgGetOidString(Oid),
  251. InformationBufferLength,
  252. InformationBuffer
  253. ));
  254. /*
  255. // Initialize these once, since this is the majority of cases.
  256. */
  257. SourceBuffer = &GenericULong;
  258. SourceBufferLength = sizeof(ULONG);
  259. *BytesWritten = 0;
  260. /*
  261. // Determine which OID is being requested and do the right thing.
  262. // Refer to section 7.4 of the NDIS 3.0 specification for a complete
  263. // description of OIDs and their return values.
  264. */
  265. switch (Oid)
  266. {
  267. case OID_GEN_CO_SUPPORTED_LIST:
  268. /*
  269. // NDIS wants to know which OID's to pass down to us.
  270. // So we report back these new IOCTL's in addition to any NDIS OID's.
  271. */
  272. SourceBuffer = (PVOID)g_SupportedOidArray;
  273. SourceBufferLength = sizeof(g_SupportedOidArray);
  274. break;
  275. case OID_GEN_CO_SUPPORTED_GUIDS:
  276. SourceBuffer = (PVOID)g_SupportedGuidArray;
  277. SourceBufferLength = sizeof(g_SupportedGuidArray);
  278. break;
  279. case OID_GEN_CO_HARDWARE_STATUS:
  280. GenericULong = NdisHardwareStatusReady;
  281. break;
  282. case OID_GEN_CO_MEDIA_SUPPORTED:
  283. GenericULong = NdisMediumCoWan;
  284. break;
  285. case OID_GEN_CO_MEDIA_IN_USE:
  286. GenericULong = NdisMediumCoWan;
  287. break;
  288. case OID_GEN_CO_LINK_SPEED:
  289. LinkSpeed.Outbound = pBChannel->LinkSpeed / 100;
  290. LinkSpeed.Inbound = pBChannel->LinkSpeed / 100;
  291. SourceBuffer = &LinkSpeed;
  292. SourceBufferLength = sizeof(LinkSpeed);
  293. break;
  294. case OID_GEN_CO_VENDOR_ID:
  295. NdisMoveMemory((PVOID)VendorId, (PVOID)g_PermanentWanAddress, 3);
  296. VendorId[3] = 0x0;
  297. SourceBuffer = &VendorId[0];
  298. SourceBufferLength = sizeof(VendorId);
  299. break;
  300. case OID_GEN_CO_VENDOR_DESCRIPTION:
  301. SourceBuffer = (PUCHAR) g_VendorDescriptionString.Buffer;
  302. SourceBufferLength = g_VendorDescriptionString.MaximumLength;
  303. break;
  304. case OID_GEN_CO_DRIVER_VERSION:
  305. GenericULong = (NDIS_MAJOR_VERSION << 8) + NDIS_MINOR_VERSION;
  306. break;
  307. case OID_GEN_CO_MAC_OPTIONS:
  308. GenericULong = 0; // Reserved - leave it set to zero.
  309. break;
  310. case OID_GEN_CO_MEDIA_CONNECT_STATUS:
  311. GenericULong = NdisMediaStateConnected;
  312. break;
  313. case OID_GEN_CO_VENDOR_DRIVER_VERSION:
  314. GenericULong = (VER_FILE_MAJOR_NUM << 8) + VER_FILE_MINOR_NUM;
  315. break;
  316. case OID_CO_TAPI_CM_CAPS:
  317. {
  318. PCO_TAPI_CM_CAPS pCallManagerCaps = InformationBuffer;
  319. SourceBufferLength = sizeof(*pCallManagerCaps);
  320. if (InformationBufferLength >= SourceBufferLength)
  321. {
  322. pCallManagerCaps->ulCoTapiVersion = CO_TAPI_VERSION;
  323. pCallManagerCaps->ulNumLines = pAdapter->NumBChannels;
  324. pCallManagerCaps->ulFlags = 0;
  325. // No need to copy, it's filled in already.
  326. SourceBuffer = InformationBuffer;
  327. }
  328. else
  329. {
  330. DBG_ERROR(pAdapter,("OID_CO_TAPI_CM_CAPS: Invalid size=%d expected=%d\n",
  331. InformationBufferLength, SourceBufferLength));
  332. }
  333. }
  334. break;
  335. case OID_CO_TAPI_LINE_CAPS:
  336. {
  337. PCO_TAPI_LINE_CAPS pLineCaps = InformationBuffer;
  338. SourceBufferLength = sizeof(*pLineCaps);
  339. if (InformationBufferLength >= SourceBufferLength)
  340. {
  341. pLineCaps->ulFlags = 0;
  342. pBChannel = GET_BCHANNEL_FROM_INDEX(pAdapter,
  343. pLineCaps->ulLineID);
  344. // We're gonna write at least this much, maybe more.
  345. *BytesWritten = SourceBufferLength;
  346. DBG_NOTICE(pAdapter,("OID_CO_TAPI_LINE_CAPS: Line=0x%X\n",
  347. pLineCaps->ulLineID));
  348. pLineCaps->LineDevCaps.ulNeededSize =
  349. pLineCaps->LineDevCaps.ulUsedSize = sizeof(pLineCaps->LineDevCaps);
  350. /*
  351. // The driver numbers lines sequentially from 1, so this will
  352. // always be the same number.
  353. */
  354. pLineCaps->LineDevCaps.ulPermanentLineID = pBChannel->ObjectID;
  355. /*
  356. // All the strings are ASCII format rather than UNICODE.
  357. */
  358. pLineCaps->LineDevCaps.ulStringFormat = STRINGFORMAT_UNICODE;
  359. /*
  360. // Report the capabilities of this device.
  361. */
  362. pLineCaps->LineDevCaps.ulAddressModes = LINEADDRESSMODE_ADDRESSID;
  363. pLineCaps->LineDevCaps.ulNumAddresses = 1;
  364. pLineCaps->LineDevCaps.ulBearerModes = pBChannel->BearerModesCaps;
  365. pLineCaps->LineDevCaps.ulMaxRate = pBChannel->LinkSpeed;
  366. pLineCaps->LineDevCaps.ulMediaModes = pBChannel->MediaModesCaps;
  367. /*
  368. // Each line on the PRI only supports a single call.
  369. */
  370. pLineCaps->LineDevCaps.ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
  371. pLineCaps->LineDevCaps.ulMaxNumActiveCalls = 1;
  372. pLineCaps->LineDevCaps.ulAnswerMode = LINEANSWERMODE_DROP;
  373. pLineCaps->LineDevCaps.ulRingModes = 1;
  374. pLineCaps->LineDevCaps.ulLineStates = pBChannel->DevStatesCaps;
  375. /*
  376. // RASTAPI requires TSPI provider name to be placed in the
  377. // ProviderInfo field at the end of this structure.
  378. */
  379. InfoOffset = sizeof(pLineCaps->LineDevCaps);
  380. InfoLength = g_VendorDescriptionString.MaximumLength;
  381. pLineCaps->LineDevCaps.ulNeededSize += InfoLength;
  382. SourceBufferLength += InfoLength;
  383. if (pLineCaps->LineDevCaps.ulNeededSize <=
  384. pLineCaps->LineDevCaps.ulTotalSize)
  385. {
  386. pLineCaps->LineDevCaps.ulProviderInfoSize = InfoLength;
  387. pLineCaps->LineDevCaps.ulProviderInfoOffset = InfoOffset;
  388. NdisMoveMemory((PUCHAR) &pLineCaps->LineDevCaps + InfoOffset,
  389. g_VendorDescriptionString.Buffer,
  390. InfoLength
  391. );
  392. pLineCaps->LineDevCaps.ulUsedSize += InfoLength;
  393. InfoOffset += InfoLength;
  394. }
  395. /*
  396. // SwitchName is not yet displayed by the Dialup Networking App,
  397. // but we'll return something reasonable just in case.
  398. */
  399. InfoLength = sizeof(LineSwitchName);
  400. pLineCaps->LineDevCaps.ulNeededSize += InfoLength;
  401. SourceBufferLength += InfoLength;
  402. if (pLineCaps->LineDevCaps.ulNeededSize <=
  403. pLineCaps->LineDevCaps.ulTotalSize)
  404. {
  405. pLineCaps->LineDevCaps.ulSwitchInfoSize = InfoLength;
  406. pLineCaps->LineDevCaps.ulSwitchInfoOffset = InfoOffset;
  407. NdisMoveMemory((PUCHAR) &pLineCaps->LineDevCaps + InfoOffset,
  408. LineSwitchName,
  409. InfoLength
  410. );
  411. pLineCaps->LineDevCaps.ulUsedSize += InfoLength;
  412. InfoOffset += InfoLength;
  413. }
  414. else
  415. {
  416. DBG_PARAMS(pAdapter,
  417. ("STRUCTURETOOSMALL %d<%d\n",
  418. pLineCaps->LineDevCaps.ulTotalSize,
  419. pLineCaps->LineDevCaps.ulNeededSize));
  420. }
  421. // No need to copy, it's filled in already.
  422. SourceBuffer = InformationBuffer;
  423. }
  424. else
  425. {
  426. DBG_ERROR(pAdapter,("OID_CO_TAPI_LINE_CAPS: Invalid size=%d expected=%d\n",
  427. InformationBufferLength, SourceBufferLength));
  428. }
  429. }
  430. break;
  431. case OID_CO_TAPI_ADDRESS_CAPS:
  432. {
  433. PCO_TAPI_ADDRESS_CAPS pAddressCaps = InformationBuffer;
  434. SourceBufferLength = sizeof(*pAddressCaps);
  435. if (InformationBufferLength >= SourceBufferLength)
  436. {
  437. pAddressCaps->ulFlags = 0;
  438. pBChannel = GET_BCHANNEL_FROM_INDEX(pAdapter,
  439. pAddressCaps->ulLineID);
  440. // We're gonna write at least this much, maybe more.
  441. *BytesWritten = SourceBufferLength;
  442. DBG_NOTICE(pAdapter,("OID_CO_TAPI_ADDRESS_CAPS: Line=0x%X Addr=0x%X\n",
  443. pAddressCaps->ulLineID, pAddressCaps->ulAddressID));
  444. pAddressCaps->LineAddressCaps.ulNeededSize =
  445. pAddressCaps->LineAddressCaps.ulUsedSize =
  446. sizeof(pAddressCaps->LineAddressCaps);
  447. pAddressCaps->LineAddressCaps.ulLineDeviceID =
  448. pBChannel->ObjectID;
  449. /*
  450. // Return the various address capabilites for the adapter.
  451. */
  452. pAddressCaps->LineAddressCaps.ulAddressSharing =
  453. LINEADDRESSSHARING_PRIVATE;
  454. pAddressCaps->LineAddressCaps.ulAddressStates =
  455. pBChannel->AddressStatesCaps;
  456. pAddressCaps->LineAddressCaps.ulCallStates =
  457. pBChannel->CallStatesCaps;
  458. pAddressCaps->LineAddressCaps.ulDialToneModes =
  459. LINEDIALTONEMODE_NORMAL;
  460. pAddressCaps->LineAddressCaps.ulDisconnectModes =
  461. LINEDISCONNECTMODE_NORMAL |
  462. LINEDISCONNECTMODE_UNKNOWN |
  463. LINEDISCONNECTMODE_BUSY |
  464. LINEDISCONNECTMODE_NOANSWER;
  465. /*
  466. // This driver does not support conference calls, transfers,
  467. // or holds.
  468. */
  469. pAddressCaps->LineAddressCaps.ulMaxNumActiveCalls = 1;
  470. pAddressCaps->LineAddressCaps.ulAddrCapFlags =
  471. LINEADDRCAPFLAGS_DIALED;
  472. pAddressCaps->LineAddressCaps.ulCallFeatures =
  473. LINECALLFEATURE_ACCEPT |
  474. LINECALLFEATURE_ANSWER |
  475. LINECALLFEATURE_DROP;
  476. /*
  477. // AddressName is displayed by the Dialup Networking App.
  478. */
  479. InfoOffset = sizeof(pAddressCaps->LineAddressCaps);
  480. InfoLength = sizeof(LineAddressName);
  481. pAddressCaps->LineAddressCaps.ulNeededSize += InfoLength;
  482. SourceBufferLength += InfoLength;
  483. if (pAddressCaps->LineAddressCaps.ulNeededSize <=
  484. pAddressCaps->LineAddressCaps.ulTotalSize)
  485. {
  486. pAddressCaps->LineAddressCaps.ulAddressSize = InfoLength;
  487. pAddressCaps->LineAddressCaps.ulAddressOffset = InfoOffset;
  488. NdisMoveMemory(
  489. (PUCHAR) &pAddressCaps->LineAddressCaps + InfoOffset,
  490. LineAddressName,
  491. InfoLength);
  492. pAddressCaps->LineAddressCaps.ulUsedSize += InfoLength;
  493. InfoOffset += InfoLength;
  494. }
  495. else
  496. {
  497. DBG_PARAMS(pAdapter,
  498. ("STRUCTURETOOSMALL %d<%d\n",
  499. pAddressCaps->LineAddressCaps.ulTotalSize,
  500. pAddressCaps->LineAddressCaps.ulNeededSize));
  501. }
  502. // No need to copy, it's filled in already.
  503. SourceBuffer = InformationBuffer;
  504. }
  505. else
  506. {
  507. DBG_ERROR(pAdapter,("OID_CO_TAPI_ADDRESS_CAPS: Invalid size=%d expected=%d\n",
  508. InformationBufferLength, SourceBufferLength));
  509. }
  510. }
  511. break;
  512. case OID_802_3_PERMANENT_ADDRESS:
  513. case OID_802_3_CURRENT_ADDRESS:
  514. case OID_WAN_PERMANENT_ADDRESS:
  515. case OID_WAN_CURRENT_ADDRESS:
  516. g_PermanentWanAddress[5] = (UCHAR) ((pAdapter->ObjectID & 0xFF) + '0');
  517. SourceBuffer = g_PermanentWanAddress;
  518. SourceBufferLength = sizeof(g_PermanentWanAddress);
  519. break;
  520. case OID_WAN_MEDIUM_SUBTYPE:
  521. GenericULong = NdisWanMediumIsdn;
  522. break;
  523. case OID_WAN_CO_GET_INFO:
  524. SourceBuffer = &pAdapter->WanInfo;
  525. SourceBufferLength = sizeof(NDIS_WAN_CO_INFO);
  526. break;
  527. case OID_WAN_CO_GET_LINK_INFO:
  528. {
  529. /*
  530. // Make sure what I just said is true.
  531. */
  532. if (!IS_VALID_BCHANNEL(pAdapter, pBChannel))
  533. {
  534. SourceBufferLength = 0;
  535. Result = NDIS_STATUS_INVALID_DATA;
  536. break;
  537. }
  538. DBG_PARAMS(pAdapter,
  539. ("Returning:\n"
  540. "MaxSendFrameSize = %08lX\n"
  541. "MaxRecvFrameSize = %08lX\n"
  542. "SendFramingBits = %08lX\n"
  543. "RecvFramingBits = %08lX\n"
  544. "SendCompressionBits = %08lX\n"
  545. "RecvCompressionBits = %08lX\n"
  546. "SendACCM = %08lX\n"
  547. "RecvACCM = %08lX\n",
  548. pBChannel->WanLinkInfo.MaxSendFrameSize ,
  549. pBChannel->WanLinkInfo.MaxRecvFrameSize ,
  550. pBChannel->WanLinkInfo.SendFramingBits ,
  551. pBChannel->WanLinkInfo.RecvFramingBits ,
  552. pBChannel->WanLinkInfo.SendCompressionBits,
  553. pBChannel->WanLinkInfo.RecvCompressionBits,
  554. pBChannel->WanLinkInfo.SendACCM ,
  555. pBChannel->WanLinkInfo.RecvACCM ));
  556. SourceBuffer = &(pBChannel->WanLinkInfo);
  557. SourceBufferLength = sizeof(NDIS_WAN_CO_GET_LINK_INFO);
  558. }
  559. break;
  560. case OID_WAN_LINE_COUNT:
  561. GenericULong = pAdapter->NumBChannels;
  562. break;
  563. case OID_PNP_CAPABILITIES:
  564. // The sample just returns success for all PM events even though we
  565. // don't really do anything with them.
  566. PnpCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp =
  567. NdisDeviceStateUnspecified;
  568. PnpCapabilities.WakeUpCapabilities.MinPatternWakeUp =
  569. NdisDeviceStateUnspecified;
  570. PnpCapabilities.WakeUpCapabilities.MinLinkChangeWakeUp =
  571. NdisDeviceStateUnspecified;
  572. SourceBuffer = &PnpCapabilities;
  573. SourceBufferLength = sizeof(PnpCapabilities);
  574. break;
  575. case OID_PNP_QUERY_POWER:
  576. // The sample just returns success for all PM events even though we
  577. // don't really do anything with them.
  578. break;
  579. default:
  580. /*
  581. // Unknown OID
  582. */
  583. Result = NDIS_STATUS_INVALID_OID;
  584. SourceBufferLength = 0;
  585. DBG_WARNING(pAdapter,("UNSUPPORTED Oid=0x%08x\n", Oid));
  586. break;
  587. }
  588. /*
  589. // Now we copy the data into the caller's buffer if there's enough room,
  590. // otherwise, we report the error and tell em how much we need.
  591. */
  592. if (SourceBufferLength > InformationBufferLength)
  593. {
  594. *BytesNeeded = SourceBufferLength;
  595. Result = NDIS_STATUS_INVALID_LENGTH;
  596. }
  597. else if (SourceBufferLength)
  598. {
  599. // Don't copy if it's already there.
  600. if (InformationBuffer != SourceBuffer)
  601. {
  602. NdisMoveMemory(InformationBuffer,
  603. SourceBuffer,
  604. SourceBufferLength
  605. );
  606. }
  607. *BytesNeeded = *BytesWritten = SourceBufferLength;
  608. }
  609. else
  610. {
  611. *BytesNeeded = *BytesWritten = 0;
  612. }
  613. DBG_REQUEST(pAdapter,
  614. ("RETURN: Status=0x%X Needed=%d Written=%d\n",
  615. Result, *BytesNeeded, *BytesWritten));
  616. DBG_RETURN(pAdapter, Result);
  617. return (Result);
  618. }
  619. /* @doc INTERNAL Request Request_c MiniportCoSetInformation
  620. @func
  621. <f MiniportCoSetInformation> allows for control of the Miniport by
  622. changing information maintained by the Miniport.
  623. Any of the settable NDIS Global Oids may be used. (see section 7.4 of
  624. the NDIS 3.0 specification for a complete description of the NDIS Oids.)
  625. If the Miniport does not complete the call immediately (by returning
  626. NDIS_STATUS_PENDING), it must call NdisMSetInformationComplete to
  627. complete the call. The Miniport controls the buffers pointed to by
  628. InformationBuffer, BytesRead, and BytesNeeded until the request completes.
  629. <f Note>: Interrupts are in any state during the call, and no other
  630. requests will be submitted to the Miniport until this request is
  631. completed.
  632. @rdesc
  633. <f MiniportCoSetInformation> returns zero if it is successful.<nl>
  634. Otherwise, a non-zero return value indicates an error condition.
  635. */
  636. DBG_STATIC NDIS_STATUS MiniportCoSetInformation(
  637. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  638. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  639. IN PBCHANNEL_OBJECT pBChannel, // @parm
  640. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  641. IN NDIS_OID Oid, // @parm
  642. // The OID. (See section 7.4 of the NDIS 3.0 specification for a complete
  643. // description of OIDs.)
  644. IN PVOID InformationBuffer, // @parm
  645. // Points to a buffer containing the OID-specific data used by
  646. // <f MiniportCoSetInformation> for the set.
  647. // See section 7.4 of the
  648. // NDIS 3.0 specification for a description of the length required for
  649. // each OID.)
  650. IN ULONG InformationBufferLength, // @parm
  651. // Specifies the number of bytes at <p InformationBuffer>.
  652. OUT PULONG BytesRead, // @parm
  653. // Points to a variable that <f MiniportCoSetInformation> sets to the
  654. // number of bytes it read from the buffer at InformationBuffer.
  655. OUT PULONG BytesNeeded // @parm
  656. // Points to a variable that <f MiniportCoSetInformation> sets to the
  657. // number of additional bytes it needs to satisfy the request if
  658. // <p InformationBufferLength> is less than Oid requires.
  659. )
  660. {
  661. DBG_FUNC("MiniportCoSetInformation")
  662. NDIS_STATUS Result;
  663. // Holds the status result returned by this function.
  664. DBG_ENTER(pAdapter);
  665. DBG_REQUEST(pAdapter,
  666. ("(OID=0x%08X %s)\n\t\tInfoLength=%d InfoBuffer=0x%X\n",
  667. Oid, DbgGetOidString(Oid),
  668. InformationBufferLength,
  669. InformationBuffer
  670. ));
  671. /*
  672. // Assume no extra bytes are needed.
  673. */
  674. ASSERT(BytesRead && BytesNeeded);
  675. *BytesRead = 0;
  676. *BytesNeeded = 0;
  677. /*
  678. // Determine which OID is being requested and do the right thing.
  679. */
  680. switch (Oid)
  681. {
  682. case OID_GEN_CURRENT_LOOKAHEAD:
  683. /*
  684. // WAN drivers always indicate the entire packet regardless of the
  685. // lookahead size. So this request should be politely ignored.
  686. */
  687. DBG_NOTICE(pAdapter,("OID_GEN_CURRENT_LOOKAHEAD: set=%d expected=%d\n",
  688. *(PULONG) InformationBuffer, CARD_MAX_LOOKAHEAD));
  689. ASSERT(InformationBufferLength == sizeof(ULONG));
  690. *BytesNeeded = *BytesRead = sizeof(ULONG);
  691. Result = NDIS_STATUS_SUCCESS;
  692. break;
  693. case OID_WAN_CO_SET_LINK_INFO:
  694. if (InformationBufferLength == sizeof(NDIS_WAN_CO_SET_LINK_INFO))
  695. {
  696. /*
  697. // Make sure what I just said is true.
  698. */
  699. if (!IS_VALID_BCHANNEL(pAdapter, pBChannel))
  700. {
  701. Result = NDIS_STATUS_INVALID_DATA;
  702. break;
  703. }
  704. ASSERT(!(pBChannel->WanLinkInfo.SendFramingBits &
  705. ~pAdapter->WanInfo.FramingBits));
  706. ASSERT(!(pBChannel->WanLinkInfo.RecvFramingBits &
  707. ~pAdapter->WanInfo.FramingBits));
  708. /*
  709. // Copy the data into our WanLinkInfo sturcture.
  710. */
  711. NdisMoveMemory(&(pBChannel->WanLinkInfo),
  712. InformationBuffer,
  713. InformationBufferLength
  714. );
  715. *BytesRead = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
  716. Result = NDIS_STATUS_SUCCESS;
  717. if (pBChannel->WanLinkInfo.MaxSendFrameSize !=
  718. pAdapter->WanInfo.MaxFrameSize ||
  719. pBChannel->WanLinkInfo.MaxRecvFrameSize !=
  720. pAdapter->WanInfo.MaxFrameSize)
  721. {
  722. DBG_NOTICE(pAdapter,("Line=%d - "
  723. "SendFrameSize=%08lX - "
  724. "RecvFrameSize=%08lX\n",
  725. pBChannel->ObjectID,
  726. pBChannel->WanLinkInfo.MaxSendFrameSize,
  727. pBChannel->WanLinkInfo.MaxRecvFrameSize));
  728. }
  729. DBG_PARAMS(pAdapter,
  730. ("\n setting expected\n"
  731. "MaxSendFrameSize = %08lX=?=%08lX\n"
  732. "MaxRecvFrameSize = %08lX=?=%08lX\n"
  733. "SendFramingBits = %08lX=?=%08lX\n"
  734. "RecvFramingBits = %08lX=?=%08lX\n"
  735. "SendACCM = %08lX=?=%08lX\n"
  736. "RecvACCM = %08lX=?=%08lX\n",
  737. pBChannel->WanLinkInfo.MaxSendFrameSize,
  738. pAdapter->WanInfo.MaxFrameSize,
  739. pBChannel->WanLinkInfo.MaxRecvFrameSize,
  740. pAdapter->WanInfo.MaxFrameSize,
  741. pBChannel->WanLinkInfo.SendFramingBits,
  742. pAdapter->WanInfo.FramingBits,
  743. pBChannel->WanLinkInfo.RecvFramingBits,
  744. pAdapter->WanInfo.FramingBits,
  745. pBChannel->WanLinkInfo.SendCompressionBits,
  746. 0,
  747. pBChannel->WanLinkInfo.RecvCompressionBits,
  748. 0,
  749. pBChannel->WanLinkInfo.SendACCM,
  750. pAdapter->WanInfo.DesiredACCM,
  751. pBChannel->WanLinkInfo.RecvACCM,
  752. pAdapter->WanInfo.DesiredACCM));
  753. }
  754. else
  755. {
  756. DBG_WARNING(pAdapter, ("OID_WAN_CO_SET_LINK_INFO: Invalid size:%d expected:%d\n",
  757. InformationBufferLength,
  758. sizeof(NDIS_WAN_CO_SET_LINK_INFO)));
  759. Result = NDIS_STATUS_INVALID_LENGTH;
  760. }
  761. *BytesNeeded = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
  762. break;
  763. case OID_PNP_SET_POWER:
  764. // TODO: The sample just returns success for all PM events even though we
  765. // don't really do anything with them.
  766. break;
  767. case OID_GEN_CO_PROTOCOL_OPTIONS:
  768. // TODO: If an intermediate driver slips in below us, we may want to
  769. // handle this OID. Although, it's probably safe to ignore it...
  770. break;
  771. default:
  772. /*
  773. // Unknown OID
  774. */
  775. Result = NDIS_STATUS_INVALID_OID;
  776. DBG_WARNING(pAdapter,("UNSUPPORTED Oid=0x%08x\n", Oid));
  777. break;
  778. }
  779. DBG_REQUEST(pAdapter,
  780. ("RETURN: Status=0x%X Needed=%d Read=%d\n",
  781. Result, *BytesNeeded, *BytesRead));
  782. DBG_RETURN(pAdapter, Result);
  783. return (Result);
  784. }
  785. /* @doc EXTERNAL INTERNAL Request Request_c MiniportCoRequest
  786. @func
  787. <f MiniportCoRequest> is a required function for connection-oriented
  788. miniports. <f MiniportCoRequest> handles a protocol-initiated request
  789. to get or set information from the miniport.
  790. @comm
  791. NDIS calls the <f MiniportCoRequest> function either on its own behalf
  792. or on behalf of a bound protocol driver that called <f NdisCoRequest>.
  793. Miniport drivers should examine the request supplied at <f NdisRequest>
  794. and take the action requested. For more information about the required
  795. and optional OID_GEN_CO_XXX that connection-oriented miniport drivers
  796. must handle, see Part 2.
  797. <f MiniportCoRequest> must be written such that it can be run from IRQL
  798. DISPATCH_LEVEL.
  799. @rdesc
  800. <f MiniportCoRequest> returns zero if it is successful.<nl>
  801. Otherwise, a non-zero return value indicates an error condition.
  802. */
  803. NDIS_STATUS MiniportCoRequest(
  804. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  805. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  806. // Specifies the handle to a miniport-allocated context area in which
  807. // the miniport maintains state information about this instance of the
  808. // adapter. The miniport provided this handle to NDIS by calling
  809. // <f NdisMSetAttributes> or <f NdisMSetAttributesEx> from its
  810. // <f MiniportInitialize> function.
  811. IN PBCHANNEL_OBJECT pBChannel OPTIONAL, // @parm
  812. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  813. // Specifies the handle to a miniport-allocated context area in which the
  814. // miniport maintains its per-VC state. The miniport supplied this handle
  815. // to NDIS from its <f MiniportCoCreateVc> function.
  816. IN OUT PNDIS_REQUEST NdisRequest // @parm
  817. // Points to a <t NDIS_REQUEST> structure that contains both the buffer
  818. // and the request packet for the miniport to handle. Depending on the
  819. // request, the miniport returns requested information in the structure
  820. // provided.
  821. )
  822. {
  823. DBG_FUNC("MiniportCoRequest")
  824. NDIS_STATUS Result;
  825. // Holds the status result returned by this function.
  826. // ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  827. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  828. ASSERT(NdisRequest);
  829. switch (NdisRequest->RequestType)
  830. {
  831. case NdisRequestQueryStatistics:
  832. case NdisRequestQueryInformation:
  833. Result = MiniportCoQueryInformation(
  834. pAdapter,
  835. pBChannel,
  836. NdisRequest->DATA.QUERY_INFORMATION.Oid,
  837. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  838. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
  839. &NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
  840. &NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded
  841. );
  842. break;
  843. case NdisRequestSetInformation:
  844. Result = MiniportCoSetInformation(
  845. pAdapter,
  846. pBChannel,
  847. NdisRequest->DATA.SET_INFORMATION.Oid,
  848. NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
  849. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
  850. &NdisRequest->DATA.SET_INFORMATION.BytesRead,
  851. &NdisRequest->DATA.SET_INFORMATION.BytesNeeded
  852. );
  853. break;
  854. default:
  855. DBG_ERROR(pAdapter,("UNKNOWN RequestType=%d\n",
  856. NdisRequest->RequestType));
  857. Result = NDIS_STATUS_NOT_SUPPORTED;
  858. break;
  859. }
  860. return (Result);
  861. }