Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3085 lines
94 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. ndis.c
  5. Abstract:
  6. This module contains code which implements the routines used to
  7. initialize the IPX <-> NDIS interface, as well as most of the
  8. interface routines.
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. Sanjay Anand (SanjayAn) 3-Oct-1995
  13. Changes to support transfer of buffer ownership to transports
  14. 1. Added the ReceivePacketHandler to the ProtChars.
  15. Sanjay Anand (SanjayAn) 27-Oct-1995
  16. Changes to support Plug and Play
  17. Tony Bell (TonyBe) 10-Dec-1995
  18. Changes to support new NdisWan Lineup.
  19. --*/
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. //
  23. // This is a one-per-driver variable used in binding
  24. // to the NDIS interface.
  25. //
  26. NDIS_HANDLE IpxNdisProtocolHandle = (NDIS_HANDLE)NULL;
  27. NDIS_HANDLE IpxGlobalPacketPool = (NDIS_HANDLE)NULL;
  28. extern CTELock IpxGlobalInterlock;
  29. void
  30. IpxMediaSenseHandler(
  31. IN CTEEvent *WorkerThreadEvent,
  32. IN PVOID Context);
  33. void
  34. LineDownOnWorkerThread(
  35. IN CTEEvent *WorkerThreadEvent,
  36. IN PVOID Context);
  37. void
  38. LineUpOnWorkerThread(
  39. IN CTEEvent *WorkerThreadEvent,
  40. IN PVOID Context);
  41. #ifndef max
  42. #define max(a, b) ((a) > (b)) ? (a) : (b)
  43. #endif
  44. NTSTATUS
  45. IpxRegisterProtocol(
  46. IN PNDIS_STRING NameString
  47. )
  48. /*++
  49. Routine Description:
  50. This routine introduces this transport to the NDIS interface.
  51. Arguments:
  52. NameString - The name of the transport.
  53. Return Value:
  54. The function value is the status of the operation.
  55. STATUS_SUCCESS if all goes well,
  56. Failure status if we tried to register and couldn't,
  57. STATUS_INSUFFICIENT_RESOURCES if we couldn't even try to register.
  58. --*/
  59. {
  60. NDIS_STATUS ndisStatus;
  61. NDIS_PROTOCOL_CHARACTERISTICS ProtChars; // Used temporarily to register
  62. RtlZeroMemory(&ProtChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  63. //
  64. // Set up the characteristics of this protocol
  65. //
  66. #if NDIS40
  67. ProtChars.MajorNdisVersion = 4;
  68. ProtChars.ReceivePacketHandler = IpxReceivePacket;
  69. #else
  70. ProtChars.MajorNdisVersion = 3;
  71. #endif
  72. ProtChars.MinorNdisVersion = 0;
  73. ProtChars.Name = *NameString;
  74. ProtChars.OpenAdapterCompleteHandler = IpxOpenAdapterComplete;
  75. ProtChars.CloseAdapterCompleteHandler = IpxCloseAdapterComplete;
  76. ProtChars.ResetCompleteHandler = IpxResetComplete;
  77. ProtChars.RequestCompleteHandler = IpxRequestComplete;
  78. ProtChars.SendCompleteHandler = IpxSendComplete;
  79. ProtChars.TransferDataCompleteHandler = IpxTransferDataComplete;
  80. ProtChars.ReceiveHandler = IpxReceiveIndication;
  81. ProtChars.ReceiveCompleteHandler = IpxReceiveComplete;
  82. ProtChars.StatusHandler = IpxStatus;
  83. ProtChars.StatusCompleteHandler = IpxStatusComplete;
  84. ProtChars.BindAdapterHandler = IpxBindAdapter;
  85. ProtChars.UnbindAdapterHandler = IpxUnbindAdapter;
  86. ProtChars.UnloadHandler = IpxNdisUnload;
  87. //
  88. // We pass up the NET_PNP_EVENT structures passed in by NDIS
  89. // to the Transports via TDI. We pass on the response from TDI to NDIS.
  90. //
  91. #ifdef _PNP_POWER_
  92. ProtChars.PnPEventHandler = IpxPnPEventHandler;
  93. #endif
  94. NdisRegisterProtocol (
  95. &ndisStatus,
  96. &IpxNdisProtocolHandle,
  97. &ProtChars,
  98. (UINT)sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + NameString->Length);
  99. if (ndisStatus != NDIS_STATUS_SUCCESS) {
  100. return (NTSTATUS)ndisStatus;
  101. }
  102. //
  103. // Allocate a pool of packets for use by single send/receive
  104. //
  105. IpxGlobalPacketPool = (void *) NDIS_PACKET_POOL_TAG_FOR_NWLNKIPX;
  106. NdisAllocatePacketPoolEx(&ndisStatus,
  107. &IpxGlobalPacketPool,
  108. 10,
  109. 90,
  110. max(sizeof(IPX_SEND_RESERVED), sizeof(IPX_RECEIVE_RESERVED)));
  111. NdisSetPacketPoolProtocolId(IpxGlobalPacketPool, NDIS_PROTOCOL_ID_IPX);
  112. return STATUS_SUCCESS;
  113. } /* IpxRegisterProtocol */
  114. VOID
  115. IpxDeregisterProtocol (
  116. VOID
  117. )
  118. /*++
  119. Routine Description:
  120. This routine removes this transport to the NDIS interface.
  121. Arguments:
  122. None.
  123. Return Value:
  124. None.
  125. --*/
  126. {
  127. NDIS_STATUS ndisStatus;
  128. CTELockHandle LockHandle;
  129. NDIS_HANDLE LocalNdisProtocolHandle = (NDIS_HANDLE)NULL;
  130. NDIS_HANDLE LocalGlobalPacketPool = (NDIS_HANDLE)NULL;
  131. CTEGetLock (&IpxGlobalInterlock, &LockHandle);
  132. if (IpxNdisProtocolHandle != (NDIS_HANDLE)NULL) {
  133. LocalNdisProtocolHandle = IpxNdisProtocolHandle;
  134. IpxNdisProtocolHandle = (NDIS_HANDLE) NULL;
  135. CTEFreeLock (&IpxGlobalInterlock, LockHandle);
  136. NdisDeregisterProtocol (
  137. &ndisStatus,
  138. LocalNdisProtocolHandle);
  139. ASSERT(ndisStatus == NDIS_STATUS_SUCCESS);
  140. } else {
  141. CTEFreeLock (&IpxGlobalInterlock, LockHandle);
  142. }
  143. CTEGetLock (&IpxGlobalInterlock, &LockHandle);
  144. if (IpxGlobalPacketPool != NULL) {
  145. LocalGlobalPacketPool = IpxGlobalPacketPool;
  146. IpxGlobalPacketPool = (NDIS_HANDLE) NULL;
  147. CTEFreeLock (&IpxGlobalInterlock, LockHandle);
  148. NdisFreePacketPool(LocalGlobalPacketPool);
  149. } else {
  150. CTEFreeLock (&IpxGlobalInterlock, LockHandle);
  151. }
  152. } /* IpxDeregisterProtocol */
  153. VOID
  154. IpxDelayedSubmitNdisRequest(
  155. IN PVOID Param
  156. )
  157. /*++
  158. Routine Description:
  159. This routine submit an ndis request at PASSIVE level. We assume that Adatper structure
  160. still exist. IpxDestroyAdapter will delay 1 sec to allow this thread to finish.
  161. Arguments:
  162. Param - pointer to the work item.
  163. Return Value:
  164. None.
  165. --*/
  166. {
  167. PIPX_DELAYED_NDISREQUEST_ITEM DelayedNdisItem = (PIPX_DELAYED_NDISREQUEST_ITEM) Param;
  168. PADAPTER Adapter;
  169. UNICODE_STRING AdapterName;
  170. NDIS_REQUEST IpxRequest;
  171. NDIS_STATUS NdisStatus;
  172. Adapter = (PADAPTER) DelayedNdisItem->Adapter;
  173. RtlInitUnicodeString(&AdapterName, Adapter->AdapterName);
  174. IpxRequest = DelayedNdisItem->IpxRequest;
  175. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, &AdapterName);
  176. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  177. IPX_DEBUG(PNP, ("Setting the QoS OID SUCCESS\n"));
  178. } else {
  179. IPX_DEBUG(PNP, ("Setting the QoS OID failed - Error %lx\n", NdisStatus));
  180. }
  181. IpxFreeMemory(IpxRequest.DATA.SET_INFORMATION.InformationBuffer,
  182. DelayedNdisItem->AddrListSize,
  183. MEMORY_ADAPTER,
  184. "QoS specific stuff");
  185. IpxFreeMemory (
  186. DelayedNdisItem,
  187. sizeof (IPX_DELAYED_NDISREQUEST_ITEM),
  188. MEMORY_WORK_ITEM,
  189. "Work Item");
  190. IpxDereferenceDevice (Adapter->Device, DREF_ADAPTER);
  191. IpxDereferenceAdapter1(Adapter,ADAP_REF_NDISREQ);
  192. } /* IpxDelayedSubmitNdisRequest */
  193. NDIS_STATUS
  194. IpxSubmitNdisRequest(
  195. IN PADAPTER Adapter,
  196. IN PNDIS_REQUEST Request,
  197. IN PNDIS_STRING AdapterString
  198. )
  199. /*++
  200. Routine Description:
  201. This routine passed an NDIS_REQUEST to the MAC and waits
  202. until it has completed before returning the final status.
  203. Arguments:
  204. Adapter - Pointer to the device context for this driver.
  205. Request - Pointer to the NDIS_REQUEST to submit.
  206. AdapterString - The name of the adapter, in case an error needs
  207. to be logged.
  208. Return Value:
  209. The function value is the status of the operation.
  210. --*/
  211. {
  212. NDIS_STATUS NdisStatus;
  213. IPX_NDIS_REQUEST IpxRequest;
  214. RtlZeroMemory(&IpxRequest, sizeof(IpxRequest));
  215. RtlCopyMemory(&IpxRequest, Request, sizeof(NDIS_REQUEST));
  216. KeInitializeEvent(&IpxRequest.NdisRequestEvent,NotificationEvent,FALSE);
  217. IpxRequest.Status = NDIS_STATUS_SUCCESS;
  218. NdisRequest(
  219. &NdisStatus,
  220. Adapter->NdisBindingHandle,
  221. (PNDIS_REQUEST) &IpxRequest);
  222. if (NdisStatus == NDIS_STATUS_PENDING) {
  223. //
  224. // The completion routine will set NdisRequestStatus.
  225. //
  226. KeWaitForSingleObject(
  227. &IpxRequest.NdisRequestEvent,
  228. Executive,
  229. KernelMode,
  230. TRUE,
  231. (PLARGE_INTEGER)NULL
  232. );
  233. NdisStatus = IpxRequest.Status;
  234. KeResetEvent(
  235. &IpxRequest.NdisRequestEvent
  236. );
  237. }
  238. // Skip event log when QoS is not installed.
  239. if (NdisStatus != NDIS_STATUS_SUCCESS &&
  240. // This is not related to QoS
  241. (Request->DATA.QUERY_INFORMATION.Oid != OID_GEN_NETWORK_LAYER_ADDRESSES ||
  242. // or it is related to QoS and the status is not the status when QoS is
  243. // not installed.
  244. (Request->DATA.QUERY_INFORMATION.Oid == OID_GEN_NETWORK_LAYER_ADDRESSES &&
  245. NdisStatus != NDIS_STATUS_INVALID_OID))) {
  246. IPX_DEBUG (NDIS, ("%s on OID %8.8lx failed %lx\n",
  247. Request->RequestType == NdisRequestSetInformation ? "Set" : "Query",
  248. Request->DATA.QUERY_INFORMATION.Oid,
  249. NdisStatus));
  250. IpxWriteOidErrorLog(
  251. Adapter->Device->DeviceObject,
  252. Request->RequestType == NdisRequestSetInformation ?
  253. EVENT_TRANSPORT_SET_OID_FAILED : EVENT_TRANSPORT_QUERY_OID_FAILED,
  254. NdisStatus,
  255. AdapterString->Buffer,
  256. Request->DATA.QUERY_INFORMATION.Oid);
  257. } else {
  258. IPX_DEBUG (NDIS, ("%s on OID %8.8lx succeeded\n",
  259. Request->RequestType == NdisRequestSetInformation ? "Set" : "Query",
  260. Request->DATA.QUERY_INFORMATION.Oid));
  261. }
  262. return NdisStatus;
  263. } /* IpxSubmitNdisRequest */
  264. NTSTATUS
  265. IpxInitializeNdis(
  266. IN PADAPTER Adapter,
  267. IN PBINDING_CONFIG ConfigBinding
  268. )
  269. /*++
  270. Routine Description:
  271. This routine introduces this transport to the NDIS interface and sets up
  272. any necessary NDIS data structures (Buffer pools and such). It will be
  273. called for each adapter opened by this transport.
  274. Arguments:
  275. Adapter - Structure describing this binding.
  276. ConfigAdapter - Configuration information for this binding.
  277. Return Value:
  278. The function value is the status of the operation.
  279. --*/
  280. {
  281. NDIS_STATUS NdisStatus;
  282. NDIS_STATUS OpenErrorStatus;
  283. NDIS_MEDIUM IpxSupportedMedia[] = { NdisMedium802_3, NdisMedium802_5, NdisMediumFddi, NdisMediumArcnet878_2, NdisMediumWan };
  284. UINT SelectedMedium;
  285. NDIS_REQUEST IpxRequest;
  286. ULONG MinimumLookahead;
  287. UCHAR WanProtocolId[6] = { 0x80, 0x00, 0x00, 0x00, 0x81, 0x37 };
  288. UCHAR FunctionalAddress[4] = { 0x00, 0x80, 0x00, 0x00 };
  289. ULONG WanHeaderFormat = NdisWanHeaderEthernet;
  290. NDIS_OID IpxOid;
  291. ULONG MacOptions;
  292. ULONG PacketFilter;
  293. PNDIS_STRING AdapterString = &ConfigBinding->AdapterName;
  294. //
  295. // Initialize this adapter for IPX use through NDIS
  296. //
  297. //
  298. // This event is used in case any of the NDIS requests
  299. // pend; we wait until it is set by the completion
  300. // routine, which also sets NdisRequestStatus.
  301. //
  302. KeInitializeEvent(
  303. &Adapter->NdisRequestEvent,
  304. NotificationEvent,
  305. FALSE
  306. );
  307. Adapter->NdisBindingHandle = NULL;
  308. OpenErrorStatus = 0;
  309. NdisOpenAdapter (
  310. &NdisStatus,
  311. &OpenErrorStatus,
  312. &Adapter->NdisBindingHandle,
  313. &SelectedMedium,
  314. IpxSupportedMedia,
  315. sizeof (IpxSupportedMedia) / sizeof(NDIS_MEDIUM),
  316. IpxNdisProtocolHandle,
  317. (NDIS_HANDLE)Adapter,
  318. &ConfigBinding->AdapterName,
  319. 0,
  320. NULL);
  321. if (NdisStatus == NDIS_STATUS_PENDING) {
  322. //
  323. // The completion routine will set NdisRequestStatus.
  324. //
  325. KeWaitForSingleObject(
  326. &Adapter->NdisRequestEvent,
  327. Executive,
  328. KernelMode,
  329. TRUE,
  330. (PLARGE_INTEGER)NULL
  331. );
  332. NdisStatus = Adapter->NdisRequestStatus;
  333. OpenErrorStatus = Adapter->OpenErrorStatus;
  334. KeResetEvent(
  335. &Adapter->NdisRequestEvent
  336. );
  337. }
  338. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  339. IPX_DEBUG (NDIS, ("Open %ws failed %lx\n", ConfigBinding->AdapterName.Buffer, NdisStatus));
  340. IpxWriteGeneralErrorLog(
  341. Adapter->Device->DeviceObject,
  342. EVENT_TRANSPORT_ADAPTER_NOT_FOUND,
  343. 807,
  344. NdisStatus,
  345. AdapterString->Buffer,
  346. 1,
  347. &OpenErrorStatus);
  348. return STATUS_INSUFFICIENT_RESOURCES;
  349. } else {
  350. IPX_DEBUG (NDIS, ("Open %ws succeeded\n", ConfigBinding->AdapterName.Buffer));
  351. }
  352. //
  353. // Get the information we need about the adapter, based on
  354. // the media type.
  355. //
  356. MacInitializeMacInfo(
  357. IpxSupportedMedia[SelectedMedium],
  358. &Adapter->MacInfo);
  359. switch (Adapter->MacInfo.RealMediumType) {
  360. case NdisMedium802_3:
  361. IpxOid = OID_802_3_CURRENT_ADDRESS;
  362. break;
  363. case NdisMedium802_5:
  364. IpxOid = OID_802_5_CURRENT_ADDRESS;
  365. break;
  366. case NdisMediumFddi:
  367. IpxOid = OID_FDDI_LONG_CURRENT_ADDR;
  368. break;
  369. case NdisMediumArcnet878_2:
  370. IpxOid = OID_ARCNET_CURRENT_ADDRESS;
  371. break;
  372. case NdisMediumWan:
  373. IpxOid = OID_WAN_CURRENT_ADDRESS;
  374. break;
  375. default:
  376. // 301870
  377. return NDIS_STATUS_FAILURE;
  378. }
  379. IpxRequest.RequestType = NdisRequestQueryInformation;
  380. IpxRequest.DATA.QUERY_INFORMATION.Oid = IpxOid;
  381. if (IpxOid != OID_ARCNET_CURRENT_ADDRESS) {
  382. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = Adapter->LocalMacAddress.Address;
  383. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 6;
  384. } else {
  385. //
  386. // We take the arcnet single-byte address and right-justify
  387. // it in a field of zeros.
  388. //
  389. RtlZeroMemory (Adapter->LocalMacAddress.Address, 5);
  390. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &Adapter->LocalMacAddress.Address[5];
  391. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 1;
  392. }
  393. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  394. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  395. IpxCloseNdis (Adapter);
  396. return STATUS_INSUFFICIENT_RESOURCES;
  397. }
  398. //
  399. // Now query the maximum packet sizes.
  400. //
  401. IpxRequest.RequestType = NdisRequestQueryInformation;
  402. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_FRAME_SIZE;
  403. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(Adapter->MaxReceivePacketSize);
  404. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  405. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  406. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  407. IpxCloseNdis (Adapter);
  408. return STATUS_INSUFFICIENT_RESOURCES;
  409. }
  410. IpxRequest.RequestType = NdisRequestQueryInformation;
  411. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
  412. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(Adapter->MaxSendPacketSize);
  413. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  414. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  415. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  416. IpxCloseNdis (Adapter);
  417. return STATUS_INSUFFICIENT_RESOURCES;
  418. }
  419. //
  420. // Query the receive buffer space.
  421. //
  422. IpxRequest.RequestType = NdisRequestQueryInformation;
  423. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_RECEIVE_BUFFER_SPACE;
  424. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(Adapter->ReceiveBufferSpace);
  425. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  426. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  427. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  428. IpxCloseNdis (Adapter);
  429. return STATUS_INSUFFICIENT_RESOURCES;
  430. }
  431. //
  432. // Now set the minimum lookahead size. The value we choose
  433. // here is the 128 needed for TDI indications, plus the size
  434. // of the IPX header, plus the largest extra header possible
  435. // (a SNAP header, 8 bytes), plus the largest higher-level
  436. // header (I think it is a Netbios datagram, 34 bytes).
  437. //
  438. // Adapt this based on higher-level bindings and
  439. // configured frame types.
  440. //
  441. MinimumLookahead = 128 + sizeof(IPX_HEADER) + 8 + 34;
  442. IpxRequest.RequestType = NdisRequestSetInformation;
  443. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_LOOKAHEAD;
  444. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &MinimumLookahead;
  445. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  446. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  447. #define HACK
  448. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  449. #if defined HACK
  450. KdPrint(("IPX: OID_GEN_CURRENT_LOOKAHEAD FAiled\n"));
  451. MinimumLookahead = 200;
  452. #else //!HACK
  453. IpxCloseNdis (Adapter);
  454. return STATUS_INSUFFICIENT_RESOURCES;
  455. #endif //HACK
  456. // The above hack is to deal with NDIS's incorrect handling on
  457. // the LOOKAHEAD request.
  458. }
  459. //
  460. // Now query the link speed
  461. //
  462. IpxRequest.RequestType = NdisRequestQueryInformation;
  463. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
  464. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(Adapter->MediumSpeed);
  465. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  466. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  467. if (NdisStatus != NDIS_STATUS_SUCCESS || Adapter->MediumSpeed == 0) {
  468. IpxCloseNdis (Adapter);
  469. return STATUS_INSUFFICIENT_RESOURCES;
  470. }
  471. //
  472. // For wan, specify our protocol ID and header format.
  473. // We don't query the medium subtype because we don't
  474. // case (since we require ethernet emulation).
  475. //
  476. if (Adapter->MacInfo.MediumAsync) {
  477. if (Adapter->BindSap != 0x8137) {
  478. *(UNALIGNED USHORT *)(&WanProtocolId[4]) = Adapter->BindSapNetworkOrder;
  479. }
  480. IpxRequest.RequestType = NdisRequestSetInformation;
  481. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_PROTOCOL_TYPE;
  482. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = WanProtocolId;
  483. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 6;
  484. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  485. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  486. IpxCloseNdis (Adapter);
  487. return STATUS_INSUFFICIENT_RESOURCES;
  488. }
  489. IpxRequest.RequestType = NdisRequestSetInformation;
  490. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_HEADER_FORMAT;
  491. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanHeaderFormat;
  492. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  493. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  494. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  495. IpxCloseNdis (Adapter);
  496. return STATUS_INSUFFICIENT_RESOURCES;
  497. }
  498. //
  499. // Now query the line count.
  500. //
  501. // NDIS returns 252
  502. IpxRequest.RequestType = NdisRequestQueryInformation;
  503. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_LINE_COUNT;
  504. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &Adapter->WanNicIdCount;
  505. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  506. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  507. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  508. DbgPrint("NdisRequest WAN_LINE_COUNT failed with status (%x)\n",NdisStatus);
  509. Adapter->WanNicIdCount = 1;
  510. }
  511. //
  512. // We dont need static info anymore. We just do it on demand...
  513. //
  514. // Allocating WAN line on demand is not done yet, the comment above
  515. // is BS.
  516. // Adapter->WanNicIdCount = 1;
  517. if (Adapter->WanNicIdCount == 0) {
  518. IPX_DEBUG (NDIS, ("OID_WAN_LINE_COUNT returned 0 lines\n"));
  519. IpxWriteOidErrorLog(
  520. Adapter->Device->DeviceObject,
  521. EVENT_TRANSPORT_QUERY_OID_FAILED,
  522. NDIS_STATUS_INVALID_DATA,
  523. AdapterString->Buffer,
  524. OID_WAN_LINE_COUNT);
  525. IpxCloseNdis (Adapter);
  526. return STATUS_INSUFFICIENT_RESOURCES;
  527. }
  528. }
  529. //
  530. // For 802.5 adapter's configured that way, we enable the
  531. // functional address (C0-00-00-80-00-00).
  532. //
  533. if ((Adapter->MacInfo.MediumType == NdisMedium802_5) &&
  534. (Adapter->EnableFunctionalAddress)) {
  535. //
  536. // For token-ring, we pass the last four bytes of the
  537. // Netbios functional address.
  538. //
  539. IpxRequest.RequestType = NdisRequestSetInformation;
  540. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL;
  541. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = FunctionalAddress;
  542. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  543. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  544. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  545. IpxCloseNdis (Adapter);
  546. return STATUS_INSUFFICIENT_RESOURCES;
  547. }
  548. }
  549. //
  550. // Now query the MAC's optional characteristics.
  551. //
  552. IpxRequest.RequestType = NdisRequestQueryInformation;
  553. IpxRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS;
  554. IpxRequest.DATA.QUERY_INFORMATION.InformationBuffer = &MacOptions;
  555. IpxRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  556. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  557. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  558. IpxCloseNdis (Adapter);
  559. return STATUS_INSUFFICIENT_RESOURCES;
  560. }
  561. Adapter->MacInfo.CopyLookahead =
  562. ((MacOptions & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA) != 0) ?
  563. TDI_RECEIVE_COPY_LOOKAHEAD : 0;
  564. Adapter->MacInfo.MacOptions = MacOptions;
  565. switch (Adapter->MacInfo.MediumType) {
  566. case NdisMedium802_3:
  567. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_2] = 17;
  568. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_3] = 14;
  569. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 14;
  570. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_SNAP] = 22;
  571. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_2] = 17;
  572. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_3] = 14;
  573. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 14;
  574. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_SNAP] = 22;
  575. break;
  576. case NdisMedium802_5:
  577. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_2] = 17;
  578. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_3] = 17;
  579. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 17;
  580. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_SNAP] = 22;
  581. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_2] = 17;
  582. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_3] = 17;
  583. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 17;
  584. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_SNAP] = 22;
  585. break;
  586. case NdisMediumFddi:
  587. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_2] = 16;
  588. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_3] = 13;
  589. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 16;
  590. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_SNAP] = 21;
  591. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_2] = 16;
  592. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_3] = 13;
  593. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 16;
  594. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_SNAP] = 21;
  595. break;
  596. case NdisMediumArcnet878_2:
  597. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_2] = 3;
  598. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_802_3] = 3;
  599. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 3;
  600. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_SNAP] = 3;
  601. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_2] = 3;
  602. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_802_3] = 3;
  603. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 3;
  604. Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_SNAP] = 3;
  605. break;
  606. }
  607. //
  608. // If functional filtering is set, set the address
  609. // for the appropriate binding.
  610. //
  611. //
  612. // Now that everything is set up, we enable the filter
  613. // for packet reception.
  614. //
  615. switch (Adapter->MacInfo.MediumType) {
  616. case NdisMedium802_3:
  617. case NdisMediumFddi:
  618. case NdisMedium802_5:
  619. case NdisMediumArcnet878_2:
  620. //
  621. // If we have a virtual network number we need to receive
  622. // broadcasts (either the router will be bound in which
  623. // case we want them, or we need to respond to rip requests
  624. // ourselves).
  625. //
  626. PacketFilter = NDIS_PACKET_TYPE_DIRECTED;
  627. if (Adapter->Device->VirtualNetworkNumber != 0) {
  628. Adapter->BroadcastEnabled = TRUE;
  629. // [MS]
  630. // New scheme: EnableBroadcastCount incremented for every client who
  631. // is interested in BCAST. Decrement this when someone
  632. // doesnt want it. If the count goes to 0, we remove this
  633. // quality in the adapter. At IPXDevice creation, we set it
  634. // to 0.
  635. //
  636. // Adapter->Device->EnableBroadcastCount = 1;
  637. PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
  638. if ((Adapter->MacInfo.MediumType == NdisMedium802_5) && (Adapter->EnableFunctionalAddress)) {
  639. PacketFilter |= NDIS_PACKET_TYPE_FUNCTIONAL;
  640. }
  641. } else {
  642. Adapter->BroadcastEnabled = FALSE;
  643. Adapter->Device->EnableBroadcastCount = 0;
  644. }
  645. break;
  646. default:
  647. CTEAssert (FALSE);
  648. break;
  649. }
  650. //
  651. // Now fill in the NDIS_REQUEST.
  652. //
  653. IpxRequest.RequestType = NdisRequestSetInformation;
  654. IpxRequest.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  655. IpxRequest.DATA.SET_INFORMATION.InformationBuffer = &PacketFilter;
  656. IpxRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof(ULONG);
  657. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, AdapterString);
  658. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  659. IpxCloseNdis (Adapter);
  660. return STATUS_INSUFFICIENT_RESOURCES;
  661. }
  662. return STATUS_SUCCESS;
  663. } /* IpxInitializeNdis */
  664. VOID
  665. IpxAddBroadcast(
  666. IN PDEVICE Device
  667. )
  668. /*++
  669. Routine Description:
  670. This routine is called when another reason for enabling
  671. broadcast reception is added. If it is the first, then
  672. reception on the card is enabled by queueing a call to
  673. IpxBroadcastOperation.
  674. THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD.
  675. Arguments:
  676. Device - The IPX device.
  677. Return Value:
  678. None.
  679. --*/
  680. {
  681. ++Device->EnableBroadcastCount;
  682. if (Device->EnableBroadcastCount == 1) {
  683. //
  684. // Broadcasts should be enabled.
  685. //
  686. if (!Device->EnableBroadcastPending) {
  687. if (Device->DisableBroadcastPending) {
  688. Device->ReverseBroadcastOperation = TRUE;
  689. } else {
  690. Device->EnableBroadcastPending = TRUE;
  691. IpxBroadcastOperation((PVOID)TRUE);
  692. }
  693. }
  694. }
  695. } /* IpxAddBroadcast */
  696. VOID
  697. IpxRemoveBroadcast(
  698. IN PDEVICE Device
  699. )
  700. /*++
  701. Routine Description:
  702. This routine is called when a reason for enabling
  703. broadcast reception is removed. If it is the last, then
  704. reception on the card is disabled by queueing a call to
  705. IpxBroadcastOperation.
  706. THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD.
  707. Arguments:
  708. Device - The IPX device.
  709. Return Value:
  710. None.
  711. --*/
  712. {
  713. --Device->EnableBroadcastCount;
  714. if (Device->EnableBroadcastCount <= 0) {
  715. //
  716. // Broadcasts should be disabled.
  717. //
  718. if (!Device->DisableBroadcastPending) {
  719. if (Device->EnableBroadcastPending) {
  720. Device->ReverseBroadcastOperation = TRUE;
  721. } else {
  722. Device->DisableBroadcastPending = TRUE;
  723. IpxBroadcastOperation((PVOID)FALSE);
  724. }
  725. }
  726. }
  727. } /* IpxRemoveBroadcast */
  728. VOID
  729. IpxBroadcastOperation(
  730. IN PVOID Parameter
  731. )
  732. /*++
  733. Routine Description:
  734. This routine is used to change whether broadcast reception
  735. is enabled or disabled. It performs the requested operation
  736. on every adapter bound to by IPX.
  737. This routine is called by a worker thread queued when a
  738. bind/unbind operation changes the broadcast state.
  739. [ShreeM] New scheme: EnableBroadcastCount incremented for every client who
  740. is interested in BCAST. Decrement this when someone
  741. doesnt want it. If the count goes to 0, we remove this
  742. quality in the adapter. At IPXDevice creation, we set it
  743. to 0.
  744. Arguments:
  745. Parameter - TRUE if broadcasts should be enabled, FALSE
  746. if they should be disabled.
  747. Return Value:
  748. None.
  749. --*/
  750. {
  751. PDEVICE Device = IpxDevice;
  752. BOOLEAN Enable = (BOOLEAN)Parameter;
  753. UINT i;
  754. PBINDING Binding;
  755. PADAPTER Adapter;
  756. ULONG PacketFilter;
  757. NDIS_REQUEST IpxRequest;
  758. NDIS_STRING AdapterName;
  759. CTELockHandle LockHandle;
  760. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  761. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  762. IPX_DEBUG (NDIS, ("%s operation started\n", Enable ? "Enable" : "Disable"));
  763. {
  764. ULONG Index = MIN (Device->MaxBindings, Device->ValidBindings);
  765. for (i = FIRST_REAL_BINDING; i <= Index; i++) {
  766. Binding = NIC_ID_TO_BINDING(Device, i);
  767. if (Binding == NULL) {
  768. continue;
  769. }
  770. Adapter = Binding->Adapter;
  771. if (Adapter->BroadcastEnabled == Enable) {
  772. continue;
  773. }
  774. if (Enable) {
  775. if ((Adapter->MacInfo.MediumType == NdisMedium802_5) && (Adapter->EnableFunctionalAddress)) {
  776. PacketFilter = (NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_FUNCTIONAL);
  777. } else {
  778. PacketFilter = (NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_BROADCAST);
  779. }
  780. } else {
  781. PacketFilter = NDIS_PACKET_TYPE_DIRECTED;
  782. }
  783. //
  784. // Now fill in the NDIS_REQUEST.
  785. //
  786. RtlZeroMemory(&IpxRequest, sizeof(NDIS_REQUEST));
  787. IpxRequest.RequestType = NdisRequestSetInformation;
  788. IpxRequest.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  789. IpxRequest.DATA.SET_INFORMATION.InformationBuffer = &PacketFilter;
  790. IpxRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof(ULONG);
  791. AdapterName.Buffer = Adapter->AdapterName;
  792. AdapterName.Length = (USHORT)Adapter->AdapterNameLength;
  793. AdapterName.MaximumLength = (USHORT)(Adapter->AdapterNameLength + sizeof(WCHAR));
  794. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  795. (VOID)IpxSubmitNdisRequest (Adapter, &IpxRequest, &AdapterName);
  796. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  797. Adapter->BroadcastEnabled = Enable;
  798. }
  799. }
  800. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  801. CTEGetLock (&Device->Lock, &LockHandle);
  802. if (Enable) {
  803. CTEAssert (Device->EnableBroadcastPending);
  804. Device->EnableBroadcastPending = FALSE;
  805. if (Device->ReverseBroadcastOperation) {
  806. Device->ReverseBroadcastOperation = FALSE;
  807. Device->DisableBroadcastPending = TRUE;
  808. ExInitializeWorkItem(
  809. &Device->BroadcastOperationQueueItem,
  810. IpxBroadcastOperation,
  811. (PVOID)FALSE);
  812. ExQueueWorkItem(&Device->BroadcastOperationQueueItem, DelayedWorkQueue);
  813. }
  814. } else {
  815. CTEAssert (Device->DisableBroadcastPending);
  816. Device->DisableBroadcastPending = FALSE;
  817. if (Device->ReverseBroadcastOperation) {
  818. Device->ReverseBroadcastOperation = FALSE;
  819. Device->EnableBroadcastPending = TRUE;
  820. ExInitializeWorkItem(
  821. &Device->BroadcastOperationQueueItem,
  822. IpxBroadcastOperation,
  823. (PVOID)TRUE);
  824. ExQueueWorkItem(&Device->BroadcastOperationQueueItem, DelayedWorkQueue);
  825. }
  826. }
  827. CTEFreeLock (&Device->Lock, LockHandle);
  828. }/* IpxBroadcastOperation */
  829. VOID
  830. IpxCloseNdis(
  831. IN PADAPTER Adapter
  832. )
  833. /*++
  834. Routine Description:
  835. This routine unbinds the transport from the NDIS interface and does
  836. any other work required to undo what was done in IpxInitializeNdis.
  837. It is written so that it can be called from within IpxInitializeNdis
  838. if it fails partway through.
  839. Arguments:
  840. DeviceObject - Pointer to the device object for this driver.
  841. Return Value:
  842. The function value is the status of the operation.
  843. --*/
  844. {
  845. NDIS_STATUS ndisStatus;
  846. //
  847. // Close the NDIS binding.
  848. //
  849. if (Adapter->NdisBindingHandle != (NDIS_HANDLE)NULL) {
  850. //
  851. // This event is used in case any of the NDIS requests
  852. // pend; we wait until it is set by the completion
  853. // routine, which also sets NdisRequestStatus.
  854. //
  855. KeInitializeEvent(
  856. &Adapter->NdisRequestEvent,
  857. NotificationEvent,
  858. FALSE
  859. );
  860. NdisCloseAdapter(
  861. &ndisStatus,
  862. Adapter->NdisBindingHandle);
  863. Adapter->NdisBindingHandle = (NDIS_HANDLE)NULL;
  864. if (ndisStatus == NDIS_STATUS_PENDING) {
  865. //
  866. // The completion routine will set NdisRequestStatus.
  867. //
  868. KeWaitForSingleObject(
  869. &Adapter->NdisRequestEvent,
  870. Executive,
  871. KernelMode,
  872. TRUE,
  873. (PLARGE_INTEGER)NULL
  874. );
  875. ndisStatus = Adapter->NdisRequestStatus;
  876. KeResetEvent(
  877. &Adapter->NdisRequestEvent
  878. );
  879. }
  880. //
  881. // We ignore ndisStatus.
  882. //
  883. }
  884. #if 0
  885. if (Adapter->SendPacketPoolHandle != NULL) {
  886. NdisFreePacketPool (Adapter->SendPacketPoolHandle);
  887. }
  888. if (Adapter->ReceivePacketPoolHandle != NULL) {
  889. NdisFreePacketPool (Adapter->ReceivePacketPoolHandle);
  890. }
  891. if (Adapter->NdisBufferPoolHandle != NULL) {
  892. NdisFreeBufferPool (Adapter->NdisBufferPoolHandle);
  893. }
  894. #endif
  895. } /* IpxCloseNdis */
  896. VOID
  897. IpxOpenAdapterComplete(
  898. IN NDIS_HANDLE BindingContext,
  899. IN NDIS_STATUS NdisStatus,
  900. IN NDIS_STATUS OpenErrorStatus
  901. )
  902. /*++
  903. Routine Description:
  904. This routine is called by NDIS to indicate that an open adapter
  905. is complete. Since we only ever have one outstanding, and then only
  906. during initialization, all we do is record the status and set
  907. the event to signalled to unblock the initialization thread.
  908. Arguments:
  909. BindingContext - Pointer to the device object for this driver.
  910. NdisStatus - The request completion code.
  911. OpenErrorStatus - More status information.
  912. Return Value:
  913. None.
  914. --*/
  915. {
  916. PADAPTER Adapter = (PADAPTER)BindingContext;
  917. Adapter->NdisRequestStatus = NdisStatus;
  918. Adapter->OpenErrorStatus = OpenErrorStatus;
  919. KeSetEvent(
  920. &Adapter->NdisRequestEvent,
  921. 0L,
  922. FALSE);
  923. } /* IpxOpenAdapterComplete */
  924. VOID
  925. IpxCloseAdapterComplete(
  926. IN NDIS_HANDLE BindingContext,
  927. IN NDIS_STATUS NdisStatus
  928. )
  929. /*++
  930. Routine Description:
  931. This routine is called by NDIS to indicate that a close adapter
  932. is complete. Currently we don't close adapters, so this is not
  933. a problem.
  934. Arguments:
  935. BindingContext - Pointer to the device object for this driver.
  936. NdisStatus - The request completion code.
  937. Return Value:
  938. None.
  939. --*/
  940. {
  941. PADAPTER Adapter = (PADAPTER)BindingContext;
  942. Adapter->NdisRequestStatus = NdisStatus;
  943. KeSetEvent(
  944. &Adapter->NdisRequestEvent,
  945. 0L,
  946. FALSE);
  947. } /* IpxCloseAdapterComplete */
  948. VOID
  949. IpxResetComplete(
  950. IN NDIS_HANDLE BindingContext,
  951. IN NDIS_STATUS NdisStatus
  952. )
  953. /*++
  954. Routine Description:
  955. This routine is called by NDIS to indicate that a reset adapter
  956. is complete. Currently we don't reset adapters, so this is not
  957. a problem.
  958. Arguments:
  959. BindingContext - Pointer to the device object for this driver.
  960. NdisStatus - The request completion code.
  961. Return Value:
  962. None.
  963. --*/
  964. {
  965. UNREFERENCED_PARAMETER(BindingContext);
  966. UNREFERENCED_PARAMETER(NdisStatus);
  967. } /* IpxResetComplete */
  968. VOID
  969. IpxRequestComplete(
  970. IN NDIS_HANDLE BindingContext,
  971. IN PNDIS_REQUEST NdisRequest,
  972. IN NDIS_STATUS NdisStatus
  973. )
  974. /*++
  975. Routine Description:
  976. This routine is called by NDIS to indicate that a request is complete.
  977. Since we only ever have one request outstanding, and then only
  978. during initialization, all we do is record the status and set
  979. the event to signalled to unblock the initialization thread.
  980. Arguments:
  981. BindingContext - Pointer to the device object for this driver.
  982. NdisRequest - The object describing the request.
  983. NdisStatus - The request completion code.
  984. Return Value:
  985. None.
  986. --*/
  987. {
  988. PADAPTER Adapter = (PADAPTER)BindingContext;
  989. PIPX_NDIS_REQUEST IpxRequest = (PIPX_NDIS_REQUEST) NdisRequest;
  990. IpxRequest->Status = NdisStatus;
  991. KeSetEvent(
  992. &IpxRequest->NdisRequestEvent,
  993. 0L,
  994. FALSE);
  995. } /* IpxRequestComplete */
  996. VOID
  997. IpxStatus(
  998. IN NDIS_HANDLE NdisBindingContext,
  999. IN NDIS_STATUS NdisStatus,
  1000. IN PVOID StatusBuffer,
  1001. IN UINT StatusBufferSize
  1002. )
  1003. {
  1004. PADAPTER Adapter, TmpAdapter;
  1005. PNDIS_WAN_LINE_UP LineUp;
  1006. PNDIS_WAN_LINE_DOWN LineDown;
  1007. PIPXCP_CONFIGURATION Configuration; // contains ipx net and node
  1008. BOOLEAN UpdateLineUp;
  1009. PBINDING Binding, TmpBinding;
  1010. PDEVICE Device;
  1011. PADDRESS Address;
  1012. ULONG CurrentHash;
  1013. PIPX_ROUTE_ENTRY RouteEntry;
  1014. PNDIS_BUFFER NdisBuffer;
  1015. PNWLINK_ACTION NwlinkAction;
  1016. PIPX_ADDRESS_DATA IpxAddressData;
  1017. PREQUEST Request;
  1018. UINT BufferLength;
  1019. IPX_LINE_INFO LineInfo;
  1020. ULONG Segment;
  1021. ULONG LinkSpeed;
  1022. PLIST_ENTRY p;
  1023. NTSTATUS Status;
  1024. #ifdef SUNDOWN
  1025. // To avoid a warning when Binding->NicId = i;
  1026. // Assume we have no more than 16-bit number of binding.
  1027. USHORT i, j;
  1028. #else
  1029. UINT i, j;
  1030. #endif
  1031. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  1032. IPX_DEFINE_LOCK_HANDLE (OldIrq)
  1033. NTSTATUS ntStatus;
  1034. CTEEvent *Event;
  1035. KIRQL irql;
  1036. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1037. Adapter = (PADAPTER)NdisBindingContext;
  1038. IpxReferenceAdapter(Adapter);
  1039. Device = Adapter->Device;
  1040. switch (NdisStatus) {
  1041. case NDIS_STATUS_WAN_LINE_UP:
  1042. //
  1043. // If the line is already up, then we are just getting
  1044. // a change in line conditions, and the IPXCP_CONFIGURATION
  1045. // information is not included. If it turns out we need
  1046. // all the info, we check the size again later.
  1047. //
  1048. if (StatusBufferSize < sizeof(NDIS_WAN_LINE_UP)) {
  1049. IPX_DEBUG (WAN, ("Line up, status buffer size wrong %d/%d\n", StatusBufferSize, sizeof(NDIS_WAN_LINE_UP)));
  1050. goto error_no_lock;
  1051. }
  1052. LineUp = (PNDIS_WAN_LINE_UP)StatusBuffer;
  1053. //
  1054. // We scan through the adapter's NIC ID range looking
  1055. // for an active binding with the same remote address.
  1056. //
  1057. UpdateLineUp = FALSE;
  1058. //
  1059. // See if this is a new lineup or not
  1060. //
  1061. *((ULONG UNALIGNED *)(&Binding)) =
  1062. *((ULONG UNALIGNED *)(&LineUp->LocalAddress[2]));
  1063. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1064. if (Binding != NULL) {
  1065. UpdateLineUp = TRUE;
  1066. }
  1067. if (LineUp->ProtocolType != Adapter->BindSap) {
  1068. IPX_DEBUG (WAN, ("Line up, wrong protocol type %lx\n", LineUp->ProtocolType));
  1069. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1070. goto error_no_lock;
  1071. }
  1072. Configuration = (PIPXCP_CONFIGURATION)LineUp->ProtocolBuffer;
  1073. //
  1074. // PNP_POWER - We hold the exclusive lock to the binding array (thru both the device and adapter)
  1075. // and the reference to the adapter at this point.
  1076. //
  1077. //
  1078. // If this line was previously down, create a new binding
  1079. // if needed.
  1080. //
  1081. if (!UpdateLineUp) {
  1082. //
  1083. // We look for a binding that is allocated but down, if
  1084. // we can't find that then we look for any empty spot in
  1085. // the adapter's NIC ID range and allocate a binding in it.
  1086. // Since we always allocate this way, the allocated
  1087. // bindings are all clumped at the beginning and once
  1088. // we find a NULL spot we know there are no more
  1089. // allocated ones.
  1090. //
  1091. // We keep track of the first binding on this adapter
  1092. // in TmpBinding in case we need config info from it.
  1093. //
  1094. TmpBinding = NULL;
  1095. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  1096. for (i = Adapter->FirstWanNicId;
  1097. i <= Adapter->LastWanNicId;
  1098. i++) {
  1099. Binding = NIC_ID_TO_BINDING(Device, i);
  1100. if (TmpBinding == NULL) {
  1101. TmpBinding = Binding;
  1102. }
  1103. if ((Binding == NULL) ||
  1104. (!Binding->LineUp)) {
  1105. break;
  1106. }
  1107. }
  1108. if (i > Adapter->LastWanNicId) {
  1109. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  1110. IPX_DEBUG (WAN, ("Line up, no WAN binding available\n"));
  1111. return;
  1112. }
  1113. if (Binding == NULL) {
  1114. //
  1115. // We need to allocate one.
  1116. //
  1117. CTEAssert (TmpBinding != NULL);
  1118. //
  1119. // CreateBinding does an InterLockedPop with the DeviceLock.
  1120. // So, release the lock here.
  1121. //
  1122. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  1123. Status = IpxCreateBinding(
  1124. Device,
  1125. NULL,
  1126. 0,
  1127. Adapter->AdapterName,
  1128. &Binding);
  1129. if (Status != STATUS_SUCCESS) {
  1130. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1131. IpxWriteGeneralErrorLog(
  1132. (PVOID)IpxDevice->DeviceObject,
  1133. EVENT_TRANSPORT_RESOURCE_POOL,
  1134. 816,
  1135. Status,
  1136. L"IpxStatus: failed to create wan binding",
  1137. 0,
  1138. NULL);
  1139. DbgPrint("IPX: IpxCreateBinding on wan binding failed with status %x\n.",Status);
  1140. IPX_DEBUG (WAN, ("Line up, could not create WAN binding\n"));
  1141. goto error_no_lock;
  1142. }
  1143. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  1144. //
  1145. // Binding->AllRouteXXX doesn't matter for WAN.
  1146. //
  1147. Binding->FrameType = ISN_FRAME_TYPE_ETHERNET_II;
  1148. Binding->SendFrameHandler = IpxSendFrameWanEthernetII;
  1149. ++Adapter->BindingCount;
  1150. Binding->Adapter = Adapter;
  1151. Binding->NicId = i;
  1152. /*
  1153. Abandoning this fix in favor of checking for null binding all over.
  1154. //
  1155. // Nt5.0 NDISWAN tells us that there are 1000 ports configured, we
  1156. // take it one line up at a time... [ShreeM]
  1157. //
  1158. Device->HighestExternalNicId += 1;
  1159. Device->ValidBindings += 1;
  1160. Device->BindingCount += 1;
  1161. Device->SapNicCount++;
  1162. */
  1163. INSERT_BINDING(Device, i, Binding);
  1164. //
  1165. // Other fields are filled in below.
  1166. //
  1167. }
  1168. //
  1169. // This is not an update, so note that the line is active.
  1170. //
  1171. // [FW] Binding->LineUp = TRUE;
  1172. Binding->LineUp = LINE_UP;
  1173. if (Configuration->ConnectionClient == 1) {
  1174. Binding->DialOutAsync = TRUE;
  1175. } else {
  1176. Binding->DialOutAsync = FALSE;
  1177. }
  1178. //
  1179. // Keep track of the highest NIC ID that we should
  1180. // send type 20s out on.
  1181. //
  1182. if (i > (UINT)MIN (Device->MaxBindings, Device->HighestType20NicId)) {
  1183. if ((Binding->DialOutAsync) ||
  1184. ((Device->DisableDialinNetbios & 0x01) == 0)) {
  1185. Device->HighestType20NicId = i;
  1186. }
  1187. }
  1188. //
  1189. // We could error out below, trying to insert this network number. In RipShortTimeout
  1190. // we dont check for LineUp when calculating the tick counts; set this before the insert
  1191. // attempt.
  1192. //
  1193. Binding->MediumSpeed = LineUp->LinkSpeed;
  1194. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  1195. //
  1196. // [FW] No need to update these if this flag is on since these values will be
  1197. // provided with IPX_WAN_CONFIG_DONE ioctl; instead we zero out the fields so that
  1198. // IPXWAN packets have proper source addresses.
  1199. //
  1200. if (Device->ForwarderBound &&
  1201. Configuration->IpxwanConfigRequired) {
  1202. Binding->LocalAddress.NetworkAddress = 0;
  1203. RtlZeroMemory (Binding->LocalAddress.NodeAddress, 6);
  1204. } else {
  1205. //
  1206. // Add a router entry for this net if there is no router.
  1207. // We want the number of ticks for a 576-byte frame,
  1208. // given the link speed in 100 bps units, so we calculate
  1209. // as:
  1210. //
  1211. // seconds 18.21 ticks 4608 bits
  1212. // --------------------- * ----------- * ---------
  1213. // link_speed * 100 bits second frame
  1214. //
  1215. // to get the formula
  1216. //
  1217. // ticks/frame = 839 / link_speed.
  1218. //
  1219. // We add link_speed to the numerator also to ensure
  1220. // that the value is at least 1.
  1221. //
  1222. if ((!Device->UpperDriverBound[IDENTIFIER_RIP]) &&
  1223. (*(UNALIGNED ULONG *)Configuration->Network != 0)) {
  1224. if (RipInsertLocalNetwork(
  1225. *(UNALIGNED ULONG *)Configuration->Network,
  1226. Binding->NicId,
  1227. Adapter->NdisBindingHandle,
  1228. (USHORT)((839 + LineUp->LinkSpeed) / LineUp->LinkSpeed)) != STATUS_SUCCESS) {
  1229. //
  1230. // This means we couldn't allocate memory, or
  1231. // the entry already existed. If it already
  1232. // exists we can ignore it for the moment.
  1233. //
  1234. // Now it will succeed if the network exists.
  1235. //
  1236. IPX_DEBUG (WAN, ("Line up, could not insert local network\n"));
  1237. // [FW] Binding->LineUp = FALSE;
  1238. Binding->LineUp = LINE_DOWN;
  1239. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1240. goto error_no_lock;
  1241. }
  1242. }
  1243. //
  1244. // Update our addresses.
  1245. //
  1246. Binding->LocalAddress.NetworkAddress = *(UNALIGNED ULONG *)Configuration->Network;
  1247. RtlCopyMemory (Binding->LocalAddress.NodeAddress, Configuration->LocalNode, 6);
  1248. RtlCopyMemory (Binding->WanRemoteNode, Configuration->RemoteNode, 6);
  1249. //
  1250. // Update the device node and all the address
  1251. // nodes if we have only one bound, or this is
  1252. // binding one.
  1253. //
  1254. if (!Device->VirtualNetwork) {
  1255. if ((!Device->MultiCardZeroVirtual) || (Binding->NicId == 1)) {
  1256. Device->SourceAddress.NetworkAddress = *(UNALIGNED ULONG *)(Configuration->Network);
  1257. RtlCopyMemory (Device->SourceAddress.NodeAddress, Configuration->LocalNode, 6);
  1258. }
  1259. //
  1260. // Scan through all the addresses that exist and modify
  1261. // their pre-constructed local IPX address to reflect
  1262. // the new local net and node.
  1263. //
  1264. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  1265. for (CurrentHash = 0; CurrentHash < IPX_ADDRESS_HASH_COUNT; CurrentHash++) {
  1266. for (p = Device->AddressDatabases[CurrentHash].Flink;
  1267. p != &Device->AddressDatabases[CurrentHash];
  1268. p = p->Flink) {
  1269. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  1270. Address->LocalAddress.NetworkAddress = *(UNALIGNED ULONG *)Configuration->Network;
  1271. RtlCopyMemory (Address->LocalAddress.NodeAddress, Configuration->LocalNode, 6);
  1272. }
  1273. }
  1274. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  1275. }
  1276. }
  1277. //
  1278. // Return the binding context for this puppy!
  1279. //
  1280. *((ULONG UNALIGNED *)(&LineUp->LocalAddress[2])) =
  1281. *((ULONG UNALIGNED *)(&Binding));
  1282. RtlCopyMemory (Binding->LocalMacAddress.Address, LineUp->LocalAddress, 6);
  1283. RtlCopyMemory (Binding->RemoteMacAddress.Address, LineUp->RemoteAddress, 6);
  1284. //
  1285. // Reset this since the line just came up.
  1286. //
  1287. Binding->WanInactivityCounter = 0;
  1288. //
  1289. // [FW] Update the InterfaceIndex and ConnectionId.
  1290. //
  1291. Binding->InterfaceIndex = Configuration->InterfaceIndex;
  1292. Binding->ConnectionId = Configuration->ConnectionId;
  1293. Binding->IpxwanConfigRequired = Configuration->IpxwanConfigRequired;
  1294. //
  1295. // [FW] We need to keep track of WAN inactivity counters ourselves.
  1296. // Every minute, the wan inactivity counters are incremented for all
  1297. // UP WAN lines.
  1298. //
  1299. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  1300. if (Device->UpWanLineCount == 0) {
  1301. }
  1302. Device->UpWanLineCount++;
  1303. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  1304. }
  1305. LinkSpeed = LineUp->LinkSpeed;
  1306. //
  1307. // Scan through bindings to update Device->LinkSpeed.
  1308. // If SingleNetworkActive is set, we only count WAN
  1309. // bindings when doing this (although it is unlikely
  1310. // a LAN binding would be the winner).
  1311. //
  1312. // Update other device information?
  1313. //
  1314. for (i = FIRST_REAL_BINDING; i <= Device->ValidBindings; i++) {
  1315. if (TmpBinding = NIC_ID_TO_BINDING(Device, i)) {
  1316. TmpAdapter = TmpBinding->Adapter;
  1317. if (TmpBinding->LineUp &&
  1318. (!Device->SingleNetworkActive || TmpAdapter->MacInfo.MediumAsync) &&
  1319. (TmpBinding->MediumSpeed < LinkSpeed)) {
  1320. LinkSpeed = TmpBinding->MediumSpeed;
  1321. }
  1322. }
  1323. }
  1324. //
  1325. // Release the lock after incrementing the reference count
  1326. //
  1327. IpxReferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1328. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1329. Device->LinkSpeed = LinkSpeed;
  1330. if ((Adapter->ConfigMaxPacketSize == 0) ||
  1331. (LineUp->MaximumTotalSize < Adapter->ConfigMaxPacketSize)) {
  1332. Binding->MaxSendPacketSize = LineUp->MaximumTotalSize;
  1333. } else {
  1334. Binding->MaxSendPacketSize = Adapter->ConfigMaxPacketSize;
  1335. }
  1336. MacInitializeBindingInfo (Binding, Adapter);
  1337. //
  1338. // [FW] If the IpxwanConfigRequired flag is true, we don't inform
  1339. // the upper layers until IPXWAN sends down the ioctl to do so.
  1340. //
  1341. // Inform IpxWan only if this is not an Update; it will be an update in
  1342. // the case of multilink. In fact, do not access the Configuration param in
  1343. // case UpdateLineUp is TRUE.
  1344. //
  1345. if (!UpdateLineUp &&
  1346. Configuration->IpxwanConfigRequired) {
  1347. IPX_DEBUG(WAN, ("IPXWAN configuration required on LineUp: %lx\n", LineUp));
  1348. CTEAssert(!UpdateLineUp);
  1349. Binding->LineUp = LINE_CONFIG;
  1350. goto InformIpxWan;
  1351. }
  1352. //
  1353. // Tell FWD if it wants to know [Shreem]
  1354. //
  1355. Binding->PastAutoDetection = TRUE;
  1356. //
  1357. // We dont give lineups; instead indicate only if the PnP reserved address
  1358. // changed to SPX. NB gets all PnP indications with the reserved address case
  1359. // marked out.
  1360. //
  1361. Event = CTEAllocMem( sizeof(CTEEvent) );
  1362. if ( Event ) {
  1363. CTEInitEvent(Event, LineUpOnWorkerThread);
  1364. CTEScheduleEvent(Event, Binding);
  1365. ntStatus = STATUS_PENDING;
  1366. } else {
  1367. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1368. }
  1369. /*
  1370. {
  1371. IPX_PNP_INFO NBPnPInfo;
  1372. if ((!Device->MultiCardZeroVirtual) || (Binding->NicId == FIRST_REAL_BINDING)) {
  1373. //
  1374. // NB's reserved address changed.
  1375. //
  1376. NBPnPInfo.NewReservedAddress = TRUE;
  1377. if (!Device->VirtualNetwork) {
  1378. //
  1379. // Let SPX know because it fills in its own headers.
  1380. //
  1381. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  1382. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1383. IPX_PNP_INFO IpxPnPInfo;
  1384. IpxPnPInfo.NewReservedAddress = TRUE;
  1385. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  1386. IpxPnPInfo.FirstORLastDevice = FALSE;
  1387. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1388. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  1389. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  1390. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1391. //
  1392. // give the PnP indication
  1393. //
  1394. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  1395. IPX_PNP_ADDRESS_CHANGE,
  1396. &IpxPnPInfo);
  1397. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_ADDRESS_CHANGED to SPX: net addr: %lx\n", Binding->LocalAddress.NetworkAddress));
  1398. }
  1399. }
  1400. } else {
  1401. NBPnPInfo.NewReservedAddress = FALSE;
  1402. }
  1403. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  1404. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1405. Binding->IsnInformed[IDENTIFIER_NB] = TRUE;
  1406. NBPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  1407. NBPnPInfo.LineInfo.MaximumPacketSize =
  1408. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  1409. NBPnPInfo.LineInfo.MaximumSendSize =
  1410. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  1411. NBPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  1412. NBPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  1413. NBPnPInfo.FirstORLastDevice = FALSE;
  1414. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1415. RtlCopyMemory(NBPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  1416. NIC_HANDLE_FROM_NIC(NBPnPInfo.NicHandle, Binding->NicId);
  1417. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1418. //
  1419. // give the PnP indication
  1420. //
  1421. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  1422. IPX_PNP_ADD_DEVICE,
  1423. &NBPnPInfo);
  1424. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_ADD_DEVICE (lineup) to NB: net addr: %lx\n", Binding->LocalAddress.NetworkAddress));
  1425. }
  1426. //
  1427. // Register this address with the TDI clients.
  1428. //
  1429. RtlCopyMemory (Device->TdiRegistrationAddress->Address, &Binding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
  1430. if ((ntStatus = TdiRegisterNetAddress(
  1431. Device->TdiRegistrationAddress,
  1432. #if defined(_PNP_POWER_)
  1433. NULL,
  1434. NULL,
  1435. #endif _PNP_POWER_
  1436. &Binding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  1437. IPX_DEBUG(PNP, ("TdiRegisterNetAddress failed: %lx", ntStatus));
  1438. }
  1439. }
  1440. */
  1441. //
  1442. // Indicate to the upper drivers.
  1443. //
  1444. LineInfo.LinkSpeed = LineUp->LinkSpeed;
  1445. LineInfo.MaximumPacketSize = LineUp->MaximumTotalSize - 14;
  1446. LineInfo.MaximumSendSize = LineUp->MaximumTotalSize - 14;
  1447. LineInfo.MacOptions = Adapter->MacInfo.MacOptions;
  1448. //
  1449. // Give line up to RIP as it is not PnP aware.
  1450. // Give lineup to FWD only if it opened this adapter first.
  1451. //
  1452. if (Device->UpperDriverBound[IDENTIFIER_RIP]) {
  1453. //
  1454. // Line status, after lineup.
  1455. //
  1456. if (UpdateLineUp) {
  1457. //
  1458. // was the lineup given earlier? if not, then dont send this up.
  1459. //
  1460. if (Binding->IsnInformed[IDENTIFIER_RIP]) {
  1461. CTEAssert(Binding->FwdAdapterContext);
  1462. (*Device->UpperDrivers[IDENTIFIER_RIP].LineUpHandler)(
  1463. Binding->NicId,
  1464. &LineInfo,
  1465. NdisMediumWan,
  1466. NULL);
  1467. }
  1468. } else {
  1469. Binding->IsnInformed[IDENTIFIER_RIP] = TRUE;
  1470. (*Device->UpperDrivers[IDENTIFIER_RIP].LineUpHandler)(
  1471. Binding->NicId,
  1472. &LineInfo,
  1473. NdisMediumWan,
  1474. Configuration);
  1475. }
  1476. }
  1477. if (!UpdateLineUp) {
  1478. if ((Device->SingleNetworkActive) &&
  1479. (Configuration->ConnectionClient == 1)) {
  1480. //
  1481. // Drop all entries in the database if rip is not bound.
  1482. //
  1483. if (!Device->UpperDriverBound[IDENTIFIER_RIP]) {
  1484. RipDropRemoteEntries();
  1485. }
  1486. Device->ActiveNetworkWan = TRUE;
  1487. //
  1488. // Find a queued line change and complete it.
  1489. //
  1490. if ((p = ExInterlockedRemoveHeadList(
  1491. &Device->LineChangeQueue,
  1492. &Device->Lock)) != NULL) {
  1493. Request = LIST_ENTRY_TO_REQUEST(p);
  1494. IoAcquireCancelSpinLock( &irql );
  1495. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1496. IoReleaseCancelSpinLock( irql );
  1497. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  1498. IpxCompleteRequest (Request);
  1499. IpxFreeRequest (Device, Request);
  1500. IpxDereferenceDevice (Device, DREF_LINE_CHANGE);
  1501. }
  1502. }
  1503. //
  1504. // If we have a virtual net, do a broadcast now so
  1505. // the router on the other end will know about us.
  1506. //
  1507. // Use RipSendResponse, and do it even
  1508. // if SingleNetworkActive is FALSE??
  1509. //
  1510. if (Device->RipResponder && (Configuration->ConnectionClient == 1)) {
  1511. DbgPrint("IPX:Sending RIP Response for Virtual Net %x\n",Device->VirtualNetworkNumber);
  1512. (VOID)RipQueueRequest (Device->VirtualNetworkNumber, RIP_RESPONSE);
  1513. }
  1514. //
  1515. // Find a queued address notify and complete it.
  1516. // If WanGlobalNetworkNumber is TRUE, we only do
  1517. // this when the first dialin line comes up.
  1518. //
  1519. if ((!Device->WanGlobalNetworkNumber ||
  1520. (!Device->GlobalNetworkIndicated && !Binding->DialOutAsync))
  1521. &&
  1522. ((p = ExInterlockedRemoveHeadList(
  1523. &Device->AddressNotifyQueue,
  1524. &Device->Lock)) != NULL)) {
  1525. if (Device->WanGlobalNetworkNumber) {
  1526. Device->GlobalWanNetwork = Binding->LocalAddress.NetworkAddress;
  1527. Device->GlobalNetworkIndicated = TRUE;
  1528. }
  1529. Request = LIST_ENTRY_TO_REQUEST(p);
  1530. NdisBuffer = REQUEST_NDIS_BUFFER(Request);
  1531. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&NwlinkAction, &BufferLength, HighPagePriority);
  1532. if (NwlinkAction != NULL) {
  1533. IpxAddressData = (PIPX_ADDRESS_DATA)(NwlinkAction->Data);
  1534. if (Device->WanGlobalNetworkNumber) {
  1535. IpxAddressData->adapternum = Device->SapNicCount - 1;
  1536. } else {
  1537. IpxAddressData->adapternum = Binding->NicId - 1;
  1538. }
  1539. *(UNALIGNED ULONG *)IpxAddressData->netnum = Binding->LocalAddress.NetworkAddress;
  1540. RtlCopyMemory(IpxAddressData->nodenum, Binding->LocalAddress.NodeAddress, 6);
  1541. IpxAddressData->wan = TRUE;
  1542. IpxAddressData->status = TRUE;
  1543. IpxAddressData->maxpkt = Binding->AnnouncedMaxDatagramSize;
  1544. IpxAddressData->linkspeed = Binding->MediumSpeed;
  1545. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  1546. } else {
  1547. REQUEST_STATUS(Request) = STATUS_INSUFFICIENT_RESOURCES;
  1548. }
  1549. IoAcquireCancelSpinLock( &irql );
  1550. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1551. IoReleaseCancelSpinLock( irql );
  1552. IpxCompleteRequest (Request);
  1553. IpxFreeRequest (Device, Request);
  1554. IpxDereferenceDevice (Device, DREF_ADDRESS_NOTIFY);
  1555. }
  1556. InformIpxWan:
  1557. Binding->fInfoIndicated = FALSE;
  1558. //
  1559. // Tell FWD if it wants to know [Shreem]
  1560. //
  1561. Binding->PastAutoDetection = TRUE;
  1562. if ((p = ExInterlockedRemoveHeadList(
  1563. &Device->NicNtfQueue,
  1564. &Device->Lock)) != NULL)
  1565. {
  1566. Request = LIST_ENTRY_TO_REQUEST(p);
  1567. IPX_DEBUG(WAN, ("IpxStatus: WAN LINE UP\n"));
  1568. Status = GetNewNics(Device, Request, FALSE, NULL, 0, TRUE);
  1569. if (Status == STATUS_PENDING)
  1570. {
  1571. IPX_DEBUG(WAN, ("WANLineUp may not be responding properly\n"));
  1572. }
  1573. else
  1574. {
  1575. IoAcquireCancelSpinLock(&OldIrq);
  1576. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1577. IoReleaseCancelSpinLock(OldIrq);
  1578. REQUEST_STATUS(Request) = Status;
  1579. IpxCompleteRequest (Request);
  1580. IpxFreeRequest (Device, Request);
  1581. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  1582. }
  1583. }
  1584. }
  1585. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1586. {
  1587. int kk;
  1588. PBINDING pb = NULL;
  1589. for (kk= LOOPBACK_NIC_ID; kk < Device->ValidBindings; kk++) {
  1590. pb = NIC_ID_TO_BINDING(Device, kk);
  1591. if (pb) {
  1592. if (pb->NicId != kk) {
  1593. DbgBreakPoint();
  1594. }
  1595. }
  1596. }
  1597. }
  1598. break;
  1599. case NDIS_STATUS_WAN_LINE_DOWN:
  1600. if (StatusBufferSize < sizeof(NDIS_WAN_LINE_DOWN)) {
  1601. IPX_DEBUG (WAN, ("Line down, status buffer size wrong %d/%d\n", StatusBufferSize, sizeof(NDIS_WAN_LINE_DOWN)));
  1602. return;
  1603. }
  1604. LineDown = (PNDIS_WAN_LINE_DOWN)StatusBuffer;
  1605. *((ULONG UNALIGNED*)(&Binding)) = *((ULONG UNALIGNED*)(&LineDown->LocalAddress[2]));
  1606. CTEAssert(Binding != NULL);
  1607. //
  1608. // Note that the WAN line is down.
  1609. //
  1610. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1611. // [FW] Binding->LineUp = FALSE;
  1612. Binding->LineUp = LINE_DOWN;
  1613. //
  1614. // PNP_POWER - we hold the exclusive lock to the binding
  1615. // and reference to the adapter at this point.
  1616. //
  1617. //
  1618. // Keep track of the highest NIC ID that we should
  1619. // send type 20s out on.
  1620. //
  1621. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  1622. if (Binding->NicId == MIN (Device->MaxBindings, Device->HighestType20NicId)) {
  1623. //
  1624. // This was the old limit, so we have to scan
  1625. // backwards to update it -- we stop when we hit
  1626. // a non-WAN binding, or a wan binding that is up and
  1627. // dialout, or any wan binding if bit 1 in
  1628. // DisableDialinNetbios is off.
  1629. //
  1630. for (i = Binding->NicId-1; i >= FIRST_REAL_BINDING; i--) {
  1631. TmpBinding = NIC_ID_TO_BINDING(Device, i);
  1632. if ((TmpBinding != NULL) &&
  1633. ((!TmpBinding->Adapter->MacInfo.MediumAsync) ||
  1634. (TmpBinding->LineUp &&
  1635. ((Binding->DialOutAsync) ||
  1636. ((Device->DisableDialinNetbios & 0x01) == 0))))) {
  1637. break;
  1638. }
  1639. }
  1640. Device->HighestType20NicId = i;
  1641. }
  1642. //
  1643. // Scan through bindings to update Device->LinkSpeed.
  1644. // If SingleNetworkActive is set, we only count LAN
  1645. // bindings when doing this.
  1646. //
  1647. // Update other device information?
  1648. //
  1649. LinkSpeed = 0xffffffff;
  1650. for (i = FIRST_REAL_BINDING; i <= Device->ValidBindings; i++) {
  1651. if (TmpBinding = NIC_ID_TO_BINDING(Device, i)) {
  1652. TmpAdapter = TmpBinding->Adapter;
  1653. if (TmpBinding->LineUp &&
  1654. (!Device->SingleNetworkActive || !TmpAdapter->MacInfo.MediumAsync) &&
  1655. (TmpBinding->MediumSpeed < LinkSpeed)) {
  1656. LinkSpeed = TmpBinding->MediumSpeed;
  1657. }
  1658. }
  1659. }
  1660. if (LinkSpeed != 0xffffffff) {
  1661. Device->LinkSpeed = LinkSpeed;
  1662. }
  1663. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  1664. IpxReferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1665. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1666. //
  1667. // Remove our router entry for this net.
  1668. //
  1669. //
  1670. // [FW] if this was a line on which IPXWAN config was happening, then we dont do this.
  1671. //
  1672. if (!Binding->IpxwanConfigRequired &&
  1673. !Device->UpperDriverBound[IDENTIFIER_RIP]) {
  1674. Segment = RipGetSegment ((PUCHAR)&Binding->LocalAddress.NetworkAddress);
  1675. IPX_GET_LOCK (&Device->SegmentLocks[Segment], &LockHandle);
  1676. RouteEntry = RipGetRoute (Segment, (PUCHAR)&Binding->LocalAddress.NetworkAddress);
  1677. if (RouteEntry != (PIPX_ROUTE_ENTRY)NULL) {
  1678. RipDeleteRoute (Segment, RouteEntry);
  1679. IPX_FREE_LOCK (&Device->SegmentLocks[Segment], LockHandle);
  1680. IpxFreeMemory (RouteEntry, sizeof(IPX_ROUTE_ENTRY), MEMORY_RIP, "RouteEntry");
  1681. } else {
  1682. IPX_FREE_LOCK (&Device->SegmentLocks[Segment], LockHandle);
  1683. }
  1684. RipAdjustForBindingChange (Binding->NicId, 0, IpxBindingDown);
  1685. }
  1686. //
  1687. // [FW] If this was the last UpWanLine, cancel the inactivity timer.
  1688. //
  1689. /*
  1690. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  1691. if (--Device->UpWanLineCount == 0) {
  1692. if (!CTEStopTimer (&IpxDevice->WanInactivityTimer)) {
  1693. DbgPrint("Could not stop the WanInactivityTimer\n");
  1694. DbgBreakPoint();
  1695. }
  1696. }
  1697. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  1698. */
  1699. //
  1700. // If this was a line on which IPXWAN config was going on, then we need to tell only the
  1701. // IPXWAN layer that the line went down since none of the other clients were informed of
  1702. // the line up in the first place.
  1703. //
  1704. if (Binding->IpxwanConfigRequired) {
  1705. goto InformIpxWan1;
  1706. }
  1707. //
  1708. // Indicate to the upper drivers.
  1709. //
  1710. //
  1711. // DeRegister this address with the TDI clients.
  1712. //
  1713. //
  1714. // Since the IRQL is too high, we will do this now on a worker thread. [Shreem]
  1715. //
  1716. Event = CTEAllocMem( sizeof(CTEEvent) );
  1717. if ( Event ) {
  1718. CTEInitEvent(Event, LineDownOnWorkerThread);
  1719. CTEScheduleEvent(Event, Binding);
  1720. ntStatus = STATUS_PENDING;
  1721. } else {
  1722. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1723. }
  1724. //
  1725. // Tell FWD if it wants to know [Shreem]
  1726. //
  1727. Binding->PastAutoDetection = FALSE;
  1728. //
  1729. // Indicate to the Fwd only if it opened this adapter first.
  1730. //
  1731. if (Device->UpperDriverBound[IDENTIFIER_RIP] &&
  1732. (!Device->ForwarderBound || Binding->FwdAdapterContext)) {
  1733. (*Device->UpperDrivers[IDENTIFIER_RIP].LineDownHandler)(
  1734. Binding->NicId,
  1735. Binding->FwdAdapterContext);
  1736. CTEAssert(Binding->IsnInformed[IDENTIFIER_RIP]);
  1737. Binding->IsnInformed[IDENTIFIER_RIP] = FALSE;
  1738. }
  1739. if ((Device->SingleNetworkActive) &&
  1740. (Binding->DialOutAsync)) {
  1741. //
  1742. // Drop all entries in the database if rip is not bound.
  1743. //
  1744. if (!Device->UpperDriverBound[IDENTIFIER_RIP]) {
  1745. RipDropRemoteEntries();
  1746. }
  1747. Device->ActiveNetworkWan = FALSE;
  1748. //
  1749. // Find a queued line change and complete it.
  1750. //
  1751. if ((p = ExInterlockedRemoveHeadList(
  1752. &Device->LineChangeQueue,
  1753. &Device->Lock)) != NULL) {
  1754. Request = LIST_ENTRY_TO_REQUEST(p);
  1755. IoAcquireCancelSpinLock( &irql );
  1756. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1757. IoReleaseCancelSpinLock( irql );
  1758. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  1759. IpxCompleteRequest (Request);
  1760. IpxFreeRequest (Device, Request);
  1761. IpxDereferenceDevice (Device, DREF_LINE_CHANGE);
  1762. }
  1763. }
  1764. //
  1765. // Find a queued address notify and complete it.
  1766. //
  1767. if ((!Device->WanGlobalNetworkNumber) &&
  1768. ((p = ExInterlockedRemoveHeadList(
  1769. &Device->AddressNotifyQueue,
  1770. &Device->Lock)) != NULL)) {
  1771. Request = LIST_ENTRY_TO_REQUEST(p);
  1772. NdisBuffer = REQUEST_NDIS_BUFFER(Request);
  1773. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&NwlinkAction, &BufferLength, HighPagePriority);
  1774. if (NwlinkAction != NULL) {
  1775. IpxAddressData = (PIPX_ADDRESS_DATA)(NwlinkAction->Data);
  1776. IpxAddressData->adapternum = Binding->NicId - 1;
  1777. *(UNALIGNED ULONG *)IpxAddressData->netnum = Binding->LocalAddress.NetworkAddress;
  1778. RtlCopyMemory(IpxAddressData->nodenum, Binding->LocalAddress.NodeAddress, 6);
  1779. IpxAddressData->wan = TRUE;
  1780. IpxAddressData->status = FALSE;
  1781. IpxAddressData->maxpkt = Binding->AnnouncedMaxDatagramSize; // Use real?
  1782. IpxAddressData->linkspeed = Binding->MediumSpeed;
  1783. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  1784. } else {
  1785. REQUEST_STATUS(Request) = STATUS_INSUFFICIENT_RESOURCES;
  1786. }
  1787. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1788. IoAcquireCancelSpinLock( &irql );
  1789. IpxCompleteRequest (Request);
  1790. IoReleaseCancelSpinLock( irql );
  1791. IpxFreeRequest (Device, Request);
  1792. IpxDereferenceDevice (Device, DREF_ADDRESS_NOTIFY);
  1793. }
  1794. InformIpxWan1:
  1795. Binding->fInfoIndicated = FALSE;
  1796. if ((p = ExInterlockedRemoveHeadList(
  1797. &Device->NicNtfQueue,
  1798. &Device->Lock)) != NULL)
  1799. {
  1800. Request = LIST_ENTRY_TO_REQUEST(p);
  1801. IPX_DEBUG(WAN, ("IpxStatus: WAN LINE DOWN\n"));
  1802. Status = GetNewNics(Device, Request, FALSE, NULL, 0, TRUE);
  1803. if (Status == STATUS_PENDING)
  1804. {
  1805. IPX_DEBUG(WAN, ("WANLineDown may not be responding properly\n"));
  1806. }
  1807. else
  1808. {
  1809. IoAcquireCancelSpinLock(&OldIrq);
  1810. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1811. IoReleaseCancelSpinLock(OldIrq);
  1812. REQUEST_STATUS(Request) = Status;
  1813. IpxCompleteRequest (Request);
  1814. IpxFreeRequest (Device, Request); //noop
  1815. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  1816. }
  1817. }
  1818. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1819. {
  1820. int kk;
  1821. PBINDING pb = NULL;
  1822. for (kk = LOOPBACK_NIC_ID; kk < Device->ValidBindings; kk++) {
  1823. pb = NIC_ID_TO_BINDING(Device, kk);
  1824. if (pb) {
  1825. if (pb->NicId != kk) {
  1826. DbgBreakPoint();
  1827. }
  1828. }
  1829. }
  1830. }
  1831. break;
  1832. case NDIS_STATUS_WAN_FRAGMENT:
  1833. //
  1834. // No response needed, IPX is a datagram service.
  1835. //
  1836. // What about telling Netbios/SPX?
  1837. //
  1838. break;
  1839. case NDIS_STATUS_MEDIA_CONNECT:
  1840. //
  1841. // We bind to the new adapter and compare if the characteristics of any of
  1842. // the previously disabled adapters matches with the characteristics of this new one.
  1843. //
  1844. // if we find a match then we must be on the same LAN/WAN as the disabled adapter.
  1845. // We just enable this adapter and Unbind the new one. If we cant find a match, we
  1846. // unbind/free one of these disbled adapters.
  1847. //
  1848. // IpxUnbindAdapter() sends the upper drivers a IPX_PNP_DELETE messages
  1849. // and they purge their addresses, caches etc.
  1850. {
  1851. #ifdef _NDIS_MEDIA_SENSE_
  1852. CTEEvent *Event;
  1853. // IPX_DEBUG(PNP, ("Ndis_Media_Sense: CONNECT for %ws. Queueing WorkerThread\n", Adapter->AdapterName));
  1854. Event = CTEAllocMem( sizeof(CTEEvent) );
  1855. if ( Event ) {
  1856. CTEInitEvent(Event, IpxMediaSenseHandler);
  1857. CTEScheduleEvent(Event, Adapter);
  1858. ntStatus = STATUS_PENDING;
  1859. } else {
  1860. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1861. }
  1862. #endif // _NDIS_MEDIA_SENSE_
  1863. break;
  1864. }
  1865. case NDIS_STATUS_MEDIA_DISCONNECT:
  1866. //
  1867. // It must fail all datagram sends. It must fail all
  1868. // connects right away but not disconnect sessions in progress.
  1869. // These must timeout the way they do today. The router
  1870. // must age out routes on this interface and not propagate them.
  1871. //
  1872. // All of the above can be achieved by setting Bindings->Lineup = DOWN;
  1873. //
  1874. #ifdef _NDIS_MEDIA_SENSE_
  1875. {
  1876. int j;
  1877. //IPX_DEBUG(PNP, ("Ndis_Status_Media_Sense: DISCONNECT for %ws\n", Adapter->AdapterName));
  1878. for ( j = 0; j< ISN_FRAME_TYPE_MAX; j++ ) {
  1879. if (Adapter->Bindings[j]) {
  1880. Adapter->Bindings[j]->Disabled = DISABLED;
  1881. }
  1882. Adapter->Disabled = DISABLED;
  1883. }
  1884. }
  1885. #endif // _NDIS_MEDIA_SENSE_
  1886. break;
  1887. default:
  1888. break;
  1889. }
  1890. error_no_lock:
  1891. IpxDereferenceAdapter(Adapter);
  1892. } /* IpxStatus */
  1893. //
  1894. // Since IPXStatus is called by NDIS at DISPATCH_LEVEL irql and TDIRegisterNetAddress
  1895. // needs to be called at PASSIVE_LEVEL, We now do this TDI and PnpNotifications on a
  1896. // worker thread launched from IpxStatus. Hopefully there arent any repercussions of this.
  1897. // [ShreeM]
  1898. void
  1899. LineUpOnWorkerThread(
  1900. IN CTEEvent *WorkerThreadEvent,
  1901. IN PVOID Context)
  1902. {
  1903. PBINDING Binding = (PBINDING) Context;
  1904. NTSTATUS ntStatus;
  1905. IPX_PNP_INFO NBPnPInfo;
  1906. PDEVICE Device = IpxDevice;
  1907. //
  1908. // Qos changes
  1909. //
  1910. int count, i;
  1911. int size;
  1912. NTSTATUS NdisStatus = STATUS_SUCCESS;
  1913. UNICODE_STRING AdapterName;
  1914. NDIS_REQUEST IpxRequest;
  1915. PNETWORK_ADDRESS_LIST AddrList;
  1916. PNETWORK_ADDRESS Address;
  1917. NETWORK_ADDRESS_IPX *TdiAddress;
  1918. PBINDING TempBinding;
  1919. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  1920. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1921. ASSERT(Context != NULL);
  1922. CTEFreeMem(WorkerThreadEvent);
  1923. IPX_DEBUG(WAN, ("TDIRegisterNetAddress etc. on worker thread.\n"));
  1924. if ((!Device->MultiCardZeroVirtual) || (Binding->NicId == FIRST_REAL_BINDING)) {
  1925. //
  1926. // NB's reserved address changed.
  1927. //
  1928. NBPnPInfo.NewReservedAddress = TRUE;
  1929. if (!Device->VirtualNetwork) {
  1930. //
  1931. // Let SPX know because it fills in its own headers.
  1932. //
  1933. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  1934. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1935. IPX_PNP_INFO IpxPnPInfo;
  1936. IpxPnPInfo.NewReservedAddress = TRUE;
  1937. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  1938. IpxPnPInfo.FirstORLastDevice = FALSE;
  1939. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1940. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  1941. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  1942. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1943. //
  1944. // give the PnP indication
  1945. //
  1946. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  1947. IPX_PNP_ADDRESS_CHANGE,
  1948. &IpxPnPInfo);
  1949. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_ADDRESS_CHANGED to SPX: net addr: %lx\n", Binding->LocalAddress.NetworkAddress));
  1950. }
  1951. }
  1952. } else {
  1953. NBPnPInfo.NewReservedAddress = FALSE;
  1954. }
  1955. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  1956. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  1957. Binding->IsnInformed[IDENTIFIER_NB] = TRUE;
  1958. NBPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  1959. NBPnPInfo.LineInfo.MaximumPacketSize =
  1960. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  1961. NBPnPInfo.LineInfo.MaximumSendSize =
  1962. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  1963. NBPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  1964. NBPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  1965. NBPnPInfo.FirstORLastDevice = FALSE;
  1966. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1967. RtlCopyMemory(NBPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  1968. NIC_HANDLE_FROM_NIC(NBPnPInfo.NicHandle, Binding->NicId);
  1969. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1970. //
  1971. // give the PnP indication
  1972. //
  1973. ASSERT(Binding->NicId != LOOPBACK_NIC_ID);
  1974. ASSERT(IpxHasInformedNbLoopback());
  1975. ASSERT(NBPnPInfo.FirstORLastDevice == FALSE);
  1976. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  1977. IPX_PNP_ADD_DEVICE,
  1978. &NBPnPInfo);
  1979. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_ADD_DEVICE (lineup) to NB: net addr: %lx\n", Binding->LocalAddress.NetworkAddress));
  1980. }
  1981. //
  1982. // Register this address with the TDI clients.
  1983. //
  1984. RtlCopyMemory (Device->TdiRegistrationAddress->Address, &Binding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
  1985. if ((ntStatus = TdiRegisterNetAddress(
  1986. Device->TdiRegistrationAddress,
  1987. #if defined(_PNP_POWER_)
  1988. &IpxDeviceName,
  1989. NULL,
  1990. #endif _PNP_POWER_
  1991. &Binding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  1992. DbgPrint("TdiRegisterNetAddress failed with %lx. (0xC000009A is STATUS_INSUFFICIENT_RESOURCES)", ntStatus);
  1993. }
  1994. #if 0
  1995. //
  1996. // Register with QoS
  1997. //
  1998. IPX_DEBUG(PNP, ("Register a new address with QoS over here\n"));
  1999. for (count=0, i=IpxDevice->HighestLanNicId+1; i < IpxDevice->ValidBindings; i++) {
  2000. if (NIC_ID_TO_BINDING(IpxDevice, i)) {
  2001. count++;
  2002. }
  2003. }
  2004. IPX_DEBUG(PNP, ("This adapter has %d valid WAN bindings\n", count));
  2005. size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) + count * (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IPX));
  2006. AddrList = IpxAllocateMemory(
  2007. size,
  2008. MEMORY_ADAPTER,
  2009. "QoS specific stuff");
  2010. // 270344
  2011. if (AddrList == NULL) {
  2012. DbgPrint("IpxAllocateMemory returned NULL. Skip QoS registration.\n");
  2013. return;
  2014. }
  2015. RtlZeroMemory(AddrList, size);
  2016. AddrList->AddressCount = count;
  2017. AddrList->AddressType = NDIS_PROTOCOL_ID_IPX;
  2018. count = 0;
  2019. Address = &AddrList->Address[0];
  2020. for (i=IpxDevice->HighestLanNicId+1; i < IpxDevice->ValidBindings; i++) {
  2021. if (TempBinding = NIC_ID_TO_BINDING(IpxDevice, i)) {
  2022. Address->AddressLength = sizeof(NETWORK_ADDRESS_IPX);
  2023. Address->AddressType = NDIS_PROTOCOL_ID_IPX;
  2024. TdiAddress = (NETWORK_ADDRESS_IPX *) &Address->Address[0];
  2025. TdiAddress->NetworkAddress = TempBinding->LocalAddress.NetworkAddress;
  2026. RtlCopyMemory (TdiAddress->NodeAddress, TempBinding->LocalAddress.NodeAddress, 6);
  2027. TdiAddress->Socket = 0;
  2028. IPX_DEBUG(PNP, ("Node is %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x, ",
  2029. TdiAddress->NodeAddress[0], TdiAddress->NodeAddress[1],
  2030. TdiAddress->NodeAddress[2], TdiAddress->NodeAddress[3],
  2031. TdiAddress->NodeAddress[4], TdiAddress->NodeAddress[5]));
  2032. IPX_DEBUG(PNP, ("Network is %lx\n", REORDER_ULONG (TdiAddress->NetworkAddress)));
  2033. count++;
  2034. Address = (PNETWORK_ADDRESS) (((PUCHAR)(&AddrList->Address[0])) + count * (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IPX)));
  2035. }
  2036. }
  2037. IpxRequest.RequestType = NdisRequestSetInformation;
  2038. IpxRequest.DATA.SET_INFORMATION.Oid = OID_GEN_NETWORK_LAYER_ADDRESSES;
  2039. IpxRequest.DATA.SET_INFORMATION.InformationBuffer = AddrList;
  2040. IpxRequest.DATA.SET_INFORMATION.InformationBufferLength = size;
  2041. TempBinding = NIC_ID_TO_BINDING(IpxDevice, IpxDevice->HighestLanNicId+1);
  2042. if (TempBinding) {
  2043. RtlInitUnicodeString(&AdapterName, TempBinding->Adapter->AdapterName);
  2044. NdisStatus = IpxSubmitNdisRequest (TempBinding->Adapter, &IpxRequest, &AdapterName);
  2045. IPX_DEBUG(PNP, ("Returned from NDISRequest :%lx\n", NdisStatus));
  2046. } else {
  2047. DbgPrint("IpxDevice->Binding[highestlannicid+1] is NULL!!\n");
  2048. CTEAssert(TempBinding != NULL);
  2049. }
  2050. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  2051. IPX_DEBUG(PNP, ("Setting the QoS OID failed - Error %lx\n", NdisStatus));
  2052. } else {
  2053. IPX_DEBUG(PNP, ("Setting the QoS OID was successful\n"));
  2054. }
  2055. IpxFreeMemory(AddrList,
  2056. size,
  2057. MEMORY_ADAPTER,
  2058. "QoS specific stuff");
  2059. #endif
  2060. } /* LineUpOnWorkerThread */
  2061. //
  2062. // Since IPXStatus is called by NDIS at DISPATCH_LEVEL irql and TDIDeregisterNetAddress
  2063. // needs to be called at PASSIVE_LEVEL, We now do this TDI and PnpNotifications on a
  2064. // worker thread launched from IpxStatus. Hopefully there arent any repercussions of this.
  2065. // [ShreeM]
  2066. void
  2067. LineDownOnWorkerThread(
  2068. IN CTEEvent *WorkerThreadEvent,
  2069. IN PVOID Context)
  2070. {
  2071. PBINDING Binding = (PBINDING) Context;
  2072. NTSTATUS ntStatus;
  2073. IPX_PNP_INFO NBPnPInfo;
  2074. PDEVICE Device = IpxDevice;
  2075. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2076. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  2077. ASSERT(Context != NULL);
  2078. CTEFreeMem(WorkerThreadEvent);
  2079. IPX_DEBUG(WAN, ("TDIDeregister etc. on worker thread.\n"));
  2080. //
  2081. // DeRegister this address with the TDI clients.
  2082. //
  2083. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  2084. // CTEAssert(Binding->TdiRegistrationHandle);
  2085. // TdiRegisterNetAddress could fail due to insufficient resources. In which case,
  2086. // TdiRegistrationHandle could be null. Removed assertion failure, added check. [TC]
  2087. if (Binding->TdiRegistrationHandle != NULL) {
  2088. if ((ntStatus = TdiDeregisterNetAddress(Binding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  2089. DbgPrint("TdiDeRegisterNetAddress failed: %lx", ntStatus);
  2090. } else {
  2091. //
  2092. // 118187: Dont deregister twice! [ShreeM]
  2093. //
  2094. Binding->TdiRegistrationHandle = NULL;
  2095. }
  2096. }
  2097. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  2098. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  2099. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  2100. // CTEAssert(Binding->IsnInformed[IDENTIFIER_NB]);
  2101. if (Binding->IsnInformed[IDENTIFIER_NB]) {
  2102. NBPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  2103. NBPnPInfo.LineInfo.MaximumPacketSize =
  2104. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  2105. NBPnPInfo.LineInfo.MaximumSendSize =
  2106. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  2107. NBPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  2108. NBPnPInfo.NewReservedAddress = FALSE;
  2109. NBPnPInfo.FirstORLastDevice = FALSE;
  2110. NBPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  2111. RtlCopyMemory(NBPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  2112. NIC_HANDLE_FROM_NIC(NBPnPInfo.NicHandle, Binding->NicId);
  2113. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  2114. //
  2115. // give the PnP indication
  2116. //
  2117. CTEAssert(Binding->NicId != LOOPBACK_NIC_ID);
  2118. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  2119. IPX_PNP_DELETE_DEVICE,
  2120. &NBPnPInfo);
  2121. Binding->IsnInformed[IDENTIFIER_NB] = FALSE;
  2122. IPX_DEBUG(PNP,("Indicate to NB IPX_PNP_DELETE_DEVICE with FirstORLastDevice = (%d)",NBPnPInfo.FirstORLastDevice));
  2123. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_DELETE_DEVICE (linedown) to NB: addr: %lx\n", Binding->LocalAddress.NetworkAddress));
  2124. } else {
  2125. DbgPrint("LineDownOnWorkerThread: Binding (%p) ->IsnInformed[IDENTIFIER_NB] is FALSE",Binding);
  2126. }
  2127. } else {
  2128. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  2129. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  2130. }
  2131. } /* LineDownOnWorkerThread */
  2132. VOID
  2133. IpxStatusComplete(
  2134. IN NDIS_HANDLE NdisBindingContext
  2135. )
  2136. {
  2137. UNREFERENCED_PARAMETER (NdisBindingContext);
  2138. } /* IpxStatusComplete */
  2139. #ifdef _NDIS_MEDIA_SENSE_
  2140. //
  2141. // CompareBindingCharacteristics
  2142. //
  2143. // Inputs: Binding1, Binding2
  2144. //
  2145. // Output:
  2146. // COMPLETE_MATCH : They match completely
  2147. // PARTIAL_MATCH : They match partially
  2148. // zero otherwise
  2149. //
  2150. UINT
  2151. CompareBindingCharacteristics(
  2152. PBINDING Binding1,
  2153. PBINDING Binding2
  2154. )
  2155. {
  2156. UINT Match = 0; // we return this if nothing matches.
  2157. //
  2158. // if the mac address happens to be the same, it must be
  2159. // the same card on a different net.
  2160. //
  2161. if (IPX_NODE_EQUAL(Binding1->LocalMacAddress.Address, Binding2->LocalMacAddress.Address)) {
  2162. Match = PARTIAL_MATCH;
  2163. }
  2164. if ((Binding1->FrameType == Binding2->FrameType) &&
  2165. (Binding1->LocalAddress.NetworkAddress == Binding2->LocalAddress.NetworkAddress) &&
  2166. (IPX_NODE_EQUAL(Binding1->LocalAddress.NodeAddress, Binding2->LocalAddress.NodeAddress))) {
  2167. /*if ((LINE_UP == Binding1->LineUp) && (LINE_UP == Binding2->LineUp) &&
  2168. (Binding1->MaxSendPacketSize == Binding2->MaxSendPacketSize) &&
  2169. (Binding1->MediumSpeed == Binding2->MediumSpeed) &&
  2170. (IPX_NODE_EQUAL(Binding1->RemoteMacAddress, Binding2->RemoteMacAddress))) {
  2171. */
  2172. return COMPLETE_MATCH;
  2173. // }
  2174. }
  2175. return Match;
  2176. }
  2177. //** IpxMediaSenseWorker - Handles Media Sense work on a CTE worker
  2178. // because NdisProtocolStatus runs at DPC.
  2179. //
  2180. // Called from the worker thread event scheduled by IPXStatus.
  2181. //
  2182. // Entry:
  2183. // NdisProtocolBindingContext == AdapterName
  2184. //
  2185. // Exit:
  2186. // None.
  2187. //
  2188. void
  2189. IpxMediaSenseHandler(
  2190. IN CTEEvent *WorkerThreadEvent,
  2191. IN PVOID Context)
  2192. {
  2193. PADAPTER Adapter = (PADAPTER) Context;
  2194. UNICODE_STRING DeviceName;
  2195. BOOLEAN MatchFound[ISN_FRAME_TYPE_MAX], AdapterMatched;
  2196. PADAPTER DisabledAdapter = NULL;
  2197. int j, MatchLevel;
  2198. ULONG Index, i;
  2199. NDIS_STRING AdapterName;
  2200. NTSTATUS Status;
  2201. PDEVICE Device = IpxDevice;
  2202. PBINDING Binding;
  2203. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2204. ASSERT(Context != NULL);
  2205. IpxReferenceAdapter(Adapter);
  2206. CTEFreeMem(WorkerThreadEvent);
  2207. IPX_DEBUG(PNP, ("Ndis_Status_Media_Sense: CONNECT for %ws\n", Adapter->AdapterName));
  2208. RtlInitUnicodeString(&AdapterName, Adapter->AdapterName);
  2209. for (j = 0; j < ISN_FRAME_TYPE_MAX; j++) {
  2210. MatchFound[j] = FALSE;
  2211. }
  2212. AdapterMatched = FALSE;
  2213. IpxBindAdapter(
  2214. &Status,
  2215. NULL, //Adapter,
  2216. &AdapterName, // \\Device\IEEPRO1
  2217. NULL,
  2218. NULL
  2219. );
  2220. if (STATUS_SUCCESS != Status) {
  2221. IPX_DEBUG(PNP, ("IpxBindAdapter returned : %x\n", Status));
  2222. }
  2223. // new Adapter's characteristics with in the list of previously disabled adapters.
  2224. Index = MIN (Device->MaxBindings, Device->HighestExternalNicId);
  2225. IPX_GET_LOCK1(&Device->BindAccessLock, LockHandle);
  2226. for (i = FIRST_REAL_BINDING; i <= Index; i++) {
  2227. Binding = NIC_ID_TO_BINDING(Device, i);
  2228. if (!Binding) {
  2229. continue;
  2230. }
  2231. if (Binding->Disabled == DISABLED) {
  2232. for (j = 0; j < ISN_FRAME_TYPE_MAX; j++) {
  2233. if (!Adapter->Bindings[j]) {
  2234. continue; // NULL Binding
  2235. }
  2236. if (!MatchFound[j]) {
  2237. MatchLevel = CompareBindingCharacteristics(Binding, Adapter->Bindings[j]);
  2238. if (COMPLETE_MATCH == MatchLevel) {
  2239. MatchFound[j] = TRUE;
  2240. DisabledAdapter = Binding->Adapter;
  2241. } else if (PARTIAL_MATCH == MatchLevel) {
  2242. // if we had more than one disabled adapters, this is
  2243. // most probably the one which is changed
  2244. DisabledAdapter = Binding->Adapter; // Free this puppy later
  2245. }
  2246. }
  2247. // Try another
  2248. }
  2249. }
  2250. }
  2251. for (j = 0; j < ISN_FRAME_TYPE_MAX; j++) {
  2252. if (MatchFound[j]) {
  2253. AdapterMatched = TRUE;
  2254. IPX_DEBUG(PNP, ("Found a matching adapter !\n"));
  2255. break;
  2256. }
  2257. }
  2258. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle);
  2259. if (AdapterMatched) {
  2260. IPX_DEBUG(PNP, ("Freeing the newly created adapter since we found a match !\n"));
  2261. IpxUnbindAdapter(
  2262. &Status,
  2263. Adapter,
  2264. NULL
  2265. );
  2266. if (STATUS_SUCCESS != Status) {
  2267. IPX_DEBUG(PNP, ("IpxUnBindAdapter returned : %x\n", Status));
  2268. } else {
  2269. for ( j = 0; j< ISN_FRAME_TYPE_MAX; j++ ) {
  2270. if (DisabledAdapter->Bindings[j]) {
  2271. DisabledAdapter->Bindings[j]->Disabled = ENABLED;
  2272. }
  2273. }
  2274. Adapter->Disabled = ENABLED;
  2275. }
  2276. } else if (DisabledAdapter != NULL) {
  2277. IPX_DEBUG(PNP, ("Freeing the previously disabled adapter since we have new characteristics...!\n"));
  2278. ASSERT(DisabledAdapter != NULL);
  2279. IpxUnbindAdapter(
  2280. &Status,
  2281. DisabledAdapter,
  2282. NULL
  2283. );
  2284. if (STATUS_SUCCESS != Status) {
  2285. IPX_DEBUG(PNP, ("IpxBindAdapter returned : %x\n", Status));
  2286. }
  2287. } else {
  2288. IPX_DEBUG(PNP, ("NULL Disabled Adapter. Ndis is probably giving random notifications.\n"));
  2289. }
  2290. IpxDereferenceAdapter(Adapter);
  2291. }
  2292. #endif // _NDIS_MEDIA_SENSE_