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.

1941 lines
49 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. nbfndis.c
  5. Abstract:
  6. This module contains code which implements the routines used to interface
  7. NBF and NDIS. All callback routines (except for Transfer Data,
  8. Send Complete, and ReceiveIndication) are here, as well as those routines
  9. called to initialize NDIS.
  10. Author:
  11. David Beaver (dbeaver) 13-Feb-1991
  12. Environment:
  13. Kernel mode
  14. Revision History:
  15. David Beaver (dbeaver) 1-July-1991
  16. modify to use new TDI interface
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #ifdef NBF_LOCKS // see spnlckdb.c
  21. VOID
  22. NbfFakeSendCompletionHandler(
  23. IN NDIS_HANDLE ProtocolBindingContext,
  24. IN PNDIS_PACKET NdisPacket,
  25. IN NDIS_STATUS NdisStatus
  26. );
  27. VOID
  28. NbfFakeTransferDataComplete (
  29. IN NDIS_HANDLE BindingContext,
  30. IN PNDIS_PACKET NdisPacket,
  31. IN NDIS_STATUS NdisStatus,
  32. IN UINT BytesTransferred
  33. );
  34. #endif
  35. //
  36. // This is a one-per-driver variable used in binding
  37. // to the NDIS interface.
  38. //
  39. NDIS_HANDLE NbfNdisProtocolHandle = (NDIS_HANDLE)NULL;
  40. NDIS_STATUS
  41. NbfSubmitNdisRequest(
  42. IN PDEVICE_CONTEXT DeviceContext,
  43. IN PNDIS_REQUEST NdisRequest,
  44. IN PNDIS_STRING AdapterName
  45. );
  46. VOID
  47. NbfOpenAdapterComplete (
  48. IN NDIS_HANDLE BindingContext,
  49. IN NDIS_STATUS NdisStatus,
  50. IN NDIS_STATUS OpenErrorStatus
  51. );
  52. VOID
  53. NbfCloseAdapterComplete(
  54. IN NDIS_HANDLE NdisBindingContext,
  55. IN NDIS_STATUS Status
  56. );
  57. VOID
  58. NbfResetComplete(
  59. IN NDIS_HANDLE NdisBindingContext,
  60. IN NDIS_STATUS Status
  61. );
  62. VOID
  63. NbfRequestComplete (
  64. IN NDIS_HANDLE BindingContext,
  65. IN PNDIS_REQUEST NdisRequest,
  66. IN NDIS_STATUS NdisStatus
  67. );
  68. VOID
  69. NbfStatusIndication (
  70. IN NDIS_HANDLE NdisBindingContext,
  71. IN NDIS_STATUS NdisStatus,
  72. IN PVOID StatusBuffer,
  73. IN UINT StatusBufferLength
  74. );
  75. VOID
  76. NbfProcessStatusClosing(
  77. IN PVOID Parameter
  78. );
  79. VOID
  80. NbfStatusComplete (
  81. IN NDIS_HANDLE NdisBindingContext
  82. );
  83. VOID
  84. NbfProtocolBindAdapter(
  85. OUT PNDIS_STATUS NdisStatus,
  86. IN NDIS_HANDLE BindContext,
  87. IN PNDIS_STRING DeviceName,
  88. IN PVOID SystemSpecific1,
  89. IN PVOID SystemSpecific2
  90. );
  91. VOID
  92. NbfProtocolUnbindAdapter(
  93. OUT PNDIS_STATUS NdisStatus,
  94. IN NDIS_HANDLE ProtocolBindContext,
  95. IN PNDIS_HANDLE UnbindContext
  96. );
  97. NDIS_STATUS
  98. NbfProtocolPnPEventHandler(
  99. IN NDIS_HANDLE ProtocolBindingContext,
  100. IN PNET_PNP_EVENT NetPnPEvent
  101. );
  102. #ifdef ALLOC_PRAGMA
  103. #pragma alloc_text(PAGE,NbfProtocolBindAdapter)
  104. #pragma alloc_text(PAGE,NbfRegisterProtocol)
  105. #pragma alloc_text(PAGE,NbfSubmitNdisRequest)
  106. #pragma alloc_text(PAGE,NbfInitializeNdis)
  107. #endif
  108. NTSTATUS
  109. NbfRegisterProtocol (
  110. IN PUNICODE_STRING NameString
  111. )
  112. /*++
  113. Routine Description:
  114. This routine introduces this transport to the NDIS interface.
  115. Arguments:
  116. Irp - Pointer to the request packet representing the I/O request.
  117. Return Value:
  118. The function value is the status of the operation.
  119. STATUS_SUCCESS if all goes well,
  120. Failure status if we tried to register and couldn't,
  121. STATUS_INSUFFICIENT_RESOURCES if we couldn't even try to register.
  122. --*/
  123. {
  124. NDIS_STATUS ndisStatus;
  125. NDIS_PROTOCOL_CHARACTERISTICS ProtChars;
  126. RtlZeroMemory(&ProtChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  127. //
  128. // Set up the characteristics of this protocol
  129. //
  130. ProtChars.MajorNdisVersion = 4;
  131. ProtChars.MinorNdisVersion = 0;
  132. ProtChars.BindAdapterHandler = NbfProtocolBindAdapter;
  133. ProtChars.UnbindAdapterHandler = NbfProtocolUnbindAdapter;
  134. ProtChars.PnPEventHandler = NbfProtocolPnPEventHandler;
  135. ProtChars.Name.Length = NameString->Length;
  136. ProtChars.Name.MaximumLength = NameString->MaximumLength;
  137. ProtChars.Name.Buffer = NameString->Buffer;
  138. ProtChars.OpenAdapterCompleteHandler = NbfOpenAdapterComplete;
  139. ProtChars.CloseAdapterCompleteHandler = NbfCloseAdapterComplete;
  140. ProtChars.ResetCompleteHandler = NbfResetComplete;
  141. ProtChars.RequestCompleteHandler = NbfRequestComplete;
  142. #ifdef NBF_LOCKS
  143. ProtChars.SendCompleteHandler = NbfFakeSendCompletionHandler;
  144. ProtChars.TransferDataCompleteHandler = NbfFakeTransferDataComplete;
  145. #else
  146. ProtChars.SendCompleteHandler = NbfSendCompletionHandler;
  147. ProtChars.TransferDataCompleteHandler = NbfTransferDataComplete;
  148. #endif
  149. ProtChars.ReceiveHandler = NbfReceiveIndication;
  150. ProtChars.ReceiveCompleteHandler = NbfReceiveComplete;
  151. ProtChars.StatusHandler = NbfStatusIndication;
  152. ProtChars.StatusCompleteHandler = NbfStatusComplete;
  153. NdisRegisterProtocol (
  154. &ndisStatus,
  155. &NbfNdisProtocolHandle,
  156. &ProtChars,
  157. sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  158. if (ndisStatus != NDIS_STATUS_SUCCESS) {
  159. #if DBG
  160. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  161. NbfPrint1("NbfInitialize: NdisRegisterProtocol failed: %s\n",
  162. NbfGetNdisStatus(ndisStatus));
  163. }
  164. #endif
  165. return (NTSTATUS)ndisStatus;
  166. }
  167. return STATUS_SUCCESS;
  168. }
  169. VOID
  170. NbfDeregisterProtocol (
  171. VOID
  172. )
  173. /*++
  174. Routine Description:
  175. This routine removes this transport to the NDIS interface.
  176. Arguments:
  177. None.
  178. Return Value:
  179. None.
  180. --*/
  181. {
  182. NDIS_STATUS ndisStatus;
  183. if (NbfNdisProtocolHandle != (NDIS_HANDLE)NULL) {
  184. NdisDeregisterProtocol (
  185. &ndisStatus,
  186. NbfNdisProtocolHandle);
  187. NbfNdisProtocolHandle = (NDIS_HANDLE)NULL;
  188. }
  189. }
  190. NDIS_STATUS
  191. NbfSubmitNdisRequest(
  192. IN PDEVICE_CONTEXT DeviceContext,
  193. IN PNDIS_REQUEST Request,
  194. IN PNDIS_STRING AdapterString
  195. )
  196. /*++
  197. Routine Description:
  198. This routine passed an NDIS_REQUEST to the MAC and waits
  199. until it has completed before returning the final status.
  200. Arguments:
  201. DeviceContext - Pointer to the device context for this driver.
  202. Request - Pointer to the NDIS_REQUEST to submit.
  203. AdapterString - The name of the adapter, in case an error needs
  204. to be logged.
  205. Return Value:
  206. The function value is the status of the operation.
  207. --*/
  208. {
  209. NDIS_STATUS NdisStatus;
  210. if (DeviceContext->NdisBindingHandle) {
  211. NdisRequest(
  212. &NdisStatus,
  213. DeviceContext->NdisBindingHandle,
  214. Request);
  215. }
  216. else {
  217. NdisStatus = STATUS_INVALID_DEVICE_STATE;
  218. }
  219. if (NdisStatus == NDIS_STATUS_PENDING) {
  220. IF_NBFDBG (NBF_DEBUG_NDIS) {
  221. NbfPrint1 ("OID %lx pended.\n",
  222. Request->DATA.QUERY_INFORMATION.Oid);
  223. }
  224. //
  225. // The completion routine will set NdisRequestStatus.
  226. //
  227. KeWaitForSingleObject(
  228. &DeviceContext->NdisRequestEvent,
  229. Executive,
  230. KernelMode,
  231. TRUE,
  232. (PLARGE_INTEGER)NULL
  233. );
  234. NdisStatus = DeviceContext->NdisRequestStatus;
  235. KeResetEvent(
  236. &DeviceContext->NdisRequestEvent
  237. );
  238. }
  239. if (NdisStatus == STATUS_SUCCESS) {
  240. IF_NBFDBG (NBF_DEBUG_NDIS) {
  241. if (Request->RequestType == NdisRequestSetInformation) {
  242. NbfPrint1 ("Nbfdrvr: Set OID %lx succeeded.\n",
  243. Request->DATA.SET_INFORMATION.Oid);
  244. } else {
  245. NbfPrint1 ("Nbfdrvr: Query OID %lx succeeded.\n",
  246. Request->DATA.QUERY_INFORMATION.Oid);
  247. }
  248. }
  249. } else {
  250. #if DBG
  251. if (Request->RequestType == NdisRequestSetInformation) {
  252. NbfPrint2 ("Nbfdrvr: Set OID %lx failed: %s.\n",
  253. Request->DATA.SET_INFORMATION.Oid, NbfGetNdisStatus(NdisStatus));
  254. } else {
  255. NbfPrint2 ("Nbfdrvr: Query OID %lx failed: %s.\n",
  256. Request->DATA.QUERY_INFORMATION.Oid, NbfGetNdisStatus(NdisStatus));
  257. }
  258. #endif
  259. if (NdisStatus != STATUS_INVALID_DEVICE_STATE) {
  260. NbfWriteOidErrorLog(
  261. DeviceContext,
  262. Request->RequestType == NdisRequestSetInformation ?
  263. EVENT_TRANSPORT_SET_OID_FAILED : EVENT_TRANSPORT_QUERY_OID_FAILED,
  264. NdisStatus,
  265. AdapterString->Buffer,
  266. Request->DATA.QUERY_INFORMATION.Oid);
  267. }
  268. }
  269. return NdisStatus;
  270. }
  271. NTSTATUS
  272. NbfInitializeNdis (
  273. IN PDEVICE_CONTEXT DeviceContext,
  274. IN PCONFIG_DATA NbfConfig,
  275. IN PNDIS_STRING AdapterString
  276. )
  277. /*++
  278. Routine Description:
  279. This routine introduces this transport to the NDIS interface and sets up
  280. any necessary NDIS data structures (Buffer pools and such). It will be
  281. called for each adapter opened by this transport.
  282. Arguments:
  283. DeviceObject - Pointer to the device object for this driver.
  284. Irp - Pointer to the request packet representing the I/O request.
  285. Return Value:
  286. The function value is the status of the operation.
  287. --*/
  288. {
  289. ULONG SendPacketReservedLength;
  290. ULONG ReceivePacketReservedLen;
  291. ULONG SendPacketPoolSize;
  292. ULONG ReceivePacketPoolSize;
  293. NDIS_STATUS NdisStatus;
  294. NDIS_STATUS OpenErrorStatus;
  295. NDIS_MEDIUM NbfSupportedMedia[] = { NdisMedium802_3, NdisMedium802_5, NdisMediumFddi, NdisMediumWan };
  296. UINT SelectedMedium;
  297. NDIS_REQUEST NbfRequest;
  298. UCHAR NbfDataBuffer[6];
  299. NDIS_OID NbfOid;
  300. UCHAR WanProtocolId[6] = { 0x80, 0x00, 0x00, 0x00, 0x80, 0xd5 };
  301. ULONG WanHeaderFormat = NdisWanHeaderEthernet;
  302. ULONG MinimumLookahead = 128 + sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS);
  303. ULONG MacOptions;
  304. //
  305. // Initialize this adapter for NBF use through NDIS
  306. //
  307. //
  308. // This event is used in case any of the NDIS requests
  309. // pend; we wait until it is set by the completion
  310. // routine, which also sets NdisRequestStatus.
  311. //
  312. KeInitializeEvent(
  313. &DeviceContext->NdisRequestEvent,
  314. NotificationEvent,
  315. FALSE
  316. );
  317. DeviceContext->NdisBindingHandle = NULL;
  318. NdisOpenAdapter (
  319. &NdisStatus,
  320. &OpenErrorStatus,
  321. &DeviceContext->NdisBindingHandle,
  322. &SelectedMedium,
  323. NbfSupportedMedia,
  324. sizeof (NbfSupportedMedia) / sizeof(NDIS_MEDIUM),
  325. NbfNdisProtocolHandle,
  326. (NDIS_HANDLE)DeviceContext,
  327. AdapterString,
  328. 0,
  329. NULL);
  330. if (NdisStatus == NDIS_STATUS_PENDING) {
  331. IF_NBFDBG (NBF_DEBUG_NDIS) {
  332. NbfPrint1 ("Adapter %S open pended.\n", AdapterString);
  333. }
  334. //
  335. // The completion routine will set NdisRequestStatus.
  336. //
  337. KeWaitForSingleObject(
  338. &DeviceContext->NdisRequestEvent,
  339. Executive,
  340. KernelMode,
  341. TRUE,
  342. (PLARGE_INTEGER)NULL
  343. );
  344. NdisStatus = DeviceContext->NdisRequestStatus;
  345. KeResetEvent(
  346. &DeviceContext->NdisRequestEvent
  347. );
  348. }
  349. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  350. #if DBG
  351. IF_NBFDBG (NBF_DEBUG_NDIS) {
  352. NbfPrint1 ("Adapter %S successfully opened.\n", AdapterString);
  353. }
  354. #endif
  355. } else {
  356. #if DBG
  357. IF_NBFDBG (NBF_DEBUG_NDIS) {
  358. NbfPrint2 ("Adapter open %S failed, status: %s.\n",
  359. AdapterString,
  360. NbfGetNdisStatus (NdisStatus));
  361. }
  362. #endif
  363. NbfWriteGeneralErrorLog(
  364. DeviceContext,
  365. EVENT_TRANSPORT_ADAPTER_NOT_FOUND,
  366. 807,
  367. NdisStatus,
  368. AdapterString->Buffer,
  369. 0,
  370. NULL);
  371. return STATUS_INSUFFICIENT_RESOURCES;
  372. }
  373. //
  374. // Get the information we need about the adapter, based on
  375. // the media type.
  376. //
  377. MacInitializeMacInfo(
  378. NbfSupportedMedia[SelectedMedium],
  379. (BOOLEAN)(NbfConfig->UseDixOverEthernet != 0),
  380. &DeviceContext->MacInfo);
  381. DeviceContext->MacInfo.QueryWithoutSourceRouting =
  382. NbfConfig->QueryWithoutSourceRouting ? TRUE : FALSE;
  383. DeviceContext->MacInfo.AllRoutesNameRecognized =
  384. NbfConfig->AllRoutesNameRecognized ? TRUE : FALSE;
  385. //
  386. // Set the multicast/functional addresses first so we avoid windows where we
  387. // receive only part of the addresses.
  388. //
  389. MacSetNetBIOSMulticast (
  390. DeviceContext->MacInfo.MediumType,
  391. DeviceContext->NetBIOSAddress.Address);
  392. switch (DeviceContext->MacInfo.MediumType) {
  393. case NdisMedium802_3:
  394. case NdisMediumDix:
  395. //
  396. // Fill in the data for our multicast list.
  397. //
  398. RtlCopyMemory(NbfDataBuffer, DeviceContext->NetBIOSAddress.Address, 6);
  399. //
  400. // Now fill in the NDIS_REQUEST.
  401. //
  402. NbfRequest.RequestType = NdisRequestSetInformation;
  403. NbfRequest.DATA.SET_INFORMATION.Oid = OID_802_3_MULTICAST_LIST;
  404. NbfRequest.DATA.SET_INFORMATION.InformationBuffer = &NbfDataBuffer;
  405. NbfRequest.DATA.SET_INFORMATION.InformationBufferLength = 6;
  406. break;
  407. case NdisMedium802_5:
  408. //
  409. // For token-ring, we pass the last four bytes of the
  410. // Netbios functional address.
  411. //
  412. //
  413. // Fill in the OVB for our functional address.
  414. //
  415. RtlCopyMemory(NbfDataBuffer, ((PUCHAR)(DeviceContext->NetBIOSAddress.Address)) + 2, 4);
  416. //
  417. // Now fill in the NDIS_REQUEST.
  418. //
  419. NbfRequest.RequestType = NdisRequestSetInformation;
  420. NbfRequest.DATA.SET_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL;
  421. NbfRequest.DATA.SET_INFORMATION.InformationBuffer = &NbfDataBuffer;
  422. NbfRequest.DATA.SET_INFORMATION.InformationBufferLength = 4;
  423. break;
  424. case NdisMediumFddi:
  425. //
  426. // Fill in the data for our multicast list.
  427. //
  428. RtlCopyMemory(NbfDataBuffer, DeviceContext->NetBIOSAddress.Address, 6);
  429. //
  430. // Now fill in the NDIS_REQUEST.
  431. //
  432. NbfRequest.RequestType = NdisRequestSetInformation;
  433. NbfRequest.DATA.SET_INFORMATION.Oid = OID_FDDI_LONG_MULTICAST_LIST;
  434. NbfRequest.DATA.SET_INFORMATION.InformationBuffer = &NbfDataBuffer;
  435. NbfRequest.DATA.SET_INFORMATION.InformationBufferLength = 6;
  436. break;
  437. }
  438. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  439. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  440. return STATUS_INSUFFICIENT_RESOURCES;
  441. }
  442. switch (DeviceContext->MacInfo.MediumType) {
  443. case NdisMedium802_3:
  444. case NdisMediumDix:
  445. if (DeviceContext->MacInfo.MediumAsync) {
  446. NbfOid = OID_WAN_CURRENT_ADDRESS;
  447. } else {
  448. NbfOid = OID_802_3_CURRENT_ADDRESS;
  449. }
  450. break;
  451. case NdisMedium802_5:
  452. NbfOid = OID_802_5_CURRENT_ADDRESS;
  453. break;
  454. case NdisMediumFddi:
  455. NbfOid = OID_FDDI_LONG_CURRENT_ADDR;
  456. break;
  457. default:
  458. NdisStatus = NDIS_STATUS_FAILURE;
  459. break;
  460. }
  461. NbfRequest.RequestType = NdisRequestQueryInformation;
  462. NbfRequest.DATA.QUERY_INFORMATION.Oid = NbfOid;
  463. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = DeviceContext->LocalAddress.Address;
  464. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 6;
  465. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  466. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  467. return STATUS_INSUFFICIENT_RESOURCES;
  468. }
  469. //
  470. // Set up the reserved Netbios address.
  471. //
  472. RtlZeroMemory(DeviceContext->ReservedNetBIOSAddress, 10);
  473. RtlCopyMemory(&DeviceContext->ReservedNetBIOSAddress[10], DeviceContext->LocalAddress.Address, 6);
  474. //
  475. // Now query the maximum packet sizes.
  476. //
  477. NbfRequest.RequestType = NdisRequestQueryInformation;
  478. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_FRAME_SIZE;
  479. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(DeviceContext->MaxReceivePacketSize);
  480. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  481. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  482. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  483. return STATUS_INSUFFICIENT_RESOURCES;
  484. }
  485. NbfRequest.RequestType = NdisRequestQueryInformation;
  486. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
  487. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(DeviceContext->MaxSendPacketSize);
  488. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  489. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  490. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  491. return STATUS_INSUFFICIENT_RESOURCES;
  492. }
  493. DeviceContext->CurSendPacketSize = DeviceContext->MaxSendPacketSize;
  494. //
  495. // Now set the minimum lookahead size.
  496. //
  497. NbfRequest.RequestType = NdisRequestSetInformation;
  498. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_LOOKAHEAD;
  499. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = &MinimumLookahead;
  500. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  501. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  502. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  503. return STATUS_INSUFFICIENT_RESOURCES;
  504. }
  505. //
  506. // Now query the link speed for non-wan media
  507. //
  508. if (!DeviceContext->MacInfo.MediumAsync) {
  509. NbfRequest.RequestType = NdisRequestQueryInformation;
  510. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
  511. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(DeviceContext->MediumSpeed);
  512. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  513. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  514. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  515. return STATUS_INSUFFICIENT_RESOURCES;
  516. }
  517. DeviceContext->MediumSpeedAccurate = TRUE;
  518. // Initialized MinimumT1Timeout in nbfdrvr.c
  519. // For a non-WAN media, this value is picked
  520. // from the registry, and remains constant.
  521. // DeviceContext->MinimumT1Timeout = 8;
  522. } else {
  523. //
  524. // On an wan media, this isn't valid until we get an
  525. // WAN_LINE_UP indication. Set the timeouts to
  526. // low values for now.
  527. //
  528. DeviceContext->DefaultT1Timeout = 8;
  529. DeviceContext->MinimumT1Timeout = 8;
  530. DeviceContext->MediumSpeedAccurate = FALSE;
  531. //
  532. // Back off our connectionless timeouts to 2 seconds.
  533. //
  534. DeviceContext->NameQueryTimeout = 2 * SECONDS;
  535. DeviceContext->AddNameQueryTimeout = 2 * SECONDS;
  536. DeviceContext->GeneralTimeout = 2 * SECONDS;
  537. //
  538. // Use the WAN parameter for name query retries.
  539. //
  540. DeviceContext->NameQueryRetries = NbfConfig->WanNameQueryRetries;
  541. //
  542. // Use this until we know better.
  543. //
  544. DeviceContext->RecommendedSendWindow = 1;
  545. }
  546. //
  547. // On media that use source routing, we double our name query
  548. // retry count if we are configured to try both ways (with and
  549. // without source routing).
  550. //
  551. if ((DeviceContext->MacInfo.QueryWithoutSourceRouting) &&
  552. (DeviceContext->MacInfo.SourceRouting)) {
  553. DeviceContext->NameQueryRetries *= 2;
  554. }
  555. //
  556. // For wan, specify our protocol ID and header format.
  557. // We don't query the medium subtype because we don't
  558. // case (since we require ethernet emulation).
  559. //
  560. if (DeviceContext->MacInfo.MediumAsync) {
  561. NbfRequest.RequestType = NdisRequestSetInformation;
  562. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_PROTOCOL_TYPE;
  563. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = WanProtocolId;
  564. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 6;
  565. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  566. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  567. return STATUS_INSUFFICIENT_RESOURCES;
  568. }
  569. NbfRequest.RequestType = NdisRequestSetInformation;
  570. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_HEADER_FORMAT;
  571. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanHeaderFormat;
  572. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  573. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  574. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  575. return STATUS_INSUFFICIENT_RESOURCES;
  576. }
  577. }
  578. //
  579. // Now query the MAC's optional characteristics.
  580. //
  581. NbfRequest.RequestType = NdisRequestQueryInformation;
  582. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS;
  583. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = &MacOptions;
  584. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  585. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  586. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  587. #if 1
  588. return STATUS_INSUFFICIENT_RESOURCES;
  589. #else
  590. MacOptions = 0;
  591. #endif
  592. }
  593. DeviceContext->MacInfo.CopyLookahead =
  594. (BOOLEAN)((MacOptions & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA) != 0);
  595. DeviceContext->MacInfo.ReceiveSerialized =
  596. (BOOLEAN)((MacOptions & NDIS_MAC_OPTION_RECEIVE_SERIALIZED) != 0);
  597. DeviceContext->MacInfo.TransferSynchronous =
  598. (BOOLEAN)((MacOptions & NDIS_MAC_OPTION_TRANSFERS_NOT_PEND) != 0);
  599. DeviceContext->MacInfo.SingleReceive =
  600. (BOOLEAN)(DeviceContext->MacInfo.ReceiveSerialized && DeviceContext->MacInfo.TransferSynchronous);
  601. #if 0
  602. //
  603. // Now set our options if needed.
  604. //
  605. // Don't allow early indications because we can't determine
  606. // if the CRC has been checked yet.
  607. //
  608. if ((DeviceContext->MacInfo.MediumType == NdisMedium802_3) ||
  609. (DeviceContext->MacInfo.MediumType == NdisMediumDix)) {
  610. ULONG ProtocolOptions = NDIS_PROT_OPTION_ESTIMATED_LENGTH;
  611. NbfRequest.RequestType = NdisRequestSetInformation;
  612. NbfRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_PROTOCOL_OPTIONS;
  613. NbfRequest.DATA.QUERY_INFORMATION.InformationBuffer = &ProtocolOptions;
  614. NbfRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  615. NdisStatus = NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  616. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  617. return STATUS_INSUFFICIENT_RESOURCES;
  618. }
  619. }
  620. #endif
  621. //
  622. // Calculate the NDIS-related stuff.
  623. //
  624. SendPacketReservedLength = sizeof (SEND_PACKET_TAG);
  625. ReceivePacketReservedLen = sizeof (RECEIVE_PACKET_TAG);
  626. //
  627. // The send packet pool is used for UI frames and regular packets.
  628. //
  629. SendPacketPoolSize = NbfConfig->SendPacketPoolSize;
  630. //
  631. // The receive packet pool is used in transfer data.
  632. //
  633. // For a MAC that will only have one receive active, we
  634. // don't need multiple receive packets. Allow an extra
  635. // one for loopback.
  636. //
  637. if (DeviceContext->MacInfo.SingleReceive) {
  638. ReceivePacketPoolSize = 2;
  639. } else {
  640. ReceivePacketPoolSize = NbfConfig->ReceivePacketPoolSize;
  641. }
  642. // Allocate Packet pool descriptors for dynamic packet allocation.
  643. if (!DeviceContext->SendPacketPoolDesc)
  644. {
  645. DeviceContext->SendPacketPoolDesc = ExAllocatePoolWithTag(
  646. NonPagedPool,
  647. sizeof(NBF_POOL_LIST_DESC),
  648. NBF_MEM_TAG_POOL_DESC);
  649. if (DeviceContext->SendPacketPoolDesc == NULL) {
  650. return STATUS_INSUFFICIENT_RESOURCES;
  651. }
  652. RtlZeroMemory(DeviceContext->SendPacketPoolDesc,
  653. sizeof(NBF_POOL_LIST_DESC));
  654. DeviceContext->SendPacketPoolDesc->NumElements =
  655. DeviceContext->SendPacketPoolDesc->TotalElements = (USHORT)SendPacketPoolSize;
  656. // To track packet pools in NDIS allocated on NBF's behalf
  657. #if NDIS_POOL_TAGGING
  658. DeviceContext->SendPacketPoolDesc->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NBF;
  659. #endif
  660. NdisAllocatePacketPoolEx (
  661. &NdisStatus,
  662. &DeviceContext->SendPacketPoolDesc->PoolHandle,
  663. SendPacketPoolSize,
  664. 0,
  665. SendPacketReservedLength);
  666. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  667. IF_NBFDBG (NBF_DEBUG_NDIS) {
  668. NbfPrint0 ("NdisInitializePacketPool successful.\n");
  669. }
  670. } else {
  671. ExFreePool(DeviceContext->SendPacketPoolDesc);
  672. DeviceContext->SendPacketPoolDesc = NULL;
  673. #if DBG
  674. NbfPrint1 ("NbfInitialize: NdisInitializePacketPool failed, reason: %s.\n",
  675. NbfGetNdisStatus (NdisStatus));
  676. #endif
  677. NbfWriteResourceErrorLog(
  678. DeviceContext,
  679. EVENT_TRANSPORT_RESOURCE_POOL,
  680. 109,
  681. SendPacketPoolSize,
  682. 0);
  683. return STATUS_INSUFFICIENT_RESOURCES;
  684. }
  685. NdisSetPacketPoolProtocolId (DeviceContext->SendPacketPoolDesc->PoolHandle, NDIS_PROTOCOL_ID_NBF);
  686. DeviceContext->SendPacketPoolSize = SendPacketPoolSize;
  687. DeviceContext->MemoryUsage +=
  688. (SendPacketPoolSize *
  689. (sizeof(NDIS_PACKET) + SendPacketReservedLength));
  690. #if DBG
  691. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  692. DbgPrint ("send pool %d hdr %d, %ld\n",
  693. SendPacketPoolSize,
  694. SendPacketReservedLength,
  695. DeviceContext->MemoryUsage);
  696. }
  697. #endif
  698. }
  699. if (!DeviceContext->ReceivePacketPoolDesc)
  700. {
  701. // Allocate Packet pool descriptors for dynamic packet allocation.
  702. DeviceContext->ReceivePacketPoolDesc = ExAllocatePoolWithTag(
  703. NonPagedPool,
  704. sizeof(NBF_POOL_LIST_DESC),
  705. NBF_MEM_TAG_POOL_DESC);
  706. if (DeviceContext->ReceivePacketPoolDesc == NULL) {
  707. return STATUS_INSUFFICIENT_RESOURCES;
  708. }
  709. RtlZeroMemory(DeviceContext->ReceivePacketPoolDesc,
  710. sizeof(NBF_POOL_LIST_DESC));
  711. DeviceContext->ReceivePacketPoolDesc->NumElements =
  712. DeviceContext->ReceivePacketPoolDesc->TotalElements = (USHORT)ReceivePacketPoolSize;
  713. // To track packet pools in NDIS allocated on NBF's behalf
  714. #if NDIS_POOL_TAGGING
  715. DeviceContext->ReceivePacketPoolDesc->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NBF;
  716. #endif
  717. NdisAllocatePacketPoolEx (
  718. &NdisStatus,
  719. &DeviceContext->ReceivePacketPoolDesc->PoolHandle,
  720. ReceivePacketPoolSize,
  721. 0,
  722. ReceivePacketReservedLen);
  723. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  724. IF_NBFDBG (NBF_DEBUG_NDIS) {
  725. NbfPrint1 ("NdisInitializePacketPool successful, Pool: %lx\n",
  726. DeviceContext->ReceivePacketPoolDesc->PoolHandle);
  727. }
  728. } else {
  729. ExFreePool(DeviceContext->ReceivePacketPoolDesc);
  730. DeviceContext->ReceivePacketPoolDesc = NULL;
  731. #if DBG
  732. NbfPrint1 ("NbfInitialize: NdisInitializePacketPool failed, reason: %s.\n",
  733. NbfGetNdisStatus (NdisStatus));
  734. #endif
  735. NbfWriteResourceErrorLog(
  736. DeviceContext,
  737. EVENT_TRANSPORT_RESOURCE_POOL,
  738. 209,
  739. ReceivePacketPoolSize,
  740. 0);
  741. return STATUS_INSUFFICIENT_RESOURCES;
  742. }
  743. NdisSetPacketPoolProtocolId (DeviceContext->ReceivePacketPoolDesc->PoolHandle, NDIS_PROTOCOL_ID_NBF);
  744. DeviceContext->ReceivePacketPoolSize = ReceivePacketPoolSize;
  745. DeviceContext->MemoryUsage +=
  746. (ReceivePacketPoolSize *
  747. (sizeof(NDIS_PACKET) + ReceivePacketReservedLen));
  748. #if DBG
  749. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  750. DbgPrint ("receive pool %d hdr %d, %ld\n",
  751. ReceivePacketPoolSize,
  752. ReceivePacketReservedLen,
  753. DeviceContext->MemoryUsage);
  754. }
  755. #endif
  756. }
  757. if (!DeviceContext->NdisBufferPool)
  758. {
  759. //
  760. // Allocate the buffer pool; as an estimate, allocate
  761. // one per send or receive packet.
  762. //
  763. NdisAllocateBufferPool (
  764. &NdisStatus,
  765. &DeviceContext->NdisBufferPool,
  766. SendPacketPoolSize + ReceivePacketPoolSize);
  767. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  768. IF_NBFDBG (NBF_DEBUG_NDIS) {
  769. NbfPrint0 ("NdisAllocateBufferPool successful.\n");
  770. }
  771. } else {
  772. #if DBG
  773. NbfPrint1 ("NbfInitialize: NdisAllocateBufferPool failed, reason: %s.\n",
  774. NbfGetNdisStatus (NdisStatus));
  775. #endif
  776. NbfWriteResourceErrorLog(
  777. DeviceContext,
  778. EVENT_TRANSPORT_RESOURCE_POOL,
  779. 309,
  780. SendPacketPoolSize + ReceivePacketPoolSize,
  781. 0);
  782. return STATUS_INSUFFICIENT_RESOURCES;
  783. }
  784. }
  785. //
  786. // Now that everything is set up, we enable the filter
  787. // for packet reception.
  788. //
  789. //
  790. // Fill in the OVB for packet filter.
  791. //
  792. switch (DeviceContext->MacInfo.MediumType) {
  793. case NdisMedium802_3:
  794. case NdisMediumDix:
  795. case NdisMediumFddi:
  796. RtlStoreUlong((PULONG)NbfDataBuffer,
  797. (NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST));
  798. break;
  799. case NdisMedium802_5:
  800. RtlStoreUlong((PULONG)NbfDataBuffer,
  801. (NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_FUNCTIONAL));
  802. break;
  803. default:
  804. NdisStatus = NDIS_STATUS_FAILURE;
  805. break;
  806. }
  807. //
  808. // Now fill in the NDIS_REQUEST.
  809. //
  810. NbfRequest.RequestType = NdisRequestSetInformation;
  811. NbfRequest.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  812. NbfRequest.DATA.SET_INFORMATION.InformationBuffer = &NbfDataBuffer;
  813. NbfRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof(ULONG);
  814. NbfSubmitNdisRequest (DeviceContext, &NbfRequest, AdapterString);
  815. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  816. return STATUS_INSUFFICIENT_RESOURCES;
  817. }
  818. return STATUS_SUCCESS;
  819. } /* NbfInitializeNdis */
  820. VOID
  821. NbfCloseNdis (
  822. IN PDEVICE_CONTEXT DeviceContext
  823. )
  824. /*++
  825. Routine Description:
  826. This routine unbinds the transport from the NDIS interface and does
  827. any other work required to undo what was done in NbfInitializeNdis.
  828. It is written so that it can be called from within NbfInitializeNdis
  829. if it fails partway through.
  830. Arguments:
  831. DeviceObject - Pointer to the device object for this driver.
  832. Return Value:
  833. The function value is the status of the operation.
  834. --*/
  835. {
  836. NDIS_STATUS ndisStatus;
  837. NDIS_HANDLE NdisBindingHandle;
  838. //
  839. // Close the NDIS binding.
  840. //
  841. NdisBindingHandle = DeviceContext->NdisBindingHandle;
  842. DeviceContext->NdisBindingHandle = NULL;
  843. if (NdisBindingHandle != NULL) {
  844. //
  845. // This event is used in case any of the NDIS requests
  846. // pend; we wait until it is set by the completion
  847. // routine, which also sets NdisRequestStatus.
  848. //
  849. KeInitializeEvent(
  850. &DeviceContext->NdisRequestEvent,
  851. NotificationEvent,
  852. FALSE
  853. );
  854. NdisCloseAdapter(
  855. &ndisStatus,
  856. NdisBindingHandle);
  857. if (ndisStatus == NDIS_STATUS_PENDING) {
  858. IF_NBFDBG (NBF_DEBUG_NDIS) {
  859. NbfPrint0 ("Adapter close pended.\n");
  860. }
  861. //
  862. // The completion routine will set NdisRequestStatus.
  863. //
  864. KeWaitForSingleObject(
  865. &DeviceContext->NdisRequestEvent,
  866. Executive,
  867. KernelMode,
  868. TRUE,
  869. (PLARGE_INTEGER)NULL
  870. );
  871. ndisStatus = DeviceContext->NdisRequestStatus;
  872. KeResetEvent(
  873. &DeviceContext->NdisRequestEvent
  874. );
  875. }
  876. //
  877. // We ignore ndisStatus.
  878. //
  879. }
  880. } /* NbfCloseNdis */
  881. VOID
  882. NbfOpenAdapterComplete (
  883. IN NDIS_HANDLE BindingContext,
  884. IN NDIS_STATUS NdisStatus,
  885. IN NDIS_STATUS OpenErrorStatus
  886. )
  887. /*++
  888. Routine Description:
  889. This routine is called by NDIS to indicate that an open adapter
  890. is complete. Since we only ever have one outstanding, and then only
  891. during initialization, all we do is record the status and set
  892. the event to signalled to unblock the initialization thread.
  893. Arguments:
  894. BindingContext - Pointer to the device object for this driver.
  895. NdisStatus - The request completion code.
  896. OpenErrorStatus - More status information.
  897. Return Value:
  898. None.
  899. --*/
  900. {
  901. PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)BindingContext;
  902. #if DBG
  903. IF_NBFDBG (NBF_DEBUG_NDIS) {
  904. NbfPrint1 ("Nbfdrvr: NbfOpenAdapterCompleteNDIS Status: %s\n",
  905. NbfGetNdisStatus (NdisStatus));
  906. }
  907. #endif
  908. ENTER_NBF;
  909. DeviceContext->NdisRequestStatus = NdisStatus;
  910. KeSetEvent(
  911. &DeviceContext->NdisRequestEvent,
  912. 0L,
  913. FALSE);
  914. LEAVE_NBF;
  915. return;
  916. }
  917. VOID
  918. NbfCloseAdapterComplete (
  919. IN NDIS_HANDLE BindingContext,
  920. IN NDIS_STATUS NdisStatus
  921. )
  922. /*++
  923. Routine Description:
  924. This routine is called by NDIS to indicate that a close adapter
  925. is complete. Currently we don't close adapters, so this is not
  926. a problem.
  927. Arguments:
  928. BindingContext - Pointer to the device object for this driver.
  929. NdisStatus - The request completion code.
  930. Return Value:
  931. None.
  932. --*/
  933. {
  934. PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)BindingContext;
  935. #if DBG
  936. IF_NBFDBG (NBF_DEBUG_NDIS) {
  937. NbfPrint1 ("Nbfdrvr: NbfCloseAdapterCompleteNDIS Status: %s\n",
  938. NbfGetNdisStatus (NdisStatus));
  939. }
  940. #endif
  941. ENTER_NBF;
  942. DeviceContext->NdisRequestStatus = NdisStatus;
  943. KeSetEvent(
  944. &DeviceContext->NdisRequestEvent,
  945. 0L,
  946. FALSE);
  947. LEAVE_NBF;
  948. return;
  949. }
  950. VOID
  951. NbfResetComplete (
  952. IN NDIS_HANDLE BindingContext,
  953. IN NDIS_STATUS NdisStatus
  954. )
  955. /*++
  956. Routine Description:
  957. This routine is called by NDIS to indicate that a reset adapter
  958. is complete. Currently we don't reset adapters, so this is not
  959. a problem.
  960. Arguments:
  961. BindingContext - Pointer to the device object for this driver.
  962. NdisStatus - The request completion code.
  963. Return Value:
  964. None.
  965. --*/
  966. {
  967. UNREFERENCED_PARAMETER(BindingContext);
  968. UNREFERENCED_PARAMETER(NdisStatus);
  969. #if DBG
  970. IF_NBFDBG (NBF_DEBUG_NDIS) {
  971. NbfPrint1 ("Nbfdrvr: NbfResetCompleteNDIS Status: %s\n",
  972. NbfGetNdisStatus (NdisStatus));
  973. }
  974. #endif
  975. return;
  976. }
  977. VOID
  978. NbfRequestComplete (
  979. IN NDIS_HANDLE BindingContext,
  980. IN PNDIS_REQUEST NdisRequest,
  981. IN NDIS_STATUS NdisStatus
  982. )
  983. /*++
  984. Routine Description:
  985. This routine is called by NDIS to indicate that a request is complete.
  986. Since we only ever have one request outstanding, and then only
  987. during initialization, all we do is record the status and set
  988. the event to signalled to unblock the initialization thread.
  989. Arguments:
  990. BindingContext - Pointer to the device object for this driver.
  991. NdisRequest - The object describing the request.
  992. NdisStatus - The request completion code.
  993. Return Value:
  994. None.
  995. --*/
  996. {
  997. PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)BindingContext;
  998. #if DBG
  999. IF_NBFDBG (NBF_DEBUG_NDIS) {
  1000. NbfPrint2 ("Nbfdrvr: NbfRequestComplete request: %i, NDIS Status: %s\n",
  1001. NdisRequest->RequestType,NbfGetNdisStatus (NdisStatus));
  1002. }
  1003. #endif
  1004. ENTER_NBF;
  1005. DeviceContext->NdisRequestStatus = NdisStatus;
  1006. KeSetEvent(
  1007. &DeviceContext->NdisRequestEvent,
  1008. 0L,
  1009. FALSE);
  1010. LEAVE_NBF;
  1011. return;
  1012. }
  1013. VOID
  1014. NbfStatusIndication (
  1015. IN NDIS_HANDLE NdisBindingContext,
  1016. IN NDIS_STATUS NdisStatus,
  1017. IN PVOID StatusBuffer,
  1018. IN UINT StatusBufferSize
  1019. )
  1020. {
  1021. PDEVICE_CONTEXT DeviceContext;
  1022. PNDIS_WAN_LINE_UP LineUp;
  1023. KIRQL oldirql;
  1024. PTP_LINK Link;
  1025. DeviceContext = (PDEVICE_CONTEXT)NdisBindingContext;
  1026. KeRaiseIrql (DISPATCH_LEVEL, &oldirql);
  1027. switch (NdisStatus) {
  1028. case NDIS_STATUS_WAN_LINE_UP:
  1029. //
  1030. // A wan line is connected.
  1031. //
  1032. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1033. //
  1034. // If this happens before we are ready, then make
  1035. // a note of it, otherwise make the device ready.
  1036. //
  1037. DeviceContext->MediumSpeedAccurate = TRUE;
  1038. LineUp = (PNDIS_WAN_LINE_UP)StatusBuffer;
  1039. //
  1040. // See if this is a new lineup for this protocol type
  1041. //
  1042. if (LineUp->ProtocolType == 0x80D5) {
  1043. NDIS_HANDLE TransportHandle;
  1044. *((ULONG UNALIGNED *)(&TransportHandle)) =
  1045. *((ULONG UNALIGNED *)(&LineUp->LocalAddress[2]));
  1046. //
  1047. // See if this is a new lineup
  1048. //
  1049. if (TransportHandle == NULL) {
  1050. *((ULONG UNALIGNED *)(&LineUp->LocalAddress[2])) = *((ULONG UNALIGNED *)(&DeviceContext));
  1051. // ETH_COPY_NETWORK_ADDRESS(DeviceContext->LocalAddress.Address, LineUp->LocalAddress);
  1052. // ETH_COPY_NETWORK_ADDRESS(&DeviceContext->ReservedNetBIOSAddress[10], DeviceContext->LocalAddress.Address);
  1053. }
  1054. //
  1055. // Calculate minimum link timeouts based on the speed,
  1056. // which is passed in StatusBuffer.
  1057. //
  1058. // The formula is (max_frame_size * 2) / speed + 0.4 sec.
  1059. // This expands to
  1060. //
  1061. // MFS (bytes) * 2 8 bits
  1062. // ------------------- x ------ == timeout (sec),
  1063. // speed (100 bits/sec) byte
  1064. //
  1065. // which is (MFS * 16 / 100) / speed. We then convert it into
  1066. // the 50 ms units that NBF uses and add 8 (which is
  1067. // 0.4 seconds in 50 ms units).
  1068. //
  1069. // As a default timeout we use the min + 0.2 seconds
  1070. // unless the configured default is more.
  1071. //
  1072. if (LineUp->LinkSpeed > 0) {
  1073. DeviceContext->MediumSpeed = LineUp->LinkSpeed;
  1074. }
  1075. if (LineUp->MaximumTotalSize > 0) {
  1076. #if DBG
  1077. if (LineUp->MaximumTotalSize > DeviceContext->MaxSendPacketSize) {
  1078. DbgPrint ("Nbf: Bad LINE_UP size, %d (> %d)\n",
  1079. LineUp->MaximumTotalSize, DeviceContext->MaxSendPacketSize);
  1080. }
  1081. if (LineUp->MaximumTotalSize < 128) {
  1082. DbgPrint ("NBF: Bad LINE_UP size, %d (< 128)\n",
  1083. LineUp->MaximumTotalSize);
  1084. }
  1085. #endif
  1086. DeviceContext->CurSendPacketSize = LineUp->MaximumTotalSize;
  1087. }
  1088. if (LineUp->SendWindow == 0) {
  1089. DeviceContext->RecommendedSendWindow = 3;
  1090. } else {
  1091. DeviceContext->RecommendedSendWindow = LineUp->SendWindow + 1;
  1092. }
  1093. DeviceContext->MinimumT1Timeout =
  1094. ((((DeviceContext->CurSendPacketSize * 16) / 100) / DeviceContext->MediumSpeed) *
  1095. ((1 * SECONDS) / (50 * MILLISECONDS))) + 8;
  1096. if (DeviceContext->DefaultT1Timeout < DeviceContext->MinimumT1Timeout) {
  1097. DeviceContext->DefaultT1Timeout = DeviceContext->MinimumT1Timeout + 4;
  1098. }
  1099. }
  1100. RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1101. break;
  1102. case NDIS_STATUS_WAN_LINE_DOWN:
  1103. //
  1104. // An wan line is disconnected.
  1105. //
  1106. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1107. DeviceContext->MediumSpeedAccurate = FALSE;
  1108. //
  1109. // Set the timeouts to small values (0.4 seconds)
  1110. //
  1111. DeviceContext->DefaultT1Timeout = 8;
  1112. DeviceContext->MinimumT1Timeout = 8;
  1113. RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1114. //
  1115. // Stop the link on this device context (there
  1116. // will only be one).
  1117. //
  1118. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1119. if (DeviceContext->LinkTreeElements > 0) {
  1120. Link = (PTP_LINK)DeviceContext->LinkTreeRoot;
  1121. if ((Link->DeferredFlags & LINK_FLAGS_DEFERRED_DELETE) == 0) {
  1122. NbfReferenceLink ("Wan line down", Link, LREF_TREE);
  1123. RELEASE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1124. //
  1125. // Put the link in ADM to shut it down.
  1126. //
  1127. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1128. if (Link->State != LINK_STATE_ADM) {
  1129. Link->State = LINK_STATE_ADM;
  1130. RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
  1131. NbfDereferenceLinkSpecial ("Wan line down", Link, LREF_NOT_ADM);
  1132. } else {
  1133. RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
  1134. }
  1135. //
  1136. // Now stop it to destroy all connections on it.
  1137. //
  1138. NbfStopLink (Link);
  1139. NbfDereferenceLink ("Wan line down", Link, LREF_TREE);
  1140. } else {
  1141. RELEASE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1142. }
  1143. } else {
  1144. RELEASE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1145. }
  1146. break;
  1147. case NDIS_STATUS_WAN_FRAGMENT:
  1148. //
  1149. // A fragment has been received on the wan line.
  1150. // Send a reject back to him.
  1151. //
  1152. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1153. if (DeviceContext->LinkTreeElements > 0) {
  1154. Link = (PTP_LINK)DeviceContext->LinkTreeRoot;
  1155. NbfReferenceLink ("Async line down", Link, LREF_TREE);
  1156. RELEASE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1157. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1158. NbfSendRej (Link, FALSE, FALSE); // release lock
  1159. NbfDereferenceLink ("Async line down", Link, LREF_TREE);
  1160. } else {
  1161. RELEASE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1162. }
  1163. break;
  1164. case NDIS_STATUS_CLOSING:
  1165. IF_NBFDBG (NBF_DEBUG_PNP) {
  1166. NbfPrint1 ("NbfStatusIndication: Device @ %08x Closing\n", DeviceContext);
  1167. }
  1168. //
  1169. // The adapter is shutting down. We queue a worker
  1170. // thread to handle this.
  1171. //
  1172. ExInitializeWorkItem(
  1173. &DeviceContext->StatusClosingQueueItem,
  1174. NbfProcessStatusClosing,
  1175. (PVOID)DeviceContext);
  1176. ExQueueWorkItem(&DeviceContext->StatusClosingQueueItem, DelayedWorkQueue);
  1177. break;
  1178. default:
  1179. break;
  1180. }
  1181. KeLowerIrql (oldirql);
  1182. }
  1183. VOID
  1184. NbfProcessStatusClosing(
  1185. IN PVOID Parameter
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. This is the thread routine which restarts packetizing
  1190. that has been delayed on WAN to allow RRs to come in.
  1191. This is very similar to PacketizeConnections.
  1192. Arguments:
  1193. Parameter - A pointer to the device context.
  1194. Return Value:
  1195. None.
  1196. --*/
  1197. {
  1198. PDEVICE_CONTEXT DeviceContext;
  1199. PLIST_ENTRY p;
  1200. #if 0
  1201. PTP_ADDRESS Address;
  1202. #endif
  1203. PTP_LINK Link;
  1204. PTP_REQUEST Request;
  1205. NDIS_STATUS ndisStatus;
  1206. KIRQL oldirql;
  1207. NDIS_HANDLE NdisBindingHandle;
  1208. DeviceContext = (PDEVICE_CONTEXT)Parameter;
  1209. //
  1210. // Prevent new activity on the connection.
  1211. //
  1212. DeviceContext->State = DEVICECONTEXT_STATE_DOWN;
  1213. #if 0
  1214. //
  1215. // Stop all the addresses.
  1216. //
  1217. while ((p = ExInterlockedRemoveHeadList(
  1218. &DeviceContext->AddressDatabase,
  1219. &DeviceContext->SpinLock)) != NULL) {
  1220. Address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
  1221. InitializeListHead(p);
  1222. NbfStopAddress (Address);
  1223. }
  1224. #endif
  1225. //
  1226. // To speed things along, stop all the links too.
  1227. //
  1228. KeRaiseIrql (DISPATCH_LEVEL, &oldirql);
  1229. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1230. DeviceContext->LastLink = NULL;
  1231. while (DeviceContext->LinkTreeRoot != NULL) {
  1232. Link = (PTP_LINK)DeviceContext->LinkTreeRoot;
  1233. DeviceContext->LinkTreeRoot = RtlDelete ((PRTL_SPLAY_LINKS)Link);
  1234. DeviceContext->LinkTreeElements--;
  1235. RELEASE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1236. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->TimerSpinLock);
  1237. if (Link->OnShortList) {
  1238. RemoveEntryList (&Link->ShortList);
  1239. }
  1240. if (Link->OnLongList) {
  1241. RemoveEntryList (&Link->LongList);
  1242. }
  1243. RELEASE_DPC_SPIN_LOCK (&DeviceContext->TimerSpinLock);
  1244. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1245. if (Link->State != LINK_STATE_ADM) {
  1246. Link->State = LINK_STATE_ADM;
  1247. NbfSendDm (Link, FALSE); // send DM/0, release lock
  1248. // moving to ADM, remove reference
  1249. NbfDereferenceLinkSpecial("Expire T1 in CONNECTING mode", Link, LREF_NOT_ADM);
  1250. } else {
  1251. RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
  1252. }
  1253. NbfStopLink (Link);
  1254. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1255. }
  1256. RELEASE_DPC_SPIN_LOCK (&DeviceContext->LinkSpinLock);
  1257. KeLowerIrql (oldirql);
  1258. //
  1259. // Shutdown the control channel.
  1260. //
  1261. while ((p = ExInterlockedRemoveHeadList(
  1262. &DeviceContext->QueryIndicationQueue,
  1263. &DeviceContext->SpinLock)) != NULL) {
  1264. Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
  1265. NbfCompleteRequest (Request, STATUS_INVALID_DEVICE_STATE, 0);
  1266. }
  1267. while ((p = ExInterlockedRemoveHeadList(
  1268. &DeviceContext->DatagramIndicationQueue,
  1269. &DeviceContext->SpinLock)) != NULL) {
  1270. Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
  1271. NbfCompleteRequest (Request, STATUS_INVALID_DEVICE_STATE, 0);
  1272. }
  1273. while ((p = ExInterlockedRemoveHeadList(
  1274. &DeviceContext->StatusQueryQueue,
  1275. &DeviceContext->SpinLock)) != NULL) {
  1276. Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
  1277. NbfCompleteRequest (Request, STATUS_INVALID_DEVICE_STATE, 0);
  1278. }
  1279. while ((p = ExInterlockedRemoveHeadList(
  1280. &DeviceContext->FindNameQueue,
  1281. &DeviceContext->SpinLock)) != NULL) {
  1282. Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
  1283. NbfCompleteRequest (Request, STATUS_INVALID_DEVICE_STATE, 0);
  1284. }
  1285. //
  1286. // Close the NDIS binding.
  1287. //
  1288. NdisBindingHandle = DeviceContext->NdisBindingHandle;
  1289. DeviceContext->NdisBindingHandle = NULL;
  1290. if (NdisBindingHandle != NULL) {
  1291. KeInitializeEvent(
  1292. &DeviceContext->NdisRequestEvent,
  1293. NotificationEvent,
  1294. FALSE
  1295. );
  1296. NdisCloseAdapter(
  1297. &ndisStatus,
  1298. NdisBindingHandle);
  1299. if (ndisStatus == NDIS_STATUS_PENDING) {
  1300. IF_NBFDBG (NBF_DEBUG_NDIS) {
  1301. NbfPrint0 ("Adapter close pended.\n");
  1302. }
  1303. //
  1304. // The completion routine will set NdisRequestStatus.
  1305. //
  1306. KeWaitForSingleObject(
  1307. &DeviceContext->NdisRequestEvent,
  1308. Executive,
  1309. KernelMode,
  1310. TRUE,
  1311. (PLARGE_INTEGER)NULL
  1312. );
  1313. ndisStatus = DeviceContext->NdisRequestStatus;
  1314. KeResetEvent(
  1315. &DeviceContext->NdisRequestEvent
  1316. );
  1317. }
  1318. }
  1319. //
  1320. // We ignore ndisStatus.
  1321. //
  1322. #if 0
  1323. //
  1324. // Remove all the storage associated with the device.
  1325. //
  1326. NbfFreeResources (DeviceContext);
  1327. NdisFreePacketPool (DeviceContext->SendPacketPoolHandle);
  1328. NdisFreePacketPool (DeviceContext->ReceivePacketPoolHandle);
  1329. NdisFreeBufferPool (DeviceContext->NdisBufferPoolHandle);
  1330. #endif
  1331. // And remove creation ref if it has not already been removed
  1332. if (InterlockedExchange(&DeviceContext->CreateRefRemoved, TRUE) == FALSE) {
  1333. // Stop all internal timers
  1334. NbfStopTimerSystem(DeviceContext);
  1335. // Remove creation reference
  1336. NbfDereferenceDeviceContext ("Unload", DeviceContext, DCREF_CREATION);
  1337. }
  1338. } /* NbfProcessStatusClosing */
  1339. VOID
  1340. NbfStatusComplete (
  1341. IN NDIS_HANDLE NdisBindingContext
  1342. )
  1343. {
  1344. UNREFERENCED_PARAMETER (NdisBindingContext);
  1345. }
  1346. #if DBG
  1347. PUCHAR
  1348. NbfGetNdisStatus(
  1349. NDIS_STATUS GeneralStatus
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. This routine returns a pointer to the string describing the NDIS error
  1354. denoted by GeneralStatus.
  1355. Arguments:
  1356. GeneralStatus - the status you wish to make readable.
  1357. Return Value:
  1358. None.
  1359. --*/
  1360. {
  1361. static NDIS_STATUS Status[] = {
  1362. NDIS_STATUS_SUCCESS,
  1363. NDIS_STATUS_PENDING,
  1364. NDIS_STATUS_ADAPTER_NOT_FOUND,
  1365. NDIS_STATUS_ADAPTER_NOT_OPEN,
  1366. NDIS_STATUS_ADAPTER_NOT_READY,
  1367. NDIS_STATUS_ADAPTER_REMOVED,
  1368. NDIS_STATUS_BAD_CHARACTERISTICS,
  1369. NDIS_STATUS_BAD_VERSION,
  1370. NDIS_STATUS_CLOSING,
  1371. NDIS_STATUS_DEVICE_FAILED,
  1372. NDIS_STATUS_FAILURE,
  1373. NDIS_STATUS_INVALID_DATA,
  1374. NDIS_STATUS_INVALID_LENGTH,
  1375. NDIS_STATUS_INVALID_OID,
  1376. NDIS_STATUS_INVALID_PACKET,
  1377. NDIS_STATUS_MULTICAST_FULL,
  1378. NDIS_STATUS_NOT_INDICATING,
  1379. NDIS_STATUS_NOT_RECOGNIZED,
  1380. NDIS_STATUS_NOT_RESETTABLE,
  1381. NDIS_STATUS_NOT_SUPPORTED,
  1382. NDIS_STATUS_OPEN_FAILED,
  1383. NDIS_STATUS_OPEN_LIST_FULL,
  1384. NDIS_STATUS_REQUEST_ABORTED,
  1385. NDIS_STATUS_RESET_IN_PROGRESS,
  1386. NDIS_STATUS_RESOURCES,
  1387. NDIS_STATUS_UNSUPPORTED_MEDIA
  1388. };
  1389. static PUCHAR String[] = {
  1390. "SUCCESS",
  1391. "PENDING",
  1392. "ADAPTER_NOT_FOUND",
  1393. "ADAPTER_NOT_OPEN",
  1394. "ADAPTER_NOT_READY",
  1395. "ADAPTER_REMOVED",
  1396. "BAD_CHARACTERISTICS",
  1397. "BAD_VERSION",
  1398. "CLOSING",
  1399. "DEVICE_FAILED",
  1400. "FAILURE",
  1401. "INVALID_DATA",
  1402. "INVALID_LENGTH",
  1403. "INVALID_OID",
  1404. "INVALID_PACKET",
  1405. "MULTICAST_FULL",
  1406. "NOT_INDICATING",
  1407. "NOT_RECOGNIZED",
  1408. "NOT_RESETTABLE",
  1409. "NOT_SUPPORTED",
  1410. "OPEN_FAILED",
  1411. "OPEN_LIST_FULL",
  1412. "REQUEST_ABORTED",
  1413. "RESET_IN_PROGRESS",
  1414. "RESOURCES",
  1415. "UNSUPPORTED_MEDIA"
  1416. };
  1417. static UCHAR BadStatus[] = "UNDEFINED";
  1418. #define StatusCount (sizeof(Status)/sizeof(NDIS_STATUS))
  1419. INT i;
  1420. for (i=0; i<StatusCount; i++)
  1421. if (GeneralStatus == Status[i])
  1422. return String[i];
  1423. return BadStatus;
  1424. #undef StatusCount
  1425. }
  1426. #endif
  1427.