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.

2269 lines
64 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. Protocol.c
  5. Abstract:
  6. This file contains the procedures that makeup most of the NDIS 4.0/5.0
  7. Protocol interface. This interface is what NdisWan exposes to the
  8. WAN Miniports below. NdisWan is not really a protocol and does not
  9. do TDI, but is a shim that sits between the protocols and the
  10. WAN Miniport drivers.
  11. Author:
  12. Tony Bell (TonyBe) June 06, 1995
  13. Environment:
  14. Kernel Mode
  15. Revision History:
  16. TonyBe 06/06/95 Created
  17. --*/
  18. #include "wan.h"
  19. #define __FILE_SIG__ PROTOCOL_FILESIG
  20. #ifdef DBG_SENDARRAY
  21. extern UCHAR SendArray[];
  22. extern ULONG __si;
  23. #endif
  24. EXPORT
  25. VOID
  26. NdisTapiRegisterProvider(
  27. IN NDIS_HANDLE,
  28. IN PNDISTAPI_CHARACTERISTICS
  29. );
  30. EXPORT
  31. VOID
  32. NdisTapiDeregisterProvider(
  33. IN NDIS_HANDLE
  34. );
  35. EXPORT
  36. VOID
  37. NdisTapiIndicateStatus(
  38. IN NDIS_HANDLE BindingContext,
  39. IN PVOID StatusBuffer,
  40. IN UINT StatusBufferLength
  41. );
  42. //
  43. // Local functions...
  44. //
  45. VOID
  46. CompleteSendDesc(
  47. PSEND_DESC SendDesc,
  48. NDIS_STATUS Status
  49. );
  50. VOID
  51. CloseWanAdapterWorker(
  52. PNDIS_WORK_ITEM WorkItem,
  53. POPENCB pOpenCB
  54. );
  55. #if 0
  56. ULONG
  57. CalcPPPHeaderLength(
  58. ULONG FramingBits,
  59. ULONG Flags
  60. );
  61. #endif
  62. //
  63. // Common functions used by both 4.0 and 5.0 miniports
  64. //
  65. NDIS_STATUS
  66. ProtoOpenWanAdapter(
  67. IN POPENCB pOpenCB
  68. )
  69. /*++
  70. Routine Name:
  71. Routine Description:
  72. Arguments:
  73. Return Values:
  74. --*/
  75. {
  76. NDIS_STATUS Status, OpenErrorStatus;
  77. ULONG SelectedMediumIndex;
  78. NDIS_MEDIUM MediumArray[] = {NdisMediumWan, NdisMediumAtm, NdisMediumCoWan};
  79. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoOpenAdapter: Enter - AdapterName %ls", pOpenCB->MiniportName.Buffer));
  80. //
  81. // This is the only initialization of this event
  82. //
  83. NdisWanInitializeNotificationEvent(&pOpenCB->NotificationEvent);
  84. NdisOpenAdapter(&Status,
  85. &OpenErrorStatus,
  86. &(pOpenCB->BindingHandle),
  87. &SelectedMediumIndex,
  88. MediumArray,
  89. sizeof(MediumArray) / sizeof(NDIS_MEDIUM),
  90. NdisWanCB.ProtocolHandle,
  91. (NDIS_HANDLE)pOpenCB,
  92. &(pOpenCB->MiniportName),
  93. 0,
  94. NULL);
  95. if (Status == NDIS_STATUS_PENDING) {
  96. NdisWanWaitForNotificationEvent(&pOpenCB->NotificationEvent);
  97. Status = pOpenCB->NotificationStatus;
  98. NdisWanClearNotificationEvent(&pOpenCB->NotificationEvent);
  99. }
  100. if (Status == NDIS_STATUS_SUCCESS) {
  101. pOpenCB->MediumType = MediumArray[SelectedMediumIndex];
  102. }
  103. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoOpenAdapter: Exit"));
  104. return (Status);
  105. }
  106. //
  107. // Enter with the opencb->lock held, exit with the lock released!
  108. //
  109. NDIS_STATUS
  110. ProtoCloseWanAdapter(
  111. IN POPENCB pOpenCB
  112. )
  113. {
  114. NDIS_STATUS Status;
  115. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoCloseWanAdapter: Enter %p", pOpenCB));
  116. pOpenCB->Flags |= OPEN_CLOSING;
  117. NdisReleaseSpinLock(&pOpenCB->Lock);
  118. //
  119. // NdisCloseAdapter must be called at IRQL PASSIVE_LEVEL!
  120. //
  121. if (KeGetCurrentIrql() > PASSIVE_LEVEL) {
  122. NdisAcquireSpinLock(&pOpenCB->Lock);
  123. ASSERT(!(pOpenCB->Flags & CLOSE_SCHEDULED));
  124. NdisInitializeWorkItem(&pOpenCB->WorkItem,
  125. CloseWanAdapterWorker,
  126. pOpenCB);
  127. NdisScheduleWorkItem(&pOpenCB->WorkItem);
  128. pOpenCB->Flags |= CLOSE_SCHEDULED;
  129. NdisReleaseSpinLock(&pOpenCB->Lock);
  130. return (NDIS_STATUS_PENDING);
  131. }
  132. NdisCloseAdapter(&Status,
  133. pOpenCB->BindingHandle);
  134. if (Status != NDIS_STATUS_PENDING) {
  135. ProtoCloseAdapterComplete(pOpenCB, Status);
  136. }
  137. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoCloseWanAdapter: Exit"));
  138. return(Status);
  139. }
  140. VOID
  141. CloseWanAdapterWorker(
  142. PNDIS_WORK_ITEM WorkItem,
  143. POPENCB pOpenCB
  144. )
  145. {
  146. NDIS_STATUS Status;
  147. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("CloseWanAdapterWorker: Enter %p", pOpenCB));
  148. NdisCloseAdapter(&Status,
  149. pOpenCB->BindingHandle);
  150. if (Status != NDIS_STATUS_PENDING) {
  151. ProtoCloseAdapterComplete(pOpenCB, Status);
  152. }
  153. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("CloseWanAdapterWorker: Exit"));
  154. }
  155. VOID
  156. ProtoOpenAdapterComplete(
  157. IN NDIS_HANDLE ProtocolBindingContext,
  158. IN NDIS_STATUS Status,
  159. IN NDIS_STATUS OpenErrorStatus
  160. )
  161. /*++
  162. Routine Name:
  163. ProtoOpenAdapterComplete
  164. Routine Description:
  165. This function is called upon completion of an open of a miniport.
  166. The status of the openadapter call is stored and the notification
  167. event is signalled.
  168. Arguments:
  169. Return Values:
  170. --*/
  171. {
  172. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  173. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoOpenAdapterComplete: Enter - OpenCB 0x%p", pOpenCB));
  174. pOpenCB->NotificationStatus = Status;
  175. NdisWanSetNotificationEvent(&pOpenCB->NotificationEvent);
  176. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoOpenAdapterComplete: Exit"));
  177. }
  178. VOID
  179. ProtoCloseAdapterComplete(
  180. IN NDIS_HANDLE ProtocolBindingContext,
  181. IN NDIS_STATUS Status
  182. )
  183. /*++
  184. Routine Name:
  185. ProtoCloseAdapterComplete
  186. Routine Description:
  187. This function is called upon completion of a close of a miniport.
  188. The status of the closeadapter call is stored and the notification
  189. event is signalled.
  190. Arguments:
  191. Return Values:
  192. --*/
  193. {
  194. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  195. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoCloseAdapterComplete: Enter - OpenCB %p", pOpenCB));
  196. if (pOpenCB->UnbindContext != NULL) {
  197. NdisCompleteUnbindAdapter(pOpenCB->UnbindContext, Status);
  198. }
  199. if (pOpenCB->Flags & OPEN_IN_BIND) {
  200. //
  201. // We are attempting to close the adapter from
  202. // within our bind handler. Per AliD we must wait
  203. // for the close to finish before we can return
  204. // from the bind handler thus we have to special case
  205. // this code and not free the OpenCB here.
  206. //
  207. NdisWanSetNotificationEvent(&pOpenCB->NotificationEvent);
  208. } else {
  209. NdisWanFreeOpenCB(pOpenCB);
  210. }
  211. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoCloseAdapterComplete: Exit"));
  212. }
  213. VOID
  214. ProtoResetComplete(
  215. IN NDIS_HANDLE ProtocolBindingContext,
  216. IN NDIS_STATUS Status
  217. )
  218. {
  219. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  220. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoResetComplete: Enter - OpenCB %p", pOpenCB));
  221. pOpenCB->NotificationStatus = Status;
  222. NdisWanSetNotificationEvent(&pOpenCB->NotificationEvent);
  223. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoResetComplete: Exit"));
  224. }
  225. VOID
  226. ProtoReceiveComplete(
  227. IN NDIS_HANDLE ProtocolBindingContext
  228. )
  229. {
  230. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  231. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProtoIndicateStatus: Enter - OpenCB %8.x8\n", pOpenCB));
  232. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProtoIndicateStatus: Exit"));
  233. }
  234. VOID
  235. ProtoIndicateStatus(
  236. IN NDIS_HANDLE ProtocolBindingContext,
  237. IN NDIS_STATUS GeneralStatus,
  238. IN PVOID StatusBuffer,
  239. IN UINT StatusBufferSize
  240. )
  241. {
  242. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  243. switch (GeneralStatus) {
  244. case NDIS_STATUS_WAN_LINE_UP:
  245. NdisWanLineUpIndication(pOpenCB,
  246. StatusBuffer,
  247. StatusBufferSize);
  248. break;
  249. case NDIS_STATUS_WAN_LINE_DOWN:
  250. NdisWanLineDownIndication(pOpenCB,
  251. StatusBuffer,
  252. StatusBufferSize);
  253. break;
  254. case NDIS_STATUS_WAN_FRAGMENT:
  255. NdisWanFragmentIndication(pOpenCB,
  256. StatusBuffer,
  257. StatusBufferSize);
  258. break;
  259. case NDIS_STATUS_TAPI_INDICATION:
  260. NdisWanTapiIndication(pOpenCB,
  261. StatusBuffer,
  262. StatusBufferSize);
  263. break;
  264. default:
  265. NdisWanDbgOut(DBG_INFO, DBG_PROTOCOL, ("Unknown Status Indication: 0x%x", GeneralStatus));
  266. break;
  267. }
  268. }
  269. VOID
  270. ProtoIndicateStatusComplete(
  271. IN NDIS_HANDLE ProtocolBindingContext
  272. )
  273. {
  274. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  275. }
  276. VOID
  277. ProtoWanSendComplete(
  278. IN NDIS_HANDLE ProtocolBindingContext,
  279. IN PNDIS_WAN_PACKET WanPacket,
  280. IN NDIS_STATUS Status
  281. )
  282. {
  283. PSEND_DESC SendDesc;
  284. PLINKCB LinkCB, RefLinkCB;
  285. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("ProtoWanSendComplete: Enter - WanPacket %p", WanPacket));
  286. //
  287. // Get info from the WanPacket
  288. //
  289. SendDesc = (PSEND_DESC)WanPacket->ProtocolReserved1;
  290. LinkCB = SendDesc->LinkCB;
  291. if (!IsLinkValid(LinkCB->hLinkHandle, FALSE, &RefLinkCB)) {
  292. NdisWanDbgOut(DBG_FAILURE, DBG_CL,
  293. ("NDISWAN: SendComplete after link has gone down NdisContext %p\n",
  294. LinkCB));
  295. return;
  296. }
  297. REMOVE_DBG_SEND(PacketTypeWan, LinkCB->OpenCB, WanPacket);
  298. ASSERT(RefLinkCB == LinkCB);
  299. NdisAcquireSpinLock(&LinkCB->Lock);
  300. CompleteSendDesc(SendDesc, Status);
  301. //
  302. // Deref for the ref applied in IsLinkValid
  303. //
  304. DEREF_LINKCB(LinkCB);
  305. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("ProtoWanSendComplete: Exit"));
  306. }
  307. NDIS_STATUS
  308. ProtoWanReceiveIndication(
  309. IN NDIS_HANDLE NdisLinkHandle,
  310. IN PUCHAR Packet,
  311. IN ULONG PacketSize
  312. )
  313. {
  314. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  315. PLINKCB LinkCB = NULL;
  316. PBUNDLECB BundleCB = NULL;
  317. PUCHAR DataBuffer;
  318. ULONG DataBufferSize;
  319. ULONG BytesCopied;
  320. PNDIS_PACKET NdisPacket;
  321. PNDIS_BUFFER NdisBuffer;
  322. PRECV_DESC RecvDesc;
  323. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProtoWanReceiveIndication: Enter - Context %x", NdisLinkHandle));
  324. do {
  325. if (!AreLinkAndBundleValid(NdisLinkHandle,
  326. TRUE,
  327. &LinkCB,
  328. &BundleCB)) {
  329. #if DBG
  330. DbgPrint("NDISWAN: Recv after link has gone down LinkContext %x\n",
  331. NdisLinkHandle);
  332. #endif
  333. break;
  334. }
  335. AcquireBundleLock(BundleCB);
  336. //
  337. // Make sure we don't try to process a receive indication
  338. // that is larger then our max data buffer size
  339. // winse 26544
  340. //
  341. if (PacketSize > glMRU) {
  342. break;
  343. }
  344. //
  345. // Build a receive descriptor for this receive. We have
  346. // to allocate with a large size because this packet might
  347. // be compressed.
  348. //
  349. RecvDesc =
  350. NdisWanAllocateRecvDesc(glLargeDataBufferSize);
  351. if (RecvDesc == NULL) {
  352. break;
  353. }
  354. //
  355. // Update the bandwidth on demand sample array with the latest send.
  356. // If we need to notify someone of a bandwidth event do it.
  357. //
  358. if (BundleCB->Flags & BOND_ENABLED) {
  359. UpdateBandwidthOnDemand(BundleCB->RUpperBonDInfo, PacketSize);
  360. CheckUpperThreshold(BundleCB);
  361. UpdateBandwidthOnDemand(BundleCB->RLowerBonDInfo, PacketSize);
  362. CheckLowerThreshold(BundleCB);
  363. }
  364. RecvDesc->CopyRequired = TRUE;
  365. RecvDesc->CurrentBuffer = Packet;
  366. RecvDesc->CurrentLength = PacketSize;
  367. RecvDesc->LinkCB = LinkCB;
  368. RecvDesc->BundleCB = BundleCB;
  369. //
  370. // Indicate to netmon if we are sniffing at
  371. // the link level
  372. //
  373. if (gbSniffLink &&
  374. (NdisWanCB.PromiscuousAdapter != NULL)) {
  375. //
  376. // Indicate a packet to netmon
  377. //
  378. IndicatePromiscuousRecv(BundleCB, RecvDesc, RECV_LINK);
  379. }
  380. //
  381. // Add up the statistics
  382. //
  383. LinkCB->Stats.BytesReceived += RecvDesc->CurrentLength;
  384. LinkCB->Stats.FramesReceived++;
  385. BundleCB->Stats.BytesReceived += RecvDesc->CurrentLength;
  386. LinkCB->Flags |= LINK_IN_RECV;
  387. BundleCB->Flags |= BUNDLE_IN_RECV;
  388. Status = (*LinkCB->RecvHandler)(LinkCB, RecvDesc);
  389. BundleCB->Flags &= ~BUNDLE_IN_RECV;
  390. LinkCB->Flags &= ~LINK_IN_RECV;
  391. if (Status != NDIS_STATUS_PENDING) {
  392. NdisWanFreeRecvDesc(RecvDesc);
  393. }
  394. } while ( 0 );
  395. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProtoWanReceiveIndication: Exit"));
  396. //
  397. // Deref's for the ref's applied in AreLinkAndBundleValid
  398. //
  399. DEREF_BUNDLECB_LOCKED(BundleCB);
  400. DEREF_LINKCB(LinkCB);
  401. return (NDIS_STATUS_SUCCESS);
  402. }
  403. VOID
  404. ProtoRequestComplete(
  405. IN NDIS_HANDLE ProtocolBindingContext,
  406. IN PNDIS_REQUEST NdisRequest,
  407. IN NDIS_STATUS Status
  408. )
  409. {
  410. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  411. PWAN_REQUEST pWanRequest;
  412. pWanRequest = CONTAINING_RECORD(NdisRequest,
  413. WAN_REQUEST,
  414. NdisRequest);
  415. NdisWanDbgOut(DBG_VERBOSE, DBG_REQUEST, ("ProtoRequestComplete: Enter - pWanRequest: 0x%p", pWanRequest));
  416. pWanRequest->NotificationStatus = Status;
  417. switch (pWanRequest->Origin) {
  418. case NDISWAN:
  419. NdisWanSetNotificationEvent(&pWanRequest->NotificationEvent);
  420. break;
  421. default:
  422. ASSERT(pWanRequest->Origin == NDISTAPI);
  423. NdisWanTapiRequestComplete(pOpenCB, pWanRequest);
  424. break;
  425. }
  426. NdisWanDbgOut(DBG_VERBOSE, DBG_REQUEST, ("ProtoRequestComplete: Exit"));
  427. }
  428. VOID
  429. ProtoBindAdapter(
  430. OUT PNDIS_STATUS Status,
  431. IN NDIS_HANDLE BindContext,
  432. IN PNDIS_STRING DeviceName,
  433. IN PVOID SystemSpecific1,
  434. IN PVOID SystemSpecific2
  435. )
  436. /*++
  437. Routine Name:
  438. ProtoBindAdapter
  439. Routine Description:
  440. This function is called by the NDIS wrapper to tell NdisWan
  441. to bind to an underlying miniport. NdisWan will open the
  442. miniport and query information on the device.
  443. Arguments:
  444. Status - Return status
  445. BindContext - Used in NdisBindAdapterComplete
  446. DeviceName - Name of device we are opening
  447. SS1 - Used in NdisOpenProtocolConfig
  448. SS2 - Reserved
  449. Return Values:
  450. --*/
  451. {
  452. POPENCB pOpenCB;
  453. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoBindAdapter - Enter %ls", DeviceName->Buffer));
  454. pOpenCB = NdisWanAllocateOpenCB(DeviceName);
  455. if (pOpenCB == NULL) {
  456. *Status = NDIS_STATUS_RESOURCES;
  457. return;
  458. }
  459. pOpenCB->Flags |= OPEN_IN_BIND;
  460. NdisWanInitializeNotificationEvent(&pOpenCB->InitEvent);
  461. *Status = ProtoOpenWanAdapter(pOpenCB);
  462. if (*Status != NDIS_STATUS_SUCCESS) {
  463. RemoveEntryGlobalList(OpenCBList, &pOpenCB->Linkage);
  464. NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("Failed to bind to %ls! Error 0x%x - %s",
  465. pOpenCB->MiniportName.Buffer, *Status, NdisWanGetNdisStatus(*Status)));
  466. NdisWanFreeOpenCB(pOpenCB);
  467. return;
  468. }
  469. //
  470. // Figure out if this is a legacy wan miniport.
  471. //
  472. if (pOpenCB->MediumType == NdisMediumWan) {
  473. pOpenCB->Flags |= OPEN_LEGACY;
  474. }
  475. NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("Successful Binding to %s miniport %ls!",
  476. (pOpenCB->Flags & OPEN_LEGACY) ? "Legacy" : "NDIS 5.0",
  477. pOpenCB->MiniportName.Buffer));
  478. //
  479. // Get the wan medium subtype
  480. //
  481. {
  482. WAN_REQUEST WanRequest;
  483. NdisZeroMemory(&WanRequest, sizeof(WanRequest));
  484. WanRequest.Type = SYNC;
  485. WanRequest.Origin = NDISWAN;
  486. WanRequest.OpenCB = pOpenCB;
  487. NdisWanInitializeNotificationEvent(&WanRequest.NotificationEvent);
  488. WanRequest.NdisRequest.RequestType =
  489. NdisRequestQueryInformation;
  490. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  491. OID_WAN_MEDIUM_SUBTYPE;
  492. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  493. &pOpenCB->MediumSubType;
  494. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  495. sizeof(pOpenCB->MediumSubType);
  496. *Status = NdisWanSubmitNdisRequest(pOpenCB, &WanRequest);
  497. if (*Status != NDIS_STATUS_SUCCESS) {
  498. NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_MEDIUM_SUBTYPE! Error 0x%x - %s",
  499. *Status, NdisWanGetNdisStatus(*Status)));
  500. pOpenCB->MediumSubType = NdisWanMediumHub;
  501. *Status = NDIS_STATUS_SUCCESS;
  502. }
  503. }
  504. if (pOpenCB->Flags & OPEN_LEGACY) {
  505. NDIS_WAN_INFO WanInfo;
  506. WAN_REQUEST WanRequest;
  507. //
  508. // This is a legacy wan miniport
  509. //
  510. NdisZeroMemory(&WanRequest, sizeof(WanRequest));
  511. WanRequest.Type = SYNC;
  512. WanRequest.Origin = NDISWAN;
  513. WanRequest.OpenCB = pOpenCB;
  514. NdisWanInitializeNotificationEvent(&WanRequest.NotificationEvent);
  515. //
  516. // Get more info...
  517. //
  518. NdisZeroMemory(&WanInfo, sizeof(WanInfo));
  519. WanRequest.NdisRequest.RequestType =
  520. NdisRequestQueryInformation;
  521. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  522. OID_WAN_GET_INFO;
  523. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  524. &WanInfo;
  525. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  526. sizeof(WanInfo);
  527. *Status = NdisWanSubmitNdisRequest(pOpenCB, &WanRequest);
  528. if (*Status != NDIS_STATUS_SUCCESS) {
  529. NDIS_STATUS CloseStatus;
  530. NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_GET_INFO! Error 0x%x - %s",
  531. *Status, NdisWanGetNdisStatus(*Status)));
  532. NdisAcquireSpinLock(&pOpenCB->Lock);
  533. pOpenCB->Flags |= OPEN_CLOSING;
  534. NdisWanInitializeNotificationEvent(&pOpenCB->NotificationEvent);
  535. NdisReleaseSpinLock(&pOpenCB->Lock);
  536. NdisCloseAdapter(&CloseStatus,
  537. pOpenCB->BindingHandle);
  538. if (CloseStatus == NDIS_STATUS_PENDING) {
  539. NdisWanWaitForNotificationEvent(&pOpenCB->NotificationEvent);
  540. }
  541. NdisWanFreeOpenCB(pOpenCB);
  542. return;
  543. }
  544. NdisMoveMemory(&pOpenCB->WanInfo, &WanInfo, sizeof(NDIS_WAN_INFO));
  545. if (pOpenCB->WanInfo.MaxTransmit == 0) {
  546. pOpenCB->WanInfo.MaxTransmit = 1;
  547. }
  548. if (pOpenCB->WanInfo.Endpoints == 0) {
  549. pOpenCB->WanInfo.Endpoints = 1000;
  550. }
  551. *Status = NdisWanAllocateSendResources(pOpenCB);
  552. if (*Status != NDIS_STATUS_SUCCESS) {
  553. NDIS_STATUS CloseStatus;
  554. NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from AllocateSendResources! Error 0x%x - %s",
  555. *Status, NdisWanGetNdisStatus(*Status)));
  556. NdisAcquireSpinLock(&pOpenCB->Lock);
  557. pOpenCB->Flags |= OPEN_CLOSING;
  558. NdisWanInitializeNotificationEvent(&pOpenCB->NotificationEvent);
  559. NdisReleaseSpinLock(&pOpenCB->Lock);
  560. NdisCloseAdapter(&CloseStatus,
  561. pOpenCB->BindingHandle);
  562. if (CloseStatus == NDIS_STATUS_PENDING) {
  563. NdisWanWaitForNotificationEvent(&pOpenCB->NotificationEvent);
  564. }
  565. NdisWanFreeOpenCB(pOpenCB);
  566. return;
  567. }
  568. //
  569. // Tell tapi about this device
  570. //
  571. if (pOpenCB->WanInfo.FramingBits & TAPI_PROVIDER) {
  572. NDISTAPI_CHARACTERISTICS Chars;
  573. ULONG NdisTapiKey;
  574. NdisMoveMemory(&Chars.Guid,
  575. &pOpenCB->Guid,
  576. sizeof(Chars.Guid));
  577. Chars.MediaType = pOpenCB->MediumSubType;
  578. Chars.RequestProc = NdisWanTapiRequestProc;
  579. //
  580. // Note that since there are typically very few
  581. // (< 10) wan miniports, just having an incrementing
  582. // counter will do. There is a pathological case where
  583. // one of the miniports can be added and removed a billion
  584. // times so that the counter wraps around and clashes with
  585. // an existing miniport - this is not even a stress scenario.
  586. //
  587. NdisTapiKey = NdisWanInterlockedInc(
  588. &glNdisTapiKey);
  589. pOpenCB->NdisTapiKey = UlongToHandle(NdisTapiKey);
  590. NdisTapiRegisterProvider(pOpenCB->NdisTapiKey, &Chars);
  591. }
  592. } else {
  593. //
  594. // This is a 5.0 miniport! We will do init work
  595. // when a call manager registers for this!
  596. //
  597. }
  598. pOpenCB->Flags &= ~OPEN_IN_BIND;
  599. NdisWanSetNotificationEvent(&pOpenCB->InitEvent);
  600. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoBindAdapter - Exit"));
  601. }
  602. VOID
  603. ProtoUnbindAdapter(
  604. OUT PNDIS_STATUS Status,
  605. IN NDIS_HANDLE ProtocolBindingContext,
  606. IN NDIS_HANDLE UnbindContext
  607. )
  608. {
  609. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  610. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnbindAdapter: Enter - OpenCB %p", pOpenCB));
  611. NdisAcquireSpinLock(&pOpenCB->Lock);
  612. while (pOpenCB->AfRegisteringCount != 0) {
  613. NdisReleaseSpinLock(&pOpenCB->Lock);
  614. NdisWanWaitForNotificationEvent(&pOpenCB->AfRegisteringEvent);
  615. NdisAcquireSpinLock(&pOpenCB->Lock);
  616. }
  617. if (!(pOpenCB->Flags & OPEN_LEGACY)) {
  618. while (!IsListEmpty(&pOpenCB->AfSapCBList)) {
  619. PCL_AFSAPCB AfSapCB;
  620. NDIS_STATUS RetStatus;
  621. AfSapCB =
  622. (PCL_AFSAPCB)RemoveHeadList(&pOpenCB->AfSapCBList);
  623. InsertTailList(&pOpenCB->AfSapCBClosing, &AfSapCB->Linkage);
  624. NdisReleaseSpinLock(&pOpenCB->Lock);
  625. NdisAcquireSpinLock(&AfSapCB->Lock);
  626. AfSapCB->Flags |= AFSAP_REMOVED_UNBIND;
  627. DEREF_CLAFSAPCB_LOCKED(AfSapCB);
  628. NdisAcquireSpinLock(&pOpenCB->Lock);
  629. }
  630. }
  631. pOpenCB->UnbindContext = UnbindContext;
  632. NdisReleaseSpinLock(&pOpenCB->Lock);
  633. if (pOpenCB->WanInfo.FramingBits & TAPI_PROVIDER) {
  634. NdisTapiDeregisterProvider(pOpenCB->NdisTapiKey);
  635. }
  636. DEREF_OPENCB(pOpenCB);
  637. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnbindAdapter: Exit"));
  638. *Status = NDIS_STATUS_PENDING;
  639. }
  640. VOID
  641. ProtoUnload(
  642. VOID
  643. )
  644. {
  645. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnload: Enter"));
  646. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnload: Exit"));
  647. }
  648. NDIS_STATUS
  649. ProtoPnPEvent(
  650. IN NDIS_HANDLE ProtocolBindingContext,
  651. IN PNET_PNP_EVENT NetPnPEvent
  652. )
  653. {
  654. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  655. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  656. if (pOpenCB == NULL) {
  657. return (NDIS_STATUS_SUCCESS);
  658. }
  659. switch (NetPnPEvent->NetEvent) {
  660. case NetEventSetPower:
  661. {
  662. NET_DEVICE_POWER_STATE PowerState;
  663. PowerState = *((NET_DEVICE_POWER_STATE*)NetPnPEvent->Buffer);
  664. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  665. ("ProtoPnPEvent: OpenCB %p %s State %d",
  666. pOpenCB, "SetPower", PowerState));
  667. switch (PowerState) {
  668. case NetDeviceStateD0:
  669. break;
  670. case NetDeviceStateD1:
  671. case NetDeviceStateD2:
  672. case NetDeviceStateD3:
  673. //
  674. // If this is the open on asyncmac I do not want it to be closed.
  675. // I will succeed the set power which should keep ndis from
  676. // unbinding me. If this is an open on any other miniport
  677. // I will return not supported so that I will get unbound from
  678. // the miniport. This is required for correct tapi behavior.
  679. //
  680. if (pOpenCB->MediumType == NdisMediumWan &&
  681. pOpenCB->MediumSubType == NdisWanMediumSerial &&
  682. !(pOpenCB->WanInfo.FramingBits & TAPI_PROVIDER)) {
  683. Status = NDIS_STATUS_SUCCESS;
  684. } else {
  685. Status = NDIS_STATUS_NOT_SUPPORTED;
  686. }
  687. //
  688. // In the case of a Critical Power event we will not
  689. // receive a Query so we must tear the connection down
  690. // directly from the Set.
  691. //
  692. // If we have any active connections signal rasman to
  693. // tear them down.
  694. //
  695. if (InterlockedCompareExchange(&pOpenCB->ActiveLinkCount, 0, 0)) {
  696. PIRP Irp;
  697. NdisAcquireSpinLock(&NdisWanCB.Lock);
  698. Irp = NdisWanCB.HibernateEventIrp;
  699. if ((Irp != NULL) &&
  700. IoSetCancelRoutine(Irp, NULL)){
  701. NdisWanCB.HibernateEventIrp = NULL;
  702. NdisReleaseSpinLock(&NdisWanCB.Lock);
  703. //
  704. // The irp is not being canceled so
  705. // lets do it!
  706. //
  707. Irp->IoStatus.Status = STATUS_SUCCESS;
  708. Irp->IoStatus.Information = 0;
  709. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  710. NdisAcquireSpinLock(&NdisWanCB.Lock);
  711. }
  712. NdisReleaseSpinLock(&NdisWanCB.Lock);
  713. }
  714. break;
  715. default:
  716. break;
  717. }
  718. }
  719. break;
  720. case NetEventQueryPower:
  721. {
  722. NET_DEVICE_POWER_STATE PowerState;
  723. PowerState = *((NET_DEVICE_POWER_STATE*)NetPnPEvent->Buffer);
  724. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  725. ("ProtoPnPEvent: OpenCB %p %s State %d",
  726. pOpenCB, "QueryPower", PowerState));
  727. //
  728. // If there is an active connection
  729. // on this binding refuse to go away
  730. //
  731. switch (PowerState) {
  732. case NetDeviceStateD0:
  733. break;
  734. case NetDeviceStateD1:
  735. case NetDeviceStateD2:
  736. case NetDeviceStateD3:
  737. //
  738. // If we have any active connections signal rasman to
  739. // tear them down.
  740. //
  741. if (InterlockedCompareExchange(&pOpenCB->ActiveLinkCount, 0, 0)) {
  742. PIRP Irp;
  743. NdisAcquireSpinLock(&NdisWanCB.Lock);
  744. Irp = NdisWanCB.HibernateEventIrp;
  745. if ((Irp != NULL) &&
  746. IoSetCancelRoutine(Irp, NULL)) {
  747. NdisWanCB.HibernateEventIrp = NULL;
  748. NdisReleaseSpinLock(&NdisWanCB.Lock);
  749. Irp->IoStatus.Status = STATUS_SUCCESS;
  750. Irp->IoStatus.Information = 0;
  751. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  752. NdisAcquireSpinLock(&NdisWanCB.Lock);
  753. }
  754. NdisReleaseSpinLock(&NdisWanCB.Lock);
  755. }
  756. break;
  757. default:
  758. break;
  759. }
  760. }
  761. break;
  762. case NetEventQueryRemoveDevice:
  763. case NetEventCancelRemoveDevice:
  764. case NetEventReconfigure:
  765. case NetEventBindList:
  766. default:
  767. break;
  768. }
  769. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoPnPEvent: Exit"));
  770. return (Status);
  771. }
  772. VOID
  773. ProtoCoSendComplete(
  774. IN NDIS_STATUS Status,
  775. IN NDIS_HANDLE ProtocolVcContext,
  776. IN PNDIS_PACKET Packet
  777. )
  778. {
  779. PLINKCB LinkCB;
  780. PBUNDLECB BundleCB;
  781. PSEND_DESC SendDesc;
  782. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  783. ("ProtoCoSendComplete: Enter - VC %p Packet: %p", ProtocolVcContext, Packet));
  784. if (!IsLinkValid(ProtocolVcContext, FALSE, &LinkCB)) {
  785. NdisWanDbgOut(DBG_FAILURE, DBG_CL,
  786. ("NDISWAN: SendComplete after link has gone down ProtocolVcContext %p\n",
  787. LinkCB));
  788. return;
  789. }
  790. REMOVE_DBG_SEND(PacketTypeNdis, LinkCB->OpenCB, Packet);
  791. //
  792. // Get Info from the NdisPacket
  793. //
  794. SendDesc = PPROTOCOL_RESERVED_FROM_NDIS(Packet)->SendDesc;
  795. NdisAcquireSpinLock(&LinkCB->Lock);
  796. ASSERT(SendDesc->LinkCB == LinkCB);
  797. CompleteSendDesc(SendDesc, Status);
  798. NdisAcquireSpinLock(&LinkCB->Lock);
  799. //
  800. // Remove ref that keeps the vc around
  801. //
  802. DerefVc(LinkCB);
  803. //
  804. // Deref for the ref applied in IsLinkValid
  805. //
  806. DEREF_LINKCB_LOCKED(LinkCB);
  807. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("ProtoCoSendComplete: Exit"));
  808. }
  809. VOID
  810. ProtoCoIndicateStatus(
  811. IN NDIS_HANDLE ProtocolBindingContext,
  812. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  813. IN NDIS_STATUS GeneralStatus,
  814. IN PVOID StatusBuffer,
  815. IN UINT StatusBufferSize
  816. )
  817. {
  818. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  819. PLINKCB LinkCB;
  820. PBUNDLECB BundleCB;
  821. if (!AreLinkAndBundleValid(ProtocolVcContext,
  822. TRUE,
  823. &LinkCB,
  824. &BundleCB)) {
  825. return;
  826. }
  827. switch (GeneralStatus) {
  828. case NDIS_STATUS_WAN_CO_FRAGMENT:
  829. NdisCoWanFragmentIndication(LinkCB,
  830. BundleCB,
  831. StatusBuffer,
  832. StatusBufferSize);
  833. break;
  834. case NDIS_STATUS_WAN_CO_LINKPARAMS:
  835. NdisCoWanLinkParamChange(LinkCB,
  836. BundleCB,
  837. StatusBuffer,
  838. StatusBufferSize);
  839. default:
  840. NdisWanDbgOut(DBG_INFO, DBG_PROTOCOL,
  841. ("Unknown Status Indication: 0x%x", GeneralStatus));
  842. break;
  843. }
  844. //
  845. // Deref's for ref's applied in AreLinkAndBundleValid
  846. //
  847. DEREF_LINKCB(LinkCB);
  848. DEREF_BUNDLECB(BundleCB);
  849. }
  850. UINT
  851. ProtoCoReceivePacket(
  852. IN NDIS_HANDLE ProtocolBindingContext,
  853. IN NDIS_HANDLE ProtocolVcContext,
  854. IN PNDIS_PACKET Packet
  855. )
  856. {
  857. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  858. PLINKCB LinkCB = NULL;
  859. PBUNDLECB BundleCB = NULL;
  860. NDIS_STATUS Status;
  861. ULONG BufferCount;
  862. LONG PacketSize;
  863. PNDIS_BUFFER FirstBuffer;
  864. PRECV_DESC RecvDesc;
  865. UINT RefCount = 0;
  866. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE,
  867. ("ProtoCoReceivePacket: Enter - OpenCB %p", pOpenCB));
  868. do {
  869. if (!AreLinkAndBundleValid(ProtocolVcContext,
  870. TRUE,
  871. &LinkCB,
  872. &BundleCB)) {
  873. break;
  874. }
  875. #if DBG
  876. NdisAcquireSpinLock(&LinkCB->Lock);
  877. if (LinkCB->ClCallState != CL_CALL_CONNECTED) {
  878. DbgPrint("NDISWAN: Vc not fully active but indicating data!\n");
  879. }
  880. NdisReleaseSpinLock(&LinkCB->Lock);
  881. #endif
  882. AcquireBundleLock(BundleCB);
  883. NdisQueryPacket(Packet,
  884. NULL,
  885. &BufferCount,
  886. &FirstBuffer,
  887. &PacketSize);
  888. if (PacketSize > (LONG)glMRU) {
  889. break;
  890. }
  891. PRECV_RESERVED_FROM_NDIS(Packet)->MagicNumber = MAGIC_EXTERNAL_RECV;
  892. RecvDesc =
  893. NdisWanAllocateRecvDesc(glLargeDataBufferSize);
  894. if (RecvDesc == NULL) {
  895. break;
  896. }
  897. RecvDesc->LinkCB = LinkCB;
  898. RecvDesc->BundleCB = BundleCB;
  899. //
  900. // If the packet has only one buffer we are happy, if not
  901. // we have to allocate our own ndis packet and buffers
  902. // and copy the data from the miniports packet into our packet
  903. //
  904. if (BufferCount > 1 ||
  905. NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) {
  906. RecvDesc->CurrentBuffer = RecvDesc->StartBuffer +
  907. MAC_HEADER_LENGTH +
  908. PROTOCOL_HEADER_LENGTH;
  909. //
  910. // Copy from the miniports packet to my packet
  911. //
  912. NdisWanCopyFromPacketToBuffer(Packet,
  913. 0,
  914. PacketSize,
  915. RecvDesc->CurrentBuffer,
  916. &RecvDesc->CurrentLength);
  917. ASSERT(PacketSize == RecvDesc->CurrentLength);
  918. } else {
  919. NdisQueryBuffer(FirstBuffer,
  920. &RecvDesc->CurrentBuffer,
  921. &RecvDesc->CurrentLength);
  922. ASSERT(PacketSize == RecvDesc->CurrentLength);
  923. RecvDesc->CopyRequired = TRUE;
  924. RecvDesc->OriginalPacket = Packet;
  925. RefCount = 1;
  926. }
  927. //
  928. // Indicate to netmon if we are sniffing at
  929. // the link level
  930. //
  931. if (gbSniffLink &&
  932. (NdisWanCB.PromiscuousAdapter != NULL)) {
  933. //
  934. // Indicate a packet to netmon
  935. //
  936. IndicatePromiscuousRecv(BundleCB, RecvDesc, RECV_LINK);
  937. }
  938. //
  939. // Update the bandwidth on demand sample array with the latest send.
  940. // If we need to notify someone of a bandwidth event do it.
  941. //
  942. if (BundleCB->Flags & BOND_ENABLED) {
  943. UpdateBandwidthOnDemand(BundleCB->RUpperBonDInfo, PacketSize);
  944. CheckUpperThreshold(BundleCB);
  945. UpdateBandwidthOnDemand(BundleCB->RLowerBonDInfo, PacketSize);
  946. CheckLowerThreshold(BundleCB);
  947. }
  948. //
  949. // Add up the statistics
  950. //
  951. LinkCB->Stats.BytesReceived += RecvDesc->CurrentLength;
  952. LinkCB->Stats.FramesReceived++;
  953. BundleCB->Stats.BytesReceived += RecvDesc->CurrentLength;
  954. Status = (*LinkCB->RecvHandler)(LinkCB, RecvDesc);
  955. if (Status != NDIS_STATUS_PENDING) {
  956. RecvDesc->OriginalPacket = NULL;
  957. NdisWanFreeRecvDesc(RecvDesc);
  958. RefCount = 0;
  959. }
  960. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProtoCoReceivePacket: Exit"));
  961. } while (0);
  962. //
  963. // Deref's for ref's applied by AreLinkAndBundleValid
  964. //
  965. DEREF_BUNDLECB_LOCKED(BundleCB);
  966. DEREF_LINKCB(LinkCB);
  967. return (RefCount);
  968. }
  969. NDIS_STATUS
  970. ProtoCoRequest(
  971. IN NDIS_HANDLE ProtocolAfContext,
  972. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  973. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  974. IN OUT PNDIS_REQUEST NdisRequest
  975. )
  976. {
  977. PCL_AFSAPCB AfSapCB = (PCL_AFSAPCB)ProtocolAfContext;
  978. NDIS_OID Oid;
  979. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequest: Enter - AfContext %p", ProtocolAfContext));
  980. if (NdisRequest->RequestType == NdisRequestQueryInformation) {
  981. Oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
  982. } else {
  983. Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
  984. }
  985. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("Oid - %x", Oid));
  986. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  987. switch (Oid) {
  988. case OID_CO_AF_CLOSE:
  989. {
  990. POPENCB OpenCB;
  991. PCL_AFSAPCB tAfSapCB;
  992. OpenCB = AfSapCB->OpenCB;
  993. NdisAcquireSpinLock(&OpenCB->Lock);
  994. while (OpenCB->AfRegisteringCount != 0) {
  995. NdisReleaseSpinLock(&OpenCB->Lock);
  996. NdisWanWaitForNotificationEvent(&OpenCB->AfRegisteringEvent);
  997. NdisAcquireSpinLock(&OpenCB->Lock);
  998. }
  999. for (tAfSapCB = (PCL_AFSAPCB)OpenCB->AfSapCBList.Flink;
  1000. (PVOID)tAfSapCB != (PVOID)&OpenCB->AfSapCBList;
  1001. tAfSapCB = (PCL_AFSAPCB)AfSapCB->Linkage.Flink) {
  1002. if (tAfSapCB == AfSapCB) {
  1003. break;
  1004. }
  1005. }
  1006. if ((PVOID)tAfSapCB == (PVOID)&OpenCB->AfSapCBList) {
  1007. NdisWanDbgOut(DBG_FAILURE, DBG_REQUEST, \
  1008. ("ProtoCoRequest: Af %p not on OpenCB %p list!", \
  1009. AfSapCB, OpenCB));
  1010. NdisReleaseSpinLock(&OpenCB->Lock);
  1011. break;
  1012. }
  1013. RemoveEntryList(&AfSapCB->Linkage);
  1014. InsertTailList(&OpenCB->AfSapCBClosing,
  1015. &AfSapCB->Linkage);
  1016. NdisReleaseSpinLock(&OpenCB->Lock);
  1017. NdisAcquireSpinLock(&AfSapCB->Lock);
  1018. ASSERT(!(AfSapCB->Flags & AFSAP_REMOVED_FLAGS));
  1019. ASSERT(AfSapCB->Flags & SAP_REGISTERED);
  1020. AfSapCB->Flags |= AFSAP_REMOVED_REQUEST;
  1021. DEREF_CLAFSAPCB_LOCKED(AfSapCB);
  1022. }
  1023. break;
  1024. default:
  1025. break;
  1026. }
  1027. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequest: Exit"));
  1028. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  1029. return (NDIS_STATUS_SUCCESS);
  1030. }
  1031. VOID
  1032. ProtoCoRequestComplete(
  1033. IN NDIS_STATUS Status,
  1034. IN NDIS_HANDLE ProtocolAfContext,
  1035. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  1036. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  1037. IN PNDIS_REQUEST NdisRequest
  1038. )
  1039. {
  1040. PCL_AFSAPCB AfSapCB = (PCL_AFSAPCB)ProtocolAfContext;
  1041. PWAN_REQUEST pWanRequest;
  1042. POPENCB pOpenCB;
  1043. pWanRequest = CONTAINING_RECORD(NdisRequest,
  1044. WAN_REQUEST,
  1045. NdisRequest);
  1046. pOpenCB = pWanRequest->OpenCB;
  1047. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequestComplete: Enter - WanRequest 0x%p", pWanRequest));
  1048. pWanRequest->NotificationStatus = Status;
  1049. switch (pWanRequest->Origin) {
  1050. case NDISWAN:
  1051. NdisWanSetNotificationEvent(&pWanRequest->NotificationEvent);
  1052. break;
  1053. default:
  1054. ASSERT(pWanRequest->Origin == NDISTAPI);
  1055. NdisWanTapiRequestComplete(pOpenCB, pWanRequest);
  1056. break;
  1057. }
  1058. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequestComplete: Exit"));
  1059. }
  1060. VOID
  1061. ProtoCoAfRegisterNotify(
  1062. IN NDIS_HANDLE ProtocolBindingContext,
  1063. IN PCO_ADDRESS_FAMILY AddressFamily
  1064. )
  1065. {
  1066. POPENCB OpenCB = (POPENCB)ProtocolBindingContext;
  1067. NDIS_CLIENT_CHARACTERISTICS ClCharacteristics;
  1068. PCL_AFSAPCB AfSapCB;
  1069. NDIS_STATUS Status;
  1070. ULONG GenericUlong;
  1071. NDIS_HANDLE AfHandle;
  1072. WAN_REQUEST WanRequest;
  1073. NDIS_WAN_CO_INFO WanInfo;
  1074. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1075. ("ProtoCoAfRegisterNotify: Enter - OpenCB %p AfType: %x", OpenCB, AddressFamily->AddressFamily));
  1076. //
  1077. // If this is a proxied address family we are interested,
  1078. // so open the address family, register a sap and return success.
  1079. //
  1080. if (AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_TAPI) {
  1081. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1082. ("ProtoCoAfRegisterNotify: Af not tapi do not open!"));
  1083. return;
  1084. }
  1085. NdisAcquireSpinLock(&OpenCB->Lock);
  1086. for (AfSapCB = (PCL_AFSAPCB)OpenCB->AfSapCBList.Flink;
  1087. (PVOID)AfSapCB != (PVOID)&OpenCB->AfSapCBList;
  1088. AfSapCB = (PCL_AFSAPCB)AfSapCB->Linkage.Flink) {
  1089. if (AfSapCB->Af.AddressFamily == AddressFamily->AddressFamily) {
  1090. //
  1091. // we already have this addressfamily on this open block.
  1092. //
  1093. NdisReleaseSpinLock(&OpenCB->Lock);
  1094. return;
  1095. }
  1096. }
  1097. AfSapCB =
  1098. NdisWanAllocateClAfSapCB(OpenCB, AddressFamily);
  1099. if (AfSapCB == NULL) {
  1100. NdisReleaseSpinLock(&OpenCB->Lock);
  1101. return;
  1102. }
  1103. //
  1104. // Use this crude mechanism to keep us from unbinding while in the
  1105. // middle of af notification. The count is cleaned up either in
  1106. // openafcomplete (if open failed) or in registersapcomplete.
  1107. //
  1108. if (OpenCB->AfRegisteringCount == 0) {
  1109. NdisWanInitializeNotificationEvent(&OpenCB->AfRegisteringEvent);
  1110. }
  1111. OpenCB->AfRegisteringCount++;
  1112. NdisReleaseSpinLock(&OpenCB->Lock);
  1113. //
  1114. // Open the address family
  1115. //
  1116. NdisZeroMemory(&ClCharacteristics, sizeof(NDIS_CLIENT_CHARACTERISTICS));
  1117. ClCharacteristics.MajorVersion = NDISWAN_MAJOR_VERSION;
  1118. ClCharacteristics.MinorVersion = NDISWAN_MINOR_VERSION;
  1119. ClCharacteristics.ClCreateVcHandler = ClCreateVc;
  1120. ClCharacteristics.ClDeleteVcHandler = ClDeleteVc;
  1121. ClCharacteristics.ClRequestHandler = ProtoCoRequest;
  1122. ClCharacteristics.ClRequestCompleteHandler = ProtoCoRequestComplete;
  1123. ClCharacteristics.ClOpenAfCompleteHandler = ClOpenAfComplete;
  1124. ClCharacteristics.ClCloseAfCompleteHandler = ClCloseAfComplete;
  1125. ClCharacteristics.ClRegisterSapCompleteHandler = ClRegisterSapComplete;
  1126. ClCharacteristics.ClDeregisterSapCompleteHandler = ClDeregisterSapComplete;
  1127. ClCharacteristics.ClMakeCallCompleteHandler = ClMakeCallComplete;
  1128. ClCharacteristics.ClModifyCallQoSCompleteHandler = ClModifyQoSComplete;
  1129. ClCharacteristics.ClCloseCallCompleteHandler = ClCloseCallComplete;
  1130. ClCharacteristics.ClAddPartyCompleteHandler = NULL;
  1131. ClCharacteristics.ClDropPartyCompleteHandler = NULL;
  1132. ClCharacteristics.ClIncomingCallHandler = ClIncomingCall;
  1133. ClCharacteristics.ClIncomingCallQoSChangeHandler = ClIncomingCallQoSChange;
  1134. ClCharacteristics.ClIncomingCloseCallHandler = ClIncomingCloseCall;
  1135. ClCharacteristics.ClIncomingDropPartyHandler = NULL;
  1136. ClCharacteristics.ClCallConnectedHandler = ClCallConnected;
  1137. Status =
  1138. NdisClOpenAddressFamily(OpenCB->BindingHandle,
  1139. AddressFamily,
  1140. AfSapCB,
  1141. &ClCharacteristics,
  1142. sizeof(NDIS_CLIENT_CHARACTERISTICS),
  1143. &AfHandle);
  1144. if (Status != NDIS_STATUS_PENDING) {
  1145. ClOpenAfComplete(Status, AfSapCB, AfHandle);
  1146. }
  1147. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1148. ("ClOpenAddressFamily AfHandle 0x%x status: 0x%x", AfSapCB->AfHandle, Status));
  1149. //
  1150. // Do some OID's to the miniport. This is a
  1151. // CoNDIS miniport and are destined for the
  1152. // miniport so AfHandle and VcHandle = NULL!
  1153. //
  1154. NdisZeroMemory(&WanRequest, sizeof(WanRequest));
  1155. WanRequest.Type = SYNC;
  1156. WanRequest.Origin = NDISWAN;
  1157. WanRequest.OpenCB = OpenCB;
  1158. WanRequest.AfHandle = NULL;
  1159. WanRequest.VcHandle = NULL;
  1160. NdisWanInitializeNotificationEvent(&WanRequest.NotificationEvent);
  1161. //
  1162. // Get more info...
  1163. //
  1164. WanRequest.NdisRequest.RequestType =
  1165. NdisRequestQueryInformation;
  1166. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  1167. OID_WAN_CO_GET_INFO;
  1168. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  1169. &WanInfo;
  1170. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  1171. sizeof(WanInfo);
  1172. Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
  1173. if (Status == NDIS_STATUS_SUCCESS) {
  1174. OpenCB->WanInfo.MaxFrameSize = WanInfo.MaxFrameSize;
  1175. OpenCB->WanInfo.MaxTransmit = WanInfo.MaxSendWindow;
  1176. OpenCB->WanInfo.FramingBits = WanInfo.FramingBits;
  1177. OpenCB->WanInfo.DesiredACCM = WanInfo.DesiredACCM;
  1178. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1179. ("CO_GET_INFO: FrameSize %d SendWindow %d",
  1180. WanInfo.MaxFrameSize, WanInfo.MaxSendWindow));
  1181. } else {
  1182. //
  1183. // This guy will get default framing behaviour
  1184. //
  1185. OpenCB->WanInfo.FramingBits = PPP_FRAMING;
  1186. OpenCB->WanInfo.DesiredACCM = 0;
  1187. //
  1188. // Find the send window
  1189. //
  1190. WanRequest.NdisRequest.RequestType =
  1191. NdisRequestQueryInformation;
  1192. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  1193. OID_GEN_MAXIMUM_SEND_PACKETS;
  1194. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  1195. &GenericUlong;
  1196. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  1197. sizeof(ULONG);
  1198. Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
  1199. OpenCB->WanInfo.MaxTransmit = (Status == NDIS_STATUS_SUCCESS &&
  1200. GenericUlong > 0) ? GenericUlong : 10;
  1201. //
  1202. // Find the max transmit size
  1203. //
  1204. WanRequest.NdisRequest.RequestType =
  1205. NdisRequestQueryInformation;
  1206. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  1207. OID_GEN_MAXIMUM_TOTAL_SIZE;
  1208. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  1209. &GenericUlong;
  1210. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  1211. sizeof(ULONG);
  1212. Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
  1213. OpenCB->WanInfo.MaxFrameSize = (Status == NDIS_STATUS_SUCCESS) ?
  1214. GenericUlong : 1500;
  1215. }
  1216. OpenCB->WanInfo.Endpoints = 1000;
  1217. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoCoAfRegisterNotify: Exit"));
  1218. }
  1219. NDIS_STATUS
  1220. DoNewLineUpToProtocol(
  1221. PPROTOCOLCB ProtocolCB
  1222. )
  1223. /*++
  1224. Routine Name:
  1225. Routine Description:
  1226. Arguments:
  1227. Return Values:
  1228. --*/
  1229. {
  1230. PMINIPORTCB MiniportCB;
  1231. NDIS_STATUS Status;
  1232. PBUNDLECB BundleCB = ProtocolCB->BundleCB;
  1233. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocol: Enter"));
  1234. do {
  1235. NdisAcquireSpinLock(&MiniportCBList.Lock);
  1236. //
  1237. // Find the adapter that this lineup is for. Look for the adapter
  1238. // that has the appropriate protocoltype. If it is NBF we need
  1239. // to look for a specific adapter.
  1240. //
  1241. for (MiniportCB = (PMINIPORTCB)MiniportCBList.List.Flink;
  1242. (PVOID)MiniportCB != (PVOID)&MiniportCBList.List;
  1243. MiniportCB = (PMINIPORTCB)MiniportCB->Linkage.Flink) {
  1244. if (MiniportCB->ProtocolType == ProtocolCB->ProtocolType) {
  1245. if (ProtocolCB->ProtocolType != PROTOCOL_NBF) {
  1246. break;
  1247. }
  1248. //
  1249. // Must be NBF so verify the AdapterName!!!
  1250. //
  1251. if (NdisEqualUnicodeString(&MiniportCB->AdapterName,&ProtocolCB->BindingName, FALSE)) {
  1252. break;
  1253. }
  1254. }
  1255. }
  1256. if ((PVOID)MiniportCB == (PVOID)&MiniportCBList.List) {
  1257. //
  1258. // The adapter was not found...
  1259. //
  1260. NdisWanDbgOut(DBG_FAILURE, DBG_PROTOCOL, ("Adapter not found!"));
  1261. NdisReleaseSpinLock(&MiniportCBList.Lock);
  1262. Status = NDISWAN_ERROR_NO_ROUTE;
  1263. break;
  1264. }
  1265. ASSERT(MiniportCB->ProtocolType == ProtocolCB->ProtocolType);
  1266. ETH_COPY_NETWORK_ADDRESS(ProtocolCB->NdisWanAddress, MiniportCB->NetworkAddress);
  1267. FillNdisWanIndices(ProtocolCB->NdisWanAddress,
  1268. BundleCB->hBundleHandle,
  1269. ProtocolCB->ProtocolHandle);
  1270. NdisZeroMemory(ProtocolCB->TransportAddress, 6);
  1271. NdisAcquireSpinLock(&MiniportCB->Lock);
  1272. InsertTailList(&MiniportCB->ProtocolCBList,
  1273. &ProtocolCB->MiniportLinkage);
  1274. ProtocolCB->MiniportCB = MiniportCB;
  1275. REF_MINIPORTCB(MiniportCB);
  1276. NdisReleaseSpinLock(&MiniportCB->Lock);
  1277. NdisReleaseSpinLock(&MiniportCBList.Lock);
  1278. Status = DoLineUpToProtocol(ProtocolCB);
  1279. if (Status != NDIS_STATUS_SUCCESS) {
  1280. NdisAcquireSpinLock(&MiniportCBList.Lock);
  1281. NdisAcquireSpinLock(&MiniportCB->Lock);
  1282. RemoveEntryList(&ProtocolCB->MiniportLinkage);
  1283. if (MiniportCB->Flags & HALT_IN_PROGRESS) {
  1284. NdisWanSetSyncEvent(&MiniportCB->HaltEvent);
  1285. }
  1286. NdisReleaseSpinLock(&MiniportCB->Lock);
  1287. NdisReleaseSpinLock(&MiniportCBList.Lock);
  1288. DEREF_MINIPORTCB(MiniportCB);
  1289. }
  1290. } while (FALSE);
  1291. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocols: Exit"));
  1292. return (Status);
  1293. }
  1294. NDIS_STATUS
  1295. DoLineUpToProtocol(
  1296. IN PPROTOCOLCB ProtocolCB
  1297. )
  1298. /*++
  1299. Routine Name:
  1300. Routine Description:
  1301. Arguments:
  1302. Return Values:
  1303. --*/
  1304. {
  1305. ULONG AllocationSize;
  1306. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1307. PNDIS_WAN_LINE_UP LineUpInfo;
  1308. PMINIPORTCB MiniportCB = ProtocolCB->MiniportCB;
  1309. PBUNDLECB BundleCB = ProtocolCB->BundleCB;
  1310. KIRQL OldIrql;
  1311. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Enter"));
  1312. ASSERT(MiniportCB != NULL);
  1313. AllocationSize = sizeof(NDIS_WAN_LINE_UP) +
  1314. ProtocolCB->ulLineUpInfoLength +
  1315. (sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
  1316. (2 * sizeof(PVOID)));
  1317. NdisWanAllocateMemory(&LineUpInfo, AllocationSize, LINEUPINFO_TAG);
  1318. if (LineUpInfo != NULL) {
  1319. ULONG LineUpHandle = ProtocolCB->ulTransportHandle;
  1320. //
  1321. // Needs to be in 1/100bps, we store in Bps
  1322. //
  1323. LineUpInfo->LinkSpeed = BundleCB->SFlowSpec.PeakBandwidth * 8 / 100;
  1324. //
  1325. // Set the MTU for this protocol
  1326. //
  1327. {
  1328. POPENCB OpenCB = BundleCB->NextLinkToXmit->OpenCB;
  1329. //
  1330. // If this connection is running over a VPN we will downsize
  1331. // the MTU
  1332. //
  1333. if ((OpenCB->MediumSubType == NdisWanMediumPPTP ||
  1334. OpenCB->MediumSubType == NdisWanMediumL2TP)) {
  1335. LineUpInfo->MaximumTotalSize = ProtocolCB->TunnelMTU;
  1336. } else {
  1337. LineUpInfo->MaximumTotalSize = ProtocolCB->MTU;
  1338. }
  1339. if (LineUpInfo->MaximumTotalSize > BundleCB->SFlowSpec.MaxSduSize) {
  1340. LineUpInfo->MaximumTotalSize =
  1341. BundleCB->SFlowSpec.MaxSduSize;
  1342. }
  1343. #if 0
  1344. //
  1345. // Figure out the size of the ppp header...
  1346. //
  1347. BundleCB->FramingInfo.PPPHeaderLength =
  1348. CalcPPPHeaderLength(BundleCB->FramingInfo.SendFramingBits,
  1349. BundleCB->SendFlags);
  1350. if (LineUpInfo->MaximumTotalSize > BundleCB->FramingInfo.PPPHeaderLength) {
  1351. LineUpInfo->MaximumTotalSize -= BundleCB->FramingInfo.PPPHeaderLength;
  1352. } else {
  1353. LineUpInfo->MaximumTotalSize = 0;
  1354. }
  1355. #endif
  1356. }
  1357. LineUpInfo->Quality = NdisWanReliable;
  1358. LineUpInfo->SendWindow = (USHORT)BundleCB->SendWindow;
  1359. LineUpInfo->ProtocolType = ProtocolCB->ProtocolType;
  1360. LineUpInfo->DeviceName.Length = ProtocolCB->InDeviceName.Length;
  1361. LineUpInfo->DeviceName.MaximumLength = MAX_NAME_LENGTH + 1;
  1362. LineUpInfo->DeviceName.Buffer = (PWCHAR)((PUCHAR)LineUpInfo +
  1363. sizeof(NDIS_WAN_LINE_UP) +
  1364. sizeof(PVOID));
  1365. (ULONG_PTR)LineUpInfo->DeviceName.Buffer &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  1366. if (ProtocolCB->InDeviceName.Length != 0) {
  1367. NdisMoveMemory(LineUpInfo->DeviceName.Buffer,
  1368. ProtocolCB->InDeviceName.Buffer,
  1369. ProtocolCB->InDeviceName.Length);
  1370. }
  1371. LineUpInfo->ProtocolBuffer = (PUCHAR)LineUpInfo +
  1372. sizeof(NDIS_WAN_LINE_UP) +
  1373. (sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
  1374. sizeof(PVOID));
  1375. (ULONG_PTR)LineUpInfo->ProtocolBuffer &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  1376. //
  1377. //
  1378. // The Remote address (DEST address in a send) is what we use to
  1379. // mutilplex sends across our single adapter/binding context.
  1380. // The address has the following format:
  1381. //
  1382. // XX XX XX YY YY ZZ
  1383. //
  1384. // XX = Randomly generated OUI
  1385. // YY = Index into the active bundle connection table to get bundlecb
  1386. // ZZ = Index into the protocol table of a bundle to get protocolcb
  1387. //
  1388. ETH_COPY_NETWORK_ADDRESS(LineUpInfo->RemoteAddress,ProtocolCB->NdisWanAddress);
  1389. ETH_COPY_NETWORK_ADDRESS(LineUpInfo->LocalAddress,ProtocolCB->TransportAddress);
  1390. //
  1391. // Fill in the protocol specific information
  1392. //
  1393. LineUpInfo->ProtocolBufferLength = ProtocolCB->ulLineUpInfoLength;
  1394. if (ProtocolCB->ulLineUpInfoLength > 0) {
  1395. NdisMoveMemory(LineUpInfo->ProtocolBuffer,
  1396. ProtocolCB->LineUpInfo,
  1397. ProtocolCB->ulLineUpInfoLength);
  1398. }
  1399. // KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1400. // DbgPrint("LineUp: %x, MTU %d\n",
  1401. // LineUpInfo->ProtocolType, LineUpInfo->MaximumTotalSize);
  1402. //
  1403. // Do the line up indication
  1404. //
  1405. NdisMIndicateStatus(MiniportCB->MiniportHandle,
  1406. NDIS_STATUS_WAN_LINE_UP,
  1407. LineUpInfo,
  1408. AllocationSize);
  1409. // KeLowerIrql(OldIrql);
  1410. //
  1411. // Update protocol queue depth
  1412. //
  1413. {
  1414. PROTOCOL_INFO ProtocolInfo = {0};
  1415. ULONG ByteDepth;
  1416. ULONG i;
  1417. AcquireBundleLock(BundleCB);
  1418. ProtocolInfo.ProtocolType = ProtocolCB->ProtocolType;
  1419. GetProtocolInfo(&ProtocolInfo);
  1420. //
  1421. // Set the send queue byte depth.
  1422. //
  1423. ByteDepth =
  1424. ProtocolInfo.PacketQueueDepth;
  1425. //
  1426. // If the byte depth is less then 4
  1427. // full packets, then set it to 4 full
  1428. // packets.
  1429. //
  1430. if (ByteDepth < (ProtocolInfo.MTU * 4)) {
  1431. ByteDepth = ProtocolInfo.MTU * 4;
  1432. }
  1433. for (i = 0; i <= MAX_MCML; i++) {
  1434. ProtocolCB->PacketQueue[i].MaxByteDepth =
  1435. ByteDepth;
  1436. }
  1437. ReleaseBundleLock(BundleCB);
  1438. }
  1439. //
  1440. // If this was the first line up for this protocolcb and
  1441. // this lineup was answered we need to collect some info
  1442. //
  1443. if (ProtocolCB->ulTransportHandle == 0) {
  1444. *((ULONG UNALIGNED *)(&LineUpHandle)) =
  1445. *((ULONG UNALIGNED *)(&LineUpInfo->LocalAddress[2]));
  1446. if (LineUpHandle != 0) {
  1447. AcquireBundleLock(BundleCB);
  1448. ETH_COPY_NETWORK_ADDRESS(ProtocolCB->TransportAddress, LineUpInfo->LocalAddress);
  1449. ProtocolCB->ulTransportHandle = LineUpHandle;
  1450. if (LineUpInfo->DeviceName.Length != 0) {
  1451. NdisWanStringToNdisString(&ProtocolCB->OutDeviceName,
  1452. LineUpInfo->DeviceName.Buffer);
  1453. }
  1454. ReleaseBundleLock(BundleCB);
  1455. //
  1456. // If this is an nbf adapter
  1457. //
  1458. if (ProtocolCB->ProtocolType == (USHORT)PROTOCOL_NBF) {
  1459. ASSERT(MiniportCB->ProtocolType == (USHORT)PROTOCOL_NBF);
  1460. MiniportCB->NbfProtocolCB = ProtocolCB;
  1461. }
  1462. } else {
  1463. Status = NDISWAN_ERROR_NO_ROUTE;
  1464. }
  1465. }
  1466. NdisWanFreeMemory(LineUpInfo);
  1467. } else {
  1468. Status = NDIS_STATUS_RESOURCES;
  1469. }
  1470. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Exit"));
  1471. return (Status);
  1472. }
  1473. NDIS_STATUS
  1474. DoLineDownToProtocol(
  1475. PPROTOCOLCB ProtocolCB
  1476. )
  1477. {
  1478. NDIS_WAN_LINE_DOWN WanLineDown;
  1479. PNDIS_WAN_LINE_DOWN LineDownInfo = &WanLineDown;
  1480. PMINIPORTCB MiniportCB = ProtocolCB->MiniportCB;
  1481. PBUNDLECB BundleCB = ProtocolCB->BundleCB;
  1482. KIRQL OldIrql;
  1483. //
  1484. // The Remote address (DEST address) is what we use to mutilplex
  1485. // sends across our single adapter/binding context. The address
  1486. // has the following format:
  1487. //
  1488. // XX XX YY YY YY YY
  1489. //
  1490. // XX = Randomly generated OUI
  1491. // YY = ProtocolCB
  1492. //
  1493. ETH_COPY_NETWORK_ADDRESS(LineDownInfo->RemoteAddress, ProtocolCB->NdisWanAddress);
  1494. ETH_COPY_NETWORK_ADDRESS(LineDownInfo->LocalAddress, ProtocolCB->TransportAddress);
  1495. //
  1496. // If this is an nbf adapter
  1497. //
  1498. if (ProtocolCB->ProtocolType == PROTOCOL_NBF) {
  1499. MiniportCB->NbfProtocolCB = NULL;
  1500. }
  1501. ProtocolCB->ulTransportHandle = 0;
  1502. ProtocolCB->State = PROTOCOL_UNROUTED;
  1503. ReleaseBundleLock(BundleCB);
  1504. NdisMIndicateStatus(MiniportCB->MiniportHandle,
  1505. NDIS_STATUS_WAN_LINE_DOWN,
  1506. LineDownInfo,
  1507. sizeof(NDIS_WAN_LINE_DOWN));
  1508. NdisAcquireSpinLock(&MiniportCB->Lock);
  1509. RemoveEntryList(&ProtocolCB->MiniportLinkage);
  1510. if (MiniportCB->Flags & HALT_IN_PROGRESS) {
  1511. NdisWanSetSyncEvent(&MiniportCB->HaltEvent);
  1512. }
  1513. NdisReleaseSpinLock(&MiniportCB->Lock);
  1514. DEREF_MINIPORTCB(MiniportCB);
  1515. AcquireBundleLock(BundleCB);
  1516. return (NDIS_STATUS_SUCCESS);
  1517. }
  1518. VOID
  1519. CompleteSendDesc(
  1520. PSEND_DESC SendDesc,
  1521. NDIS_STATUS Status
  1522. )
  1523. {
  1524. PLINKCB LinkCB;
  1525. PBUNDLECB BundleCB;
  1526. PPROTOCOLCB ProtocolCB;
  1527. PNDIS_PACKET OriginalPacket;
  1528. BOOLEAN FreeLink = FALSE, FreeBundle = FALSE;
  1529. BOOLEAN LegacyLink;
  1530. PULONG pulRefCount;
  1531. PCM_VCCB CmVcCB;
  1532. INT Class;
  1533. ULONG DescFlags;
  1534. LinkCB = SendDesc->LinkCB;
  1535. ProtocolCB = SendDesc->ProtocolCB;
  1536. OriginalPacket = SendDesc->OriginalPacket;
  1537. Class = SendDesc->Class;
  1538. DescFlags = SendDesc->Flags;
  1539. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  1540. ("SendDesc: 0x%p, OriginalPacket: 0x%p, Status: %x",
  1541. SendDesc, OriginalPacket, Status));
  1542. NdisWanFreeSendDesc(SendDesc);
  1543. //
  1544. // Bundle that this link is on
  1545. //
  1546. BundleCB = LinkCB->BundleCB;
  1547. //
  1548. // Deref for the ref applied when a senddesc
  1549. // was retrieved for this link. We don't need to do
  1550. // the full deref here because we are keeping the
  1551. // link from going away with the ref applied when
  1552. // we got the sendcomplete.
  1553. //
  1554. --LinkCB->RefCount;
  1555. #ifdef DBG_SENDARRAY
  1556. {
  1557. SendArray[__si] = 'c';
  1558. if (++__si == MAX_BYTE_DEPTH) {
  1559. __si = 0;
  1560. }
  1561. }
  1562. #endif
  1563. NdisReleaseSpinLock(&LinkCB->Lock);
  1564. AcquireBundleLock(BundleCB);
  1565. LegacyLink = (LinkCB->OpenCB->Flags & OPEN_LEGACY) ? 1 : 0;
  1566. //
  1567. // If the sendwindow is currently full, this completion
  1568. // opens the sendwindow.
  1569. //
  1570. if (LinkCB->OutstandingFrames == LinkCB->SendWindow) {
  1571. LinkCB->SendWindowOpen = TRUE;
  1572. if (LinkCB->LinkActive) {
  1573. BundleCB->SendingLinks++;
  1574. }
  1575. }
  1576. LinkCB->OutstandingFrames--;
  1577. if (DescFlags & SEND_DESC_FRAG) {
  1578. InterlockedDecrement(&ProtocolCB->PacketQueue[Class].OutstandingFrags);
  1579. }
  1580. pulRefCount =
  1581. &(PMINIPORT_RESERVED_FROM_NDIS(OriginalPacket)->RefCount);
  1582. ASSERT(*pulRefCount > 0);
  1583. //
  1584. // See if the reference count is zero, if it is not
  1585. // we just return.
  1586. //
  1587. if (InterlockedDecrement(pulRefCount) != 0) {
  1588. SendPacketOnBundle(BundleCB);
  1589. return;
  1590. }
  1591. ReleaseBundleLock(BundleCB);
  1592. //
  1593. // Complete this NdisPacket back to the transport
  1594. //
  1595. NDIS_SET_PACKET_STATUS(OriginalPacket, Status);
  1596. CompleteNdisPacket(ProtocolCB->MiniportCB,
  1597. ProtocolCB,
  1598. OriginalPacket);
  1599. AcquireBundleLock(BundleCB);
  1600. BundleCB->OutstandingFrames--;
  1601. if ((BundleCB->Flags & FRAMES_PENDING_EVENT) &&
  1602. (BundleCB->OutstandingFrames == 0)) {
  1603. NdisWanSetSyncEvent(&BundleCB->OutstandingFramesEvent);
  1604. }
  1605. //
  1606. // Called with bundle lock help but returns with lock released
  1607. //
  1608. SendPacketOnBundle(BundleCB);
  1609. //
  1610. // Deref for ref applied when sent a packet to be framed.
  1611. //
  1612. DEREF_BUNDLECB(BundleCB);
  1613. }
  1614. #if 0
  1615. ULONG
  1616. CalcPPPHeaderLength(
  1617. ULONG FramingBits,
  1618. ULONG Flags
  1619. )
  1620. {
  1621. ULONG HeaderLength = 0;
  1622. if (FramingBits & PPP_FRAMING) {
  1623. if (!(FramingBits & PPP_COMPRESS_ADDRESS_CONTROL)) {
  1624. //
  1625. // If there is no address/control compression
  1626. // we need a pointer and a length
  1627. //
  1628. if (FramingBits & LLC_ENCAPSULATION) {
  1629. HeaderLength += 4;
  1630. } else {
  1631. HeaderLength += 2;
  1632. }
  1633. }
  1634. //
  1635. // If this is not from our private I/O interface we will
  1636. // build the rest of the header.
  1637. //
  1638. if (FramingBits & PPP_MULTILINK_FRAMING) {
  1639. if (!(FramingBits & PPP_COMPRESS_PROTOCOL_FIELD)) {
  1640. //
  1641. // No protocol compression
  1642. //
  1643. HeaderLength += 1;
  1644. }
  1645. HeaderLength += 1;
  1646. if (!(FramingBits & PPP_SHORT_SEQUENCE_HDR_FORMAT)) {
  1647. //
  1648. // We are using long sequence number
  1649. //
  1650. HeaderLength += 2;
  1651. }
  1652. HeaderLength += 2;
  1653. }
  1654. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  1655. //
  1656. // We are doing compression/encryption so we need
  1657. // a length
  1658. //
  1659. //
  1660. // It appears that legacy ras (< NT 4.0) requires that
  1661. // the PPP protocol field in a compressed packet not
  1662. // be compressed, ie has to have the leading 0x00
  1663. //
  1664. if (!(FramingBits & PPP_COMPRESS_PROTOCOL_FIELD)) {
  1665. //
  1666. // No protocol compression
  1667. //
  1668. HeaderLength += 1;
  1669. }
  1670. //
  1671. // Add protocol and coherency bytes
  1672. //
  1673. HeaderLength += 3;
  1674. }
  1675. if (!(FramingBits & PPP_COMPRESS_PROTOCOL_FIELD) ||
  1676. (Flags & (DO_COMPRESSION | DO_ENCRYPTION))) {
  1677. HeaderLength += 1;
  1678. }
  1679. HeaderLength += 1;
  1680. } else if (FramingBits & RAS_FRAMING) {
  1681. //
  1682. // If this is old ras framing:
  1683. //
  1684. // Alter the framing so that 0xFF 0x03 is not added
  1685. // and that the first byte is 0xFD not 0x00 0xFD
  1686. //
  1687. // So basically, a RAS compression looks like
  1688. // <0xFD> <2 BYTE COHERENCY> <NBF DATA FIELD>
  1689. //
  1690. // Whereas uncompressed looks like
  1691. // <NBF DATA FIELD> which always starts with 0xF0
  1692. //
  1693. // If this is ppp framing:
  1694. //
  1695. // A compressed frame will look like (before address/control
  1696. // - multilink is added)
  1697. // <0x00> <0xFD> <2 Byte Coherency> <Compressed Data>
  1698. //
  1699. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  1700. //
  1701. // Coherency bytes
  1702. //
  1703. HeaderLength += 3;
  1704. }
  1705. }
  1706. // DbgPrint("PPPHeaderLength %d\n", HeaderLength);
  1707. return (HeaderLength);
  1708. }
  1709. #endif