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.

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