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.

2082 lines
65 KiB

  1. // Copyright (c) 1997, Microsoft Corporation, all rights reserved
  2. // Copyright (c) 1997, Parallel Technologies, Inc., all rights reserved
  3. //
  4. // mp.c
  5. // RAS DirectParallel WAN mini-port/call-manager driver
  6. // Mini-port routines
  7. //
  8. // 01/07/97 Steve Cobb
  9. // 09/15/97 Jay Lowe, Parallel Technologies, Inc.
  10. #include "ptiwan.h"
  11. #include "ptilink.h"
  12. // The adapter control block address is recorded in this global as a debugging
  13. // aid. This global must not be read by any code.
  14. //
  15. ADAPTERCB* g_pDebugAdapter;
  16. // Default settings for the NDIS_WAN_CO_INFO capabilities of an adapter.
  17. //
  18. static NDIS_WAN_CO_INFO g_infoDefaults =
  19. {
  20. PTI_MaxFrameSize, // MaxFrameSize
  21. 1, // MaxSendWindow (placeholder)
  22. PPP_FRAMING // FramingBits
  23. | PPP_COMPRESS_ADDRESS_CONTROL
  24. | PPP_COMPRESS_PROTOCOL_FIELD,
  25. 0, // DesiredACCM
  26. };
  27. // String constants for Win9x UNIMODEM emulation
  28. //
  29. CHAR g_szClient[] = "CLIENT";
  30. #define CLIENTLEN 6
  31. CHAR g_szClientServer[] = "CLIENTSERVER";
  32. #define CLIENTSERVERLEN 12
  33. // Async framing definitions.
  34. //
  35. #define PPPFLAGBYTE 0x7E
  36. #define PPPESCBYTE 0x7D
  37. #if DBG
  38. BOOLEAN g_fAssumeWin9x = FALSE;
  39. BOOLEAN g_fNoAccmFastPath = FALSE;
  40. #endif
  41. NDIS_PNP_CAPABILITIES PnpCaps =
  42. {
  43. 0, // Flags
  44. {
  45. NdisDeviceStateUnspecified,
  46. NdisDeviceStateUnspecified,
  47. NdisDeviceStateUnspecified
  48. }
  49. };
  50. //-----------------------------------------------------------------------------
  51. // Local prototypes (alphabetically)
  52. //-----------------------------------------------------------------------------
  53. VOID
  54. AsyncFromHdlcFraming(
  55. IN UCHAR* pInBuf,
  56. IN ULONG ulInBufLen,
  57. OUT UCHAR* pOutBuf,
  58. OUT ULONG* pulOutBufLen,
  59. IN ULONG ulAccmMask );
  60. USHORT
  61. CalculatePppFcs(
  62. IN UCHAR* pBuf,
  63. IN ULONG ulBufLen );
  64. VOID
  65. FreeAdapter(
  66. IN ADAPTERCB* pAdapter );
  67. NDIS_STATUS
  68. RegistrySettings(
  69. IN OUT ADAPTERCB* pAdapter,
  70. IN NDIS_HANDLE WrapperConfigurationContext );
  71. BOOLEAN
  72. HdlcFromAsyncFraming(
  73. IN UCHAR* pInBuf,
  74. IN ULONG ulInBufLen,
  75. OUT UCHAR* pOutBuf,
  76. OUT ULONG* pulOutBufLen );
  77. NDIS_STATUS
  78. QueryInformation(
  79. IN ADAPTERCB* pAdapter,
  80. IN VCCB* pLink,
  81. IN NDIS_OID Oid,
  82. IN PVOID InformationBuffer,
  83. IN ULONG InformationBufferLength,
  84. OUT PULONG BytesWritten,
  85. OUT PULONG BytesNeeded );
  86. NDIS_STATUS
  87. SetInformation(
  88. IN ADAPTERCB* pAdapter,
  89. IN VCCB* pLink,
  90. IN NDIS_OID Oid,
  91. IN PVOID InformationBuffer,
  92. IN ULONG InformationBufferLength,
  93. OUT PULONG BytesRead,
  94. OUT PULONG BytesNeeded );
  95. //-----------------------------------------------------------------------------
  96. // Mini-port handlers
  97. //-----------------------------------------------------------------------------
  98. NDIS_STATUS
  99. PtiInit(
  100. OUT PNDIS_STATUS OpenErrorStatus,
  101. OUT PUINT SelectedMediumIndex,
  102. IN PNDIS_MEDIUM MediumArray,
  103. IN UINT MediumArraySize,
  104. IN NDIS_HANDLE MiniportAdapterHandle,
  105. IN NDIS_HANDLE WrapperConfigurationContext )
  106. // Standard 'MiniportInitialize' routine called by NDIS to initialize a
  107. // new WAN adapter. See DDK doc. The driver will receive no requests
  108. // until this initialization has completed.
  109. //
  110. {
  111. NDIS_STATUS status;
  112. ADAPTERCB* pAdapter;
  113. TRACE( TL_N, TM_Init, ( "PtiInit" ) );
  114. #ifdef TESTMODE
  115. DbgBreakPoint();
  116. #endif
  117. status = *OpenErrorStatus = NDIS_STATUS_SUCCESS;
  118. // Find the medium index in the array of media, looking for the only one
  119. // we support, 'NdisMediumCoWan'.
  120. //
  121. {
  122. UINT i;
  123. for (i = 0; i < MediumArraySize; ++i)
  124. {
  125. if (MediumArray[ i ] == NdisMediumCoWan)
  126. {
  127. break;
  128. }
  129. }
  130. if (i >= MediumArraySize)
  131. {
  132. TRACE( TL_A, TM_Init, ( "medium?" ) );
  133. return NDIS_STATUS_FAILURE;
  134. }
  135. *SelectedMediumIndex = i;
  136. }
  137. // Allocate and zero a control block for the new adapter.
  138. //
  139. pAdapter = ALLOC_NONPAGED( sizeof(*pAdapter), MTAG_ADAPTERCB );
  140. TRACE( TL_N, TM_Init, ( "PtiInit: pAdapter=$%p", pAdapter ) );
  141. if (!pAdapter)
  142. {
  143. return NDIS_STATUS_RESOURCES;
  144. }
  145. NdisZeroMemory( pAdapter, sizeof(*pAdapter) );
  146. // The adapter control block address is recorded in 'g_pDebugAdapter' as a
  147. // debugging aid only. This global is not to be read by any code.
  148. //
  149. g_pDebugAdapter = pAdapter;
  150. // Set a marker for easier memory dump browsing and future assertions.
  151. //
  152. pAdapter->ulTag = MTAG_ADAPTERCB;
  153. // Save the NDIS handle associated with this adapter for use in future
  154. // NdixXxx calls.
  155. //
  156. pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
  157. // Copy defaults NDISWAN information. Some of these are updated below.
  158. //
  159. NdisMoveMemory( &pAdapter->info, &g_infoDefaults, sizeof(pAdapter->info) );
  160. do
  161. {
  162. // Read/write this adapter's registry settings.
  163. //
  164. status = RegistrySettings(
  165. pAdapter,
  166. WrapperConfigurationContext );
  167. if (status != NDIS_STATUS_SUCCESS)
  168. {
  169. // Set 'usMaxVcs' to 0 as an indication to FreeAdapter that the
  170. // lookaside lists and pools were not initialized.
  171. //
  172. pAdapter->usMaxVcs = 0;
  173. break;
  174. }
  175. // Initialize lookaside lists, buffer pools, and packet pool. On NT,
  176. // lookaside depths are optimized by the system based on usage
  177. // regardless of the depth set, but choose something reasonable
  178. // anyway.
  179. //
  180. {
  181. NdisInitializeNPagedLookasideList(
  182. &pAdapter->llistWorkItems,
  183. NULL, NULL, 0,
  184. sizeof(NDIS_WORK_ITEM),
  185. MTAG_WORKITEM,
  186. 4 );
  187. NdisInitializeNPagedLookasideList(
  188. &pAdapter->llistVcs,
  189. NULL, NULL, 0,
  190. sizeof(VCCB),
  191. MTAG_VCCB,
  192. 4 );
  193. InitBufferPool(
  194. &pAdapter->poolFrameBuffers,
  195. PTI_FrameBufferSize,
  196. 0, 10, 0,
  197. TRUE, MTAG_FBUFPOOL );
  198. InitPacketPool(
  199. &pAdapter->poolPackets,
  200. 0, 0, 10, 0,
  201. MTAG_PACKETPOOL );
  202. }
  203. // Inform NDIS of the attributes of our adapter. Set the
  204. // 'MiniportAdapterContext' returned to us by NDIS when it calls our
  205. // handlers to the address of our adapter control block. Turn off
  206. // hardware oriented timeouts.
  207. //
  208. NdisMSetAttributesEx(
  209. MiniportAdapterHandle,
  210. (NDIS_HANDLE)pAdapter,
  211. (UINT)-1,
  212. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
  213. | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT,
  214. NdisInterfaceInternal );
  215. // Register the address family of our call manager with NDIS for the
  216. // newly bound adapter. We use the mini-port form of
  217. // RegisterAddressFamily instead of the protocol form, though that
  218. // would also work. With the protocol form, our internal call manager
  219. // would have to go thru NDIS to talk to the mini-port instead of just
  220. // calling directly. Since the DirectParallel call manager is not
  221. // useful with anything but the DirectParallel mini-port, this would be a waste.
  222. // The mini-port form also causes the call manager VC context to
  223. // automatically map to the mini-port VC context, which is exactly
  224. // what we want.
  225. //
  226. // NDIS notifies all call manager clients of the new family we
  227. // register. The TAPI proxy is the only client expected to be
  228. // interested. NDISWAN will receive the notification, but ignore it
  229. // and wait for the TAPI proxy to notify it of the proxied version.
  230. //
  231. {
  232. NDIS_CALL_MANAGER_CHARACTERISTICS ncmc;
  233. CO_ADDRESS_FAMILY family;
  234. NdisZeroMemory( &family, sizeof(family) );
  235. family.MajorVersion = NDIS_MajorVersion;
  236. family.MinorVersion = NDIS_MinorVersion;
  237. family.AddressFamily = CO_ADDRESS_FAMILY_TAPI_PROXY;
  238. NdisZeroMemory( &ncmc, sizeof(ncmc) );
  239. ncmc.MajorVersion = NDIS_MajorVersion;
  240. ncmc.MinorVersion = NDIS_MinorVersion;
  241. ncmc.CmCreateVcHandler = PtiCmCreateVc;
  242. ncmc.CmDeleteVcHandler = PtiCmDeleteVc;
  243. ncmc.CmOpenAfHandler = PtiCmOpenAf;
  244. ncmc.CmCloseAfHandler = PtiCmCloseAf;
  245. ncmc.CmRegisterSapHandler = PtiCmRegisterSap;
  246. ncmc.CmDeregisterSapHandler = PtiCmDeregisterSap;
  247. ncmc.CmMakeCallHandler = PtiCmMakeCall;
  248. ncmc.CmCloseCallHandler = PtiCmCloseCall;
  249. ncmc.CmIncomingCallCompleteHandler = PtiCmIncomingCallComplete;
  250. // no CmAddPartyHandler
  251. // no CmDropPartyHandler
  252. ncmc.CmActivateVcCompleteHandler = PtiCmActivateVcComplete;
  253. ncmc.CmDeactivateVcCompleteHandler = PtiCmDeactivateVcComplete;
  254. ncmc.CmModifyCallQoSHandler = PtiCmModifyCallQoS;
  255. ncmc.CmRequestHandler = PtiCmRequest;
  256. TRACE( TL_I, TM_Mp, ( "PtiInit: NdisMCmRegAf" ) );
  257. status = NdisMCmRegisterAddressFamily(
  258. MiniportAdapterHandle, &family, &ncmc, sizeof(ncmc) );
  259. TRACE( TL_I, TM_Mp, ( "PtiInit: NdisMCmRegAf=$%x", status ) );
  260. }
  261. }
  262. while (FALSE);
  263. if (status == NDIS_STATUS_SUCCESS)
  264. {
  265. // Add a reference that will eventually be removed by an NDIS call to
  266. // the LmpHalt handler.
  267. //
  268. ReferenceAdapter( pAdapter );
  269. }
  270. else
  271. {
  272. // Failed, so undo whatever portion succeeded.
  273. //
  274. if (pAdapter)
  275. {
  276. FreeAdapter( pAdapter );
  277. }
  278. }
  279. TRACE( TL_V, TM_Init, ( "PtiInit: Exit: status=$%x", status ) );
  280. return status;
  281. }
  282. VOID
  283. PtiHalt(
  284. IN NDIS_HANDLE MiniportAdapterContext )
  285. // Standard 'MiniportHalt' routine called by NDIS to deallocate all
  286. // resources attached to the adapter. NDIS does not make any other calls
  287. // for this mini-port adapter during or after this call. NDIS will not
  288. // call this routine when packets indicated as received have not been
  289. // returned, or when any VC is created and known to NDIS. Runs at PASSIVE
  290. // IRQL.
  291. //
  292. {
  293. ADAPTERCB* pAdapter;
  294. TRACE( TL_N, TM_Mp, ( "PtiHalt" ) );
  295. pAdapter = (ADAPTERCB* )MiniportAdapterContext;
  296. if (pAdapter->ulTag != MTAG_ADAPTERCB)
  297. {
  298. ASSERT( !"Atag?" );
  299. return;
  300. }
  301. DereferenceAdapter( pAdapter );
  302. TRACE( TL_V, TM_Mp, ( "PtiHalt: Exit" ) );
  303. }
  304. NDIS_STATUS
  305. PtiReset(
  306. OUT PBOOLEAN AddressingReset,
  307. IN NDIS_HANDLE MiniportAdapterContext )
  308. // Standard 'MiniportReset' routine called by NDIS to reset the driver's
  309. // software state.
  310. //
  311. {
  312. TRACE( TL_N, TM_Mp, ( "PtiReset" ) );
  313. return NDIS_STATUS_NOT_RESETTABLE;
  314. }
  315. VOID
  316. PtiReturnPacket(
  317. IN NDIS_HANDLE MiniportAdapterContext,
  318. IN PNDIS_PACKET Packet )
  319. // Standard 'MiniportReturnPacket' routine called by NDIS when a packet
  320. // used to indicate a receive has been released by the driver above.
  321. //
  322. {
  323. VCCB* pVc;
  324. CHAR* pBuffer;
  325. ADAPTERCB* pAdapter;
  326. NDIS_BUFFER* pTrimmedBuffer;
  327. PACKETHEAD* pHead;
  328. PACKETPOOL* pPool;
  329. TRACE( TL_V, TM_Recv, ( "PtiReturnPacket" ) );
  330. // Unpack the context information we stashed earlier.
  331. //
  332. pHead = *((PACKETHEAD** )(&Packet->MiniportReserved[ 0 ]));
  333. pBuffer = *((CHAR** )(&Packet->MiniportReserved[ sizeof(VOID*) ]));
  334. // Find the adapter from the PACKETHEAD address.
  335. //
  336. pPool = PacketPoolFromPacketHead( pHead );
  337. pAdapter = CONTAINING_RECORD( pPool, ADAPTERCB, poolPackets );
  338. ASSERT( pAdapter->ulTag == MTAG_ADAPTERCB );
  339. // Free the descriptor created by NdisCopyBuffer.
  340. //
  341. NdisUnchainBufferAtFront( Packet, &pTrimmedBuffer );
  342. if (pTrimmedBuffer)
  343. {
  344. NdisFreeBuffer( pTrimmedBuffer );
  345. }
  346. // Free the buffer and packet back to the pools.
  347. //
  348. FreeBufferToPool( &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  349. FreePacketToPool( &pAdapter->poolPackets, pHead, TRUE );
  350. TRACE( TL_V, TM_Recv, ( "PtiReturnPacket: Exit" ) );
  351. }
  352. NDIS_STATUS
  353. PtiCoActivateVc(
  354. IN NDIS_HANDLE MiniportVcContext,
  355. IN OUT PCO_CALL_PARAMETERS CallParameters )
  356. // Standard 'MiniportCoActivateVc' routine called by NDIS in response to a
  357. // protocol's request to activate a virtual circuit.
  358. //
  359. {
  360. ASSERT( !"PtiCoActVc?" );
  361. return NDIS_STATUS_SUCCESS;
  362. }
  363. NDIS_STATUS
  364. PtiCoDeactivateVc(
  365. IN NDIS_HANDLE MiniportVcContext )
  366. // Standard 'MiniportCoDeactivateVc' routine called by NDIS in response to
  367. // a protocol's request to de-activate a virtual circuit.
  368. //
  369. {
  370. ASSERT( !"PtiCoDeactVc?" );
  371. return NDIS_STATUS_SUCCESS;
  372. }
  373. VOID
  374. PtiCoSendPackets(
  375. IN NDIS_HANDLE MiniportVcContext,
  376. IN PPNDIS_PACKET PacketArray,
  377. IN UINT NumberOfPackets )
  378. // Standard 'MiniportCoSendPackets' routine called by NDIS in response to
  379. // a protocol's request to send packets on a virtual circuit.
  380. //
  381. {
  382. UINT i;
  383. NDIS_STATUS status;
  384. NDIS_PACKET** ppPacket;
  385. VCCB* pVc;
  386. ADAPTERCB* pAdapter;
  387. ULONG ulLength;
  388. PNDIS_BUFFER pBuffer;
  389. PVOID pFrameVirtualAddress;
  390. KIRQL oldIrql;
  391. TRACE( TL_V, TM_Send,
  392. ( "PtiCoSendPackets: pVc=$%p, nPackets=$%x",
  393. MiniportVcContext, NumberOfPackets ) );
  394. pVc = (VCCB* )MiniportVcContext;
  395. ASSERT( pVc->ulTag == MTAG_VCCB );
  396. pAdapter = pVc->pAdapter;
  397. ReferenceVc( pVc );
  398. for (i = 0, ppPacket = PacketArray;
  399. i < NumberOfPackets;
  400. ++i, ++ppPacket)
  401. {
  402. NDIS_PACKET* pPacket = *ppPacket;
  403. if (ReferenceCall( pVc ))
  404. {
  405. // Send the packet and call NdisMCoSendComplete to notify caller
  406. //
  407. NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_PENDING );
  408. // Request the first buffer descriptor
  409. //
  410. NdisQueryPacket( pPacket, NULL, NULL, &pBuffer, NULL );
  411. // While pBuffer <> NULL
  412. do
  413. {
  414. UCHAR* pAsyncBuf;
  415. ULONG ulAsyncLen;
  416. // request buffer address and length
  417. //
  418. NdisQueryBuffer( pBuffer,
  419. &pFrameVirtualAddress,
  420. &ulLength );
  421. if (IsWin9xPeer( pVc ))
  422. {
  423. pAsyncBuf = (UCHAR* )
  424. GetBufferFromPool( &pAdapter->poolFrameBuffers );
  425. if (!pAsyncBuf)
  426. {
  427. status = NDIS_STATUS_FAILURE;
  428. TRACE( TL_A, TM_Send, ( "PtiSP: !pAsyncBuf" ) );
  429. break;
  430. }
  431. AsyncFromHdlcFraming(
  432. pFrameVirtualAddress, ulLength,
  433. pAsyncBuf, &ulAsyncLen,
  434. pVc->linkinfo.SendACCM );
  435. pFrameVirtualAddress = pAsyncBuf;
  436. ulLength = ulAsyncLen;
  437. }
  438. else
  439. {
  440. pAsyncBuf = NULL;
  441. }
  442. // send the buffer
  443. //
  444. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
  445. status = (NDIS_STATUS) PtiWrite( pVc->PtiExtension,
  446. pFrameVirtualAddress,
  447. ulLength,
  448. PID_STANDARD );
  449. KeLowerIrql(oldIrql);
  450. TRACE( TL_N, TM_Send,
  451. ( "PtiCoSendPackets=%x: $%x bytes", status, ulLength ) );
  452. #ifdef TESTMODE
  453. if ( g_ulTraceMask & TM_Data )
  454. {
  455. if (pFrameVirtualAddress != NULL) {
  456. Dump( pFrameVirtualAddress, ulLength, 0, TRUE );
  457. }
  458. }
  459. #endif
  460. if (pAsyncBuf)
  461. {
  462. FreeBufferToPool(
  463. &pAdapter->poolFrameBuffers, pAsyncBuf, TRUE );
  464. }
  465. if (!NT_SUCCESS(status)){
  466. break;
  467. }
  468. // get next pBuffer
  469. //
  470. NdisGetNextBuffer( pBuffer, &pBuffer );
  471. // With current NDISWAN behavior only one NDIS_BUFFER will
  472. // ever be received. If multiples are received, we need to
  473. // coalesce the chained buffers into an input buffer for the
  474. // call to AsyncFromHdlcFraming above. For that matter, this
  475. // would send partial PPP frames, which, it seems to me, would
  476. // be discarded as fragments on the other end. Tony, am I
  477. // wrong? To avoid a useless copy, we will skip that for now,
  478. // but acknowledge here that the current code is not strictly
  479. // correct. (SLC)
  480. //
  481. ASSERT( !pBuffer );
  482. }
  483. while ( pBuffer != NULL );
  484. NDIS_SET_PACKET_STATUS( pPacket, status );
  485. TRACE( TL_V, TM_Send,
  486. ( "PtiCoSendPackets: NdisMCoSendComp: status=$%x", status ) );
  487. NdisMCoSendComplete( status, pVc->NdisVcHandle, pPacket );
  488. TRACE( TL_V, TM_Send,
  489. ( "PtiCoSendPackets: NdisMCoSendComp done" ) );
  490. pVc->ulTotalPackets++;
  491. DereferenceCall( pVc );
  492. }
  493. else
  494. {
  495. TRACE( TL_A, TM_Send, ( "Send to inactive call ignored" ) );
  496. NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_FAILURE );
  497. NdisMCoSendComplete( status, pVc->NdisVcHandle, pPacket );
  498. }
  499. }
  500. DereferenceVc( pVc );
  501. TRACE( TL_V, TM_Send, ( "PtiCoSendPackets: Exit" ) );
  502. }
  503. NDIS_STATUS
  504. PtiCoRequest(
  505. IN NDIS_HANDLE MiniportAdapterContext,
  506. IN NDIS_HANDLE MiniportVcContext,
  507. IN OUT PNDIS_REQUEST NdisRequest )
  508. // Standard 'MiniportCoRequestHandler' routine called by NDIS in response
  509. // to a protocol's request information from the mini-port. Unlike the
  510. // Query/SetInformation handlers that this routine obsoletes, requests are
  511. // not serialized.
  512. //
  513. {
  514. ADAPTERCB* pAdapter;
  515. VCCB* pVc;
  516. NDIS_STATUS status;
  517. TRACE( TL_N, TM_Mp, ( "PtiCoReq" ) );
  518. pAdapter = (ADAPTERCB* )MiniportAdapterContext;
  519. if (pAdapter->ulTag != MTAG_ADAPTERCB)
  520. {
  521. ASSERT( !"Atag?" );
  522. return NDIS_STATUS_INVALID_DATA;
  523. }
  524. pVc = (VCCB* )MiniportVcContext;
  525. if (pVc && pVc->ulTag != MTAG_VCCB)
  526. {
  527. ASSERT( !"Vtag?" );
  528. return NDIS_STATUS_INVALID_DATA;
  529. }
  530. switch (NdisRequest->RequestType)
  531. {
  532. case NdisRequestQueryInformation:
  533. {
  534. status = QueryInformation(
  535. pAdapter,
  536. pVc,
  537. NdisRequest->DATA.QUERY_INFORMATION.Oid,
  538. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  539. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
  540. &NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
  541. &NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded );
  542. break;
  543. }
  544. case NdisRequestSetInformation:
  545. {
  546. status = SetInformation(
  547. pAdapter,
  548. pVc,
  549. NdisRequest->DATA.SET_INFORMATION.Oid,
  550. NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
  551. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
  552. &NdisRequest->DATA.SET_INFORMATION.BytesRead,
  553. &NdisRequest->DATA.SET_INFORMATION.BytesNeeded );
  554. break;
  555. }
  556. default:
  557. {
  558. status = NDIS_STATUS_NOT_SUPPORTED;
  559. TRACE( TL_A, TM_Mp, ( "PtiCoReq: type=%d unsupported", NdisRequest->RequestType ) );
  560. break;
  561. }
  562. }
  563. TRACE( TL_V, TM_Mp, ( "PtiCoReq: Exit: $%x", status ) );
  564. return status;
  565. }
  566. //-----------------------------------------------------------------------------
  567. // Callback routines ... called by the PtiLink layer below
  568. //-----------------------------------------------------------------------------
  569. PVOID
  570. PtiCbGetReadBuffer(
  571. IN PVOID Context,
  572. OUT PULONG BufferSize,
  573. OUT PVOID* RequestContext )
  574. // PtiLink is requesting a read buffer, get one and return it
  575. // This is a the start of a receive event ...
  576. {
  577. VCCB* pVc;
  578. ADAPTERCB* pAdapter;
  579. PCHAR pBuffer;
  580. TRACE( TL_V, TM_Spec, ( "PtiCbGetReadBuffer: pVc=$%p", Context ) );
  581. pVc = (VCCB* )Context;
  582. if (pVc->ulTag != MTAG_VCCB)
  583. {
  584. ASSERT( !"Vtag?" );
  585. return NULL;
  586. }
  587. pAdapter = pVc->pAdapter;
  588. // the pVc is our context for use of this buffer
  589. //
  590. *RequestContext = pVc;
  591. // Give caller the length of this buffer
  592. //
  593. *BufferSize = PTI_FrameBufferSize;
  594. // ask for a buffer, caller must check for NULL
  595. //
  596. pBuffer = GetBufferFromPool( &pAdapter->poolFrameBuffers );
  597. TRACE( TL_V, TM_Spec,
  598. ( "PtiCbGetReadBuffer: Exit: Issuing pBuffer=$%p", pBuffer ) );
  599. // return the buffer to the caller
  600. // this is a raw system va
  601. //
  602. return pBuffer;
  603. }
  604. VOID
  605. PtiRx(
  606. IN PVOID Context,
  607. IN PVOID pBuffer,
  608. IN NTSTATUS Status,
  609. IN ULONG ulLength,
  610. IN PVOID RequestContext )
  611. // Ptilink has completed a read, i.e., receive complete
  612. // buffer now belongs to this layer
  613. //
  614. // Context -- is the pVC
  615. //
  616. // pBuffer -- is the pointer to buffer previously allocated
  617. // to the PtiLink driver via the PtiCbGetReadBuffer function
  618. //
  619. // Status -- one of: NT_SUCCESS = good packet received
  620. // DATA_OVERRUN = header failure
  621. // BUFFER_TOO_SMALL= pBuffer is too small to receive packet
  622. //
  623. // ulLength - packet length
  624. //
  625. // RequestContext -- don't care
  626. //
  627. // General Note: PtiLink below us sends and receives link manangement
  628. // packets using the Our and His structures ... link management packets to
  629. // not flow through here. Link events are announced to us via our
  630. // registered callback (PtiCbLinkEventHandler) below. We have nothing to
  631. // do with Tx/Rx of link pkts.
  632. //
  633. {
  634. VCCB* pVc;
  635. ADAPTERCB* pAdapter;
  636. NDIS_STATUS status;
  637. NDIS_STATUS writestatus;
  638. NDIS_PACKET* pPacket;
  639. NDIS_BUFFER* pNdisBuffer;
  640. PACKETHEAD* pHead;
  641. ULONGLONG ullTimeReceived;
  642. KIRQL oldIrql;
  643. UCHAR* pHdlcBuf;
  644. ULONG ulHdlcLen;
  645. UCHAR* pTmp;
  646. TRACE( TL_N, TM_Recv, ( "PtiRx=%x: bytes=$%x", Status, ulLength ) );
  647. TRACE( TL_V, TM_Recv, ( "PtiRx=%x, pVc=$%p, pBuf=$%p, bytes=$%x",
  648. Status, Context, pBuffer, ulLength ) );
  649. pVc = (VCCB* )Context;
  650. if (pVc->ulTag != MTAG_VCCB)
  651. {
  652. ASSERT( !"Vtag?" );
  653. return;
  654. }
  655. ReferenceVc( pVc );
  656. pAdapter = pVc->pAdapter;
  657. // NOT A REAL DATA PACKET
  658. // return any buffers used for non-data or losing reads
  659. //
  660. if ( !NT_SUCCESS( Status ) ){
  661. TRACE( TL_A, TM_Pool, ( "PtiRx: Status != SUCCESS, freeing buffer", Status ) );
  662. if ( pBuffer != NULL ) {
  663. FreeBufferToPool( &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  664. }
  665. DereferenceVc( pVc );
  666. return;
  667. }
  668. #ifdef TESTMODE
  669. if ( g_ulTraceMask & TM_Data )
  670. {
  671. if (pBuffer != NULL) {
  672. Dump( pBuffer, ulLength, 0, TRUE );
  673. }
  674. }
  675. #endif
  676. // INCOMING CALL ... NO VC EXISTS YET for this incoming data packet
  677. //
  678. if (ReferenceSap( pAdapter ))
  679. {
  680. if (!(ReadFlags( &pAdapter->pListenVc->ulFlags ) & VCBF_CallInProgress))
  681. {
  682. // Setting in Listen VC here.
  683. //
  684. SetFlags( &pAdapter->pListenVc->ulFlags, VCBF_CallInProgress );
  685. // This is the start of an incoming call which may also start via
  686. // LINK_OPEN event to PtiCbLinkEventHandler
  687. //
  688. // Ignore this packet and proceed to dispatch an incoming call
  689. //
  690. TRACE( TL_V, TM_Recv, ( "PtiRx: Incoming call", Status ) );
  691. // Free the buffer associated with this read ... we throw away the
  692. // data thus losing one packet off the front of an attempt to
  693. // connect, unless the LPKT_OPEN function beats us (a LPKT_OPEN
  694. // notification occurs before first data packet is received ... it
  695. // could happen either way.)
  696. //
  697. if (pBuffer != NULL ) {
  698. FreeBufferToPool( &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  699. }
  700. // set up a VC for the incoming call
  701. //
  702. SetupVcAsynchronously( pAdapter );
  703. DereferenceVc( pVc );
  704. DereferenceSap( pAdapter );
  705. return;
  706. }
  707. DereferenceSap( pAdapter );
  708. }
  709. // NOW HAVE A REAL DATA PACKET
  710. if (ReferenceCall( pVc ))
  711. {
  712. do
  713. {
  714. if (IsWin9xPeer( pVc ))
  715. {
  716. if (pVc->ulTotalPackets < 4)
  717. {
  718. // If packet matches "CLIENT", we emit one saying
  719. // "CLIENTSERVER"
  720. //
  721. // If packet matches "CLIENTSERVER", throw it away
  722. //
  723. // This hack emulates the Win9x UNIMODEM behavior which is
  724. // required to allow Win9x systems to connect to us.
  725. //
  726. // Also, it appears that sending the "CLIENT" packet up
  727. // the stack causes RasTapi to disconnect us immediately.
  728. // It wants to see PPP?
  729. //
  730. if ( StrCmp(
  731. pBuffer, g_szClientServer, CLIENTSERVERLEN ) == 0 )
  732. {
  733. // throw away packets containing "CLIENTSERVER"
  734. //
  735. FreeBufferToPool(
  736. &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  737. TRACE( TL_V, TM_Recv,
  738. ( "PtiRx: CLIENTSERVER ignored", Status ) );
  739. pVc->ulTotalPackets++;
  740. break;
  741. }
  742. else if ( StrCmp(
  743. pBuffer, g_szClient, CLIENTLEN ) == 0 )
  744. {
  745. // when we see "CLIENT", throw away and respond
  746. // "CLIENTSERVER".
  747. //
  748. TRACE( TL_V, TM_Recv, ( "PtiRx: See CLIENT", Status ) );
  749. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
  750. writestatus = (NDIS_STATUS) PtiWrite(
  751. pVc->PtiExtension,
  752. g_szClientServer,
  753. CLIENTSERVERLEN,
  754. PID_STANDARD );
  755. KeLowerIrql(oldIrql);
  756. FreeBufferToPool(
  757. &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  758. TRACE( TL_V, TM_Recv,
  759. ( "PtiRx: CLIENTSERVER sent", Status ) );
  760. pVc->ulTotalPackets++;
  761. break;
  762. }
  763. }
  764. // Un-byte-stuff the received buffer into a second buffer,
  765. // then swap it with the received buffer.
  766. //
  767. pHdlcBuf = (UCHAR* )
  768. GetBufferFromPool( &pAdapter->poolFrameBuffers );
  769. if (!pHdlcBuf)
  770. {
  771. FreeBufferToPool(
  772. &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  773. TRACE( TL_A, TM_Recv, ( "PtiRx: !Alloc HDLC" ) );
  774. break;
  775. }
  776. HdlcFromAsyncFraming(
  777. pBuffer, ulLength, pHdlcBuf, &ulHdlcLen );
  778. pTmp = pBuffer;
  779. pBuffer = pHdlcBuf;
  780. ulLength = ulHdlcLen;
  781. FreeBufferToPool( &pAdapter->poolFrameBuffers, pTmp, TRUE );
  782. }
  783. // Note the time if client's call parameters indicated interest in
  784. // time received.
  785. //
  786. if (ReadFlags( &pVc->ulFlags ) & VCBF_IndicateTimeReceived)
  787. {
  788. NdisGetCurrentSystemTime( (LARGE_INTEGER* )&ullTimeReceived );
  789. }
  790. else
  791. {
  792. ullTimeReceived = 0;
  793. }
  794. TRACE( TL_V, TM_Recv,
  795. ( "PtiRx: Rx Packet: nBytes=$%x", ulLength ) );
  796. // Get a packet from the packet pool
  797. //
  798. pPacket = GetPacketFromPool( &pAdapter->poolPackets, &pHead );
  799. if (!pPacket)
  800. {
  801. // Packet descriptor pool is maxed.
  802. //
  803. ASSERT( !"GetPfP?" );
  804. break;
  805. }
  806. // Hook the NDIS_BUFFER to the packet. The "copy" here refers to
  807. // descriptor information only. The packet data is not copied.
  808. //
  809. NdisCopyBuffer(
  810. &status,
  811. &pNdisBuffer,
  812. PoolHandleForNdisCopyBufferFromBuffer( pBuffer ),
  813. NdisBufferFromBuffer( pBuffer ),
  814. 0,
  815. ulLength );
  816. if (status != STATUS_SUCCESS)
  817. {
  818. // Can't get a MDL which likely means the system is toast.
  819. //
  820. FreePacketToPool( &pAdapter->poolPackets, pHead, TRUE );
  821. TRACE( TL_A, TM_Recv, ( "NdisCopyBuffer=%08x?", status ) );
  822. break;
  823. }
  824. NdisChainBufferAtFront( pPacket, pNdisBuffer );
  825. // Stash the time the packet was received in the packet.
  826. //
  827. NDIS_SET_PACKET_TIME_RECEIVED( pPacket, ullTimeReceived );
  828. // Pre-set the packet to success, since a random value of
  829. // NDIS_STATUS_RESOURCES would prevent our ReturnPackets handler
  830. // from getting called.
  831. //
  832. NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_SUCCESS );
  833. // Stash our context information with the packet for clean-up use
  834. // in PtiReturnPacket, then indicate the packet to NDISWAN.
  835. //
  836. *((PACKETHEAD** )(&pPacket->MiniportReserved[ 0 ])) = pHead;
  837. *((CHAR** )(&pPacket->MiniportReserved[ sizeof(VOID*) ])) = pBuffer;
  838. TRACE( TL_V, TM_Recv,
  839. ( "PtiRx: NdisMCoIndRecPkt: hVc=$%p, pPacket=$%p, len=$%x",
  840. pVc->NdisVcHandle, pPacket, ulLength ) );
  841. NdisMCoIndicateReceivePacket( pVc->NdisVcHandle, &pPacket, 1 );
  842. TRACE( TL_V, TM_Recv, ( "PtiRx: NdisMCoIndRecPkt done" ) );
  843. // Tell NDIS our "receive process" is complete. Since we deal
  844. // with one packet at a time and NDISWAN does also, this doesn't
  845. // accomplish anything, but the consensus is it's bad form to omit
  846. // it.
  847. //
  848. TRACE( TL_V, TM_Recv, ( "PtiRx: NdisMCoRecComp" ) );
  849. NdisMCoReceiveComplete( pAdapter->MiniportAdapterHandle );
  850. TRACE( TL_V, TM_Recv, ( "PtiRx: NdisMCoRecComp done" ) );
  851. pVc->ulTotalPackets++;
  852. }
  853. while (FALSE);
  854. DereferenceCall( pVc );
  855. }
  856. else
  857. {
  858. TRACE( TL_A, TM_Recv, ( "Receive on inactive call ignored" ) );
  859. }
  860. DereferenceVc( pVc );
  861. return;
  862. }
  863. VOID
  864. PtiCbLinkEventHandler(
  865. IN PVOID Context,
  866. IN ULONG PtiLinkEventId,
  867. IN ULONG PtiLinkEventData )
  868. // Ptilink is reporting a link management event (Link up or down)
  869. //
  870. {
  871. VCCB* pVc;
  872. ADAPTERCB* pAdapter;
  873. pVc = (VCCB* )Context;
  874. if (pVc->ulTag != MTAG_VCCB)
  875. {
  876. ASSERT( !"Vtag?" );
  877. return;
  878. }
  879. pAdapter = pVc->pAdapter;
  880. switch (PtiLinkEventId)
  881. {
  882. case PTILINK_LINK_UP:
  883. {
  884. TRACE( TL_A, TM_Cm, ( "LinkEvent: LINK UP, pVc=$%p", pVc ) );
  885. // peer is initiating a call (also happens in PtiRx)
  886. //
  887. break;
  888. }
  889. case PTILINK_LINK_DOWN:
  890. {
  891. TRACE( TL_A, TM_Cm, ( "LinkEvent: LINK DOWN, pVc=$%p", pVc ) );
  892. // peer is closing a call
  893. //
  894. if (pVc == pAdapter->pListenVc)
  895. {
  896. TRACE( TL_A, TM_Cm,
  897. ( "LinkEvent: LINK DOWN on ListenVc ignored" ) );
  898. break;
  899. }
  900. NdisAcquireSpinLock( &pVc->lockV );
  901. {
  902. pVc->status = NDIS_STATUS_TAPI_DISCONNECTMODE_NORMAL;
  903. CallTransitionComplete( pVc );
  904. }
  905. NdisReleaseSpinLock( &pVc->lockV );
  906. TRACE( TL_A, TM_Cm, ( "LinkEvent: LINK DOWN causing disconnect" ) );
  907. CompleteVc( pVc );
  908. break;
  909. }
  910. default:
  911. {
  912. TRACE( TL_A, TM_Cm,
  913. ( "LinkEvent: Bad LinkEvent = %d", PtiLinkEventId ) );
  914. break;
  915. }
  916. }
  917. }
  918. //-----------------------------------------------------------------------------
  919. // Mini-port utility routines (alphabetically)
  920. // Some are used externally
  921. //-----------------------------------------------------------------------------
  922. VOID
  923. AsyncFromHdlcFraming(
  924. IN UCHAR* pInBuf,
  925. IN ULONG ulInBufLen,
  926. OUT UCHAR* pOutBuf,
  927. OUT ULONG* pulOutBufLen,
  928. IN ULONG ulAccmMask )
  929. // Make a copy of PPP HDLC framed data buffer 'pInBuf' of length
  930. // 'ulInBufLen' bytes in caller's 'pOutBuf' buffer, converting to
  931. // byte-stuffed asynchronous PPP framed format in the process.
  932. // 'POutBufLen' is the length in bytes of the returned output buffer. Due
  933. // to the byte stuffing, caller must allow for up to twice the length of
  934. // 'pInfBuf'. 'UlAccmMask' is the bitmask of characters to be byte
  935. // stuffed.
  936. //
  937. // With current implementation, user must allow 2 extra bytes at the end
  938. // of the input buffer for stashing the FCS during byte-stuffing.
  939. //
  940. // This routine is adapted from the ASYNCMAC AssemblePppFrame routine, as
  941. // is the following description, which in turn was lifted from RFC 1331
  942. // (May 1992). The PPP frame NDISWAN passes us for sends is the data from
  943. // the Address field through the Information field inclusive, without any
  944. // byte stuffing, of course.
  945. //
  946. // Asynchronously framed PPP packet:
  947. //
  948. // +----------+----------+----------+----------+------------...
  949. // | Flag | Address | Control | Protocol | Information
  950. // | 01111110 | 11111111 | 00000011 | 16 bits | *
  951. // +----------+----------+----------+----------+------------...
  952. // ...---+----------+----------+-----------------
  953. // | FCS | Flag | Inter-frame Fill
  954. // | 16 bits | 01111110 | or next Address
  955. // ...---+----------+----------+-----------------
  956. //
  957. // Frame Check Sequence (FCS) Field
  958. //
  959. // The Frame Check Sequence field is normally 16 bits (two octets). The
  960. // use of other FCS lengths may be defined at a later time, or by prior
  961. // agreement.
  962. //
  963. // The FCS field is calculated over all bits of the Address, Control,
  964. // Protocol and Information fields not including any start and stop bits
  965. // (asynchronous) and any bits (synchronous) or octets (asynchronous)
  966. // inserted for transparency. This does not include the Flag Sequences
  967. // or the FCS field itself. The FCS is transmitted with the coefficient
  968. // of the highest term first.
  969. //
  970. // Note: When octets are received which are flagged in the Async-
  971. // Control-Character-Map, they are discarded before calculating the
  972. // FCS. See the description in Appendix A.
  973. //
  974. // On asynchronous links, a character stuffing procedure is used.
  975. // The Control Escape octet is defined as binary 01111101
  976. // (hexadecimal 0x7d) where the bit positions are numbered 87654321
  977. // (not 76543210, BEWARE).
  978. //
  979. // After FCS computation, the transmitter examines the entire frame
  980. // between the two Flag Sequences. Each Flag Sequence, Control
  981. // Escape octet and octet with value less than hexadecimal 0x20 which
  982. // is flagged in the Remote Async-Control-Character-Map is replaced
  983. // by a two octet sequence consisting of the Control Escape octet and
  984. // the original octet with bit 6 complemented (i.e., exclusive-or'd
  985. // with hexadecimal 0x20).
  986. //
  987. // Prior to FCS computation, the receiver examines the entire frame
  988. // between the two Flag Sequences. Each octet with value less than
  989. // hexadecimal 0x20 is checked. If it is flagged in the Local
  990. // Async-Control-Character-Map, it is simply removed (it may have
  991. // been inserted by intervening data communications equipment). For
  992. // each Control Escape octet, that octet is also removed, but bit 6
  993. // of the following octet is complemented. A Control Escape octet
  994. // immediately preceding the closing Flag Sequence indicates an
  995. // invalid frame.
  996. //
  997. // Note: The inclusion of all octets less than hexadecimal 0x20
  998. // allows all ASCII control characters [10] excluding DEL (Delete)
  999. // to be transparently communicated through almost all known data
  1000. // communications equipment.
  1001. //
  1002. //
  1003. // The transmitter may also send octets with value in the range 0x40
  1004. // through 0xff (except 0x5e) in Control Escape format. Since these
  1005. // octet values are not negotiable, this does not solve the problem
  1006. // of receivers which cannot handle all non-control characters.
  1007. // Also, since the technique does not affect the 8th bit, this does
  1008. // not solve problems for communications links that can send only 7-
  1009. // bit characters.
  1010. //
  1011. // A few examples may make this more clear. Packet data is
  1012. // transmitted on the link as follows:
  1013. //
  1014. // 0x7e is encoded as 0x7d, 0x5e.
  1015. // 0x7d is encoded as 0x7d, 0x5d.
  1016. //
  1017. // 0x01 is encoded as 0x7d, 0x21.
  1018. //
  1019. // Some modems with software flow control may intercept outgoing DC1
  1020. // and DC3 ignoring the 8th (parity) bit. This data would be
  1021. // transmitted on the link as follows:
  1022. //
  1023. // 0x11 is encoded as 0x7d, 0x31.
  1024. // 0x13 is encoded as 0x7d, 0x33.
  1025. // 0x91 is encoded as 0x7d, 0xb1.
  1026. // 0x93 is encoded as 0x7d, 0xb3.
  1027. //
  1028. {
  1029. USHORT usFcs;
  1030. UCHAR* pIn;
  1031. UCHAR* pOut;
  1032. ULONG ulInBytesLeft;
  1033. pIn = pInBuf;
  1034. ulInBytesLeft = ulInBufLen;
  1035. pOut = pOutBuf;
  1036. // Calculate the frame check sequence on the data.
  1037. //
  1038. TRACE( TL_I, TM_Data, ( "AfromH (send) dump:" ) );
  1039. DUMPB( TL_I, TM_Data, pInBuf, ulInBufLen );
  1040. usFcs = CalculatePppFcs( pInBuf, ulInBufLen );
  1041. usFcs ^= 0xFFFF;
  1042. // Add the calculated FCS. Added to the input buffer for convenience as
  1043. // it must be byte-stuffed along with the other data, though this uglies
  1044. // the interface a bit.
  1045. //
  1046. pIn[ ulInBytesLeft ] = (UCHAR )usFcs;
  1047. ++ulInBytesLeft;
  1048. pIn[ ulInBytesLeft ] = (UCHAR )(usFcs >> 8);
  1049. ++ulInBytesLeft;
  1050. // Add the initial flag byte.
  1051. //
  1052. *pOut = PPPFLAGBYTE;
  1053. ++pOut;
  1054. // Because an empty control character mask is common, an optimized loop is
  1055. // provided in that case.
  1056. //
  1057. if (ulAccmMask
  1058. #ifdef TESTMODE
  1059. || g_fNoAccmFastPath
  1060. #endif
  1061. )
  1062. {
  1063. // Have bitmask...slower path.
  1064. //
  1065. while (ulInBytesLeft--)
  1066. {
  1067. UCHAR uch;
  1068. uch = *pIn;
  1069. ++pIn;
  1070. if (((uch < 0x20) && ((1 << uch) & ulAccmMask))
  1071. || (uch == PPPESCBYTE) || (uch == PPPFLAGBYTE))
  1072. {
  1073. // Byte stuff the character.
  1074. //
  1075. *pOut = PPPESCBYTE;
  1076. ++pOut;
  1077. *pOut = uch ^ 0x20;
  1078. ++pOut;
  1079. }
  1080. else
  1081. {
  1082. // Copy the character as is.
  1083. //
  1084. *pOut = uch;
  1085. ++pOut;
  1086. }
  1087. }
  1088. }
  1089. else
  1090. {
  1091. // No bitmask...fast path.
  1092. //
  1093. while (ulInBytesLeft--)
  1094. {
  1095. UCHAR uch;
  1096. uch = *pIn;
  1097. ++pIn;
  1098. if ((uch == PPPESCBYTE) || (uch == PPPFLAGBYTE))
  1099. {
  1100. // Byte stuff the character.
  1101. //
  1102. *pOut = PPPESCBYTE;
  1103. ++pOut;
  1104. *pOut = uch ^ 0x20;
  1105. ++pOut;
  1106. }
  1107. else
  1108. {
  1109. // Copy the character as is.
  1110. //
  1111. *pOut = uch;
  1112. ++pOut;
  1113. }
  1114. }
  1115. }
  1116. // Add the trailing flag byte.
  1117. //
  1118. *pOut = PPPFLAGBYTE;
  1119. ++pOut;
  1120. // Calculate length of output.
  1121. //
  1122. *pulOutBufLen = (ULONG )(pOut - pOutBuf);
  1123. }
  1124. USHORT
  1125. CalculatePppFcs(
  1126. IN UCHAR* pBuf,
  1127. IN ULONG ulBufLen )
  1128. // Return the PPP Frame Check Sequence on 'ulBufLen' bytes starting at
  1129. // 'pBuf'.
  1130. //
  1131. // (Taken from ASYNCMAC)
  1132. //
  1133. {
  1134. static USHORT ausFcsTable[ 256 ] =
  1135. {
  1136. 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
  1137. 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
  1138. 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
  1139. 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
  1140. 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
  1141. 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
  1142. 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
  1143. 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
  1144. 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
  1145. 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
  1146. 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
  1147. 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
  1148. 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
  1149. 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
  1150. 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
  1151. 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
  1152. 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
  1153. 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
  1154. 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
  1155. 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
  1156. 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
  1157. 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
  1158. 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
  1159. 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
  1160. 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
  1161. 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
  1162. 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
  1163. 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
  1164. 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
  1165. 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
  1166. 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
  1167. 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
  1168. };
  1169. register USHORT usFcs;
  1170. usFcs = 0xFFFF;
  1171. while (ulBufLen--)
  1172. {
  1173. usFcs = (usFcs >> 8) ^ ausFcsTable[ (usFcs ^ (USHORT )*pBuf) & 0xFF ];
  1174. ++pBuf;
  1175. }
  1176. return usFcs;
  1177. }
  1178. VOID
  1179. DereferenceAdapter(
  1180. IN ADAPTERCB* pAdapter )
  1181. // Removes a reference from the adapter control block 'pAdapter', and when
  1182. // frees the adapter resources when the last reference is removed.
  1183. //
  1184. {
  1185. LONG lRef;
  1186. lRef = NdisInterlockedDecrement( &pAdapter->lRef );
  1187. TRACE( TL_N, TM_Ref, ( "DerefA to %d", lRef ) );
  1188. ASSERT( lRef >= 0 );
  1189. if (lRef == 0)
  1190. {
  1191. FreeAdapter( pAdapter );
  1192. }
  1193. }
  1194. VOID
  1195. DereferenceVc(
  1196. IN VCCB* pVc )
  1197. // Removes a reference to the VC control block 'pVc', and when frees the
  1198. // block when the last reference is removed.
  1199. //
  1200. {
  1201. LONG lRef;
  1202. lRef = NdisInterlockedDecrement( &pVc->lRef );
  1203. TRACE( TL_N, TM_Ref, ( "DerefVc to %d", lRef ) );
  1204. ASSERT( lRef >= 0 );
  1205. if (lRef == 0)
  1206. {
  1207. ADAPTERCB* pAdapter;
  1208. // now for an interesting bit ...
  1209. //
  1210. // if we have a listenVc allocated, then revert to using that
  1211. //
  1212. pAdapter = pVc->pAdapter;
  1213. if (pAdapter->ulTag != MTAG_ADAPTERCB)
  1214. {
  1215. ASSERT( !"Atag?" );
  1216. return;
  1217. }
  1218. if (pAdapter->pListenVc && pAdapter->pListenVc->hPtiLink)
  1219. {
  1220. TRACE( TL_V, TM_Mp,
  1221. ( "DerefVc: Reverting to pVc=$%p", pAdapter->pListenVc ) );
  1222. ClearFlags( &pAdapter->pListenVc->ulFlags, VCBF_CallInProgress );
  1223. // reregister using the listen Vc
  1224. //
  1225. TRACE( TL_V, TM_Mp, ( "DerefVc: RegCb pLV=$%p",
  1226. pAdapter->pListenVc ) );
  1227. PtiRegisterCallbacks(pAdapter->pListenVc->Extension, // the PTILINKx extension
  1228. PtiCbGetReadBuffer, // our get buffer routine
  1229. PtiRx, // our receive complete routine
  1230. PtiCbLinkEventHandler, // our link event handler
  1231. pAdapter->pListenVc); // our new context
  1232. }
  1233. // Can make these assumptions because NDIS will not call the delete-VC
  1234. // handler while the VC is active. All the nasty VC clean up occurs
  1235. // before the VC is deactivated and the call closed.
  1236. //
  1237. pVc->ulTag = MTAG_FREED;
  1238. FREE_VCCB( pAdapter, pVc );
  1239. DereferenceAdapter( pAdapter );
  1240. TRACE( TL_I, TM_Mp, ( "pVc=$%p freed", pVc ) );
  1241. }
  1242. }
  1243. VOID
  1244. FreeAdapter(
  1245. IN ADAPTERCB* pAdapter )
  1246. // Frees all resources allocated for adapter 'pAdapter', including
  1247. // 'pAdapter' itself.
  1248. //
  1249. {
  1250. BOOLEAN fSuccess;
  1251. // Setting 'usMaxVcs' to 0 is PtiInitialize's way of telling us that the
  1252. // lookaside lists and pools were not initialized.
  1253. //
  1254. if (pAdapter->usMaxVcs)
  1255. {
  1256. NdisDeleteNPagedLookasideList( &pAdapter->llistWorkItems );
  1257. NdisDeleteNPagedLookasideList( &pAdapter->llistVcs );
  1258. }
  1259. TRACE( TL_V, TM_Mp, ( "FreeAdapter" ) );
  1260. pAdapter->ulTag = MTAG_FREED;
  1261. FREE_NONPAGED( pAdapter );
  1262. }
  1263. NDIS_STATUS
  1264. RegistrySettings(
  1265. IN OUT ADAPTERCB* pAdapter,
  1266. IN NDIS_HANDLE WrapperConfigurationContext )
  1267. // Read this mini-port's registry settings into 'pAdapter' fields. Also
  1268. // writes registry values read by RASTAPI, overriding SETUPs.
  1269. // 'WrapperConfigurationContext' is the handle to passed to
  1270. // MiniportInitialize.
  1271. //
  1272. {
  1273. NDIS_STATUS status;
  1274. NDIS_HANDLE hCfg;
  1275. NDIS_CONFIGURATION_PARAMETER* pncp;
  1276. NdisOpenConfiguration( &status, &hCfg, WrapperConfigurationContext );
  1277. if (status != NDIS_STATUS_SUCCESS)
  1278. {
  1279. return status;
  1280. }
  1281. do
  1282. {
  1283. // The delay in milliseconds to wait for PARPORT to initialize all the
  1284. // parallel ports. With PnP there is no deterministic time at which
  1285. // to do this.
  1286. //
  1287. {
  1288. NDIS_STRING nstr = NDIS_STRING_CONST( "ParportDelayMs" );
  1289. NdisReadConfiguration(
  1290. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1291. if (status == NDIS_STATUS_SUCCESS)
  1292. {
  1293. pAdapter->ulParportDelayMs = pncp->ParameterData.IntegerData;
  1294. }
  1295. else
  1296. {
  1297. // Default is 3 seconds.
  1298. //
  1299. pAdapter->ulParportDelayMs = 3000;
  1300. status = NDIS_STATUS_SUCCESS;
  1301. }
  1302. }
  1303. // The secondary delay in milliseconds to wait for PARPORT to
  1304. // initialize all the parallel ports, if there are no ports after the
  1305. // initial delay above.
  1306. //
  1307. {
  1308. NDIS_STRING nstr = NDIS_STRING_CONST( "ExtraParportDelayMs" );
  1309. NdisReadConfiguration(
  1310. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1311. if (status == NDIS_STATUS_SUCCESS)
  1312. {
  1313. pAdapter->ulExtraParportDelayMs =
  1314. pncp->ParameterData.IntegerData;
  1315. }
  1316. else
  1317. {
  1318. // Default is 30 seconds.
  1319. //
  1320. pAdapter->ulExtraParportDelayMs = 30000;
  1321. status = NDIS_STATUS_SUCCESS;
  1322. }
  1323. }
  1324. // The number of VCs we must be able to provide.
  1325. //
  1326. {
  1327. #if 0
  1328. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxVcs" );
  1329. NdisReadConfiguration(
  1330. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1331. if (status == NDIS_STATUS_SUCCESS)
  1332. {
  1333. pAdapter->usMaxVcs = (USHORT )pncp->ParameterData.IntegerData;
  1334. // Make sure it's a valid value.
  1335. //
  1336. if (pAdapter->usMaxVcs < 1)
  1337. {
  1338. status = NDIS_STATUS_INVALID_DATA;
  1339. break;
  1340. }
  1341. }
  1342. else
  1343. {
  1344. pAdapter->usMaxVcs = 1;
  1345. status = NDIS_STATUS_SUCCESS;
  1346. }
  1347. #else
  1348. // Registry value is currently ignored, and hard-coded maximum
  1349. // used.
  1350. //
  1351. pAdapter->usMaxVcs = NPORTS;
  1352. #endif
  1353. }
  1354. }
  1355. while (FALSE);
  1356. NdisCloseConfiguration( hCfg );
  1357. TRACE( TL_N, TM_Init,
  1358. ( "Reg: vcs=%d ppd=%d",
  1359. (UINT )pAdapter->usMaxVcs,
  1360. (UINT )pAdapter->ulParportDelayMs ) );
  1361. return status;
  1362. }
  1363. BOOLEAN
  1364. HdlcFromAsyncFraming(
  1365. IN UCHAR* pInBuf,
  1366. IN ULONG ulInBufLen,
  1367. OUT UCHAR* pOutBuf,
  1368. OUT ULONG* pulOutBufLen )
  1369. // Make a copy of asynchronously framed PPP data buffer 'pInBuf' of length
  1370. // 'ulInBufLen' bytes in caller's 'pOutBuf' buffer, converting to PPP HDLC
  1371. // framed format in the process. 'POutBufLen' is the length in bytes of
  1372. // the returned output buffer. Caller must allow for up to the length of
  1373. // 'pInBuf' in 'pOutBuf'.
  1374. //
  1375. // Returns true if the packet is valid, false if corrupt.
  1376. //
  1377. // Adapted from ASYNCMAC's AsyncPPPCompletionRoutine.
  1378. //
  1379. {
  1380. UCHAR* pIn;
  1381. UCHAR* pInEnd;
  1382. UCHAR* pOut;
  1383. USHORT usFcs;
  1384. if (ulInBufLen < 5)
  1385. {
  1386. // Expecting at least 2 flag bytes, 1 data byte, and the FCS.
  1387. //
  1388. TRACE( TL_A, TM_Mp, ( "HfA: frame too short=%d", ulInBufLen ) );
  1389. return FALSE;
  1390. }
  1391. if (pInBuf[ 0 ] != PPPFLAGBYTE)
  1392. {
  1393. TRACE( TL_A, TM_Mp, ( "HfA: No head flag" ) );
  1394. return FALSE;
  1395. }
  1396. if (pInBuf[ ulInBufLen - 1 ] != PPPFLAGBYTE)
  1397. {
  1398. TRACE( TL_A, TM_Mp, ( "HfA: No tail flag" ) );
  1399. return FALSE;
  1400. }
  1401. pIn = pInBuf + 1;
  1402. pInEnd = pInBuf + ulInBufLen - 1;
  1403. pOut = pOutBuf;
  1404. while (pIn < pInEnd)
  1405. {
  1406. if (*pIn == PPPESCBYTE)
  1407. {
  1408. ++pIn;
  1409. *pOut = *pIn ^ 0x20;
  1410. }
  1411. else
  1412. {
  1413. *pOut = *pIn;
  1414. }
  1415. ++pOut;
  1416. ++pIn;
  1417. }
  1418. *pulOutBufLen = (ULONG )(pOut - pOutBuf - 2);
  1419. {
  1420. USHORT usCalcFcs;
  1421. usFcs = (USHORT )(pOut[ -2 ]) + (USHORT )(pOut[ -1 ] << 8);
  1422. usFcs ^= 0xFFFF;
  1423. TRACE( TL_I, TM_Data, ( "HfromA (recv) dump:" ) );
  1424. DUMPB( TL_I, TM_Data, pOutBuf, *pulOutBufLen );
  1425. usCalcFcs = CalculatePppFcs( pOutBuf, *pulOutBufLen );
  1426. if (usFcs != usCalcFcs)
  1427. {
  1428. TRACE( TL_A, TM_Mp, (
  1429. "HfA: FCS mismatch, R=$%04x C=$%04x, L=%d",
  1430. (INT )usFcs, (INT )usCalcFcs, *pulOutBufLen ) );
  1431. return FALSE;
  1432. }
  1433. #if 0
  1434. #ifdef TESTMODE
  1435. else
  1436. {
  1437. TRACE( TL_A, TM_Mp, (
  1438. "HfA: Good FCS, R=$%04x C=$%04x, L=%d",
  1439. (INT )usFcs, (INT )usCalcFcs, *pulOutBufLen ) );
  1440. }
  1441. #endif
  1442. #endif
  1443. }
  1444. return TRUE;
  1445. }
  1446. BOOLEAN
  1447. IsWin9xPeer(
  1448. IN VCCB* pVc )
  1449. // Returns true if the link level has determined that the VC's peer is a
  1450. // Win9x box, false otherwise.
  1451. //
  1452. {
  1453. ULONG Platform;
  1454. PPTI_EXTENSION pPtiExtension;
  1455. #ifdef TESTMODE
  1456. if (g_fAssumeWin9x)
  1457. {
  1458. return TRUE;
  1459. }
  1460. #endif
  1461. pPtiExtension = (PPTI_EXTENSION )pVc->PtiExtension;
  1462. // try to check the validity of the PtiExtension pointer
  1463. //
  1464. if ( pPtiExtension == NULL )
  1465. {
  1466. TRACE( TL_A, TM_Recv, ( "PtiRx: pPtiExtension is NULL!" ) );
  1467. return FALSE;
  1468. }
  1469. Platform = (ULONG) pPtiExtension->His.VerPlat;
  1470. TRACE( TL_V, TM_Recv, ( "IsWin9xPeer: far platform=$%x", Platform ) );
  1471. if (Platform == PLAT_WIN9X)
  1472. {
  1473. // Win9x -- we reformat the asynch framing used by Win9x DCC
  1474. // and also play the CLIENT->CLIENTSERVER game
  1475. //
  1476. return TRUE;
  1477. }
  1478. // WinNT (or DOS maybe)
  1479. //
  1480. return FALSE;
  1481. }
  1482. NDIS_STATUS
  1483. QueryInformation(
  1484. IN ADAPTERCB* pAdapter,
  1485. IN VCCB* pVc,
  1486. IN NDIS_OID Oid,
  1487. IN PVOID InformationBuffer,
  1488. IN ULONG InformationBufferLength,
  1489. OUT PULONG BytesWritten,
  1490. OUT PULONG BytesNeeded )
  1491. // Handle QueryInformation requests. Arguments are as for the standard
  1492. // NDIS 'MiniportQueryInformation' handler except this routine does not
  1493. // count on being serialized with respect to other requests.
  1494. //
  1495. {
  1496. NDIS_STATUS status;
  1497. ULONG ulInfo;
  1498. VOID* pInfo;
  1499. ULONG ulInfoLen;
  1500. status = NDIS_STATUS_SUCCESS;
  1501. // The cases in this switch statement find or create a buffer containing
  1502. // the requested information and point 'pInfo' at it, noting it's length
  1503. // in 'ulInfoLen'. Since many of the OIDs return a ULONG, a 'ulInfo'
  1504. // buffer is set up as the default.
  1505. //
  1506. ulInfo = 0;
  1507. pInfo = &ulInfo;
  1508. ulInfoLen = sizeof(ulInfo);
  1509. switch (Oid)
  1510. {
  1511. case OID_GEN_MAXIMUM_LOOKAHEAD:
  1512. {
  1513. // Report the maximum number of bytes we can always provide as
  1514. // lookahead data on receive indications. We always indicate full
  1515. // packets so this is the same as the receive block size. And
  1516. // since we always allocate enough for a full packet, the receive
  1517. // block size is the same as the frame size.
  1518. //
  1519. TRACE( TL_N, TM_Mp, ( "QInfo(OID_GEN_MAXIMUM_LOOKAHEAD)" ) );
  1520. ulInfo = PTI_MaxFrameSize;
  1521. break;
  1522. }
  1523. case OID_GEN_MAC_OPTIONS:
  1524. {
  1525. // Report a bitmask defining optional properties of the driver.
  1526. //
  1527. // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA promises that our receive
  1528. // buffer is not on a device-specific card.
  1529. //
  1530. // NDIS_MAC_OPTION_TRANSFERS_NOT_PEND promises we won't return
  1531. // NDIS_STATUS_PENDING from our TransferData handler which is true
  1532. // since we don't have one.
  1533. //
  1534. TRACE( TL_N, TM_Mp, ( "QInfo(OID_GEN_MAC_OPTIONS)" ) );
  1535. ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
  1536. | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND;
  1537. break;
  1538. }
  1539. case OID_WAN_MEDIUM_SUBTYPE:
  1540. {
  1541. // Report the media subtype we support. NDISWAN may use this in
  1542. // the future (doesn't now) to provide framing differences for
  1543. // different media.
  1544. //
  1545. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_MEDIUM_SUBTYPE)" ) );
  1546. ulInfo = NdisWanMediumParallel;
  1547. break;
  1548. }
  1549. case OID_WAN_CO_GET_INFO:
  1550. {
  1551. // Report the capabilities of the adapter.
  1552. //
  1553. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_CO_GET_INFO)" ) );
  1554. pInfo = &pAdapter->info;
  1555. ulInfoLen = sizeof(NDIS_WAN_CO_INFO);
  1556. break;
  1557. }
  1558. case OID_WAN_CO_GET_LINK_INFO:
  1559. {
  1560. // Report the current state of the link.
  1561. //
  1562. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_CO_GET_LINK_INFO)" ) );
  1563. if (!pVc)
  1564. return NDIS_STATUS_INVALID_DATA;
  1565. pInfo = &pVc->linkinfo;
  1566. ulInfoLen = sizeof(NDIS_WAN_CO_GET_LINK_INFO);
  1567. break;
  1568. }
  1569. case OID_WAN_CO_GET_COMP_INFO:
  1570. {
  1571. // Report the type of compression we provide, which is none.
  1572. //
  1573. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_CO_GET_COMP_INFO)" ) );
  1574. status = NDIS_STATUS_NOT_SUPPORTED;
  1575. ulInfoLen = 0;
  1576. break;
  1577. }
  1578. case OID_WAN_CO_GET_STATS_INFO:
  1579. {
  1580. // Because DirectParallel doesn't do compression, NDISWAN will use
  1581. // it's own statistics and not query ours.
  1582. //
  1583. ASSERT( !"OID_WAN_CO_GET_STATS_INFO?" );
  1584. status = NDIS_STATUS_NOT_SUPPORTED;
  1585. ulInfoLen = 0;
  1586. break;
  1587. }
  1588. case OID_GEN_SUPPORTED_LIST:
  1589. {
  1590. static ULONG aulSupportedOids[] = {
  1591. OID_GEN_SUPPORTED_LIST,
  1592. OID_GEN_MAXIMUM_LOOKAHEAD,
  1593. OID_GEN_MAC_OPTIONS,
  1594. OID_WAN_MEDIUM_SUBTYPE,
  1595. OID_WAN_CO_GET_INFO,
  1596. OID_WAN_CO_GET_LINK_INFO,
  1597. OID_WAN_CO_SET_LINK_INFO,
  1598. OID_CO_TAPI_CM_CAPS,
  1599. OID_CO_TAPI_LINE_CAPS,
  1600. OID_CO_TAPI_ADDRESS_CAPS,
  1601. OID_CO_TAPI_GET_CALL_DIAGNOSTICS
  1602. };
  1603. TRACE( TL_N, TM_Mp, ( "QInfo(OID_GEN_SUPPORTED_LIST)" ) );
  1604. pInfo = aulSupportedOids;
  1605. ulInfoLen = sizeof(aulSupportedOids);
  1606. break;
  1607. }
  1608. case OID_PNP_CAPABILITIES:
  1609. {
  1610. pInfo = &PnpCaps;
  1611. ulInfoLen = sizeof(PnpCaps);
  1612. break;
  1613. }
  1614. case OID_PNP_SET_POWER:
  1615. break;
  1616. case OID_PNP_QUERY_POWER:
  1617. break;
  1618. case OID_PNP_ENABLE_WAKE_UP:
  1619. break;
  1620. #if 0
  1621. // These OIDs are mandatory according to current doc, but since
  1622. // NDISWAN never requests them they are omitted.
  1623. //
  1624. case OID_GEN_HARDWARE_STATUS:
  1625. case OID_GEN_MEDIA_SUPPORTED:
  1626. case OID_GEN_MEDIA_IN_USE:
  1627. case OID_GEN_MEDIA_IN_USE:
  1628. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1629. case OID_GEN_LINK_SPEED:
  1630. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1631. case OID_GEN_RECEIVE_BUFFER_SPACE:
  1632. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1633. case OID_GEN_RECEIVE_BLOCK_SIZE:
  1634. case OID_GEN_VENDOR_ID:
  1635. case OID_GEN_VENDOR_DESCRIPTION:
  1636. case OID_GEN_VENDOR_DRIVER_VERSION:
  1637. case OID_GEN_CURRENT_PACKET_FILTER:
  1638. case OID_GEN_CURRENT_LOOKAHEAD:
  1639. case OID_GEN_DRIVER_VERSION:
  1640. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1641. case OID_GEN_MAC_OPTIONS:
  1642. case OID_GEN_MEDIA_CONNECT_STATUS:
  1643. case OID_GEN_MAXIMUM_SEND_PACKETS:
  1644. case OID_WAN_PERMANENT_ADDRESS:
  1645. case OID_WAN_CURRENT_ADDRESS:
  1646. case OID_WAN_QUALITY_OF_SERVICE:
  1647. case OID_WAN_LINE_COUNT:
  1648. #endif
  1649. default:
  1650. {
  1651. TRACE( TL_A, TM_Mp, ( "QueryInfo: Oid=$%08x?", Oid ) );
  1652. status = NDIS_STATUS_NOT_SUPPORTED; // JAY per SLC
  1653. ulInfoLen = 0;
  1654. break;
  1655. }
  1656. }
  1657. if (ulInfoLen > InformationBufferLength)
  1658. {
  1659. // Caller's buffer is too small. Tell him what he needs.
  1660. //
  1661. *BytesNeeded = ulInfoLen;
  1662. status = NDIS_STATUS_INVALID_LENGTH;
  1663. }
  1664. else
  1665. {
  1666. // Copy the found result to caller's buffer.
  1667. //
  1668. if (ulInfoLen > 0)
  1669. {
  1670. NdisMoveMemory( InformationBuffer, pInfo, ulInfoLen );
  1671. DUMPDW( TL_N, TM_Mp, pInfo, ulInfoLen );
  1672. }
  1673. *BytesNeeded = *BytesWritten = ulInfoLen;
  1674. }
  1675. return status;
  1676. }
  1677. VOID
  1678. ReferenceAdapter(
  1679. IN ADAPTERCB* pAdapter )
  1680. // Adds areference to the adapter block, 'pAdapter'.
  1681. //
  1682. {
  1683. LONG lRef;
  1684. lRef = NdisInterlockedIncrement( &pAdapter->lRef );
  1685. TRACE( TL_N, TM_Ref, ( "RefA to %d", lRef ) );
  1686. }
  1687. VOID
  1688. ReferenceVc(
  1689. IN VCCB* pVc )
  1690. // Adds a reference to the VC control block 'pVc'.
  1691. //
  1692. {
  1693. LONG lRef;
  1694. lRef = NdisInterlockedIncrement( &pVc->lRef );
  1695. TRACE( TL_N, TM_Ref, ( "RefVc to %d", lRef ) );
  1696. }
  1697. VOID
  1698. SendClientString(
  1699. IN PVOID pPtiExtension )
  1700. // Send "CLIENT" so Win9x, which views us as a NULL modem, is happy.
  1701. //
  1702. {
  1703. KIRQL oldIrql;
  1704. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
  1705. PtiWrite( pPtiExtension, g_szClient, CLIENTLEN, PID_STANDARD );
  1706. KeLowerIrql(oldIrql);
  1707. }
  1708. NDIS_STATUS
  1709. SetInformation(
  1710. IN ADAPTERCB* pAdapter,
  1711. IN VCCB* pVc,
  1712. IN NDIS_OID Oid,
  1713. IN PVOID InformationBuffer,
  1714. IN ULONG InformationBufferLength,
  1715. OUT PULONG BytesRead,
  1716. OUT PULONG BytesNeeded )
  1717. // Handle SetInformation requests. Arguments are as for the standard NDIS
  1718. // 'MiniportQueryInformation' handler except this routine does not count
  1719. // on being serialized with respect to other requests.
  1720. //
  1721. {
  1722. NDIS_STATUS status;
  1723. status = NDIS_STATUS_SUCCESS;
  1724. switch (Oid)
  1725. {
  1726. case OID_WAN_CO_SET_LINK_INFO:
  1727. {
  1728. // Read new link state settings.
  1729. //
  1730. TRACE( TL_N, TM_Mp, ( "SInfo(OID_WAN_CO_SET_LINK_INFO)" ) );
  1731. if (InformationBufferLength < sizeof(NDIS_WAN_CO_SET_LINK_INFO))
  1732. {
  1733. status = NDIS_STATUS_INVALID_LENGTH;
  1734. *BytesRead = 0;
  1735. }
  1736. else
  1737. {
  1738. if (!pVc)
  1739. {
  1740. return NDIS_STATUS_INVALID_DATA;
  1741. }
  1742. ASSERT( sizeof(pVc->linkinfo)
  1743. == sizeof(NDIS_WAN_CO_SET_LINK_INFO) );
  1744. NdisMoveMemory( &pVc->linkinfo, InformationBuffer,
  1745. sizeof(pVc->linkinfo) );
  1746. DUMPB( TL_N, TM_Mp, &pVc->linkinfo, sizeof(pVc->linkinfo) );
  1747. *BytesRead = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
  1748. }
  1749. *BytesNeeded = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
  1750. }
  1751. break;
  1752. case OID_WAN_CO_SET_COMP_INFO:
  1753. {
  1754. // DirectParallel doesn't provide compression.
  1755. //
  1756. TRACE( TL_N, TM_Mp, ( "SInfo(OID_WAN_CO_SET_COMP_INFO)" ) );
  1757. status = NDIS_STATUS_NOT_SUPPORTED;
  1758. *BytesRead = *BytesNeeded = 0;
  1759. break;
  1760. }
  1761. #if 0
  1762. // These OIDs are mandatory according to current doc, but since
  1763. // NDISWAN never requests them they are omitted.
  1764. //
  1765. case OID_GEN_CURRENT_PACKET_FILTER:
  1766. case OID_GEN_CURRENT_LOOKAHEAD:
  1767. case OID_GEN_PROTOCOL_OPTIONS:
  1768. case OID_WAN_PROTOCOL_TYPE:
  1769. case OID_WAN_HEADER_FORMAT:
  1770. #endif
  1771. default:
  1772. {
  1773. TRACE( TL_A, TM_Mp, ( "SetInfo: Oid=$%08x?", Oid ) );
  1774. status = NDIS_STATUS_NOT_SUPPORTED; // JAY per SLC
  1775. *BytesRead = *BytesNeeded = 0;
  1776. break;
  1777. }
  1778. }
  1779. return status;
  1780. }