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.

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