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.

615 lines
20 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. Request.c
  5. Abstract:
  6. Author:
  7. Tony Bell (TonyBe) June 06, 1995
  8. Environment:
  9. Kernel Mode
  10. Revision History:
  11. TonyBe 06/06/95 Created
  12. --*/
  13. #include "wan.h"
  14. #define __FILE_SIG__ REQUEST_FILESIG
  15. static UINT CoSupportedOids[] =
  16. {
  17. OID_GEN_CO_SUPPORTED_LIST,
  18. OID_GEN_CO_HARDWARE_STATUS,
  19. OID_GEN_CO_MEDIA_SUPPORTED,
  20. OID_GEN_CO_MEDIA_IN_USE,
  21. OID_GEN_MAXIMUM_LOOKAHEAD,
  22. OID_GEN_MAXIMUM_FRAME_SIZE,
  23. OID_GEN_CO_LINK_SPEED,
  24. OID_GEN_TRANSMIT_BUFFER_SPACE,
  25. OID_GEN_RECEIVE_BUFFER_SPACE,
  26. OID_GEN_TRANSMIT_BLOCK_SIZE,
  27. OID_GEN_RECEIVE_BLOCK_SIZE,
  28. OID_GEN_CO_VENDOR_ID,
  29. OID_GEN_CO_VENDOR_DESCRIPTION,
  30. OID_GEN_CURRENT_PACKET_FILTER,
  31. OID_GEN_CURRENT_LOOKAHEAD,
  32. OID_GEN_CO_DRIVER_VERSION,
  33. OID_GEN_MAXIMUM_TOTAL_SIZE,
  34. OID_GEN_CO_PROTOCOL_OPTIONS,
  35. OID_GEN_CO_MAC_OPTIONS,
  36. OID_GEN_CO_MEDIA_CONNECT_STATUS,
  37. OID_GEN_MAXIMUM_SEND_PACKETS,
  38. OID_GEN_CO_VENDOR_DRIVER_VERSION,
  39. OID_GEN_CO_MINIMUM_LINK_SPEED,
  40. OID_802_3_PERMANENT_ADDRESS,
  41. OID_802_3_CURRENT_ADDRESS,
  42. OID_802_3_MULTICAST_LIST,
  43. OID_802_3_MAXIMUM_LIST_SIZE,
  44. OID_WAN_PERMANENT_ADDRESS,
  45. OID_WAN_CURRENT_ADDRESS,
  46. OID_WAN_QUALITY_OF_SERVICE,
  47. OID_WAN_MEDIUM_SUBTYPE,
  48. OID_WAN_PROTOCOL_TYPE,
  49. OID_WAN_HEADER_FORMAT,
  50. OID_WAN_LINE_COUNT,
  51. OID_QOS_ISSLOW_FRAGMENT_SIZE
  52. };
  53. NDIS_STATUS
  54. NdisWanCoOidProc(
  55. IN PMINIPORTCB pMiniportCB,
  56. IN PCM_VCCB CmVcCB OPTIONAL,
  57. IN OUT PNDIS_REQUEST NdisRequest
  58. )
  59. {
  60. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  61. NDIS_MEDIUM MediumType;
  62. ULONG GenericULong = 0, i;
  63. USHORT GenericUShort = 0;
  64. UCHAR GenericArray[6];
  65. PVOID MoveSource = (PVOID)&GenericULong;
  66. ULONG MoveBytes = sizeof(ULONG);
  67. NDIS_HARDWARE_STATUS HardwareStatus;
  68. ULONG Filter = 0, Oid, OidCat;
  69. ULONG InformationBufferLength;
  70. PUCHAR InformationBuffer;
  71. PROTOCOL_INFO ProtocolInfo = {0};
  72. Oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
  73. OidCat = Oid & 0xFF000000;
  74. InformationBufferLength =
  75. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
  76. InformationBuffer =
  77. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
  78. NdisAcquireSpinLock(&pMiniportCB->Lock);
  79. //
  80. // We will break the OID's down into smaller categories
  81. //
  82. switch (OidCat) {
  83. //
  84. // Swith on General Oid's
  85. //
  86. case OID_CO_GEN:
  87. switch (Oid) {
  88. case OID_GEN_CO_SUPPORTED_LIST:
  89. MoveSource = (PVOID)CoSupportedOids;
  90. MoveBytes = sizeof(CoSupportedOids);
  91. break;
  92. case OID_GEN_CO_HARDWARE_STATUS:
  93. HardwareStatus = pMiniportCB->HardwareStatus;
  94. MoveSource = (PVOID)&HardwareStatus;
  95. MoveBytes = sizeof(HardwareStatus);
  96. break;
  97. case OID_GEN_CO_MEDIA_SUPPORTED:
  98. case OID_GEN_CO_MEDIA_IN_USE:
  99. MediumType = pMiniportCB->MediumType;
  100. MoveSource = (PVOID)&MediumType;
  101. MoveBytes = sizeof(MediumType);
  102. break;
  103. case OID_GEN_MAXIMUM_LOOKAHEAD:
  104. case OID_GEN_CURRENT_LOOKAHEAD:
  105. GenericULong = glMRRU;
  106. break;
  107. case OID_GEN_MAXIMUM_FRAME_SIZE:
  108. ProtocolInfo.ProtocolType = pMiniportCB->ProtocolType;
  109. GetProtocolInfo(&ProtocolInfo);
  110. GenericULong =
  111. (ProtocolInfo.MTU == 0) ? glMaxMTU : ProtocolInfo.MTU;
  112. break;
  113. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  114. ProtocolInfo.ProtocolType = pMiniportCB->ProtocolType;
  115. GetProtocolInfo(&ProtocolInfo);
  116. GenericULong =
  117. (ProtocolInfo.MTU == 0) ? glMaxMTU : ProtocolInfo.MTU;
  118. GenericULong += 14;
  119. break;
  120. case OID_GEN_CO_LINK_SPEED:
  121. //
  122. // Who knows what the initial link speed is?
  123. // This should not be called, right?
  124. //
  125. GenericULong = (ULONG)288;
  126. break;
  127. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  128. case OID_GEN_RECEIVE_BUFFER_SPACE:
  129. ProtocolInfo.ProtocolType = pMiniportCB->ProtocolType;
  130. GetProtocolInfo(&ProtocolInfo);
  131. GenericULong =
  132. (ProtocolInfo.MTU == 0) ?
  133. (ULONG)(glMaxMTU * MAX_OUTSTANDING_PACKETS) :
  134. (ULONG)(ProtocolInfo.MTU * MAX_OUTSTANDING_PACKETS);
  135. break;
  136. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  137. ProtocolInfo.ProtocolType = pMiniportCB->ProtocolType;
  138. GetProtocolInfo(&ProtocolInfo);
  139. GenericULong =
  140. (ProtocolInfo.MTU == 0) ? glMaxMTU : ProtocolInfo.MTU;
  141. break;
  142. case OID_GEN_RECEIVE_BLOCK_SIZE:
  143. GenericULong = glMRRU;
  144. break;
  145. case OID_GEN_CO_VENDOR_ID:
  146. GenericULong = 0xFFFFFFFF;
  147. MoveBytes = 3;
  148. break;
  149. case OID_GEN_CO_VENDOR_DESCRIPTION:
  150. MoveSource = (PVOID)"NdisWan Adapter";
  151. MoveBytes = 16;
  152. break;
  153. case OID_GEN_CURRENT_PACKET_FILTER:
  154. if (NdisRequest->RequestType == NdisRequestSetInformation) {
  155. if (InformationBufferLength > 3) {
  156. NdisMoveMemory(&Filter, InformationBuffer, 4);
  157. NdisAcquireSpinLock(&NdisWanCB.Lock);
  158. if (Filter &
  159. (NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_ALL_LOCAL)) {
  160. NdisWanCB.PromiscuousAdapter = pMiniportCB;
  161. } else if (NdisWanCB.PromiscuousAdapter == pMiniportCB) {
  162. NdisWanCB.PromiscuousAdapter = NULL;
  163. }
  164. NdisReleaseSpinLock(&NdisWanCB.Lock);
  165. } else {
  166. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  167. NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  168. NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 4;
  169. }
  170. }
  171. break;
  172. case OID_GEN_CO_DRIVER_VERSION:
  173. GenericUShort = 0x0500;
  174. MoveSource = (PVOID)&GenericUShort;
  175. MoveBytes = sizeof(USHORT);
  176. break;
  177. case OID_GEN_CO_MAC_OPTIONS:
  178. GenericULong = (ULONG)(NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
  179. NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
  180. NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
  181. NDIS_MAC_OPTION_RESERVED |
  182. NDIS_MAC_OPTION_NDISWAN);
  183. break;
  184. case OID_GEN_CO_MEDIA_CONNECT_STATUS:
  185. GenericULong = (ULONG)NdisMediaStateConnected;
  186. break;
  187. case OID_GEN_CO_XMIT_PDUS_OK:
  188. //
  189. //
  190. //
  191. break;
  192. case OID_GEN_CO_RCV_PDUS_OK:
  193. //
  194. //
  195. //
  196. break;
  197. case OID_GEN_CO_XMIT_PDUS_ERROR:
  198. //
  199. //
  200. //
  201. break;
  202. case OID_GEN_CO_RCV_PDUS_ERROR:
  203. //
  204. //
  205. //
  206. break;
  207. case OID_GEN_CO_RCV_PDUS_NO_BUFFER:
  208. //
  209. //
  210. //
  211. break;
  212. case OID_GEN_CO_TRANSMIT_QUEUE_LENGTH:
  213. //
  214. //
  215. //
  216. break;
  217. default:
  218. Status = NDIS_STATUS_INVALID_OID;
  219. break;
  220. }
  221. break;
  222. //
  223. // Switch on ethernet media specific Oid's
  224. //
  225. case OID_802_3:
  226. switch (Oid) {
  227. case OID_802_3_PERMANENT_ADDRESS:
  228. case OID_802_3_CURRENT_ADDRESS:
  229. ETH_COPY_NETWORK_ADDRESS(GenericArray, pMiniportCB->NetworkAddress);
  230. MoveSource = (PVOID)GenericArray;
  231. MoveBytes = ETH_LENGTH_OF_ADDRESS;
  232. break;
  233. case OID_802_3_MULTICAST_LIST:
  234. MoveBytes = 0;
  235. break;
  236. case OID_802_3_MAXIMUM_LIST_SIZE:
  237. GenericULong = 1;
  238. break;
  239. default:
  240. Status = NDIS_STATUS_INVALID_OID;
  241. break;
  242. }
  243. break;
  244. //
  245. // Switch on WAN specific Oid's
  246. //
  247. case OID_WAN:
  248. switch (Oid) {
  249. case OID_WAN_PERMANENT_ADDRESS:
  250. case OID_WAN_CURRENT_ADDRESS:
  251. ETH_COPY_NETWORK_ADDRESS(GenericArray, pMiniportCB->NetworkAddress);
  252. MoveSource = (PVOID)GenericArray;
  253. MoveBytes = ETH_LENGTH_OF_ADDRESS;
  254. break;
  255. case OID_WAN_QUALITY_OF_SERVICE:
  256. GenericULong = NdisWanReliable;
  257. break;
  258. case OID_WAN_MEDIUM_SUBTYPE:
  259. GenericULong = NdisWanMediumHub;
  260. break;
  261. case OID_WAN_PROTOCOL_TYPE:
  262. {
  263. PMINIPORTCB mcb;
  264. BOOLEAN Found = FALSE;
  265. if (InformationBufferLength > 5) {
  266. pMiniportCB->ProtocolType =
  267. (((PUCHAR)InformationBuffer)[4] << 8) |
  268. ((PUCHAR)InformationBuffer)[5];
  269. pMiniportCB->NumberofProtocols++;
  270. MoveBytes = 6;
  271. NdisReleaseSpinLock(&pMiniportCB->Lock);
  272. //
  273. // Walk the miniportcb list and see if this is the only
  274. // instance of this protocol. If it is we need to notify
  275. // user-mode that a new protocol is available.
  276. //
  277. NdisAcquireSpinLock(&MiniportCBList.Lock);
  278. mcb = (PMINIPORTCB)MiniportCBList.List.Flink;
  279. while ((PVOID)mcb != (PVOID)&MiniportCBList.List) {
  280. if (mcb != pMiniportCB) {
  281. if (mcb->ProtocolType ==
  282. pMiniportCB->ProtocolType) {
  283. Found = TRUE;
  284. }
  285. }
  286. mcb = (PMINIPORTCB)mcb->Linkage.Flink;
  287. }
  288. NdisReleaseSpinLock(&MiniportCBList.Lock);
  289. if (Found == FALSE) {
  290. PROTOCOL_INFO pinfo;
  291. NdisZeroMemory(&pinfo, sizeof(pinfo));
  292. pinfo.ProtocolType = pMiniportCB->ProtocolType;
  293. pinfo.Flags = PROTOCOL_BOUND;
  294. SetProtocolInfo(&pinfo);
  295. }
  296. NdisAcquireSpinLock(&pMiniportCB->Lock);
  297. } else {
  298. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  299. NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  300. NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 6;
  301. }
  302. }
  303. break;
  304. case OID_WAN_HEADER_FORMAT:
  305. GenericULong = NdisWanHeaderEthernet;
  306. break;
  307. case OID_WAN_LINE_COUNT:
  308. GenericULong = NdisWanCB.NumberOfLinks;
  309. break;
  310. case OID_WAN_PROTOCOL_CAPS:
  311. do {
  312. PNDIS_WAN_PROTOCOL_CAPS pcaps;
  313. if (InformationBufferLength < sizeof(NDIS_WAN_PROTOCOL_CAPS)) {
  314. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  315. NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  316. NdisRequest->DATA.SET_INFORMATION.BytesNeeded =
  317. sizeof(NDIS_WAN_PROTOCOL_CAPS);
  318. break;
  319. }
  320. pcaps = (PNDIS_WAN_PROTOCOL_CAPS)InformationBuffer;
  321. if (pcaps->Flags & WAN_PROTOCOL_KEEPS_STATS) {
  322. pMiniportCB->Flags |= PROTOCOL_KEEPS_STATS;
  323. }
  324. MoveBytes = sizeof(NDIS_WAN_PROTOCOL_CAPS);
  325. } while (FALSE);
  326. break;
  327. default:
  328. Status = NDIS_STATUS_INVALID_OID;
  329. break;
  330. }
  331. break;
  332. case OID_PNP:
  333. switch (Oid) {
  334. case OID_PNP_CAPABILITIES:
  335. break;
  336. case OID_PNP_SET_POWER:
  337. break;
  338. case OID_PNP_QUERY_POWER:
  339. break;
  340. case OID_PNP_ENABLE_WAKE_UP:
  341. break;
  342. default:
  343. Status = NDIS_STATUS_INVALID_OID;
  344. break;
  345. }
  346. break;
  347. case OID_QOS:
  348. switch (Oid) {
  349. case OID_QOS_ISSLOW_FRAGMENT_SIZE:
  350. do {
  351. PBUNDLECB BundleCB;
  352. PSEND_FRAG_INFO FragInfo;
  353. if (InformationBufferLength < 4) {
  354. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  355. NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  356. NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 4;
  357. break;
  358. }
  359. if (((PLONG)InformationBuffer)[0] < 0) {
  360. Status = NDIS_STATUS_INVALID_DATA;
  361. NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  362. NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 4;
  363. break;
  364. }
  365. if (((PULONG)InformationBuffer)[0] == 0) {
  366. Status = NDIS_STATUS_INVALID_DATA;
  367. NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  368. NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 4;
  369. break;
  370. }
  371. if (CmVcCB == NULL) {
  372. if (((PULONG)InformationBuffer)[0] < glMaxFragSize) {
  373. glMaxFragSize = ((PULONG)InformationBuffer)[0];
  374. }
  375. if (glMaxFragSize < glMinFragSize) {
  376. glMinFragSize = glMaxFragSize;
  377. }
  378. } else {
  379. BundleCB = CmVcCB->ProtocolCB->BundleCB;
  380. AcquireBundleLock(BundleCB);
  381. FragInfo = &BundleCB->SendFragInfo[0];
  382. if (((PULONG)InformationBuffer)[0] < FragInfo->MaxFragSize) {
  383. FragInfo->MaxFragSize =
  384. ((PULONG)InformationBuffer)[0];
  385. }
  386. if (FragInfo->MaxFragSize < glMinFragSize) {
  387. FragInfo->MaxFragSize = glMinFragSize;
  388. }
  389. if (FragInfo->MaxFragSize > glMaxFragSize) {
  390. FragInfo->MaxFragSize = glMaxFragSize;
  391. }
  392. ReleaseBundleLock(BundleCB);
  393. }
  394. MoveBytes = 4;
  395. } while (FALSE);
  396. break;
  397. default:
  398. Status = NDIS_STATUS_INVALID_OID;
  399. break;
  400. }
  401. break;
  402. default:
  403. Status = NDIS_STATUS_INVALID_OID;
  404. break;
  405. }
  406. if (Status == NDIS_STATUS_SUCCESS) {
  407. if (NdisRequest->RequestType == NdisRequestSetInformation) {
  408. NdisRequest->DATA.SET_INFORMATION.BytesRead = MoveBytes;
  409. } else if (NdisRequest->RequestType == NdisRequestQueryInformation ||
  410. NdisRequest->RequestType == NdisRequestQueryStatistics) {
  411. if (MoveBytes > InformationBufferLength) {
  412. //
  413. // Not enough room in the information buffer
  414. //
  415. NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded =
  416. MoveBytes;
  417. Status = NDIS_STATUS_INVALID_LENGTH;
  418. } else {
  419. NdisRequest->DATA.QUERY_INFORMATION.BytesWritten =
  420. MoveBytes;
  421. NdisMoveMemory(InformationBuffer,
  422. MoveSource,
  423. MoveBytes);
  424. }
  425. } else {
  426. Status = NDIS_STATUS_INVALID_OID;
  427. }
  428. }
  429. NdisReleaseSpinLock(&pMiniportCB->Lock);
  430. return (Status);
  431. }
  432. NDIS_STATUS
  433. NdisWanSubmitNdisRequest(
  434. IN POPENCB pOpenCB,
  435. IN PWAN_REQUEST WanRequest
  436. )
  437. /*++
  438. Routine Name:
  439. Routine Description:
  440. Arguments:
  441. Return Values:
  442. --*/
  443. {
  444. NDIS_STATUS Status;
  445. BOOLEAN SyncRequest;
  446. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("SubmitNdisRequest: Enter - WanRequest %p", WanRequest));
  447. NdisAcquireSpinLock(&pOpenCB->Lock);
  448. if (pOpenCB->Flags & OPEN_CLOSING) {
  449. NdisReleaseSpinLock(&pOpenCB->Lock);
  450. return (NDIS_STATUS_FAILURE);
  451. }
  452. REF_OPENCB(pOpenCB);
  453. NdisReleaseSpinLock(&pOpenCB->Lock);
  454. SyncRequest = (WanRequest->Type == SYNC);
  455. if (pOpenCB->Flags & OPEN_LEGACY ||
  456. WanRequest->VcHandle == NULL) {
  457. NdisRequest(&Status,
  458. pOpenCB->BindingHandle,
  459. &WanRequest->NdisRequest);
  460. } else {
  461. Status =
  462. NdisCoRequest(pOpenCB->BindingHandle,
  463. WanRequest->AfHandle,
  464. WanRequest->VcHandle,
  465. NULL,
  466. &WanRequest->NdisRequest);
  467. }
  468. //
  469. // We will only wait for request that are to complete
  470. // synchronously with respect to this function. We will
  471. // wait here for completion.
  472. //
  473. if ((SyncRequest == TRUE) &&
  474. (Status == NDIS_STATUS_PENDING)) {
  475. NdisWanWaitForNotificationEvent(&WanRequest->NotificationEvent);
  476. Status = WanRequest->NotificationStatus;
  477. NdisWanClearNotificationEvent(&WanRequest->NotificationEvent);
  478. }
  479. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST,
  480. ("SubmitNdisRequest: Exit Status 0x%x", Status));
  481. DEREF_OPENCB(pOpenCB);
  482. return (Status);
  483. }