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.

580 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. oid.c
  5. Abstract:
  6. This source file handles ALL oid requests from the wrapper.
  7. Author:
  8. Ray Patch (raypa) 04/12/94
  9. Environment:
  10. Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
  11. Revision History:
  12. raypa 04/12/94 Created.
  13. --*/
  14. #include "asyncall.h"
  15. //
  16. // New WAN OID supported list.
  17. //
  18. NDIS_OID AsyncGlobalSupportedOids[] = {
  19. OID_GEN_SUPPORTED_LIST,
  20. OID_GEN_MEDIA_SUPPORTED,
  21. OID_GEN_MEDIA_IN_USE,
  22. OID_GEN_MAXIMUM_LOOKAHEAD,
  23. OID_GEN_MAXIMUM_FRAME_SIZE,
  24. OID_GEN_LINK_SPEED,
  25. OID_GEN_TRANSMIT_BUFFER_SPACE,
  26. OID_GEN_RECEIVE_BUFFER_SPACE,
  27. OID_GEN_TRANSMIT_BLOCK_SIZE,
  28. OID_GEN_RECEIVE_BLOCK_SIZE,
  29. OID_GEN_VENDOR_ID,
  30. OID_GEN_VENDOR_DESCRIPTION,
  31. OID_GEN_CURRENT_PACKET_FILTER,
  32. OID_GEN_CURRENT_LOOKAHEAD,
  33. OID_GEN_DRIVER_VERSION,
  34. OID_GEN_MAXIMUM_TOTAL_SIZE,
  35. OID_GEN_MAC_OPTIONS,
  36. OID_WAN_PERMANENT_ADDRESS,
  37. OID_WAN_CURRENT_ADDRESS,
  38. OID_WAN_PROTOCOL_TYPE,
  39. OID_WAN_MEDIUM_SUBTYPE,
  40. OID_WAN_HEADER_FORMAT,
  41. OID_WAN_GET_INFO,
  42. OID_WAN_GET_LINK_INFO,
  43. OID_WAN_GET_COMP_INFO,
  44. OID_WAN_SET_LINK_INFO,
  45. OID_WAN_SET_COMP_INFO,
  46. OID_WAN_GET_STATS_INFO,
  47. OID_GEN_XMIT_OK,
  48. OID_GEN_RCV_OK,
  49. OID_GEN_XMIT_ERROR,
  50. OID_GEN_RCV_ERROR,
  51. OID_GEN_RCV_NO_BUFFER,
  52. OID_PNP_CAPABILITIES,
  53. OID_PNP_SET_POWER,
  54. OID_PNP_QUERY_POWER,
  55. OID_PNP_ENABLE_WAKE_UP
  56. };
  57. //
  58. // Forward references for this source file.
  59. //
  60. NDIS_STATUS
  61. AsyncSetLinkInfo(
  62. IN POID_WORK_ITEM OidWorkItem
  63. );
  64. NDIS_STATUS
  65. MpQueryInfo(
  66. IN NDIS_HANDLE MiniportAdapterContext,
  67. IN NDIS_OID Oid,
  68. IN PVOID InformationBuffer,
  69. IN ULONG InformationBufferLength,
  70. OUT PULONG BytesWritten,
  71. OUT PULONG BytesNeeded
  72. )
  73. /*++
  74. Routine Description:
  75. The MpQueryProtocolInformation process a Query request for
  76. NDIS_OIDs that are specific to a binding about the MAC. Note that
  77. some of the OIDs that are specific to bindings are also queryable
  78. on a global basis. Rather than recreate this code to handle the
  79. global queries, I use a flag to indicate if this is a query for the
  80. global data or the binding specific data.
  81. Arguments:
  82. Adapter - a pointer to the adapter.
  83. Oid - the NDIS_OID to process.
  84. Return Value:
  85. The function value is the status of the operation.
  86. --*/
  87. {
  88. NDIS_MEDIUM Medium = NdisMediumWan;
  89. ULONG GenericULong = 0;
  90. USHORT GenericUShort = 0;
  91. UCHAR GenericArray[] = {' ', 'A', 'S', 'Y', 'N', 0xFF};
  92. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  93. NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  94. PVOID MoveSource;
  95. ULONG MoveBytes;
  96. INT fDoCommonMove = TRUE;
  97. PASYNC_ADAPTER Adapter = MiniportAdapterContext;
  98. ASSERT( sizeof(ULONG) == 4 );
  99. //
  100. // Switch on request type
  101. //
  102. // By default we assume the source and the number of bytes to move
  103. MoveSource = &GenericULong;
  104. MoveBytes = sizeof(GenericULong);
  105. switch ( Oid ) {
  106. case OID_GEN_SUPPORTED_LIST:
  107. MoveSource = AsyncGlobalSupportedOids;
  108. MoveBytes = sizeof(AsyncGlobalSupportedOids);
  109. break;
  110. case OID_GEN_HARDWARE_STATUS:
  111. MoveSource = (PVOID)&HardwareStatus;
  112. MoveBytes = sizeof(HardwareStatus);
  113. break;
  114. case OID_GEN_MEDIA_SUPPORTED:
  115. case OID_GEN_MEDIA_IN_USE:
  116. MoveSource = (PVOID)&Medium;
  117. MoveBytes = sizeof(Medium);
  118. break;
  119. case OID_GEN_MAXIMUM_LOOKAHEAD:
  120. case OID_GEN_CURRENT_LOOKAHEAD:
  121. case OID_GEN_MAXIMUM_FRAME_SIZE:
  122. GenericULong = Adapter->MaxFrameSize;
  123. break;
  124. case OID_GEN_LINK_SPEED:
  125. //
  126. // Who knows what the initial link speed is?
  127. // This should not be called, right?
  128. //
  129. GenericULong = (ULONG)288;
  130. break;
  131. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  132. case OID_GEN_RECEIVE_BUFFER_SPACE:
  133. GenericULong = (ULONG)(Adapter->MaxFrameSize * 2);
  134. break;
  135. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  136. case OID_GEN_RECEIVE_BLOCK_SIZE:
  137. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  138. GenericULong = (ULONG)(Adapter->MaxFrameSize);
  139. break;
  140. case OID_GEN_VENDOR_ID:
  141. GenericULong = 0xFFFFFFFF;
  142. MoveBytes = 3;
  143. break;
  144. case OID_GEN_VENDOR_DESCRIPTION:
  145. MoveSource = (PVOID)"AsyncMac Adapter";
  146. MoveBytes = 16;
  147. break;
  148. case OID_GEN_DRIVER_VERSION:
  149. GenericUShort = 0x0500;
  150. MoveSource = (PVOID)&GenericUShort;
  151. MoveBytes = sizeof(USHORT);
  152. break;
  153. case OID_GEN_MAC_OPTIONS:
  154. GenericULong = (ULONG)(NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
  155. NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
  156. NDIS_MAC_OPTION_FULL_DUPLEX |
  157. NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA);
  158. break;
  159. case OID_WAN_PROTOCOL_TYPE:
  160. DbgTracef(0,("AsyncQueryProtocolInformation: Oid = OID_WAN_PROTOCOL_TYPE.\n"));
  161. break;
  162. case OID_WAN_PERMANENT_ADDRESS:
  163. case OID_WAN_CURRENT_ADDRESS:
  164. MoveSource = (PVOID)GenericArray;
  165. MoveBytes = ETH_LENGTH_OF_ADDRESS;
  166. break;
  167. case OID_WAN_MEDIUM_SUBTYPE:
  168. GenericULong = NdisWanMediumSerial;
  169. break;
  170. case OID_WAN_HEADER_FORMAT:
  171. GenericULong = NdisWanHeaderEthernet;
  172. break;
  173. case OID_WAN_GET_INFO:
  174. DbgTracef(0,("AsyncQueryProtocolInformation: Oid = OID_WAN_GET_INFO.\n"));
  175. MoveSource = &Adapter->WanInfo;
  176. MoveBytes = sizeof(NDIS_WAN_INFO);
  177. break;
  178. case OID_WAN_GET_LINK_INFO:
  179. {
  180. NDIS_WAN_GET_LINK_INFO* pInfo;
  181. PASYNC_INFO AsyncInfo;
  182. DbgTracef(0,("AsyncQueryProtocolInformation: Oid = OID_WAN_GET_LINK_INFO.\n"));
  183. pInfo = (NDIS_WAN_GET_LINK_INFO* )InformationBuffer;
  184. AsyncInfo = (PASYNC_INFO) pInfo->NdisLinkHandle;
  185. MoveSource = &AsyncInfo->GetLinkInfo,
  186. MoveBytes = sizeof(NDIS_WAN_GET_LINK_INFO);
  187. }
  188. break;
  189. case OID_WAN_GET_COMP_INFO:
  190. {
  191. DbgTracef(0,("AsyncQueryProtocolInformation: Oid = OID_WAN_GET_COMP_INFO.\n"));
  192. StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
  193. break;
  194. }
  195. case OID_WAN_GET_STATS_INFO:
  196. {
  197. DbgTracef(0,("AsyncQueryProtocolInformation: Oid = OID_WAN_GET_STATS_INFO\n"));
  198. StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
  199. break;
  200. }
  201. case OID_GEN_XMIT_OK:
  202. case OID_GEN_RCV_OK:
  203. case OID_GEN_XMIT_ERROR:
  204. case OID_GEN_RCV_ERROR:
  205. case OID_GEN_RCV_NO_BUFFER:
  206. break;
  207. case OID_PNP_CAPABILITIES:
  208. case OID_PNP_SET_POWER:
  209. case OID_PNP_QUERY_POWER:
  210. case OID_PNP_ENABLE_WAKE_UP:
  211. break;
  212. default:
  213. StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
  214. break;
  215. }
  216. //
  217. // If were here then we need to move the data into the callers buffer.
  218. //
  219. if ( StatusToReturn == NDIS_STATUS_SUCCESS ) {
  220. if (fDoCommonMove)
  221. {
  222. //
  223. // If there is enough room then we can copy the data and
  224. // return the number of bytes copied, otherwise we must
  225. // fail and return the number of bytes needed.
  226. //
  227. if ( MoveBytes <= InformationBufferLength ) {
  228. ASYNC_MOVE_MEMORY(InformationBuffer, MoveSource, MoveBytes);
  229. *BytesWritten += MoveBytes;
  230. } else {
  231. *BytesNeeded = MoveBytes;
  232. StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
  233. }
  234. }
  235. }
  236. return StatusToReturn;
  237. }
  238. NDIS_STATUS
  239. MpSetInfo(
  240. IN NDIS_HANDLE MiniportAdapterContext,
  241. IN NDIS_OID Oid,
  242. IN PVOID InformationBuffer,
  243. IN ULONG InformationBufferLength,
  244. OUT PULONG BytesRead,
  245. OUT PULONG BytesNeeded
  246. )
  247. /*++
  248. Routine Description:
  249. The AsyncSetInformation is used by AsyncRequest to set information
  250. about the MAC.
  251. Note: Assumes it is called with the lock held. Any calls are made down
  252. to the serial driver from this routine may return pending. If this happens
  253. the completion routine for the call needs to complete this request by
  254. calling NdisMSetInformationComplete.
  255. Arguments:
  256. MiniportAdapterContext - A pointer to the adapter.
  257. Return Value:
  258. The function value is the status of the operation.
  259. --*/
  260. {
  261. NDIS_STATUS StatusToReturn;
  262. PASYNC_ADAPTER Adapter = MiniportAdapterContext;
  263. //
  264. // Initialize locals.
  265. //
  266. StatusToReturn = NDIS_STATUS_SUCCESS;
  267. switch ( Oid ) {
  268. case OID_WAN_SET_LINK_INFO:
  269. {
  270. PASYNC_INFO AsyncInfo;
  271. WORK_QUEUE_ITEM WorkItem;
  272. PNDIS_WAN_SET_LINK_INFO SetLinkInfo;
  273. POID_WORK_ITEM OidWorkItem;
  274. SetLinkInfo = (PNDIS_WAN_SET_LINK_INFO)InformationBuffer;
  275. AsyncInfo = (PASYNC_INFO) SetLinkInfo->NdisLinkHandle;
  276. NdisAcquireSpinLock(&AsyncInfo->Lock);
  277. if (AsyncInfo->PortState != PORT_FRAMING) {
  278. NdisReleaseSpinLock(&AsyncInfo->Lock);
  279. break;
  280. }
  281. OidWorkItem = ExAllocatePoolWithTag(NonPagedPool,
  282. sizeof(OID_WORK_ITEM), ASYNC_WORKITEM_TAG);
  283. if (OidWorkItem == NULL) {
  284. NdisReleaseSpinLock(&AsyncInfo->Lock);
  285. break;
  286. }
  287. AsyncInfo->Flags |= OID_WORK_SCHEDULED;
  288. //
  289. // Cannot issue IRPs at anything but PASSIVE level!
  290. // We must schedule a passive worker to carry this out.
  291. //
  292. DbgTracef(-2,("AsyncSetInformation: Oid = OID_WAN_SET_LINK_INFO\n"));
  293. NdisReleaseSpinLock(&AsyncInfo->Lock);
  294. OidWorkItem->Context = SetLinkInfo;
  295. ExInitializeWorkItem(&OidWorkItem->WorkQueueItem,
  296. AsyncSetLinkInfo, OidWorkItem);
  297. ExQueueWorkItem(&OidWorkItem->WorkQueueItem, DelayedWorkQueue);
  298. StatusToReturn = NDIS_STATUS_PENDING;
  299. break;
  300. }
  301. case OID_WAN_SET_COMP_INFO:
  302. {
  303. DbgTracef(0,("AsyncSetInformation: Oid = OID_WAN_SET_COMP_INFO.\n"));
  304. StatusToReturn = NDIS_STATUS_INVALID_OID;
  305. break;
  306. }
  307. case OID_PNP_CAPABILITIES:
  308. case OID_PNP_SET_POWER:
  309. case OID_PNP_QUERY_POWER:
  310. case OID_PNP_ENABLE_WAKE_UP:
  311. break;
  312. default:
  313. StatusToReturn = NDIS_STATUS_INVALID_OID;
  314. *BytesRead = 0;
  315. *BytesNeeded = 0;
  316. break;
  317. }
  318. if ( StatusToReturn == NDIS_STATUS_SUCCESS ) {
  319. *BytesRead = InformationBufferLength;
  320. *BytesNeeded = 0;
  321. }
  322. return StatusToReturn;
  323. }
  324. NDIS_STATUS
  325. AsyncSetLinkInfo(
  326. IN POID_WORK_ITEM OidWorkItem
  327. )
  328. {
  329. PASYNC_INFO AsyncInfo;
  330. ULONG RecvFramingBits;
  331. NDIS_STATUS Status;
  332. PNDIS_WAN_SET_LINK_INFO SetLinkInfo;
  333. SetLinkInfo = (PNDIS_WAN_SET_LINK_INFO)OidWorkItem->Context;
  334. AsyncInfo = (PASYNC_INFO) SetLinkInfo->NdisLinkHandle;
  335. ExFreePool(OidWorkItem);
  336. do {
  337. //
  338. // If the port is already closed, we bail out.
  339. //
  340. NdisAcquireSpinLock(&AsyncInfo->Lock);
  341. AsyncInfo->Flags &= ~OID_WORK_SCHEDULED;
  342. if (AsyncInfo->PortState != PORT_FRAMING) {
  343. Status = NDIS_STATUS_FAILURE;
  344. NdisReleaseSpinLock(&AsyncInfo->Lock);
  345. break;
  346. }
  347. //
  348. // Save off the current receive framing bits before we copy the
  349. // incoming link information into our local copy.
  350. //
  351. RecvFramingBits = AsyncInfo->SetLinkInfo.RecvFramingBits;
  352. //
  353. // Fill in the NDIS_WAN_SET_LINK_INFO structure.
  354. //
  355. ASYNC_MOVE_MEMORY(&AsyncInfo->SetLinkInfo,
  356. SetLinkInfo,
  357. sizeof(NDIS_WAN_SET_LINK_INFO));
  358. DbgTracef(1,("ASYNC: Framing change to 0x%.8x from 0x%.8x\n",
  359. SetLinkInfo->RecvFramingBits, RecvFramingBits));
  360. //
  361. // If we are in auto-detect and they want auto-detect
  362. // then there is nothing to do!!!
  363. //
  364. if (!(RecvFramingBits | SetLinkInfo->RecvFramingBits)) {
  365. Status = NDIS_STATUS_SUCCESS;
  366. NdisReleaseSpinLock(&AsyncInfo->Lock);
  367. break;
  368. }
  369. if (SetLinkInfo->RecvFramingBits == 0 && AsyncInfo->PortState == PORT_FRAMING) {
  370. //
  371. // ignore the request
  372. //
  373. Status = NDIS_STATUS_SUCCESS;
  374. NdisReleaseSpinLock(&AsyncInfo->Lock);
  375. break;
  376. }
  377. //
  378. // If we are changing from PPP framing to another
  379. // form of PPP framing, or from SLIP framing to
  380. // another form then there is no need to kill the
  381. // current framing.
  382. //
  383. if ((RecvFramingBits & SetLinkInfo->RecvFramingBits & PPP_FRAMING) ||
  384. (RecvFramingBits & SetLinkInfo->RecvFramingBits & SLIP_FRAMING) ) {
  385. DbgTracef(-1,("ASYNC: Framing already set to 0x%.8x - ignoring\n",
  386. SetLinkInfo->RecvFramingBits));
  387. //
  388. // We are framing, start reading.
  389. //
  390. AsyncInfo->PortState = PORT_FRAMING;
  391. Status = NDIS_STATUS_SUCCESS;
  392. NdisReleaseSpinLock(&AsyncInfo->Lock);
  393. break;
  394. }
  395. //
  396. // If we have some sort of framing we must
  397. // kill that framing and wait for it to die down
  398. //
  399. KeInitializeEvent(&AsyncInfo->ClosingEvent,
  400. SynchronizationEvent,
  401. FALSE);
  402. //
  403. // Signal that port is closing.
  404. //
  405. AsyncInfo->PortState = PORT_CLOSING;
  406. NdisReleaseSpinLock(&AsyncInfo->Lock);
  407. //
  408. // Now we must send down an IRP
  409. //
  410. CancelSerialRequests(AsyncInfo);
  411. //
  412. // Synchronize closing with the read irp
  413. //
  414. KeWaitForSingleObject (&AsyncInfo->ClosingEvent,
  415. UserRequest,
  416. KernelMode,
  417. FALSE,
  418. NULL);
  419. AsyncInfo->PortState = PORT_FRAMING;
  420. AsyncStartReads(AsyncInfo);
  421. Status = NDIS_STATUS_SUCCESS;
  422. } while ( 0 );
  423. NdisMSetInformationComplete(AsyncInfo->Adapter->MiniportHandle, Status);
  424. return Status;
  425. }