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.

2254 lines
61 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. NdisMoveMemory(&Chars.Guid,
  574. &pOpenCB->Guid,
  575. sizeof(Chars.Guid));
  576. Chars.MediaType = pOpenCB->MediumSubType;
  577. Chars.RequestProc = NdisWanTapiRequestProc;
  578. NdisTapiRegisterProvider(pOpenCB, &Chars);
  579. }
  580. } else {
  581. //
  582. // This is a 5.0 miniport! We will do init work
  583. // when a call manager registers for this!
  584. //
  585. }
  586. pOpenCB->Flags &= ~OPEN_IN_BIND;
  587. NdisWanSetNotificationEvent(&pOpenCB->InitEvent);
  588. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoBindAdapter - Exit"));
  589. }
  590. VOID
  591. ProtoUnbindAdapter(
  592. OUT PNDIS_STATUS Status,
  593. IN NDIS_HANDLE ProtocolBindingContext,
  594. IN NDIS_HANDLE UnbindContext
  595. )
  596. {
  597. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  598. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnbindAdapter: Enter - OpenCB %p", pOpenCB));
  599. NdisAcquireSpinLock(&pOpenCB->Lock);
  600. while (pOpenCB->AfRegisteringCount != 0) {
  601. NdisReleaseSpinLock(&pOpenCB->Lock);
  602. NdisWanWaitForNotificationEvent(&pOpenCB->AfRegisteringEvent);
  603. NdisAcquireSpinLock(&pOpenCB->Lock);
  604. }
  605. if (!(pOpenCB->Flags & OPEN_LEGACY)) {
  606. while (!IsListEmpty(&pOpenCB->AfSapCBList)) {
  607. PCL_AFSAPCB AfSapCB;
  608. NDIS_STATUS RetStatus;
  609. AfSapCB =
  610. (PCL_AFSAPCB)RemoveHeadList(&pOpenCB->AfSapCBList);
  611. InsertTailList(&pOpenCB->AfSapCBClosing, &AfSapCB->Linkage);
  612. NdisReleaseSpinLock(&pOpenCB->Lock);
  613. NdisAcquireSpinLock(&AfSapCB->Lock);
  614. AfSapCB->Flags |= AFSAP_REMOVED_UNBIND;
  615. DEREF_CLAFSAPCB_LOCKED(AfSapCB);
  616. NdisAcquireSpinLock(&pOpenCB->Lock);
  617. }
  618. }
  619. pOpenCB->UnbindContext = UnbindContext;
  620. NdisReleaseSpinLock(&pOpenCB->Lock);
  621. if (pOpenCB->WanInfo.FramingBits & TAPI_PROVIDER) {
  622. NdisTapiDeregisterProvider(pOpenCB);
  623. }
  624. DEREF_OPENCB(pOpenCB);
  625. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnbindAdapter: Exit"));
  626. *Status = NDIS_STATUS_PENDING;
  627. }
  628. VOID
  629. ProtoUnload(
  630. VOID
  631. )
  632. {
  633. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnload: Enter"));
  634. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoUnload: Exit"));
  635. }
  636. NDIS_STATUS
  637. ProtoPnPEvent(
  638. IN NDIS_HANDLE ProtocolBindingContext,
  639. IN PNET_PNP_EVENT NetPnPEvent
  640. )
  641. {
  642. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  643. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  644. if (pOpenCB == NULL) {
  645. return (NDIS_STATUS_SUCCESS);
  646. }
  647. switch (NetPnPEvent->NetEvent) {
  648. case NetEventSetPower:
  649. {
  650. NET_DEVICE_POWER_STATE PowerState;
  651. PowerState = *((NET_DEVICE_POWER_STATE*)NetPnPEvent->Buffer);
  652. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  653. ("ProtoPnPEvent: OpenCB %p %s State %d",
  654. pOpenCB, "SetPower", PowerState));
  655. switch (PowerState) {
  656. case NetDeviceStateD0:
  657. break;
  658. case NetDeviceStateD1:
  659. case NetDeviceStateD2:
  660. case NetDeviceStateD3:
  661. //
  662. // If this is the open on asyncmac I do not want it to be closed.
  663. // I will succeed the set power which should keep ndis from
  664. // unbinding me. If this is an open on any other miniport
  665. // I will return not supported so that I will get unbound from
  666. // the miniport. This is required for correct tapi behavior.
  667. //
  668. if (pOpenCB->MediumType == NdisMediumWan &&
  669. pOpenCB->MediumSubType == NdisWanMediumSerial &&
  670. !(pOpenCB->WanInfo.FramingBits & TAPI_PROVIDER)) {
  671. Status = NDIS_STATUS_SUCCESS;
  672. } else {
  673. Status = NDIS_STATUS_NOT_SUPPORTED;
  674. }
  675. //
  676. // In the case of a Critical Power event we will not
  677. // receive a Query so we must tear the connection down
  678. // directly from the Set.
  679. //
  680. // If we have any active connections signal rasman to
  681. // tear them down.
  682. //
  683. if (InterlockedCompareExchange(&pOpenCB->ActiveLinkCount, 0, 0)) {
  684. PIRP Irp;
  685. NdisAcquireSpinLock(&NdisWanCB.Lock);
  686. Irp = NdisWanCB.HibernateEventIrp;
  687. if ((Irp != NULL) &&
  688. IoSetCancelRoutine(Irp, NULL)){
  689. NdisWanCB.HibernateEventIrp = NULL;
  690. NdisReleaseSpinLock(&NdisWanCB.Lock);
  691. //
  692. // The irp is not being canceled so
  693. // lets do it!
  694. //
  695. Irp->IoStatus.Status = STATUS_SUCCESS;
  696. Irp->IoStatus.Information = 0;
  697. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  698. NdisAcquireSpinLock(&NdisWanCB.Lock);
  699. }
  700. NdisReleaseSpinLock(&NdisWanCB.Lock);
  701. }
  702. break;
  703. default:
  704. break;
  705. }
  706. }
  707. break;
  708. case NetEventQueryPower:
  709. {
  710. NET_DEVICE_POWER_STATE PowerState;
  711. PowerState = *((NET_DEVICE_POWER_STATE*)NetPnPEvent->Buffer);
  712. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  713. ("ProtoPnPEvent: OpenCB %p %s State %d",
  714. pOpenCB, "QueryPower", PowerState));
  715. //
  716. // If there is an active connection
  717. // on this binding refuse to go away
  718. //
  719. switch (PowerState) {
  720. case NetDeviceStateD0:
  721. break;
  722. case NetDeviceStateD1:
  723. case NetDeviceStateD2:
  724. case NetDeviceStateD3:
  725. //
  726. // If we have any active connections signal rasman to
  727. // tear them down.
  728. //
  729. if (InterlockedCompareExchange(&pOpenCB->ActiveLinkCount, 0, 0)) {
  730. PIRP Irp;
  731. NdisAcquireSpinLock(&NdisWanCB.Lock);
  732. Irp = NdisWanCB.HibernateEventIrp;
  733. if ((Irp != NULL) &&
  734. IoSetCancelRoutine(Irp, NULL)) {
  735. NdisWanCB.HibernateEventIrp = NULL;
  736. NdisReleaseSpinLock(&NdisWanCB.Lock);
  737. Irp->IoStatus.Status = STATUS_SUCCESS;
  738. Irp->IoStatus.Information = 0;
  739. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  740. NdisAcquireSpinLock(&NdisWanCB.Lock);
  741. }
  742. NdisReleaseSpinLock(&NdisWanCB.Lock);
  743. }
  744. break;
  745. default:
  746. break;
  747. }
  748. }
  749. break;
  750. case NetEventQueryRemoveDevice:
  751. case NetEventCancelRemoveDevice:
  752. case NetEventReconfigure:
  753. case NetEventBindList:
  754. default:
  755. break;
  756. }
  757. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoPnPEvent: Exit"));
  758. return (Status);
  759. }
  760. VOID
  761. ProtoCoSendComplete(
  762. IN NDIS_STATUS Status,
  763. IN NDIS_HANDLE ProtocolVcContext,
  764. IN PNDIS_PACKET Packet
  765. )
  766. {
  767. PLINKCB LinkCB;
  768. PBUNDLECB BundleCB;
  769. PSEND_DESC SendDesc;
  770. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  771. ("ProtoCoSendComplete: Enter - VC %p Packet: %p", ProtocolVcContext, Packet));
  772. if (!IsLinkValid(ProtocolVcContext, FALSE, &LinkCB)) {
  773. NdisWanDbgOut(DBG_FAILURE, DBG_CL,
  774. ("NDISWAN: SendComplete after link has gone down ProtocolVcContext %p\n",
  775. LinkCB));
  776. return;
  777. }
  778. REMOVE_DBG_SEND(PacketTypeNdis, LinkCB->OpenCB, Packet);
  779. //
  780. // Get Info from the NdisPacket
  781. //
  782. SendDesc = PPROTOCOL_RESERVED_FROM_NDIS(Packet)->SendDesc;
  783. NdisAcquireSpinLock(&LinkCB->Lock);
  784. ASSERT(SendDesc->LinkCB == LinkCB);
  785. CompleteSendDesc(SendDesc, Status);
  786. NdisAcquireSpinLock(&LinkCB->Lock);
  787. //
  788. // Remove ref that keeps the vc around
  789. //
  790. DerefVc(LinkCB);
  791. //
  792. // Deref for the ref applied in IsLinkValid
  793. //
  794. DEREF_LINKCB_LOCKED(LinkCB);
  795. NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("ProtoCoSendComplete: Exit"));
  796. }
  797. VOID
  798. ProtoCoIndicateStatus(
  799. IN NDIS_HANDLE ProtocolBindingContext,
  800. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  801. IN NDIS_STATUS GeneralStatus,
  802. IN PVOID StatusBuffer,
  803. IN UINT StatusBufferSize
  804. )
  805. {
  806. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  807. PLINKCB LinkCB;
  808. PBUNDLECB BundleCB;
  809. if (!AreLinkAndBundleValid(ProtocolVcContext,
  810. TRUE,
  811. &LinkCB,
  812. &BundleCB)) {
  813. return;
  814. }
  815. switch (GeneralStatus) {
  816. case NDIS_STATUS_WAN_CO_FRAGMENT:
  817. NdisCoWanFragmentIndication(LinkCB,
  818. BundleCB,
  819. StatusBuffer,
  820. StatusBufferSize);
  821. break;
  822. case NDIS_STATUS_WAN_CO_LINKPARAMS:
  823. NdisCoWanLinkParamChange(LinkCB,
  824. BundleCB,
  825. StatusBuffer,
  826. StatusBufferSize);
  827. default:
  828. NdisWanDbgOut(DBG_INFO, DBG_PROTOCOL,
  829. ("Unknown Status Indication: 0x%x", GeneralStatus));
  830. break;
  831. }
  832. //
  833. // Deref's for ref's applied in AreLinkAndBundleValid
  834. //
  835. DEREF_LINKCB(LinkCB);
  836. DEREF_BUNDLECB(BundleCB);
  837. }
  838. UINT
  839. ProtoCoReceivePacket(
  840. IN NDIS_HANDLE ProtocolBindingContext,
  841. IN NDIS_HANDLE ProtocolVcContext,
  842. IN PNDIS_PACKET Packet
  843. )
  844. {
  845. POPENCB pOpenCB = (POPENCB)ProtocolBindingContext;
  846. PLINKCB LinkCB = NULL;
  847. PBUNDLECB BundleCB = NULL;
  848. NDIS_STATUS Status;
  849. ULONG BufferCount;
  850. LONG PacketSize;
  851. PNDIS_BUFFER FirstBuffer;
  852. PRECV_DESC RecvDesc;
  853. UINT RefCount = 0;
  854. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE,
  855. ("ProtoCoReceivePacket: Enter - OpenCB %p", pOpenCB));
  856. do {
  857. if (!AreLinkAndBundleValid(ProtocolVcContext,
  858. TRUE,
  859. &LinkCB,
  860. &BundleCB)) {
  861. break;
  862. }
  863. #if DBG
  864. NdisAcquireSpinLock(&LinkCB->Lock);
  865. if (LinkCB->ClCallState != CL_CALL_CONNECTED) {
  866. DbgPrint("NDISWAN: Vc not fully active but indicating data!\n");
  867. }
  868. NdisReleaseSpinLock(&LinkCB->Lock);
  869. #endif
  870. AcquireBundleLock(BundleCB);
  871. NdisQueryPacket(Packet,
  872. NULL,
  873. &BufferCount,
  874. &FirstBuffer,
  875. &PacketSize);
  876. if (PacketSize > (LONG)glMRU) {
  877. break;
  878. }
  879. PRECV_RESERVED_FROM_NDIS(Packet)->MagicNumber = MAGIC_EXTERNAL_RECV;
  880. RecvDesc =
  881. NdisWanAllocateRecvDesc(glLargeDataBufferSize);
  882. if (RecvDesc == NULL) {
  883. break;
  884. }
  885. RecvDesc->LinkCB = LinkCB;
  886. RecvDesc->BundleCB = BundleCB;
  887. //
  888. // If the packet has only one buffer we are happy, if not
  889. // we have to allocate our own ndis packet and buffers
  890. // and copy the data from the miniports packet into our packet
  891. //
  892. if (BufferCount > 1 ||
  893. NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) {
  894. RecvDesc->CurrentBuffer = RecvDesc->StartBuffer +
  895. MAC_HEADER_LENGTH +
  896. PROTOCOL_HEADER_LENGTH;
  897. //
  898. // Copy from the miniports packet to my packet
  899. //
  900. NdisWanCopyFromPacketToBuffer(Packet,
  901. 0,
  902. PacketSize,
  903. RecvDesc->CurrentBuffer,
  904. &RecvDesc->CurrentLength);
  905. ASSERT(PacketSize == RecvDesc->CurrentLength);
  906. } else {
  907. NdisQueryBuffer(FirstBuffer,
  908. &RecvDesc->CurrentBuffer,
  909. &RecvDesc->CurrentLength);
  910. ASSERT(PacketSize == RecvDesc->CurrentLength);
  911. RecvDesc->CopyRequired = TRUE;
  912. RecvDesc->OriginalPacket = Packet;
  913. RefCount = 1;
  914. }
  915. //
  916. // Indicate to netmon if we are sniffing at
  917. // the link level
  918. //
  919. if (gbSniffLink &&
  920. (NdisWanCB.PromiscuousAdapter != NULL)) {
  921. //
  922. // Indicate a packet to netmon
  923. //
  924. IndicatePromiscuousRecv(BundleCB, RecvDesc, RECV_LINK);
  925. }
  926. //
  927. // Update the bandwidth on demand sample array with the latest send.
  928. // If we need to notify someone of a bandwidth event do it.
  929. //
  930. if (BundleCB->Flags & BOND_ENABLED) {
  931. UpdateBandwidthOnDemand(BundleCB->RUpperBonDInfo, PacketSize);
  932. CheckUpperThreshold(BundleCB);
  933. UpdateBandwidthOnDemand(BundleCB->RLowerBonDInfo, PacketSize);
  934. CheckLowerThreshold(BundleCB);
  935. }
  936. //
  937. // Add up the statistics
  938. //
  939. LinkCB->Stats.BytesReceived += RecvDesc->CurrentLength;
  940. LinkCB->Stats.FramesReceived++;
  941. BundleCB->Stats.BytesReceived += RecvDesc->CurrentLength;
  942. Status = (*LinkCB->RecvHandler)(LinkCB, RecvDesc);
  943. if (Status != NDIS_STATUS_PENDING) {
  944. RecvDesc->OriginalPacket = NULL;
  945. NdisWanFreeRecvDesc(RecvDesc);
  946. RefCount = 0;
  947. }
  948. NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProtoCoReceivePacket: Exit"));
  949. } while (0);
  950. //
  951. // Deref's for ref's applied by AreLinkAndBundleValid
  952. //
  953. DEREF_BUNDLECB_LOCKED(BundleCB);
  954. DEREF_LINKCB(LinkCB);
  955. return (RefCount);
  956. }
  957. NDIS_STATUS
  958. ProtoCoRequest(
  959. IN NDIS_HANDLE ProtocolAfContext,
  960. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  961. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  962. IN OUT PNDIS_REQUEST NdisRequest
  963. )
  964. {
  965. PCL_AFSAPCB AfSapCB = (PCL_AFSAPCB)ProtocolAfContext;
  966. NDIS_OID Oid;
  967. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequest: Enter - AfContext %p", ProtocolAfContext));
  968. if (NdisRequest->RequestType == NdisRequestQueryInformation) {
  969. Oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
  970. } else {
  971. Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
  972. }
  973. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("Oid - %x", Oid));
  974. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  975. switch (Oid) {
  976. case OID_CO_AF_CLOSE:
  977. {
  978. POPENCB OpenCB;
  979. PCL_AFSAPCB tAfSapCB;
  980. OpenCB = AfSapCB->OpenCB;
  981. NdisAcquireSpinLock(&OpenCB->Lock);
  982. while (OpenCB->AfRegisteringCount != 0) {
  983. NdisReleaseSpinLock(&OpenCB->Lock);
  984. NdisWanWaitForNotificationEvent(&OpenCB->AfRegisteringEvent);
  985. NdisAcquireSpinLock(&OpenCB->Lock);
  986. }
  987. for (tAfSapCB = (PCL_AFSAPCB)OpenCB->AfSapCBList.Flink;
  988. (PVOID)tAfSapCB != (PVOID)&OpenCB->AfSapCBList;
  989. tAfSapCB = (PCL_AFSAPCB)AfSapCB->Linkage.Flink) {
  990. if (tAfSapCB == AfSapCB) {
  991. break;
  992. }
  993. }
  994. if ((PVOID)tAfSapCB == (PVOID)&OpenCB->AfSapCBList) {
  995. NdisWanDbgOut(DBG_FAILURE, DBG_REQUEST, \
  996. ("ProtoCoRequest: Af %p not on OpenCB %p list!", \
  997. AfSapCB, OpenCB));
  998. NdisReleaseSpinLock(&OpenCB->Lock);
  999. break;
  1000. }
  1001. RemoveEntryList(&AfSapCB->Linkage);
  1002. InsertTailList(&OpenCB->AfSapCBClosing,
  1003. &AfSapCB->Linkage);
  1004. NdisReleaseSpinLock(&OpenCB->Lock);
  1005. NdisAcquireSpinLock(&AfSapCB->Lock);
  1006. ASSERT(!(AfSapCB->Flags & AFSAP_REMOVED_FLAGS));
  1007. ASSERT(AfSapCB->Flags & SAP_REGISTERED);
  1008. AfSapCB->Flags |= AFSAP_REMOVED_REQUEST;
  1009. DEREF_CLAFSAPCB_LOCKED(AfSapCB);
  1010. }
  1011. break;
  1012. default:
  1013. break;
  1014. }
  1015. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequest: Exit"));
  1016. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  1017. return (NDIS_STATUS_SUCCESS);
  1018. }
  1019. VOID
  1020. ProtoCoRequestComplete(
  1021. IN NDIS_STATUS Status,
  1022. IN NDIS_HANDLE ProtocolAfContext,
  1023. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  1024. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  1025. IN PNDIS_REQUEST NdisRequest
  1026. )
  1027. {
  1028. PCL_AFSAPCB AfSapCB = (PCL_AFSAPCB)ProtocolAfContext;
  1029. PWAN_REQUEST pWanRequest;
  1030. POPENCB pOpenCB;
  1031. pWanRequest = CONTAINING_RECORD(NdisRequest,
  1032. WAN_REQUEST,
  1033. NdisRequest);
  1034. pOpenCB = pWanRequest->OpenCB;
  1035. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequestComplete: Enter - WanRequest 0x%p", pWanRequest));
  1036. pWanRequest->NotificationStatus = Status;
  1037. switch (pWanRequest->Origin) {
  1038. case NDISWAN:
  1039. NdisWanSetNotificationEvent(&pWanRequest->NotificationEvent);
  1040. break;
  1041. default:
  1042. ASSERT(pWanRequest->Origin == NDISTAPI);
  1043. NdisWanTapiRequestComplete(pOpenCB, pWanRequest);
  1044. break;
  1045. }
  1046. NdisWanDbgOut(DBG_TRACE, DBG_REQUEST, ("ProtoCoRequestComplete: Exit"));
  1047. }
  1048. VOID
  1049. ProtoCoAfRegisterNotify(
  1050. IN NDIS_HANDLE ProtocolBindingContext,
  1051. IN PCO_ADDRESS_FAMILY AddressFamily
  1052. )
  1053. {
  1054. POPENCB OpenCB = (POPENCB)ProtocolBindingContext;
  1055. NDIS_CLIENT_CHARACTERISTICS ClCharacteristics;
  1056. PCL_AFSAPCB AfSapCB;
  1057. NDIS_STATUS Status;
  1058. ULONG GenericUlong;
  1059. NDIS_HANDLE AfHandle;
  1060. WAN_REQUEST WanRequest;
  1061. NDIS_WAN_CO_INFO WanInfo;
  1062. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1063. ("ProtoCoAfRegisterNotify: Enter - OpenCB %p AfType: %x", OpenCB, AddressFamily->AddressFamily));
  1064. //
  1065. // If this is a proxied address family we are interested,
  1066. // so open the address family, register a sap and return success.
  1067. //
  1068. if (AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_TAPI) {
  1069. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1070. ("ProtoCoAfRegisterNotify: Af not tapi do not open!"));
  1071. return;
  1072. }
  1073. NdisAcquireSpinLock(&OpenCB->Lock);
  1074. for (AfSapCB = (PCL_AFSAPCB)OpenCB->AfSapCBList.Flink;
  1075. (PVOID)AfSapCB != (PVOID)&OpenCB->AfSapCBList;
  1076. AfSapCB = (PCL_AFSAPCB)AfSapCB->Linkage.Flink) {
  1077. if (AfSapCB->Af.AddressFamily == AddressFamily->AddressFamily) {
  1078. //
  1079. // we already have this addressfamily on this open block.
  1080. //
  1081. NdisReleaseSpinLock(&OpenCB->Lock);
  1082. return;
  1083. }
  1084. }
  1085. AfSapCB =
  1086. NdisWanAllocateClAfSapCB(OpenCB, AddressFamily);
  1087. if (AfSapCB == NULL) {
  1088. NdisReleaseSpinLock(&OpenCB->Lock);
  1089. return;
  1090. }
  1091. //
  1092. // Use this crude mechanism to keep us from unbinding while in the
  1093. // middle of af notification. The count is cleaned up either in
  1094. // openafcomplete (if open failed) or in registersapcomplete.
  1095. //
  1096. if (OpenCB->AfRegisteringCount == 0) {
  1097. NdisWanInitializeNotificationEvent(&OpenCB->AfRegisteringEvent);
  1098. }
  1099. OpenCB->AfRegisteringCount++;
  1100. NdisReleaseSpinLock(&OpenCB->Lock);
  1101. //
  1102. // Open the address family
  1103. //
  1104. NdisZeroMemory(&ClCharacteristics, sizeof(NDIS_CLIENT_CHARACTERISTICS));
  1105. ClCharacteristics.MajorVersion = NDISWAN_MAJOR_VERSION;
  1106. ClCharacteristics.MinorVersion = NDISWAN_MINOR_VERSION;
  1107. ClCharacteristics.ClCreateVcHandler = ClCreateVc;
  1108. ClCharacteristics.ClDeleteVcHandler = ClDeleteVc;
  1109. ClCharacteristics.ClRequestHandler = ProtoCoRequest;
  1110. ClCharacteristics.ClRequestCompleteHandler = ProtoCoRequestComplete;
  1111. ClCharacteristics.ClOpenAfCompleteHandler = ClOpenAfComplete;
  1112. ClCharacteristics.ClCloseAfCompleteHandler = ClCloseAfComplete;
  1113. ClCharacteristics.ClRegisterSapCompleteHandler = ClRegisterSapComplete;
  1114. ClCharacteristics.ClDeregisterSapCompleteHandler = ClDeregisterSapComplete;
  1115. ClCharacteristics.ClMakeCallCompleteHandler = ClMakeCallComplete;
  1116. ClCharacteristics.ClModifyCallQoSCompleteHandler = ClModifyQoSComplete;
  1117. ClCharacteristics.ClCloseCallCompleteHandler = ClCloseCallComplete;
  1118. ClCharacteristics.ClAddPartyCompleteHandler = NULL;
  1119. ClCharacteristics.ClDropPartyCompleteHandler = NULL;
  1120. ClCharacteristics.ClIncomingCallHandler = ClIncomingCall;
  1121. ClCharacteristics.ClIncomingCallQoSChangeHandler = ClIncomingCallQoSChange;
  1122. ClCharacteristics.ClIncomingCloseCallHandler = ClIncomingCloseCall;
  1123. ClCharacteristics.ClIncomingDropPartyHandler = NULL;
  1124. ClCharacteristics.ClCallConnectedHandler = ClCallConnected;
  1125. Status =
  1126. NdisClOpenAddressFamily(OpenCB->BindingHandle,
  1127. AddressFamily,
  1128. AfSapCB,
  1129. &ClCharacteristics,
  1130. sizeof(NDIS_CLIENT_CHARACTERISTICS),
  1131. &AfHandle);
  1132. if (Status != NDIS_STATUS_PENDING) {
  1133. ClOpenAfComplete(Status, AfSapCB, AfHandle);
  1134. }
  1135. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1136. ("ClOpenAddressFamily AfHandle 0x%x status: 0x%x", AfSapCB->AfHandle, Status));
  1137. //
  1138. // Do some OID's to the miniport. This is a
  1139. // CoNDIS miniport and are destined for the
  1140. // miniport so AfHandle and VcHandle = NULL!
  1141. //
  1142. NdisZeroMemory(&WanRequest, sizeof(WanRequest));
  1143. WanRequest.Type = SYNC;
  1144. WanRequest.Origin = NDISWAN;
  1145. WanRequest.OpenCB = OpenCB;
  1146. WanRequest.AfHandle = NULL;
  1147. WanRequest.VcHandle = NULL;
  1148. NdisWanInitializeNotificationEvent(&WanRequest.NotificationEvent);
  1149. //
  1150. // Get more info...
  1151. //
  1152. WanRequest.NdisRequest.RequestType =
  1153. NdisRequestQueryInformation;
  1154. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  1155. OID_WAN_CO_GET_INFO;
  1156. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  1157. &WanInfo;
  1158. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  1159. sizeof(WanInfo);
  1160. Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
  1161. if (Status == NDIS_STATUS_SUCCESS) {
  1162. OpenCB->WanInfo.MaxFrameSize = WanInfo.MaxFrameSize;
  1163. OpenCB->WanInfo.MaxTransmit = WanInfo.MaxSendWindow;
  1164. OpenCB->WanInfo.FramingBits = WanInfo.FramingBits;
  1165. OpenCB->WanInfo.DesiredACCM = WanInfo.DesiredACCM;
  1166. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL,
  1167. ("CO_GET_INFO: FrameSize %d SendWindow %d",
  1168. WanInfo.MaxFrameSize, WanInfo.MaxSendWindow));
  1169. } else {
  1170. //
  1171. // This guy will get default framing behaviour
  1172. //
  1173. OpenCB->WanInfo.FramingBits = PPP_FRAMING;
  1174. OpenCB->WanInfo.DesiredACCM = 0;
  1175. //
  1176. // Find the send window
  1177. //
  1178. WanRequest.NdisRequest.RequestType =
  1179. NdisRequestQueryInformation;
  1180. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  1181. OID_GEN_MAXIMUM_SEND_PACKETS;
  1182. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  1183. &GenericUlong;
  1184. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  1185. sizeof(ULONG);
  1186. Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
  1187. OpenCB->WanInfo.MaxTransmit = (Status == NDIS_STATUS_SUCCESS &&
  1188. GenericUlong > 0) ? GenericUlong : 10;
  1189. //
  1190. // Find the max transmit size
  1191. //
  1192. WanRequest.NdisRequest.RequestType =
  1193. NdisRequestQueryInformation;
  1194. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
  1195. OID_GEN_MAXIMUM_TOTAL_SIZE;
  1196. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
  1197. &GenericUlong;
  1198. WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
  1199. sizeof(ULONG);
  1200. Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
  1201. OpenCB->WanInfo.MaxFrameSize = (Status == NDIS_STATUS_SUCCESS) ?
  1202. GenericUlong : 1500;
  1203. }
  1204. OpenCB->WanInfo.Endpoints = 1000;
  1205. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("ProtoCoAfRegisterNotify: Exit"));
  1206. }
  1207. NDIS_STATUS
  1208. DoNewLineUpToProtocol(
  1209. PPROTOCOLCB ProtocolCB
  1210. )
  1211. /*++
  1212. Routine Name:
  1213. Routine Description:
  1214. Arguments:
  1215. Return Values:
  1216. --*/
  1217. {
  1218. PMINIPORTCB MiniportCB;
  1219. NDIS_STATUS Status;
  1220. PBUNDLECB BundleCB = ProtocolCB->BundleCB;
  1221. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocol: Enter"));
  1222. do {
  1223. NdisAcquireSpinLock(&MiniportCBList.Lock);
  1224. //
  1225. // Find the adapter that this lineup is for. Look for the adapter
  1226. // that has the appropriate protocoltype. If it is NBF we need
  1227. // to look for a specific adapter.
  1228. //
  1229. for (MiniportCB = (PMINIPORTCB)MiniportCBList.List.Flink;
  1230. (PVOID)MiniportCB != (PVOID)&MiniportCBList.List;
  1231. MiniportCB = (PMINIPORTCB)MiniportCB->Linkage.Flink) {
  1232. if (MiniportCB->ProtocolType == ProtocolCB->ProtocolType) {
  1233. if (ProtocolCB->ProtocolType != PROTOCOL_NBF) {
  1234. break;
  1235. }
  1236. //
  1237. // Must be NBF so verify the AdapterName!!!
  1238. //
  1239. if (NdisWanCompareNdisString(&MiniportCB->AdapterName,&ProtocolCB->BindingName)) {
  1240. break;
  1241. }
  1242. }
  1243. }
  1244. if ((PVOID)MiniportCB == (PVOID)&MiniportCBList.List) {
  1245. //
  1246. // The adapter was not found...
  1247. //
  1248. NdisWanDbgOut(DBG_FAILURE, DBG_PROTOCOL, ("Adapter not found!"));
  1249. NdisReleaseSpinLock(&MiniportCBList.Lock);
  1250. Status = NDISWAN_ERROR_NO_ROUTE;
  1251. break;
  1252. }
  1253. ASSERT(MiniportCB->ProtocolType == ProtocolCB->ProtocolType);
  1254. ETH_COPY_NETWORK_ADDRESS(ProtocolCB->NdisWanAddress, MiniportCB->NetworkAddress);
  1255. FillNdisWanIndices(ProtocolCB->NdisWanAddress,
  1256. BundleCB->hBundleHandle,
  1257. ProtocolCB->ProtocolHandle);
  1258. NdisZeroMemory(ProtocolCB->TransportAddress, 6);
  1259. NdisAcquireSpinLock(&MiniportCB->Lock);
  1260. InsertTailList(&MiniportCB->ProtocolCBList,
  1261. &ProtocolCB->MiniportLinkage);
  1262. ProtocolCB->MiniportCB = MiniportCB;
  1263. REF_MINIPORTCB(MiniportCB);
  1264. NdisReleaseSpinLock(&MiniportCB->Lock);
  1265. NdisReleaseSpinLock(&MiniportCBList.Lock);
  1266. Status = DoLineUpToProtocol(ProtocolCB);
  1267. if (Status != NDIS_STATUS_SUCCESS) {
  1268. NdisAcquireSpinLock(&MiniportCBList.Lock);
  1269. NdisAcquireSpinLock(&MiniportCB->Lock);
  1270. RemoveEntryList(&ProtocolCB->MiniportLinkage);
  1271. if (MiniportCB->Flags & HALT_IN_PROGRESS) {
  1272. NdisWanSetSyncEvent(&MiniportCB->HaltEvent);
  1273. }
  1274. NdisReleaseSpinLock(&MiniportCB->Lock);
  1275. NdisReleaseSpinLock(&MiniportCBList.Lock);
  1276. DEREF_MINIPORTCB(MiniportCB);
  1277. }
  1278. } while (FALSE);
  1279. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocols: Exit"));
  1280. return (Status);
  1281. }
  1282. NDIS_STATUS
  1283. DoLineUpToProtocol(
  1284. IN PPROTOCOLCB ProtocolCB
  1285. )
  1286. /*++
  1287. Routine Name:
  1288. Routine Description:
  1289. Arguments:
  1290. Return Values:
  1291. --*/
  1292. {
  1293. ULONG AllocationSize;
  1294. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1295. PNDIS_WAN_LINE_UP LineUpInfo;
  1296. PMINIPORTCB MiniportCB = ProtocolCB->MiniportCB;
  1297. PBUNDLECB BundleCB = ProtocolCB->BundleCB;
  1298. KIRQL OldIrql;
  1299. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Enter"));
  1300. ASSERT(MiniportCB != NULL);
  1301. AllocationSize = sizeof(NDIS_WAN_LINE_UP) +
  1302. ProtocolCB->ulLineUpInfoLength +
  1303. (sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
  1304. (2 * sizeof(PVOID)));
  1305. NdisWanAllocateMemory(&LineUpInfo, AllocationSize, LINEUPINFO_TAG);
  1306. if (LineUpInfo != NULL) {
  1307. ULONG LineUpHandle = ProtocolCB->ulTransportHandle;
  1308. //
  1309. // Needs to be in 1/100bps, we store in Bps
  1310. //
  1311. LineUpInfo->LinkSpeed = BundleCB->SFlowSpec.PeakBandwidth * 8 / 100;
  1312. //
  1313. // Set the MTU for this protocol
  1314. //
  1315. {
  1316. POPENCB OpenCB = BundleCB->NextLinkToXmit->OpenCB;
  1317. //
  1318. // If this connection is running over a VPN we will downsize
  1319. // the MTU
  1320. //
  1321. if ((OpenCB->MediumSubType == NdisWanMediumPPTP ||
  1322. OpenCB->MediumSubType == NdisWanMediumL2TP)) {
  1323. LineUpInfo->MaximumTotalSize = ProtocolCB->TunnelMTU;
  1324. } else {
  1325. LineUpInfo->MaximumTotalSize = ProtocolCB->MTU;
  1326. }
  1327. if (LineUpInfo->MaximumTotalSize > BundleCB->SFlowSpec.MaxSduSize) {
  1328. LineUpInfo->MaximumTotalSize =
  1329. BundleCB->SFlowSpec.MaxSduSize;
  1330. }
  1331. #if 0
  1332. //
  1333. // Figure out the size of the ppp header...
  1334. //
  1335. BundleCB->FramingInfo.PPPHeaderLength =
  1336. CalcPPPHeaderLength(BundleCB->FramingInfo.SendFramingBits,
  1337. BundleCB->SendFlags);
  1338. if (LineUpInfo->MaximumTotalSize > BundleCB->FramingInfo.PPPHeaderLength) {
  1339. LineUpInfo->MaximumTotalSize -= BundleCB->FramingInfo.PPPHeaderLength;
  1340. } else {
  1341. LineUpInfo->MaximumTotalSize = 0;
  1342. }
  1343. #endif
  1344. }
  1345. LineUpInfo->Quality = NdisWanReliable;
  1346. LineUpInfo->SendWindow = (USHORT)BundleCB->SendWindow;
  1347. LineUpInfo->ProtocolType = ProtocolCB->ProtocolType;
  1348. LineUpInfo->DeviceName.Length = ProtocolCB->InDeviceName.Length;
  1349. LineUpInfo->DeviceName.MaximumLength = MAX_NAME_LENGTH + 1;
  1350. LineUpInfo->DeviceName.Buffer = (PWCHAR)((PUCHAR)LineUpInfo +
  1351. sizeof(NDIS_WAN_LINE_UP) +
  1352. sizeof(PVOID));
  1353. (ULONG_PTR)LineUpInfo->DeviceName.Buffer &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  1354. if (ProtocolCB->InDeviceName.Length != 0) {
  1355. NdisMoveMemory(LineUpInfo->DeviceName.Buffer,
  1356. ProtocolCB->InDeviceName.Buffer,
  1357. ProtocolCB->InDeviceName.Length);
  1358. }
  1359. LineUpInfo->ProtocolBuffer = (PUCHAR)LineUpInfo +
  1360. sizeof(NDIS_WAN_LINE_UP) +
  1361. (sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
  1362. sizeof(PVOID));
  1363. (ULONG_PTR)LineUpInfo->ProtocolBuffer &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  1364. //
  1365. //
  1366. // The Remote address (DEST address in a send) is what we use to
  1367. // mutilplex sends across our single adapter/binding context.
  1368. // The address has the following format:
  1369. //
  1370. // XX XX XX YY YY ZZ
  1371. //
  1372. // XX = Randomly generated OUI
  1373. // YY = Index into the active bundle connection table to get bundlecb
  1374. // ZZ = Index into the protocol table of a bundle to get protocolcb
  1375. //
  1376. ETH_COPY_NETWORK_ADDRESS(LineUpInfo->RemoteAddress,ProtocolCB->NdisWanAddress);
  1377. ETH_COPY_NETWORK_ADDRESS(LineUpInfo->LocalAddress,ProtocolCB->TransportAddress);
  1378. //
  1379. // Fill in the protocol specific information
  1380. //
  1381. LineUpInfo->ProtocolBufferLength = ProtocolCB->ulLineUpInfoLength;
  1382. if (ProtocolCB->ulLineUpInfoLength > 0) {
  1383. NdisMoveMemory(LineUpInfo->ProtocolBuffer,
  1384. ProtocolCB->LineUpInfo,
  1385. ProtocolCB->ulLineUpInfoLength);
  1386. }
  1387. // KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1388. // DbgPrint("LineUp: %x, MTU %d\n",
  1389. // LineUpInfo->ProtocolType, LineUpInfo->MaximumTotalSize);
  1390. //
  1391. // Do the line up indication
  1392. //
  1393. NdisMIndicateStatus(MiniportCB->MiniportHandle,
  1394. NDIS_STATUS_WAN_LINE_UP,
  1395. LineUpInfo,
  1396. AllocationSize);
  1397. // KeLowerIrql(OldIrql);
  1398. //
  1399. // Update protocol queue depth
  1400. //
  1401. {
  1402. PROTOCOL_INFO ProtocolInfo = {0};
  1403. ULONG ByteDepth;
  1404. ULONG i;
  1405. AcquireBundleLock(BundleCB);
  1406. ProtocolInfo.ProtocolType = ProtocolCB->ProtocolType;
  1407. GetProtocolInfo(&ProtocolInfo);
  1408. //
  1409. // Set the send queue byte depth.
  1410. //
  1411. ByteDepth =
  1412. ProtocolInfo.PacketQueueDepth;
  1413. //
  1414. // If the byte depth is less then 4
  1415. // full packets, then set it to 4 full
  1416. // packets.
  1417. //
  1418. if (ByteDepth < (ProtocolInfo.MTU * 4)) {
  1419. ByteDepth = ProtocolInfo.MTU * 4;
  1420. }
  1421. for (i = 0; i <= MAX_MCML; i++) {
  1422. ProtocolCB->PacketQueue[i].MaxByteDepth =
  1423. ByteDepth;
  1424. }
  1425. ReleaseBundleLock(BundleCB);
  1426. }
  1427. //
  1428. // If this was the first line up for this protocolcb and
  1429. // this lineup was answered we need to collect some info
  1430. //
  1431. if (ProtocolCB->ulTransportHandle == 0) {
  1432. *((ULONG UNALIGNED *)(&LineUpHandle)) =
  1433. *((ULONG UNALIGNED *)(&LineUpInfo->LocalAddress[2]));
  1434. if (LineUpHandle != 0) {
  1435. AcquireBundleLock(BundleCB);
  1436. ETH_COPY_NETWORK_ADDRESS(ProtocolCB->TransportAddress, LineUpInfo->LocalAddress);
  1437. ProtocolCB->ulTransportHandle = LineUpHandle;
  1438. if (LineUpInfo->DeviceName.Length != 0) {
  1439. NdisWanStringToNdisString(&ProtocolCB->OutDeviceName,
  1440. LineUpInfo->DeviceName.Buffer);
  1441. }
  1442. ReleaseBundleLock(BundleCB);
  1443. //
  1444. // If this is an nbf adapter
  1445. //
  1446. if (ProtocolCB->ProtocolType == (USHORT)PROTOCOL_NBF) {
  1447. ASSERT(MiniportCB->ProtocolType == (USHORT)PROTOCOL_NBF);
  1448. MiniportCB->NbfProtocolCB = ProtocolCB;
  1449. }
  1450. } else {
  1451. Status = NDISWAN_ERROR_NO_ROUTE;
  1452. }
  1453. }
  1454. NdisWanFreeMemory(LineUpInfo);
  1455. } else {
  1456. Status = NDIS_STATUS_RESOURCES;
  1457. }
  1458. NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Exit"));
  1459. return (Status);
  1460. }
  1461. NDIS_STATUS
  1462. DoLineDownToProtocol(
  1463. PPROTOCOLCB ProtocolCB
  1464. )
  1465. {
  1466. NDIS_WAN_LINE_DOWN WanLineDown;
  1467. PNDIS_WAN_LINE_DOWN LineDownInfo = &WanLineDown;
  1468. PMINIPORTCB MiniportCB = ProtocolCB->MiniportCB;
  1469. PBUNDLECB BundleCB = ProtocolCB->BundleCB;
  1470. KIRQL OldIrql;
  1471. //
  1472. // The Remote address (DEST address) is what we use to mutilplex
  1473. // sends across our single adapter/binding context. The address
  1474. // has the following format:
  1475. //
  1476. // XX XX YY YY YY YY
  1477. //
  1478. // XX = Randomly generated OUI
  1479. // YY = ProtocolCB
  1480. //
  1481. ETH_COPY_NETWORK_ADDRESS(LineDownInfo->RemoteAddress, ProtocolCB->NdisWanAddress);
  1482. ETH_COPY_NETWORK_ADDRESS(LineDownInfo->LocalAddress, ProtocolCB->TransportAddress);
  1483. //
  1484. // If this is an nbf adapter
  1485. //
  1486. if (ProtocolCB->ProtocolType == PROTOCOL_NBF) {
  1487. MiniportCB->NbfProtocolCB = NULL;
  1488. }
  1489. ProtocolCB->ulTransportHandle = 0;
  1490. ProtocolCB->State = PROTOCOL_UNROUTED;
  1491. ReleaseBundleLock(BundleCB);
  1492. NdisMIndicateStatus(MiniportCB->MiniportHandle,
  1493. NDIS_STATUS_WAN_LINE_DOWN,
  1494. LineDownInfo,
  1495. sizeof(NDIS_WAN_LINE_DOWN));
  1496. NdisAcquireSpinLock(&MiniportCB->Lock);
  1497. RemoveEntryList(&ProtocolCB->MiniportLinkage);
  1498. if (MiniportCB->Flags & HALT_IN_PROGRESS) {
  1499. NdisWanSetSyncEvent(&MiniportCB->HaltEvent);
  1500. }
  1501. NdisReleaseSpinLock(&MiniportCB->Lock);
  1502. DEREF_MINIPORTCB(MiniportCB);
  1503. AcquireBundleLock(BundleCB);
  1504. return (NDIS_STATUS_SUCCESS);
  1505. }
  1506. VOID
  1507. CompleteSendDesc(
  1508. PSEND_DESC SendDesc,
  1509. NDIS_STATUS Status
  1510. )
  1511. {
  1512. PLINKCB LinkCB;
  1513. PBUNDLECB BundleCB;
  1514. PPROTOCOLCB ProtocolCB;
  1515. PNDIS_PACKET OriginalPacket;
  1516. BOOLEAN FreeLink = FALSE, FreeBundle = FALSE;
  1517. BOOLEAN LegacyLink;
  1518. PULONG pulRefCount;
  1519. PCM_VCCB CmVcCB;
  1520. INT Class;
  1521. ULONG DescFlags;
  1522. LinkCB = SendDesc->LinkCB;
  1523. ProtocolCB = SendDesc->ProtocolCB;
  1524. OriginalPacket = SendDesc->OriginalPacket;
  1525. Class = SendDesc->Class;
  1526. DescFlags = SendDesc->Flags;
  1527. NdisWanDbgOut(DBG_TRACE, DBG_SEND,
  1528. ("SendDesc: 0x%p, OriginalPacket: 0x%p, Status: %x",
  1529. SendDesc, OriginalPacket, Status));
  1530. NdisWanFreeSendDesc(SendDesc);
  1531. //
  1532. // Bundle that this link is on
  1533. //
  1534. BundleCB = LinkCB->BundleCB;
  1535. //
  1536. // Deref for the ref applied when a senddesc
  1537. // was retrieved for this link. We don't need to do
  1538. // the full deref here because we are keeping the
  1539. // link from going away with the ref applied when
  1540. // we got the sendcomplete.
  1541. //
  1542. --LinkCB->RefCount;
  1543. #ifdef DBG_SENDARRAY
  1544. {
  1545. SendArray[__si] = 'c';
  1546. if (++__si == MAX_BYTE_DEPTH) {
  1547. __si = 0;
  1548. }
  1549. }
  1550. #endif
  1551. NdisReleaseSpinLock(&LinkCB->Lock);
  1552. AcquireBundleLock(BundleCB);
  1553. LegacyLink = (LinkCB->OpenCB->Flags & OPEN_LEGACY) ? 1 : 0;
  1554. //
  1555. // If the sendwindow is currently full, this completion
  1556. // opens the sendwindow.
  1557. //
  1558. if (LinkCB->OutstandingFrames == LinkCB->SendWindow) {
  1559. LinkCB->SendWindowOpen = TRUE;
  1560. if (LinkCB->LinkActive) {
  1561. BundleCB->SendingLinks++;
  1562. }
  1563. }
  1564. LinkCB->OutstandingFrames--;
  1565. if (DescFlags & SEND_DESC_FRAG) {
  1566. InterlockedDecrement(&ProtocolCB->PacketQueue[Class].OutstandingFrags);
  1567. }
  1568. pulRefCount =
  1569. &(PMINIPORT_RESERVED_FROM_NDIS(OriginalPacket)->RefCount);
  1570. ASSERT(*pulRefCount > 0);
  1571. //
  1572. // See if the reference count is zero, if it is not
  1573. // we just return.
  1574. //
  1575. if (InterlockedDecrement(pulRefCount) != 0) {
  1576. SendPacketOnBundle(BundleCB);
  1577. return;
  1578. }
  1579. ReleaseBundleLock(BundleCB);
  1580. //
  1581. // Complete this NdisPacket back to the transport
  1582. //
  1583. NDIS_SET_PACKET_STATUS(OriginalPacket, Status);
  1584. CompleteNdisPacket(ProtocolCB->MiniportCB,
  1585. ProtocolCB,
  1586. OriginalPacket);
  1587. AcquireBundleLock(BundleCB);
  1588. BundleCB->OutstandingFrames--;
  1589. if ((BundleCB->Flags & FRAMES_PENDING_EVENT) &&
  1590. (BundleCB->OutstandingFrames == 0)) {
  1591. NdisWanSetSyncEvent(&BundleCB->OutstandingFramesEvent);
  1592. }
  1593. //
  1594. // Called with bundle lock help but returns with lock released
  1595. //
  1596. SendPacketOnBundle(BundleCB);
  1597. //
  1598. // Deref for ref applied when sent a packet to be framed.
  1599. //
  1600. DEREF_BUNDLECB(BundleCB);
  1601. }
  1602. #if 0
  1603. ULONG
  1604. CalcPPPHeaderLength(
  1605. ULONG FramingBits,
  1606. ULONG Flags
  1607. )
  1608. {
  1609. ULONG HeaderLength = 0;
  1610. if (FramingBits & PPP_FRAMING) {
  1611. if (!(FramingBits & PPP_COMPRESS_ADDRESS_CONTROL)) {
  1612. //
  1613. // If there is no address/control compression
  1614. // we need a pointer and a length
  1615. //
  1616. if (FramingBits & LLC_ENCAPSULATION) {
  1617. HeaderLength += 4;
  1618. } else {
  1619. HeaderLength += 2;
  1620. }
  1621. }
  1622. //
  1623. // If this is not from our private I/O interface we will
  1624. // build the rest of the header.
  1625. //
  1626. if (FramingBits & PPP_MULTILINK_FRAMING) {
  1627. if (!(FramingBits & PPP_COMPRESS_PROTOCOL_FIELD)) {
  1628. //
  1629. // No protocol compression
  1630. //
  1631. HeaderLength += 1;
  1632. }
  1633. HeaderLength += 1;
  1634. if (!(FramingBits & PPP_SHORT_SEQUENCE_HDR_FORMAT)) {
  1635. //
  1636. // We are using long sequence number
  1637. //
  1638. HeaderLength += 2;
  1639. }
  1640. HeaderLength += 2;
  1641. }
  1642. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  1643. //
  1644. // We are doing compression/encryption so we need
  1645. // a length
  1646. //
  1647. //
  1648. // It appears that legacy ras (< NT 4.0) requires that
  1649. // the PPP protocol field in a compressed packet not
  1650. // be compressed, ie has to have the leading 0x00
  1651. //
  1652. if (!(FramingBits & PPP_COMPRESS_PROTOCOL_FIELD)) {
  1653. //
  1654. // No protocol compression
  1655. //
  1656. HeaderLength += 1;
  1657. }
  1658. //
  1659. // Add protocol and coherency bytes
  1660. //
  1661. HeaderLength += 3;
  1662. }
  1663. if (!(FramingBits & PPP_COMPRESS_PROTOCOL_FIELD) ||
  1664. (Flags & (DO_COMPRESSION | DO_ENCRYPTION))) {
  1665. HeaderLength += 1;
  1666. }
  1667. HeaderLength += 1;
  1668. } else if (FramingBits & RAS_FRAMING) {
  1669. //
  1670. // If this is old ras framing:
  1671. //
  1672. // Alter the framing so that 0xFF 0x03 is not added
  1673. // and that the first byte is 0xFD not 0x00 0xFD
  1674. //
  1675. // So basically, a RAS compression looks like
  1676. // <0xFD> <2 BYTE COHERENCY> <NBF DATA FIELD>
  1677. //
  1678. // Whereas uncompressed looks like
  1679. // <NBF DATA FIELD> which always starts with 0xF0
  1680. //
  1681. // If this is ppp framing:
  1682. //
  1683. // A compressed frame will look like (before address/control
  1684. // - multilink is added)
  1685. // <0x00> <0xFD> <2 Byte Coherency> <Compressed Data>
  1686. //
  1687. if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
  1688. //
  1689. // Coherency bytes
  1690. //
  1691. HeaderLength += 3;
  1692. }
  1693. }
  1694. // DbgPrint("PPPHeaderLength %d\n", HeaderLength);
  1695. return (HeaderLength);
  1696. }
  1697. #endif