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.

3834 lines
108 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Copyright (c) 1991 Nokia Data Systems Ab
  4. Module Name:
  5. llcndis.c
  6. Abstract:
  7. The module binds and unbinds a protocol level module to DLC and binds the
  8. data link driver to an NDIS driver if it is necessary.
  9. All NDIS specific code is also gathered into this module such as the network
  10. status indications.
  11. Note: The DLC driver assumes that all DLC level code assumes a Token Ring
  12. adapter. If we bind to an ethernet adapter, or the required NDIS medium
  13. type is Ethernet, then we set up DLC to transform Token Ring addresses and
  14. packet formats to Ethernet (including DIX ethernet format). However, we can
  15. build a version of DLC/LLC which understands Ethernet format at the API
  16. level. Define SUPPORT_ETHERNET_CLIENT in order to build such a DLC
  17. NB: As of 07/13/92, SUPPORT_ETHERNET_CLIENT code has not been tested!
  18. Contents:
  19. LlcOpenAdapter
  20. LlcNdisOpenAdapterComplete
  21. LlcDisableAdapter
  22. LlcCloseAdapter
  23. LlcResetBroadcastAddresses
  24. InitNdisPackets
  25. LlcNdisCloseComplete
  26. NdisStatusHandler
  27. GetNdisParameter
  28. SetNdisParameter
  29. SyncNdisRequest
  30. WaitAsyncOperation
  31. LlcNdisRequest
  32. LlcNdisRequestComplete
  33. LlcNdisReset
  34. LlcNdisResetComplete
  35. UnicodeStringCompare
  36. PurgeLlcEventQueue
  37. Author:
  38. Antti Saarenheimo (o-anttis) 30-MAY-1991
  39. Revision History:
  40. 04-AUG-1991, o-anttis
  41. Rewritten for NDIS 3.0 (and for real use).
  42. 28-Apr-1994 rfirth
  43. * Modified to use single driver-level spinlock
  44. * Cleaned-up open/close - found a few bugs when stressing adapter
  45. open & close
  46. 04-May-1994 rfirth
  47. * Added MAC address caching for TEST/XID/SABME frames when adapter
  48. opened in LLC_ETHERNET_TYPE_AUTO mode
  49. --*/
  50. #ifndef i386
  51. #define LLC_PRIVATE_PROTOTYPES
  52. #endif
  53. #include <dlc.h> // need DLC_FILE_CONTEXT for memory allocation charged to handle
  54. #include <llc.h>
  55. #include <dbgmsg.h>
  56. #if DBG
  57. int DbgSettings = 0x80000000;
  58. //int DbgSettings = 0xC0000007;
  59. #endif // DBG
  60. //
  61. // private prototypes
  62. //
  63. BOOLEAN
  64. UnicodeStringCompare(
  65. IN PUNICODE_STRING String1,
  66. IN PUNICODE_STRING String2
  67. );
  68. VOID
  69. PurgeLlcEventQueue(
  70. IN PBINDING_CONTEXT pBindingContext
  71. );
  72. #ifdef NDIS40
  73. //
  74. // Private prototypes for PnP.
  75. //
  76. PADAPTER_CONTEXT
  77. AllocateAdapterContext(
  78. PNDIS_STRING pAdapterName
  79. );
  80. VOID
  81. FreeAdapterContext(
  82. PADAPTER_CONTEXT pAdapterContext
  83. );
  84. NDIS_STATUS
  85. OpenAdapter(
  86. PADAPTER_CONTEXT pAdapterContext,
  87. BOOLEAN fFirstOpen
  88. );
  89. VOID
  90. CloseAdapter(
  91. PVOID pv_pAdapterContext
  92. );
  93. #endif
  94. //
  95. // Internal statics used in NDIS 3.1 initialization in NT OS/2
  96. //
  97. KSPIN_LOCK LlcSpinLock;
  98. PVOID LlcProtocolHandle;
  99. PADAPTER_CONTEXT pAdapters = NULL;
  100. #ifdef NDIS40
  101. NDIS_EVENT PnPBindsComplete;
  102. ULONG gWaitForAdapter;
  103. #endif // NDIS40
  104. //
  105. // We do not support FDDI because it is the same as token-ring
  106. //
  107. UINT LlcMediumArray[3] = {
  108. NdisMedium802_5,
  109. NdisMedium802_3,
  110. NdisMediumFddi
  111. };
  112. DLC_STATUS
  113. LlcOpenAdapter(
  114. IN PWSTR pAdapterName,
  115. IN PVOID hClientContext,
  116. IN PFLLC_COMMAND_COMPLETE pfCommandComplete,
  117. IN PFLLC_RECEIVE_INDICATION pfReceiveIndication,
  118. IN PFLLC_EVENT_INDICATION pfEventIndication,
  119. IN NDIS_MEDIUM NdisMedium,
  120. IN LLC_ETHERNET_TYPE EthernetType,
  121. IN UCHAR AdapterNumber,
  122. OUT PVOID *phBindingContext,
  123. OUT PUINT puiOpenStatus,
  124. OUT PUSHORT pusMaxFrameLength,
  125. OUT PNDIS_MEDIUM pActualNdisMedium
  126. )
  127. /*++
  128. Routine Description:
  129. The first call to a new adapter initializes the NDIS interface
  130. and allocates internal data structures for the new adapter.
  131. Subsequent opens for the same adapter only increment the reference count
  132. of that adapter context.
  133. The execution is synchronous! The procedure waits (sleeps) until
  134. the adapter has been opened by the MAC.
  135. Special:
  136. Must be called IRQL < DPC
  137. Arguments:
  138. pAdapterName......... MAC adapter name. Zero-terminated, wide-character string
  139. hClientContext....... client context for this adapter
  140. pfCommandComplete.... send/receive/request command completion handler of the
  141. client
  142. pfReceiveIndication.. receive data indication handler of the client
  143. pfEventIndication.... event indication handler of the client
  144. NdisMedium........... the NdisMedium used by the protocol driver (ie DLC).
  145. Only NdisMedium802_5 is supported
  146. EthernetType......... type of Ethernet connection - 802.3 or DIX
  147. AdapterNumber........ adapter mapping from CCB
  148. phBindingContext..... the returned binding context handle used with the file
  149. context (by DirOpenAdapter)
  150. puiOpenStatus........ status of NdisOpenAadapter
  151. pusMaxFrameLength.... returned maximum I-frame length
  152. pActualNdisMedium.... returned actual NDIS medium; may be different from
  153. that requested (NdisMedium)
  154. Return Value:
  155. DLC_STATUS
  156. Success - STATUS_SUCCESS
  157. Failure - all NDIS error status from NdisOpenAdapter
  158. DLC_STATUS_TIMEOUT
  159. asynchronous NdisOpenAdapter failed.
  160. --*/
  161. {
  162. NDIS_STATUS NdisStatus;
  163. PADAPTER_CONTEXT pAdapterContext;
  164. UINT OpenStatus = STATUS_SUCCESS;
  165. PBINDING_CONTEXT pBindingContext;
  166. UINT MediumIndex;
  167. KIRQL irql;
  168. BOOLEAN DoNdisClose = FALSE;
  169. UNICODE_STRING unicodeString;
  170. BOOLEAN newAdapter;
  171. ULONG cacheEntries;
  172. BOOLEAN initUnicodeString = TRUE;
  173. NTSTATUS ntstatus;
  174. #ifdef NDIS40
  175. LONG BindState;
  176. ULONG DelaySeconds;
  177. LARGE_INTEGER SleepSec;
  178. #endif // NDIS40
  179. #if DBG
  180. PDLC_FILE_CONTEXT pFileContext = (PDLC_FILE_CONTEXT)hClientContext;
  181. #endif
  182. DEBUGMSG(DBG_NDIS_OPEN,
  183. (TEXT("+LlcOpenAdapter(%#x...)\n"), pAdapterName));
  184. ASSUME_IRQL(DISPATCH_LEVEL);
  185. #ifdef SUPPORT_ETHERNET_CLIENT
  186. if (NdisMedium != NdisMedium802_3 && NdisMedium != NdisMedium802_5) {
  187. return DLC_STATUS_UNKNOWN_MEDIUM;
  188. }
  189. #else
  190. if (NdisMedium != NdisMedium802_5) {
  191. return DLC_STATUS_UNKNOWN_MEDIUM;
  192. }
  193. #endif
  194. RELEASE_DRIVER_LOCK();
  195. ASSUME_IRQL(PASSIVE_LEVEL);
  196. #ifdef NDIS40
  197. //
  198. // Wait for all NDIS bindings to have completed before trying to open
  199. // the adapter.
  200. //
  201. if (NdisWaitEvent(&PnPBindsComplete, 0) == FALSE)
  202. {
  203. ACQUIRE_DRIVER_LOCK();
  204. return (DLC_STATUS_WAIT_TIMEOUT);
  205. }
  206. #endif // NDIS40
  207. //
  208. // RLF 04/19/93
  209. //
  210. // The adapter name passed to this routine is a zero-terminated wide
  211. // character string mapped to system space. Create a UNICODE_STRING for
  212. // the name and use standard Rtl function to compare with names of adapters
  213. // already opened by DLC
  214. //
  215. // Although its assumed that the adapter name is NULL-terminated,
  216. // we will anyway check whether this is the case or not
  217. // We know the length of the wide character string is 260 (MAX_PATH)
  218. // BUG: 127246 (security bug)
  219. {
  220. ULONG len = 0;
  221. while (len < MAX_PATH) {
  222. if (pAdapterName[len] == L'\0') {
  223. break;
  224. }
  225. len++;
  226. }
  227. if (len == MAX_PATH) {
  228. // the wchar string is not NULL terminated
  229. ACQUIRE_DRIVER_LOCK();
  230. return DLC_STATUS_INVALID_ADAPTER;
  231. }
  232. }
  233. RtlInitUnicodeString(&unicodeString, pAdapterName);
  234. //
  235. // if the adapter is being opened in LLC_ETHERNET_TYPE_AUTO mode then we
  236. // get the cache size from the registry
  237. //
  238. if (EthernetType == LLC_ETHERNET_TYPE_AUTO) {
  239. static DLC_REGISTRY_PARAMETER framingCacheParameterTemplate = {
  240. L"AutoFramingCacheSize",
  241. (PVOID)DEFAULT_AUTO_FRAMING_CACHE_SIZE,
  242. {
  243. REG_DWORD,
  244. PARAMETER_AS_SPECIFIED,
  245. NULL,
  246. sizeof(ULONG),
  247. NULL,
  248. MIN_AUTO_FRAMING_CACHE_SIZE,
  249. MAX_AUTO_FRAMING_CACHE_SIZE
  250. }
  251. };
  252. PDLC_REGISTRY_PARAMETER parameterTable;
  253. //
  254. // create a private copy of the parameter table descriptor
  255. //
  256. parameterTable = (PDLC_REGISTRY_PARAMETER)
  257. ALLOCATE_ZEROMEMORY_DRIVER(sizeof(*parameterTable));
  258. if (!parameterTable) {
  259. ACQUIRE_DRIVER_LOCK();
  260. return DLC_STATUS_NO_MEMORY;
  261. }
  262. RtlCopyMemory(parameterTable,
  263. &framingCacheParameterTemplate,
  264. sizeof(framingCacheParameterTemplate)
  265. );
  266. //
  267. // point the Variable field at cacheEntries and set it to the default
  268. // value then call GetRegistryParameters to retrieve the registry value.
  269. // (and set it if not already in the registry). Ignore the return value
  270. // - if GetAdapterParameters failed, cacheEntries will still contain the
  271. // default value
  272. //
  273. cacheEntries = DEFAULT_AUTO_FRAMING_CACHE_SIZE;
  274. parameterTable->Descriptor.Variable = (PVOID)&cacheEntries;
  275. parameterTable->Descriptor.Value = (PVOID)&parameterTable->DefaultValue;
  276. GetAdapterParameters(&unicodeString, parameterTable, 1, TRUE);
  277. FREE_MEMORY_DRIVER(parameterTable);
  278. } else {
  279. cacheEntries = 0;
  280. }
  281. //
  282. // allocate a BINDING_CONTEXT with enough additional space to store the
  283. // required framing discovery cache
  284. //
  285. // DEBUG: BINDING_CONTEXT structures are charged to the FILE_CONTEXT
  286. //
  287. #if defined(DEBUG_DISCOVERY)
  288. DbgPrint("cacheEntries=%d\n", cacheEntries);
  289. #endif
  290. pBindingContext = (PBINDING_CONTEXT)
  291. ALLOCATE_ZEROMEMORY_FILE(sizeof(BINDING_CONTEXT)
  292. + cacheEntries
  293. * sizeof(FRAMING_DISCOVERY_CACHE_ENTRY)
  294. );
  295. if (!pBindingContext) {
  296. ACQUIRE_DRIVER_LOCK();
  297. return DLC_STATUS_NO_MEMORY;
  298. }
  299. //
  300. // set the maximum size of the framing discovery cache. Will be zero if the
  301. // requested ethernet type is not LLC_ETHERNET_TYPE_AUTO
  302. //
  303. pBindingContext->FramingDiscoveryCacheEntries = cacheEntries;
  304. #if DBG
  305. //
  306. // we need the FILE_CONTEXT structure in the BINDING_CONTEXT in the event
  307. // the open fails and we need to deallocate memory. Normally this field is
  308. // not set til everything has successfully been completed
  309. //
  310. pBindingContext->hClientContext = hClientContext;
  311. #endif
  312. //
  313. // RtlUpcaseUnicodeString is a paged routine - lower IRQL
  314. //
  315. //
  316. // to avoid having to case-insensitive compare unicode strings every time,
  317. // we do a one-shot convert to upper-cased unicode strings. This also helps
  318. // out since we do our own unicode string comparison (case-sensitive)
  319. //
  320. // Note that this modifies the input parameter
  321. //
  322. RtlUpcaseUnicodeString(&unicodeString, &unicodeString, FALSE);
  323. //
  324. // before we re-acquire the driver spin-lock, we wait on the OpenAdapter
  325. // semaphore. We serialize access to the following code because simultaneous
  326. // opens (in different processes) and closes (different threads within
  327. // same process) check to see if the adapter is on the pAdapters list.
  328. // We don't want multiple processes creating the same adapter context
  329. // simultaneously. Similarly, we must protect against the situation where
  330. // one process is adding a binding and another could be closing what it
  331. // thinks is the sole binding, thereby deleting the adapter context we
  332. // are about to update
  333. // Note that this is a non-optimal solution since it means an app opening
  334. // or closing an ethernet adapter could get stuck behind another opening
  335. // a token ring adapter (slow)
  336. //
  337. KeWaitForSingleObject((PVOID)&OpenAdapterSemaphore,
  338. Executive,
  339. KernelMode,
  340. FALSE, // not alertable
  341. NULL // wait until object is signalled
  342. );
  343. //
  344. // grab the global LLC spin lock whilst we are looking at/updating the list
  345. // of adapters
  346. //
  347. ACQUIRE_LLC_LOCK(irql);
  348. //
  349. // because we are doing the compare within spinlock, we use our own function
  350. // which checks for an exact match (i.e. case-sensitive). This is ok since
  351. // always upper-case the string before comparing it or storing it in an
  352. // ADAPTER_CONTEXT
  353. //
  354. for (pAdapterContext = pAdapters; pAdapterContext; pAdapterContext = pAdapterContext->pNext) {
  355. if (UnicodeStringCompare(&unicodeString, &pAdapterContext->Name)) {
  356. break;
  357. }
  358. }
  359. //
  360. // if we didn't locate an adapter context with our adapter name then we're
  361. // creating a new binding: allocate a new adapter context structure
  362. //
  363. #ifdef NDIS40
  364. //
  365. // Some adapters may come up after the PnPBindsComplete event, such
  366. // as an ATM LANE. Just in case the adapter initialization is delayed,
  367. // we will wait for 'gWaitForAdapter' seconds or until the adapter
  368. // is found.
  369. //
  370. DEBUGMSG(DBG_NDIS_OPEN && pAdapterContext == NULL,
  371. (TEXT("LlcOpenAdapter - WaitForAdapter %d\n"),
  372. gWaitForAdapter));
  373. SleepSec.QuadPart = -(10*1000*1000); // 1 second.
  374. for (DelaySeconds = gWaitForAdapter;
  375. (DelaySeconds > 0) && (pAdapterContext == NULL);
  376. DelaySeconds--)
  377. {
  378. DEBUGMSG(DBG_NDIS_OPEN && DBG_VERBOSE,
  379. (TEXT("LlcOpenAdapter - waiting %d\n"), DelaySeconds));
  380. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  381. KeDelayExecutionThread(KernelMode, FALSE, &SleepSec);
  382. KeWaitForSingleObject((PVOID)&OpenAdapterSemaphore,
  383. Executive,
  384. KernelMode,
  385. FALSE, // not alertable
  386. NULL // wait until object is signalled
  387. );
  388. // Search for the adapter again.
  389. for (pAdapterContext = pAdapters;
  390. pAdapterContext != NULL;
  391. pAdapterContext = pAdapterContext->pNext)
  392. {
  393. if (UnicodeStringCompare(&unicodeString, &pAdapterContext->Name))
  394. {
  395. break;
  396. }
  397. }
  398. }
  399. //
  400. // For NDIS40, with bind and unbind handlers, the ADAPTER_CONTEXT is
  401. // managed by the bind/unbind handler. If the adapter is in the list,
  402. // then we can attach the binding context, else fail the open request.
  403. //
  404. newAdapter = FALSE;
  405. //
  406. // If NDIS has never indicated a binding for this adapter, then fail
  407. // open adapter request.
  408. //
  409. if (pAdapterContext == NULL)
  410. {
  411. DEBUGMSG(DBG_NDIS_OPEN || DBG_WARN,
  412. (TEXT("LlcOpenAdapter - adapter '%ws' not found.\n"),
  413. pAdapterName));
  414. RELEASE_LLC_LOCK(irql);
  415. FREE_MEMORY_FILE(pBindingContext);
  416. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  417. ACQUIRE_DRIVER_LOCK();
  418. return (DLC_STATUS_ADAPTER_NOT_INSTALLED);
  419. }
  420. //
  421. // Reference count the NdisBindingHandle to make sure that it doesn't
  422. // go away while initializing this binding instance.
  423. //
  424. REFADD(&pAdapterContext->AdapterRefCnt, 'nepO');
  425. //
  426. // Check to see if the adapter is BOUND/enabled.
  427. //
  428. BindState = InterlockedCompareExchange(
  429. &pAdapterContext->BindState,
  430. BIND_STATE_BOUND,
  431. BIND_STATE_BOUND);
  432. if (BindState != BIND_STATE_BOUND)
  433. {
  434. //
  435. // Adapter is currently unbound (or unbinding).
  436. //
  437. RELEASE_LLC_LOCK(irql);
  438. FREE_MEMORY_FILE(pBindingContext);
  439. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  440. ACQUIRE_DRIVER_LOCK();
  441. REFDEL(&pAdapterContext->AdapterRefCnt, 'nepO');
  442. DEBUGMSG(DBG_NDIS_OPEN || DBG_WARN,
  443. (TEXT("LlcOpenAdapter - adapter %#x not bound.\n"),
  444. pAdapterName));
  445. return (DLC_STATUS_ADAPTER_NOT_INSTALLED);
  446. }
  447. //
  448. // if we allocated a framing discovery cache, but this adapter is not
  449. // ethernet or FDDI then disable the cache (we should free the
  450. // memory used by the cache in this case!!)
  451. //
  452. if ((pAdapterContext->NdisMedium != NdisMedium802_3) &&
  453. (pAdapterContext->NdisMedium != NdisMediumFddi))
  454. {
  455. pBindingContext->FramingDiscoveryCacheEntries = 0;
  456. #if defined(DEBUG_DISCOVERY)
  457. DbgPrint("LlcOpenAdapter: setting cache entries to 0 (medium = %s)\n",
  458. (pAdapterContext->NdisMedium == NdisMedium802_5) ? "802.5" :
  459. (pAdapterContext->NdisMedium == NdisMediumWan) ? "WAN" :
  460. (pAdapterContext->NdisMedium == NdisMediumLocalTalk) ? "LocalTalk" :
  461. (pAdapterContext->NdisMedium == NdisMediumDix) ? "DIX?" :
  462. (pAdapterContext->NdisMedium == NdisMediumArcnetRaw) ? "ArcnetRaw" :
  463. (pAdapterContext->NdisMedium == NdisMediumArcnet878_2) ? "Arcnet878_2" :
  464. "UNKNOWN!");
  465. #endif
  466. }
  467. //
  468. // Fall through and link the BIND_CONTEXT with the adapter context.
  469. //
  470. #else // NDIS40
  471. if (!pAdapterContext) {
  472. //
  473. // DEBUG: ADAPTER_CONTEXT structures are charged to the driver
  474. //
  475. pAdapterContext = (PADAPTER_CONTEXT)
  476. ALLOCATE_ZEROMEMORY_DRIVER(sizeof(ADAPTER_CONTEXT));
  477. if (!pAdapterContext) {
  478. RELEASE_LLC_LOCK(irql);
  479. //
  480. // DEBUG: refund memory charged for BINDING_CONTEXT to FILE_CONTEXT
  481. //
  482. FREE_MEMORY_FILE(pBindingContext);
  483. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  484. ACQUIRE_DRIVER_LOCK();
  485. return DLC_STATUS_NO_MEMORY;
  486. }
  487. newAdapter = TRUE;
  488. #if DBG
  489. //
  490. // record who owns this memory usage structure and add it to the
  491. // list of all memory usages created in the driver
  492. //
  493. pAdapterContext->MemoryUsage.Owner = (PVOID)pAdapterContext;
  494. pAdapterContext->MemoryUsage.OwnerObjectId = AdapterContextObject;
  495. pAdapterContext->StringUsage.Owner = (PVOID)pAdapterContext;
  496. pAdapterContext->StringUsage.OwnerObjectId = AdapterContextObject;
  497. LinkMemoryUsage(&pAdapterContext->MemoryUsage);
  498. LinkMemoryUsage(&pAdapterContext->StringUsage);
  499. #endif
  500. //
  501. // We must allocate all spinlocks immediately after the
  502. // adapter context has been allocated, because
  503. // they can also deallocated simultaneously.
  504. //
  505. ALLOCATE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  506. ALLOCATE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  507. //
  508. // allocate space for the adapter name string from non-paged pool
  509. // and initialize the name in the adapter context structure
  510. //
  511. NdisStatus = LlcInitUnicodeString(&pAdapterContext->Name,
  512. &unicodeString
  513. );
  514. if (NdisStatus != STATUS_SUCCESS) {
  515. initUnicodeString = FALSE;
  516. goto CleanUp;
  517. }
  518. pAdapterContext->OpenCompleteStatus = NDIS_STATUS_PENDING;
  519. //
  520. // and release the global spin lock: we have finished updating the
  521. // adapter list and initializing this adapter context. From now
  522. // on we use spin locks specific to this adapter context
  523. //
  524. RELEASE_LLC_LOCK(irql);
  525. //
  526. // We must initialize the list heads before we open the adapter!!!
  527. //
  528. InitializeListHead(&pAdapterContext->QueueEvents);
  529. InitializeListHead(&pAdapterContext->QueueCommands);
  530. InitializeListHead(&pAdapterContext->NextSendTask);
  531. pAdapterContext->OpenErrorStatus = NDIS_STATUS_PENDING;
  532. ASSUME_IRQL(PASSIVE_LEVEL);
  533. KeInitializeEvent(&pAdapterContext->Event, NotificationEvent, FALSE);
  534. //
  535. // when the NDIS level adapter open completes, it will call
  536. // LlcNdisOpenAdapterComplete which will reset the kernel event that
  537. // we are now going to wait on (note: this plagiarized from Nbf)
  538. //
  539. NdisOpenAdapter(&NdisStatus,
  540. &pAdapterContext->OpenErrorStatus,
  541. &pAdapterContext->NdisBindingHandle,
  542. &MediumIndex,
  543. (NDIS_MEDIUM *)&LlcMediumArray[0],
  544. sizeof(LlcMediumArray),
  545. (NDIS_HANDLE)LlcProtocolHandle,
  546. (NDIS_HANDLE)pAdapterContext,
  547. &pAdapterContext->Name,
  548. NDIS_OPEN_RECEIVE_NOT_REENTRANT,
  549. NULL // no addressing information
  550. );
  551. if (NdisStatus == NDIS_STATUS_PENDING) {
  552. ASSUME_IRQL(PASSIVE_LEVEL);
  553. do {
  554. ntstatus = KeWaitForSingleObject(&pAdapterContext->Event,
  555. Executive,
  556. KernelMode,
  557. TRUE, // alertable
  558. (PLARGE_INTEGER)NULL
  559. );
  560. } while (ntstatus == STATUS_ALERTED);
  561. //
  562. // get the return status from the Ndis adapter open call
  563. //
  564. NdisStatus = pAdapterContext->AsyncOpenStatus;
  565. //
  566. // place the event in not-signalled state. We don't expect to use
  567. // this event for this adapter context again: currently it's only
  568. // used for the adapter open at NDIS level
  569. //
  570. KeResetEvent(&pAdapterContext->Event);
  571. }
  572. *puiOpenStatus = (UINT)pAdapterContext->OpenErrorStatus;
  573. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  574. IF_LOCK_CHECK {
  575. DbgPrint("LlcOpenAdapter: NdisOpenAdapter failed\n");
  576. }
  577. goto CleanUp;
  578. } else {
  579. //
  580. // from this point on, if this function fails, we have to call
  581. // LlcCloseAdapter to close the adapter @ NDIS level
  582. //
  583. DoNdisClose = TRUE;
  584. }
  585. pAdapterContext->NdisMedium = LlcMediumArray[MediumIndex];
  586. ASSUME_IRQL(PASSIVE_LEVEL);
  587. //
  588. // fill-in some medium-specific fields
  589. //
  590. switch (pAdapterContext->NdisMedium) {
  591. case NdisMedium802_5:
  592. pAdapterContext->cbMaxFrameHeader = 32; // 6 + 6 + 2 + 18
  593. //
  594. // the top bit of the destination address signifies a broadcast
  595. // frame. On Token Ring, the top bit is bit 7
  596. //
  597. pAdapterContext->IsBroadcast = 0x80;
  598. //
  599. // functional address starts C0-00-... The top 2 bytes are compared
  600. // as a USHORT = 0x00C0
  601. //
  602. pAdapterContext->usHighFunctionalBits = 0x00C0;
  603. pAdapterContext->AddressTranslationMode = LLC_SEND_802_5_TO_802_5;
  604. break;
  605. case NdisMedium802_3:
  606. pAdapterContext->cbMaxFrameHeader = 14; // 6 + 6 + 2
  607. //
  608. // the top bit of the destination address signifies a broadcast
  609. // frame. On Ethernet, the top bit is bit 0
  610. //
  611. pAdapterContext->IsBroadcast = 0x01;
  612. //
  613. // functional address starts 03-00-... The top 2 bytes are compared as
  614. // a USHORT = 0x0003
  615. //
  616. pAdapterContext->usHighFunctionalBits = 0x0003;
  617. pAdapterContext->AddressTranslationMode = LLC_SEND_802_3_TO_802_3;
  618. break;
  619. case NdisMediumFddi:
  620. pAdapterContext->cbMaxFrameHeader = 13; // 1 + 6 + 6
  621. //
  622. // bits are in same order as for ethernet
  623. //
  624. pAdapterContext->IsBroadcast = 0x01;
  625. pAdapterContext->usHighFunctionalBits = 0x0003;
  626. pAdapterContext->AddressTranslationMode = LLC_SEND_FDDI_TO_FDDI;
  627. break;
  628. }
  629. //
  630. // allocate the ndis packets. The NDIS packet must have space
  631. // for the maximum frame header and the maximum LLC response
  632. // and its information field (quite small)
  633. //
  634. NdisAllocatePacketPool(&NdisStatus,
  635. &pAdapterContext->hNdisPacketPool,
  636. MAX_NDIS_PACKETS + 1,
  637. sizeof(LLC_NDIS_PACKET) - sizeof(NDIS_MAC_PACKET)
  638. );
  639. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  640. IF_LOCK_CHECK {
  641. DbgPrint("LlcOpenAdapter: NdisAllocatePacketPool failed\n");
  642. }
  643. goto CleanUp;
  644. }
  645. NdisStatus = InitNdisPackets(&pAdapterContext->pNdisPacketPool,
  646. pAdapterContext->hNdisPacketPool
  647. );
  648. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  649. IF_LOCK_CHECK {
  650. DbgPrint("LlcOpenAdapter: InitNdisPackets failed\n");
  651. }
  652. goto CleanUp;
  653. }
  654. //
  655. // Initialize the LLC packet pool
  656. //
  657. pAdapterContext->hPacketPool = CREATE_PACKET_POOL_ADAPTER(
  658. LlcPacketPoolObject,
  659. sizeof(UNITED_PACKETS),
  660. 8
  661. );
  662. if (!pAdapterContext->hPacketPool) {
  663. NdisStatus = DLC_STATUS_NO_MEMORY;
  664. IF_LOCK_CHECK {
  665. DbgPrint("LlcOpenAdapter: CreatePacketPool failed\n");
  666. }
  667. goto CleanUp;
  668. }
  669. pAdapterContext->hLinkPool = CREATE_PACKET_POOL_ADAPTER(
  670. LlcLinkPoolObject,
  671. pAdapterContext->cbMaxFrameHeader
  672. + sizeof(DATA_LINK),
  673. 2
  674. );
  675. if (!pAdapterContext->hLinkPool) {
  676. NdisStatus = DLC_STATUS_NO_MEMORY;
  677. IF_LOCK_CHECK {
  678. DbgPrint("LlcOpenAdapter: CreatePacketPool #2 failed\n");
  679. }
  680. goto CleanUp;
  681. }
  682. //
  683. // Read the current node address and maximum frame size
  684. //
  685. NdisStatus = GetNdisParameter(pAdapterContext,
  686. (pAdapterContext->NdisMedium == NdisMedium802_3)
  687. ? OID_802_3_CURRENT_ADDRESS
  688. : (pAdapterContext->NdisMedium == NdisMediumFddi)
  689. ? OID_FDDI_LONG_CURRENT_ADDR
  690. : OID_802_5_CURRENT_ADDRESS,
  691. pAdapterContext->NodeAddress,
  692. sizeof(pAdapterContext->NodeAddress)
  693. );
  694. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  695. IF_LOCK_CHECK {
  696. DbgPrint("LlcOpenAdapter: GetNdisParameter failed\n");
  697. }
  698. goto CleanUp;
  699. }
  700. NdisStatus = GetNdisParameter(pAdapterContext,
  701. (pAdapterContext->NdisMedium == NdisMedium802_3)
  702. ? OID_802_3_PERMANENT_ADDRESS
  703. : (pAdapterContext->NdisMedium == NdisMediumFddi)
  704. ? OID_FDDI_LONG_PERMANENT_ADDR
  705. : OID_802_5_PERMANENT_ADDRESS,
  706. pAdapterContext->PermanentAddress,
  707. sizeof(pAdapterContext->PermanentAddress)
  708. );
  709. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  710. IF_LOCK_CHECK {
  711. DbgPrint("LlcOpenAdapter: GetNdisParameter #2 failed\n");
  712. }
  713. goto CleanUp;
  714. }
  715. {
  716. //
  717. // Mod RLF 07/10/92
  718. //
  719. // apparently, TR adapter does not support NDIS_PACKET_TYPE_MULTICAST
  720. // as a filter. Up to now, it seems to have been reasonably happy
  721. // with this type. However, we're not going to include it from now on
  722. //
  723. //
  724. // Mod RLF 01/13/93
  725. //
  726. // Similarly, Ethernet doesn't support FUNCTIONAL addresses (Token
  727. // Ring's functional address is equivalent to Ethernet's multicast
  728. // address)
  729. //
  730. ULONG PacketFilter = NDIS_PACKET_TYPE_DIRECTED
  731. | NDIS_PACKET_TYPE_BROADCAST
  732. | (((pAdapterContext->NdisMedium == NdisMedium802_3)
  733. || (pAdapterContext->NdisMedium == NdisMediumFddi))
  734. ? NDIS_PACKET_TYPE_MULTICAST
  735. : NDIS_PACKET_TYPE_FUNCTIONAL
  736. );
  737. //
  738. // EndMod
  739. //
  740. NdisStatus = SetNdisParameter(pAdapterContext,
  741. OID_GEN_CURRENT_PACKET_FILTER,
  742. &PacketFilter,
  743. sizeof(PacketFilter)
  744. );
  745. #if DBG
  746. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  747. DbgPrint("Error: NdisStatus = %x\n", NdisStatus);
  748. ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
  749. }
  750. #endif
  751. }
  752. LlcMemCpy(pAdapterContext->Adapter.Node.auchAddress,
  753. pAdapterContext->NodeAddress,
  754. 6
  755. );
  756. NdisStatus = GetNdisParameter(pAdapterContext,
  757. OID_GEN_MAXIMUM_TOTAL_SIZE,
  758. &pAdapterContext->MaxFrameSize,
  759. sizeof(pAdapterContext->MaxFrameSize)
  760. );
  761. if (NdisStatus == STATUS_SUCCESS) {
  762. NdisStatus = GetNdisParameter(pAdapterContext,
  763. OID_GEN_LINK_SPEED,
  764. &pAdapterContext->LinkSpeed,
  765. sizeof(pAdapterContext->LinkSpeed)
  766. );
  767. }
  768. if (NdisStatus != STATUS_SUCCESS) {
  769. IF_LOCK_CHECK {
  770. DbgPrint("LlcOpenAdapter: GetNdisParameter #3/#4 failed\n");
  771. }
  772. goto CleanUp;
  773. }
  774. //
  775. // RLF 04/12/93
  776. //
  777. // Here we used to load the LLC_TICKS array from TimerTicks - a global
  778. // array of timer tick values.
  779. // Instead, we get any per-adapter configuration information stored in
  780. // the registry
  781. //
  782. LoadAdapterConfiguration(&pAdapterContext->Name,
  783. &pAdapterContext->ConfigInfo
  784. );
  785. //
  786. // RLF 04/02/94
  787. //
  788. // if this is not a Token Ring card then check the MaxFrameSize retrieved
  789. // above. If the UseEthernetFrameSize parameter was set in the registry
  790. // then we use the smaller of the ethernet size (1514) and the value
  791. // reported by the MAC. If the parameter was not set then we just use
  792. // the value already retrieved. If the card is Token Ring then we use
  793. // the value already retrieved
  794. //
  795. if (pAdapterContext->NdisMedium != NdisMedium802_5
  796. && pAdapterContext->ConfigInfo.UseEthernetFrameSize
  797. && pAdapterContext->MaxFrameSize > MAX_ETHERNET_FRAME_LENGTH) {
  798. pAdapterContext->MaxFrameSize = MAX_ETHERNET_FRAME_LENGTH;
  799. }
  800. pAdapterContext->QueueI.pObject = (PVOID)GetI_Packet;
  801. InitializeListHead(&pAdapterContext->QueueI.ListHead);
  802. pAdapterContext->QueueDirAndU.pObject = (PVOID)BuildDirOrU_Packet;
  803. InitializeListHead(&pAdapterContext->QueueDirAndU.ListHead);
  804. pAdapterContext->QueueExpidited.pObject = (PVOID)GetLlcCommandPacket;
  805. InitializeListHead(&pAdapterContext->QueueExpidited.ListHead);
  806. pAdapterContext->AdapterNumber = (UCHAR)AdapterNumber;
  807. pAdapterContext->OpenCompleteStatus = STATUS_SUCCESS;
  808. //
  809. // if we allocated a framing discovery cache, but this adapter is not
  810. // ethernet or FDDI then disable the cache (we should free the
  811. // memory used by the cache in this case!!)
  812. //
  813. if ((pAdapterContext->NdisMedium != NdisMedium802_3)
  814. && (pAdapterContext->NdisMedium != NdisMediumFddi)) {
  815. pBindingContext->FramingDiscoveryCacheEntries = 0;
  816. #if defined(DEBUG_DISCOVERY)
  817. DbgPrint("LlcOpenAdapter: setting cache entries to 0 (medium = %s)\n",
  818. (pAdapterContext->NdisMedium == NdisMedium802_5) ? "802.5" :
  819. (pAdapterContext->NdisMedium == NdisMediumWan) ? "WAN" :
  820. (pAdapterContext->NdisMedium == NdisMediumLocalTalk) ? "LocalTalk" :
  821. (pAdapterContext->NdisMedium == NdisMediumDix) ? "DIX?" :
  822. (pAdapterContext->NdisMedium == NdisMediumArcnetRaw) ? "ArcnetRaw" :
  823. (pAdapterContext->NdisMedium == NdisMediumArcnet878_2) ? "Arcnet878_2" :
  824. "UNKNOWN!"
  825. );
  826. #endif
  827. }
  828. } else {
  829. newAdapter = FALSE;
  830. }
  831. #endif // !NDIS40
  832. //
  833. // at this point, we have an allocated, but as yet not filled in binding
  834. // context and an adapter context that we either found on the pAdapters
  835. // list, or we just allocated and filled in. We are currently operating
  836. // at PASSIVE_LEVEL. Re-acquire the driver lock and fill in the binding
  837. // context
  838. //
  839. ACQUIRE_DRIVER_LOCK();
  840. ASSUME_IRQL(DISPATCH_LEVEL);
  841. switch (pAdapterContext->NdisMedium) {
  842. case NdisMedium802_5:
  843. pBindingContext->EthernetType = LLC_ETHERNET_TYPE_802_3;
  844. pBindingContext->InternalAddressTranslation = LLC_SEND_802_5_TO_802_5;
  845. #ifdef SUPPORT_ETHERNET_CLIENT
  846. if (NdisMedium == NdisMedium802_3) {
  847. pBindingContext->SwapCopiedLanAddresses = TRUE;
  848. pBindingContext->AddressTranslation = LLC_SEND_802_3_TO_802_5;
  849. } else {
  850. pBindingContext->AddressTranslation = LLC_SEND_802_5_TO_802_5;
  851. }
  852. #else
  853. pBindingContext->AddressTranslation = LLC_SEND_802_5_TO_802_5;
  854. #endif
  855. pBindingContext->SwapCopiedLanAddresses = FALSE;
  856. break;
  857. case NdisMediumFddi:
  858. pBindingContext->EthernetType = LLC_ETHERNET_TYPE_802_3;
  859. pBindingContext->InternalAddressTranslation = LLC_SEND_FDDI_TO_FDDI;
  860. pBindingContext->AddressTranslation = LLC_SEND_802_5_TO_FDDI;
  861. pBindingContext->SwapCopiedLanAddresses = TRUE;
  862. break;
  863. case NdisMedium802_3:
  864. //
  865. // if EthernetType is LLC_ETHERNET_TYPE_DEFAULT then set it to DIX based
  866. // on the UseDix entry in the registry
  867. //
  868. if (EthernetType == LLC_ETHERNET_TYPE_DEFAULT) {
  869. EthernetType = pAdapterContext->ConfigInfo.UseDix
  870. ? LLC_ETHERNET_TYPE_DIX
  871. : LLC_ETHERNET_TYPE_802_3
  872. ;
  873. }
  874. pBindingContext->EthernetType = (USHORT)EthernetType;
  875. if (EthernetType == LLC_ETHERNET_TYPE_DIX) {
  876. pBindingContext->InternalAddressTranslation = LLC_SEND_802_3_TO_DIX;
  877. } else {
  878. pBindingContext->InternalAddressTranslation = LLC_SEND_802_3_TO_802_3;
  879. }
  880. #ifdef SUPPORT_ETHERNET_CLIENT
  881. if (NdisMedium == NdisMedium802_3) {
  882. pBindingContext->AddressTranslation = LLC_SEND_802_3_TO_802_3;
  883. if (EthernetType == LLC_ETHERNET_TYPE_DIX) {
  884. pBindingContext->AddressTranslation = LLC_SEND_802_3_TO_DIX;
  885. }
  886. } else {
  887. pBindingContext->SwapCopiedLanAddresses = TRUE;
  888. pBindingContext->AddressTranslation = LLC_SEND_802_5_TO_802_3;
  889. if (EthernetType == LLC_ETHERNET_TYPE_DIX) {
  890. pBindingContext->AddressTranslation = LLC_SEND_802_5_TO_DIX;
  891. }
  892. }
  893. #else
  894. pBindingContext->SwapCopiedLanAddresses = TRUE;
  895. pBindingContext->AddressTranslation = LLC_SEND_802_5_TO_802_3;
  896. if (EthernetType == LLC_ETHERNET_TYPE_DIX) {
  897. pBindingContext->AddressTranslation = LLC_SEND_802_5_TO_DIX;
  898. }
  899. #endif
  900. }
  901. pBindingContext->NdisMedium = NdisMedium;
  902. pBindingContext->hClientContext = hClientContext;
  903. pBindingContext->pfCommandComplete = pfCommandComplete;
  904. pBindingContext->pfReceiveIndication = pfReceiveIndication;
  905. pBindingContext->pfEventIndication = pfEventIndication;
  906. *pusMaxFrameLength = (USHORT)pAdapterContext->MaxFrameSize;
  907. *pActualNdisMedium = pAdapterContext->NdisMedium;
  908. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  909. //
  910. // create a new timer tick (or update one that already exists) and add a
  911. // timer to it for the DLC timer (used by the DIR.TIMER.XXX routines). The
  912. // DLC timer fires every 0.5 seconds. The LLC timer fires every 40 mSec. The
  913. // multiplier is therefore 13 (13 * 40 mSec = 520 mSec). We need to add 5
  914. // because InitializeTimer is expecting DLC timer tick values of 1-5 and
  915. // 6-10. If the timer tick value is greater than 5, InitializeTimer will
  916. // subtract 5 and multiply by the second multiplier value
  917. //
  918. NdisStatus = InitializeTimer(pAdapterContext,
  919. &pBindingContext->DlcTimer,
  920. (UCHAR)13 + 5,
  921. (UCHAR)1,
  922. (UCHAR)1,
  923. LLC_TIMER_TICK_EVENT,
  924. pBindingContext,
  925. 0, // ResponseDelay
  926. FALSE
  927. );
  928. if (NdisStatus != STATUS_SUCCESS) {
  929. IF_LOCK_CHECK {
  930. DbgPrint("LlcOpenAdapter: InitializeTimer failed\n");
  931. }
  932. //
  933. // we failed to initialize the timer. Free up all resources and return
  934. // the error
  935. //
  936. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  937. RELEASE_DRIVER_LOCK();
  938. ASSUME_IRQL(PASSIVE_LEVEL);
  939. goto CleanUp;
  940. } else {
  941. StartTimer(&pBindingContext->DlcTimer);
  942. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  943. }
  944. //
  945. // everything worked: point the binding context at the adapter context,
  946. // point the adapter context at the binding context, incrementing the binding
  947. // count (note that if this is the first binding, the count field will be
  948. // zero since we allocated the adapter context from ZeroMemory). Finally add
  949. // the adapter context to pAdapters if it wasn't already on the list
  950. //
  951. pBindingContext->pAdapterContext = pAdapterContext;
  952. IF_LOCK_CHECK {
  953. if (!pAdapterContext->BindingCount) {
  954. if (pAdapterContext->pBindings) {
  955. DbgPrint("**** binding count/pointer mismatch ****\n");
  956. DbgBreakPoint();
  957. }
  958. }
  959. }
  960. pBindingContext->pNext = pAdapterContext->pBindings;
  961. pAdapterContext->pBindings = pBindingContext;
  962. ++pAdapterContext->BindingCount;
  963. //
  964. // we can now add this adapter context structure to the global list
  965. // of adapter contexts
  966. //
  967. #ifdef NDIS40
  968. ASSERT(newAdapter == FALSE);
  969. #else // NDIS40
  970. if (newAdapter) {
  971. pAdapterContext->pNext = pAdapters;
  972. pAdapters = pAdapterContext;
  973. }
  974. #endif // !NDIS40
  975. //
  976. // now release the semaphore, allowing any other threads waiting to open an
  977. // adapter to check the pAdapter list
  978. //
  979. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  980. #ifdef NDIS40
  981. //
  982. // Release the NdisBindingHandle reference.
  983. //
  984. REFDEL(&pAdapterContext->AdapterRefCnt, 'nepO');
  985. #endif // NDIS40
  986. //
  987. // return a pointer to the allocated binding context
  988. //
  989. *phBindingContext = (PVOID)pBindingContext;
  990. return STATUS_SUCCESS;
  991. CleanUp:
  992. //
  993. // an error occurred. If we just allocated and (partially) filled in an
  994. // adapter context then close the adapter (if required), release the adapter
  995. // context resources and free the adapter context.
  996. // We have a binding context that we just allocated. Deallocate it
  997. // N.B. We cannot be here if the binding context's timer was successfully
  998. // initialized/started
  999. //
  1000. ASSUME_IRQL(PASSIVE_LEVEL);
  1001. //
  1002. // if we are to close this adapter then this is the first and only open of
  1003. // this adapter, so we don't need to worry about synchronizing other threads
  1004. // open the same adapter
  1005. //
  1006. #ifdef NDIS40
  1007. ASSERT(DoNdisClose == FALSE);
  1008. //
  1009. // Release the NdisBindingHandle reference.
  1010. //
  1011. ASSERT(pAdapterContext);
  1012. REFDEL(&pAdapterContext->AdapterRefCnt, 'nepO');
  1013. #else // NDIS40
  1014. if (DoNdisClose) {
  1015. NDIS_STATUS status;
  1016. pAdapterContext->AsyncCloseResetStatus = NDIS_STATUS_PENDING;
  1017. NdisCloseAdapter(&status,
  1018. pAdapterContext->NdisBindingHandle
  1019. );
  1020. WaitAsyncOperation(&pAdapterContext->Event,
  1021. &(pAdapterContext->AsyncCloseResetStatus),
  1022. status);
  1023. pAdapterContext->NdisBindingHandle = NULL;
  1024. }
  1025. #endif // !NDIS40
  1026. //
  1027. // release the semaphore - any other threads can now get in and access
  1028. // pAdapters
  1029. //
  1030. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  1031. #ifdef NDIS40
  1032. ASSERT(newAdapter == FALSE);
  1033. #else // NDIS40
  1034. //
  1035. // if a newly allocated adapter context, release any resources allocated
  1036. //
  1037. if (newAdapter) {
  1038. if (pAdapterContext->hNdisPacketPool) {
  1039. //
  1040. // Free MDLs allocated for each NDIS packet.
  1041. //
  1042. while (pAdapterContext->pNdisPacketPool) {
  1043. PLLC_NDIS_PACKET pNdisPacket;
  1044. pNdisPacket = PopFromList(((PLLC_PACKET)pAdapterContext->pNdisPacketPool));
  1045. IoFreeMdl(pNdisPacket->pMdl);
  1046. NdisFreePacket((PNDIS_PACKET)pNdisPacket);
  1047. DBG_INTERLOCKED_DECREMENT(AllocatedMdlCount);
  1048. }
  1049. NdisFreePacketPool(pAdapterContext->hNdisPacketPool);
  1050. }
  1051. //
  1052. // DEBUG: refund memory charged for UNICODE buffer to driver string usage
  1053. //
  1054. if (initUnicodeString) {
  1055. FREE_STRING_DRIVER(pAdapterContext->Name.Buffer);
  1056. }
  1057. DELETE_PACKET_POOL_ADAPTER(&pAdapterContext->hLinkPool);
  1058. DELETE_PACKET_POOL_ADAPTER(&pAdapterContext->hPacketPool);
  1059. CHECK_MEMORY_RETURNED_ADAPTER();
  1060. CHECK_STRING_RETURNED_ADAPTER();
  1061. UNLINK_MEMORY_USAGE(pAdapterContext);
  1062. UNLINK_STRING_USAGE(pAdapterContext);
  1063. //
  1064. // free the adapter context
  1065. //
  1066. FREE_MEMORY_DRIVER(pAdapterContext);
  1067. }
  1068. #endif // !NDIS40
  1069. //
  1070. // free the binding context
  1071. //
  1072. FREE_MEMORY_FILE(pBindingContext);
  1073. //
  1074. // finally retake the spin lock and return the error status
  1075. //
  1076. ACQUIRE_DRIVER_LOCK();
  1077. return NdisStatus;
  1078. }
  1079. VOID
  1080. LlcNdisOpenAdapterComplete(
  1081. IN PVOID hAdapterContext,
  1082. IN NDIS_STATUS NdisStatus,
  1083. IN NDIS_STATUS OpenErrorStatus
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. The routine completes the adapter opening.
  1088. It only clears and sets the status flags, that are
  1089. polled by the BindToAdapter primitive.
  1090. Arguments:
  1091. hAdapterContext - describes adapter being opened
  1092. NdisStatus - the return status of NdisOpenAdapter
  1093. OpenErrorStatus - additional error info from NDIS
  1094. Return Value:
  1095. None.
  1096. --*/
  1097. {
  1098. ASSUME_IRQL(DISPATCH_LEVEL);
  1099. DEBUGMSG(DBG_NDIS_BIND,
  1100. (TEXT("LLcNdisOpenAdapterComplete(%#x, %#x, %#x)\n"),
  1101. hAdapterContext, NdisStatus, OpenErrorStatus));
  1102. //
  1103. // set the relevant fields in the adapter context
  1104. //
  1105. ((PADAPTER_CONTEXT)hAdapterContext)->AsyncOpenStatus = NdisStatus;
  1106. ((PADAPTER_CONTEXT)hAdapterContext)->OpenErrorStatus = OpenErrorStatus;
  1107. //
  1108. // signal the event that LlcOpenAdapter is waiting on
  1109. //
  1110. ASSUME_IRQL(ANY_IRQL);
  1111. KeSetEvent(&((PADAPTER_CONTEXT)hAdapterContext)->Event, 0L, FALSE);
  1112. }
  1113. VOID
  1114. LlcDisableAdapter(
  1115. IN PBINDING_CONTEXT pBindingContext
  1116. )
  1117. /*++
  1118. Routine Description:
  1119. The primitive disables all network indications on a data link binding.
  1120. This routine can be called from a llc indication handler.
  1121. Arguments:
  1122. pBindingContext - The context of the current adapter binding.
  1123. Return Value:
  1124. None.
  1125. --*/
  1126. {
  1127. PADAPTER_CONTEXT pAdapterContext;
  1128. ASSUME_IRQL(DISPATCH_LEVEL);
  1129. pAdapterContext = pBindingContext->pAdapterContext;
  1130. if (pAdapterContext) {
  1131. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1132. TerminateTimer(pAdapterContext, &pBindingContext->DlcTimer);
  1133. //
  1134. // RLF 04/27/94
  1135. //
  1136. // this is a slight hack: we zap the pointer to the timer tick structure
  1137. // so that if this is called again, TerminateTimer will see that the
  1138. // pointer to the timer tick is NULL and will return immediately. We
  1139. // shouldn't have to do this - we shouldn't poke around inside the
  1140. // timer 'object' - but this function can potentially be called from two
  1141. // places on the termination path - from DirCloseAdapter and now from
  1142. // CloseAdapterFileContext.
  1143. // We only do this for the DLC timer; if we did it for all timers - in
  1144. // TerminateTimer - DLC would break (scandalous, I know)
  1145. //
  1146. pBindingContext->DlcTimer.pTimerTick = NULL;
  1147. #ifdef LOCK_CHECK
  1148. pBindingContext->DlcTimer.Disabled = 0xd0bed0be; // do be do be do...
  1149. #endif
  1150. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1151. }
  1152. }
  1153. DLC_STATUS
  1154. LlcCloseAdapter(
  1155. IN PBINDING_CONTEXT pBindingContext,
  1156. IN BOOLEAN CloseAtNdisLevel
  1157. )
  1158. /*++
  1159. Routine Description:
  1160. remove a binding from an adapter. The binding context structure is unlinked
  1161. from the adapter context structure and the count of bindings to the adapter
  1162. context is decremented. The binding context structure is freed. If this is
  1163. the last binding to the adapter then close the adapter at NDIS level, unlink
  1164. the adapter context structure from the global adapter list and free the
  1165. memory used by the adapter context structure
  1166. Arguments:
  1167. pBindingContext - describes adapter to close
  1168. CloseAtNdisLevel - TRUE if we need to perform NdisCloseAdapter
  1169. Return Value:
  1170. DLC_STATUS
  1171. Success - STATUS_SUCCESS
  1172. Failure - All NDIS error status from NdisCloseAdapter
  1173. --*/
  1174. {
  1175. PADAPTER_CONTEXT pAdapterContext;
  1176. NDIS_STATUS NdisStatus = STATUS_SUCCESS;
  1177. KIRQL irql;
  1178. USHORT bindingCount;
  1179. #if DBG
  1180. PDLC_FILE_CONTEXT pFileContext = (PDLC_FILE_CONTEXT)(pBindingContext->hClientContext);
  1181. #endif
  1182. #ifdef LOCK_CHECK
  1183. PBINDING_CONTEXT p;
  1184. BOOLEAN found = FALSE;
  1185. DEBUGMSG(DBG_NDIS_OPEN, (TEXT("+LlcCloseAdapter(%#x, %#x)\n"),
  1186. pBindingContext, CloseAtNdisLevel));
  1187. #endif
  1188. ASSUME_IRQL(DISPATCH_LEVEL);
  1189. pAdapterContext = pBindingContext->pAdapterContext;
  1190. if (!pAdapterContext) {
  1191. #if DBG
  1192. DbgPrint("*** LlcCloseAdapter: NULL adapter context! ***\n");
  1193. DbgBreakPoint();
  1194. #endif
  1195. return STATUS_SUCCESS;
  1196. }
  1197. //
  1198. // we must wait on the OpenAdapterSemaphore. We need to do this because a
  1199. // thread in another process may be simultaneously generating a new binding
  1200. // to this adapter context - it mustn't be removed until we are certain
  1201. // there are no threads accessing this adapter context
  1202. //
  1203. RELEASE_DRIVER_LOCK();
  1204. ASSUME_IRQL(PASSIVE_LEVEL);
  1205. KeWaitForSingleObject((PVOID)&OpenAdapterSemaphore,
  1206. Executive,
  1207. KernelMode,
  1208. FALSE, // not alertable
  1209. NULL // wait until object is signalled
  1210. );
  1211. ACQUIRE_DRIVER_LOCK();
  1212. ASSUME_IRQL(DISPATCH_LEVEL);
  1213. ACQUIRE_LLC_LOCK(irql);
  1214. ACQUIRE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  1215. #ifdef LOCK_CHECK
  1216. for (p = pAdapterContext->pBindings; p; p = p->pNext) {
  1217. if (p == pBindingContext) {
  1218. found = TRUE;
  1219. break;
  1220. }
  1221. }
  1222. if (!found) {
  1223. DbgPrint("\n**** LlcCloseAdapter: can't find BC %x ****\n\n", pBindingContext);
  1224. DbgBreakPoint();
  1225. } else if (p->pNext == p) {
  1226. DbgPrint("\n**** LlcCloseAdapter: circular list ****\n\n");
  1227. DbgBreakPoint();
  1228. }
  1229. #endif
  1230. RemoveFromLinkList((PVOID*)&(pAdapterContext->pBindings), pBindingContext);
  1231. bindingCount = --pAdapterContext->BindingCount;
  1232. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  1233. #ifdef LOCK_CHECK
  1234. if (!pBindingContext->DlcTimer.Disabled) {
  1235. DbgPrint("LlcCloseAdapter: mashing active timer. bc=%x\n", pBindingContext);
  1236. DbgBreakPoint();
  1237. }
  1238. #endif
  1239. //
  1240. // RLF 08/20/94
  1241. //
  1242. // here we must kill any events on the adapter context that may access
  1243. // this binding context's event indication function pointer. If not, we
  1244. // can end up with a blue screen (hey! it happened)
  1245. //
  1246. PurgeLlcEventQueue(pBindingContext);
  1247. //
  1248. // DEBUG: refund memory charged for BINDING_CONTEXT to FILE_CONTEXT
  1249. //
  1250. FREE_MEMORY_FILE(pBindingContext);
  1251. #ifdef NDIS40
  1252. //
  1253. // For PnP, the ADAPTER_CONTEXT is not cleaned up nor the NdisBindingHandle
  1254. // closed when the last reference goes away. Instead this is controlled
  1255. // by the NDIS bind/unbind handlers.
  1256. //
  1257. RELEASE_LLC_LOCK(irql);
  1258. RELEASE_DRIVER_LOCK();
  1259. #else
  1260. if (!bindingCount) {
  1261. RemoveFromLinkList((PVOID*)&pAdapters, pAdapterContext);
  1262. //
  1263. // Now the adapter is isolated from any global connections.
  1264. // We may clear the global spin lock and free all resources
  1265. // allocated for the adapter context.
  1266. //
  1267. RELEASE_LLC_LOCK(irql);
  1268. RELEASE_DRIVER_LOCK();
  1269. ASSUME_IRQL(PASSIVE_LEVEL);
  1270. //
  1271. // Out of memory conditions the upper driver cannot properly
  1272. // wait until all pending NDIS packets have been sent.
  1273. // In that case we must poll here.
  1274. // (This should happen only if ExAllocatePool fails, but
  1275. // after an inproper shutdown we will loop here forever)
  1276. //
  1277. #if DBG
  1278. if (pAdapterContext->ObjectCount) {
  1279. DbgPrint("Waiting LLC objects to be closed ...\n");
  1280. }
  1281. #endif
  1282. while (pAdapterContext->ObjectCount) {
  1283. LlcSleep(1000L); // check the situation after 1 ms
  1284. }
  1285. //
  1286. // RLF 10/26/92
  1287. //
  1288. // we used to test pAdapterContext->NdisBindingHandle for NULL here,
  1289. // but that is an unreliable test since the NdisBindingHandle can be
  1290. // non-NULL even though the binding was not made. We now use the
  1291. // CloseAtNdisLevel parameter to indicate whether we should call the
  1292. // Ndis function to close the adapter
  1293. //
  1294. //
  1295. // MunilS 6/13/96
  1296. //
  1297. // Moved NdisFreePacketPool etc after NdisCloseAdapter to prevent
  1298. // bugcheck in NDIS while handling outstanding sends.
  1299. //
  1300. if (CloseAtNdisLevel)
  1301. {
  1302. pAdapterContext->AsyncCloseResetStatus = NDIS_STATUS_PENDING;
  1303. NdisCloseAdapter(&NdisStatus,
  1304. pAdapterContext->NdisBindingHandle
  1305. );
  1306. WaitAsyncOperation(&pAdapterContext->Event,
  1307. &(pAdapterContext->AsyncCloseResetStatus),
  1308. NdisStatus);
  1309. pAdapterContext->NdisBindingHandle = NULL;
  1310. }
  1311. if (pAdapterContext->hNdisPacketPool)
  1312. {
  1313. //
  1314. // Free MDLs allocated for each NDIS packet.
  1315. //
  1316. while (pAdapterContext->pNdisPacketPool) {
  1317. PLLC_NDIS_PACKET pNdisPacket;
  1318. pNdisPacket = PopFromList(((PLLC_PACKET)pAdapterContext->pNdisPacketPool));
  1319. IoFreeMdl(pNdisPacket->pMdl);
  1320. NdisFreePacket((PNDIS_PACKET)pNdisPacket);
  1321. DBG_INTERLOCKED_DECREMENT(AllocatedMdlCount);
  1322. }
  1323. NdisFreePacketPool(pAdapterContext->hNdisPacketPool);
  1324. }
  1325. //
  1326. // DEBUG: refund memory charged for UNICODE buffer to driver string usage
  1327. //
  1328. FREE_STRING_DRIVER(pAdapterContext->Name.Buffer);
  1329. DELETE_PACKET_POOL_ADAPTER(&pAdapterContext->hLinkPool);
  1330. DELETE_PACKET_POOL_ADAPTER(&pAdapterContext->hPacketPool);
  1331. CHECK_MEMORY_RETURNED_ADAPTER();
  1332. CHECK_STRING_RETURNED_ADAPTER();
  1333. UNLINK_MEMORY_USAGE(pAdapterContext);
  1334. UNLINK_STRING_USAGE(pAdapterContext);
  1335. FREE_MEMORY_DRIVER(pAdapterContext);
  1336. } else {
  1337. RELEASE_LLC_LOCK(irql);
  1338. RELEASE_DRIVER_LOCK();
  1339. }
  1340. #endif // !NDIS40
  1341. //
  1342. // now we can enable any other threads waiting on the open semaphore
  1343. //
  1344. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  1345. ACQUIRE_DRIVER_LOCK();
  1346. return NdisStatus;
  1347. }
  1348. DLC_STATUS
  1349. LlcResetBroadcastAddresses(
  1350. IN PBINDING_CONTEXT pBindingContext
  1351. )
  1352. /*++
  1353. Routine Description:
  1354. The primitive deletes the broadcast addresses used by the binding.
  1355. In the case of ethernet it updates multicast address list on
  1356. the adapter, that excludes any addresses set by this binding.
  1357. The last binding actually gives an empty list, that resets
  1358. all addresses set by this protocol binding.
  1359. Arguments:
  1360. pBindingContext - The context of the current adapter binding.
  1361. Return Value:
  1362. DLC_STATUS:
  1363. Success - STATUS_SUCCESS
  1364. Failure - All NDIS error status from NdisCloseAdapter
  1365. --*/
  1366. {
  1367. PADAPTER_CONTEXT pAdapterContext;
  1368. ASSUME_IRQL(DISPATCH_LEVEL);
  1369. pAdapterContext = pBindingContext->pAdapterContext;
  1370. if (pAdapterContext == NULL) {
  1371. return STATUS_SUCCESS;
  1372. }
  1373. //
  1374. // Reset the functional and group addresses of this binding context.
  1375. // In the case of ethernet, functional and group addresses of
  1376. // binding contexts are mapped to one global multicast list of
  1377. // this NDIS binding. Token-ring may have only one group
  1378. // address, that must be reset, when the application owning it
  1379. // is closing its dlc adapter context. Functional address
  1380. // must also set again in that case.
  1381. //
  1382. pBindingContext->Functional.ulAddress = 0;
  1383. UpdateFunctionalAddress(pAdapterContext);
  1384. if (pBindingContext->ulBroadcastAddress != 0) {
  1385. pBindingContext->ulBroadcastAddress = 0;
  1386. UpdateGroupAddress(pAdapterContext, pBindingContext);
  1387. }
  1388. return STATUS_SUCCESS;
  1389. }
  1390. NDIS_STATUS
  1391. InitNdisPackets(
  1392. OUT PLLC_NDIS_PACKET* ppLlcPacketPool,
  1393. IN NDIS_HANDLE hNdisPool
  1394. )
  1395. /*++
  1396. Routine Description:
  1397. The primitive copies Ndis packets from the NDIS pool to the
  1398. given internal packet pool.
  1399. Arguments:
  1400. ppLlcPacketPool - pointer to pointer to packet pool
  1401. hNdisPool - handle of NDIS packet pool
  1402. Return Value:
  1403. NDIS_STATUS
  1404. --*/
  1405. {
  1406. PLLC_NDIS_PACKET pNdisPacket;
  1407. NDIS_STATUS NdisStatus;
  1408. UINT i;
  1409. ASSUME_IRQL(PASSIVE_LEVEL);
  1410. for (i = 0; i < MAX_NDIS_PACKETS; i++) {
  1411. NdisAllocatePacket(&NdisStatus,
  1412. (PNDIS_PACKET*)&pNdisPacket,
  1413. hNdisPool
  1414. );
  1415. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  1416. return NdisStatus;
  1417. }
  1418. //
  1419. // Every NDIS packet includes a MDL, that has been
  1420. // initialized for the data buffer within the same
  1421. // structure. Thus data link driver does need to
  1422. // do any MDL calls during the runtime
  1423. //
  1424. pNdisPacket->pMdl = IoAllocateMdl(pNdisPacket->auchLanHeader,
  1425. sizeof(pNdisPacket->auchLanHeader),
  1426. FALSE,
  1427. FALSE,
  1428. NULL
  1429. );
  1430. if (pNdisPacket->pMdl == NULL) {
  1431. NdisFreePacket((PNDIS_PACKET) pNdisPacket);
  1432. return DLC_STATUS_NO_MEMORY;
  1433. }
  1434. DBG_INTERLOCKED_INCREMENT(AllocatedMdlCount);
  1435. MmBuildMdlForNonPagedPool(pNdisPacket->pMdl);
  1436. PushToList(((PLLC_PACKET)*ppLlcPacketPool),
  1437. ((PLLC_PACKET)pNdisPacket)
  1438. );
  1439. }
  1440. return NDIS_STATUS_SUCCESS;
  1441. }
  1442. VOID
  1443. LlcNdisCloseComplete(
  1444. IN PADAPTER_CONTEXT pAdapterContext,
  1445. IN NDIS_STATUS NdisStatus
  1446. )
  1447. /*++
  1448. Routine Description:
  1449. call-back from NDIS when the adapter close operation is completed
  1450. Arguments:
  1451. pAdapterContext - describes the adapter being closed
  1452. NdisStatus - the return status of NdisOpenAdapter
  1453. Return Value:
  1454. None
  1455. --*/
  1456. {
  1457. ASSUME_IRQL(ANY_IRQL);
  1458. ACQUIRE_DRIVER_LOCK();
  1459. ACQUIRE_LLC_LOCK(irql);
  1460. pAdapterContext->AsyncCloseResetStatus = NdisStatus;
  1461. RELEASE_LLC_LOCK(irql);
  1462. RELEASE_DRIVER_LOCK();
  1463. KeSetEvent(&pAdapterContext->Event, 0L, FALSE);
  1464. }
  1465. VOID
  1466. NdisStatusHandler(
  1467. IN PADAPTER_CONTEXT pAdapterContext,
  1468. IN NDIS_STATUS NdisStatus,
  1469. IN PVOID StatusBuffer,
  1470. IN UINT StatusBufferSize
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. indication handler for all NDIS status events
  1475. Arguments:
  1476. pAdapterContext - context of the NDIS adapter
  1477. NdisStatus - the major NDIS status code
  1478. StatusBuffer - A buffer holding more status information
  1479. StatusBufferSize - The length of StatusBuffer.
  1480. Return Value:
  1481. None.
  1482. --*/
  1483. {
  1484. PBINDING_CONTEXT pBinding;
  1485. PEVENT_PACKET pEvent;
  1486. KIRQL irql;
  1487. //
  1488. // seems that this handler can be called at PASSIVE_LEVEL too
  1489. //
  1490. ASSUME_IRQL(ANY_IRQL);
  1491. //
  1492. // We must synchronize the access to the binding list,
  1493. // the reference count will not allow the client
  1494. // to delete or modify the bindings list while
  1495. // we are routing the status indication to the
  1496. // clients.
  1497. //
  1498. ACQUIRE_DRIVER_LOCK();
  1499. ACQUIRE_LLC_LOCK(irql);
  1500. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1501. //
  1502. // The NDIS send process is stopped by the reset flag.
  1503. //
  1504. if (NdisStatus == NDIS_STATUS_RESET_START) {
  1505. pAdapterContext->ResetInProgress = TRUE;
  1506. } else if (NdisStatus == NDIS_STATUS_RESET_END) {
  1507. pAdapterContext->ResetInProgress = FALSE;
  1508. } else if (StatusBufferSize == sizeof(NTSTATUS)) {
  1509. //
  1510. // ADAMBA - Declare and assign SpecificStatus locally.
  1511. //
  1512. NTSTATUS SpecificStatus = *(PULONG)StatusBuffer;
  1513. if ( NdisStatus == NDIS_STATUS_RING_STATUS ) {
  1514. #if DBG
  1515. ASSERT (IS_NDIS_RING_STATUS(SpecificStatus));
  1516. #else // DBG
  1517. if (IS_NDIS_RING_STATUS(SpecificStatus))
  1518. #endif // DBG
  1519. {
  1520. SpecificStatus = NDIS_RING_STATUS_TO_DLC_RING_STATUS(SpecificStatus);
  1521. }
  1522. }
  1523. //
  1524. // These ndis status codes are indicated to all LLC
  1525. // protocol drivers, that have been bound to this adapter:
  1526. //
  1527. // NDIS_STATUS_ONLINE
  1528. // NDIS_STATUS_CLOSED
  1529. // NDIS_STATUS_RING_STATUS
  1530. //
  1531. for (pBinding = pAdapterContext->pBindings;
  1532. pBinding;
  1533. pBinding = pBinding->pNext) {
  1534. pEvent = ALLOCATE_PACKET_LLC_PKT(pAdapterContext->hPacketPool);
  1535. if (pEvent) {
  1536. pEvent->pBinding = pBinding;
  1537. pEvent->hClientHandle = NULL;
  1538. pEvent->Event = LLC_NETWORK_STATUS;
  1539. pEvent->pEventInformation = (PVOID)UlongToPtr(NdisStatus);
  1540. pEvent->SecondaryInfo = SpecificStatus;
  1541. LlcInsertTailList(&pAdapterContext->QueueEvents, pEvent);
  1542. }
  1543. }
  1544. }
  1545. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1546. RELEASE_LLC_LOCK(irql);
  1547. RELEASE_DRIVER_LOCK();
  1548. }
  1549. NDIS_STATUS
  1550. GetNdisParameter(
  1551. IN PADAPTER_CONTEXT pAdapterContext,
  1552. IN NDIS_OID NdisOid,
  1553. IN PVOID pDataBuffer,
  1554. IN UINT DataSize
  1555. )
  1556. /*++
  1557. Routine Description:
  1558. get parameter from NDIS using OID interface
  1559. Arguments:
  1560. pAdapterContext - describes adapter
  1561. NdisOid - indentifies the requested NDIS data
  1562. pDataBuffer - the buffer for the returned data
  1563. DataSize - size of pDataBuffer
  1564. Return Value:
  1565. NDIS_STATUS
  1566. --*/
  1567. {
  1568. LLC_NDIS_REQUEST Request;
  1569. ASSUME_IRQL(PASSIVE_LEVEL);
  1570. Request.Ndis.RequestType = NdisRequestQueryInformation;
  1571. Request.Ndis.DATA.QUERY_INFORMATION.Oid = NdisOid;
  1572. Request.Ndis.DATA.QUERY_INFORMATION.InformationBuffer = pDataBuffer;
  1573. Request.Ndis.DATA.QUERY_INFORMATION.InformationBufferLength = DataSize;
  1574. return SyncNdisRequest(pAdapterContext, &Request);
  1575. }
  1576. NDIS_STATUS
  1577. SetNdisParameter(
  1578. IN PADAPTER_CONTEXT pAdapterContext,
  1579. IN NDIS_OID NdisOid,
  1580. IN PVOID pRequestInfo,
  1581. IN UINT RequestLength
  1582. )
  1583. /*++
  1584. Routine Description:
  1585. set NDIS parameter using OID interface
  1586. Arguments:
  1587. pAdapterContext - describes adapter
  1588. NdisOid - describes info to set
  1589. pRequestInfo - pointer to info
  1590. RequestLength - size of info
  1591. Return Value:
  1592. NDIS_STATUS
  1593. --*/
  1594. {
  1595. LLC_NDIS_REQUEST Request;
  1596. ASSUME_IRQL(PASSIVE_LEVEL);
  1597. Request.Ndis.RequestType = NdisRequestSetInformation;
  1598. Request.Ndis.DATA.SET_INFORMATION.Oid = NdisOid;
  1599. Request.Ndis.DATA.SET_INFORMATION.InformationBuffer = pRequestInfo;
  1600. Request.Ndis.DATA.SET_INFORMATION.InformationBufferLength = RequestLength;
  1601. return SyncNdisRequest(pAdapterContext, &Request);
  1602. }
  1603. DLC_STATUS
  1604. SyncNdisRequest(
  1605. IN PADAPTER_CONTEXT pAdapterContext,
  1606. IN PLLC_NDIS_REQUEST pRequest
  1607. )
  1608. /*++
  1609. Routine Description:
  1610. Perform an NDIS request synchronously, even if the actual request would
  1611. be asynchronous
  1612. Arguments:
  1613. pAdapterContext - pointer to adapter context
  1614. pRequest - pointer to NDIS request structure
  1615. Return Value:
  1616. DLC_STATUS
  1617. --*/
  1618. {
  1619. DLC_STATUS Status;
  1620. ASSUME_IRQL(PASSIVE_LEVEL);
  1621. KeInitializeEvent(&pRequest->SyncEvent, NotificationEvent, FALSE);
  1622. #ifdef NDIS40
  1623. REFADD(&pAdapterContext->AdapterRefCnt, 'tqeR');
  1624. if (InterlockedCompareExchange(
  1625. &pAdapterContext->BindState,
  1626. BIND_STATE_BOUND,
  1627. BIND_STATE_BOUND) != BIND_STATE_BOUND)
  1628. {
  1629. REFDEL(&pAdapterContext->AdapterRefCnt, 'tqeR');
  1630. return (NDIS_STATUS_ADAPTER_NOT_OPEN);
  1631. }
  1632. // Above reference is removed by WaitAsyncOperation.
  1633. #endif // NDIS40
  1634. pRequest->AsyncStatus = NDIS_STATUS_PENDING;
  1635. NdisRequest((PNDIS_STATUS)&Status, pAdapterContext->NdisBindingHandle, &pRequest->Ndis);
  1636. Status = (DLC_STATUS)WaitAsyncOperation(&pRequest->SyncEvent,
  1637. &(pRequest->AsyncStatus),
  1638. Status);
  1639. #ifdef NDIS40
  1640. REFDEL(&pAdapterContext->AdapterRefCnt, 'tqeR');
  1641. #endif // NDIS40
  1642. return (Status);
  1643. }
  1644. NDIS_STATUS
  1645. WaitAsyncOperation(
  1646. IN PKEVENT pEvent,
  1647. IN PNDIS_STATUS pAsyncStatus,
  1648. IN NDIS_STATUS NdisStatus
  1649. )
  1650. /*++
  1651. Routine Description:
  1652. Wait for an asynchronous NDIS operation to complete
  1653. Arguments:
  1654. pAsyncStatus - pointer to status returned from NDIS
  1655. NdisStatus - status to wait for. Should be NDIS_STATUS_PENDING
  1656. Return Value:
  1657. NDIS_STATUS
  1658. --*/
  1659. {
  1660. NDIS_STATUS AsyncStatus;
  1661. ASSUME_IRQL(PASSIVE_LEVEL);
  1662. //
  1663. // Check if we got a synchronous status
  1664. //
  1665. if (NdisStatus != NDIS_STATUS_PENDING) {
  1666. AsyncStatus = NdisStatus;
  1667. }
  1668. else{
  1669. //
  1670. // Wait until the async status flag has been set
  1671. //
  1672. for ( ; ; ) {
  1673. KIRQL irql;
  1674. NTSTATUS ntstatus;
  1675. do {
  1676. ntstatus = KeWaitForSingleObject(pEvent,
  1677. Executive,
  1678. KernelMode,
  1679. TRUE, // alertable
  1680. (PLARGE_INTEGER)NULL
  1681. );
  1682. } while (ntstatus == STATUS_ALERTED);
  1683. //
  1684. // The result may be undefined, if we read it in a wrong time.
  1685. // Do it interlocked.
  1686. //
  1687. ACQUIRE_DRIVER_LOCK();
  1688. ACQUIRE_LLC_LOCK(irql);
  1689. AsyncStatus = *pAsyncStatus;
  1690. RELEASE_LLC_LOCK(irql);
  1691. RELEASE_DRIVER_LOCK();
  1692. if (AsyncStatus != NDIS_STATUS_PENDING) {
  1693. break;
  1694. }
  1695. else{
  1696. KeClearEvent(pEvent);
  1697. }
  1698. }
  1699. KeClearEvent(pEvent);
  1700. }
  1701. return AsyncStatus;
  1702. }
  1703. DLC_STATUS
  1704. LlcNdisRequest(
  1705. IN PVOID hBindingContext,
  1706. IN PLLC_NDIS_REQUEST pDlcParms
  1707. )
  1708. /*++
  1709. Routine Description:
  1710. makes an NDIS request
  1711. Arguments:
  1712. hBindingContext - pointer to binding context
  1713. pDlcParms - pointer to request-specific parameters
  1714. Return Value:
  1715. DLC_STATUS
  1716. --*/
  1717. {
  1718. return SyncNdisRequest(((PBINDING_CONTEXT)hBindingContext)->pAdapterContext,
  1719. pDlcParms
  1720. );
  1721. }
  1722. VOID
  1723. LlcNdisRequestComplete(
  1724. IN PADAPTER_CONTEXT pAdapterContext,
  1725. IN PNDIS_REQUEST RequestHandle,
  1726. IN NDIS_STATUS NdisStatus
  1727. )
  1728. /*++
  1729. Routine Description:
  1730. receives control when an aync NDIS command completes
  1731. Arguments:
  1732. pAdapterContext - pointer to ADAPTER_CONTEXT for which request was made
  1733. RequestHandle - handle of request
  1734. NdisStatus - returned status from NDIS
  1735. Return Value:
  1736. None.
  1737. --*/
  1738. {
  1739. KIRQL irql;
  1740. PLLC_NDIS_REQUEST pLlcNdisRequest =
  1741. CONTAINING_RECORD ( RequestHandle, LLC_NDIS_REQUEST, Ndis );
  1742. UNREFERENCED_PARAMETER(pAdapterContext);
  1743. ASSUME_IRQL(ANY_IRQL);
  1744. ACQUIRE_DRIVER_LOCK();
  1745. ACQUIRE_LLC_LOCK(irql);
  1746. pLlcNdisRequest->AsyncStatus = NdisStatus;
  1747. RELEASE_LLC_LOCK(irql);
  1748. RELEASE_DRIVER_LOCK();
  1749. KeSetEvent(&pLlcNdisRequest->SyncEvent, 0L, FALSE);
  1750. }
  1751. VOID
  1752. LlcNdisReset(
  1753. IN PBINDING_CONTEXT pBindingContext,
  1754. IN PLLC_PACKET pPacket
  1755. )
  1756. /*++
  1757. Routine Description:
  1758. The routine issues a hardware reset command for a network adapter.
  1759. Arguments:
  1760. pBindingContext - context of protocol module bound to the data link
  1761. pPacket - command packet
  1762. Return Value:
  1763. None.
  1764. --*/
  1765. {
  1766. PADAPTER_CONTEXT pAdapterContext = pBindingContext->pAdapterContext;
  1767. BOOLEAN ResetIt;
  1768. NDIS_STATUS Status;
  1769. ASSUME_IRQL(DISPATCH_LEVEL);
  1770. pPacket->pBinding = pBindingContext;
  1771. pPacket->Data.Completion.CompletedCommand = LLC_RESET_COMPLETION;
  1772. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1773. ResetIt = FALSE;
  1774. if (pAdapterContext->pResetPackets != NULL) {
  1775. ResetIt = TRUE;
  1776. }
  1777. pPacket->pNext = pAdapterContext->pResetPackets;
  1778. pAdapterContext->pResetPackets = pPacket;
  1779. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1780. //
  1781. // We don't reset NDIS, if there is already a pending reset command
  1782. //
  1783. RELEASE_DRIVER_LOCK();
  1784. if (ResetIt) {
  1785. NdisReset(&Status, pAdapterContext->NdisBindingHandle);
  1786. }
  1787. if (Status != STATUS_PENDING) {
  1788. LlcNdisResetComplete(pAdapterContext, Status);
  1789. }
  1790. //
  1791. // Note: we will return always a pending status =>
  1792. // multiple protocols may issue simultaneous reset
  1793. // and complete it normally.
  1794. //
  1795. ACQUIRE_DRIVER_LOCK();
  1796. }
  1797. VOID
  1798. LlcNdisResetComplete(
  1799. PADAPTER_CONTEXT pAdapterContext,
  1800. NDIS_STATUS NdisStatus
  1801. )
  1802. /*++
  1803. Routine Description:
  1804. The routine is called when a hard reset command is complete.
  1805. Arguments:
  1806. pAdapterContext - describes adapter being reset
  1807. NdisStatus - result of adapter reset operation from NDIS
  1808. Return Value:
  1809. None.
  1810. --*/
  1811. {
  1812. PLLC_PACKET pPacket;
  1813. //
  1814. // this function can be called from an NDIS DPC or from LlcNdisReset (above)
  1815. //
  1816. ASSUME_IRQL(ANY_IRQL);
  1817. ACQUIRE_DRIVER_LOCK();
  1818. //
  1819. // Indicate the completed reset command completion to all
  1820. // protocols, that had a pending reset command.
  1821. //
  1822. for (;;) {
  1823. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1824. pPacket = pAdapterContext->pResetPackets;
  1825. if (pPacket != NULL) {
  1826. pAdapterContext->pResetPackets = pPacket->pNext;
  1827. }
  1828. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1829. if (pPacket == NULL) {
  1830. break;
  1831. } else {
  1832. pPacket->Data.Completion.Status = NdisStatus;
  1833. pPacket->pBinding->pfCommandComplete(pPacket->pBinding->hClientContext,
  1834. NULL,
  1835. pPacket
  1836. );
  1837. }
  1838. }
  1839. RELEASE_DRIVER_LOCK();
  1840. }
  1841. BOOLEAN
  1842. UnicodeStringCompare(
  1843. IN PUNICODE_STRING String1,
  1844. IN PUNICODE_STRING String2
  1845. )
  1846. /*++
  1847. Routine Description:
  1848. Compare 2 unicode strings. Difference between this and RtlEqualUnicodeString
  1849. is that this is callable from within spinlocks (i.e. non-pageable)
  1850. Arguments:
  1851. String1 - pointer to UNICODE_STRING 1
  1852. String2 - pointer to UNICODE_STRING 2
  1853. Return Value:
  1854. BOOLEAN
  1855. TRUE - String1 == String2
  1856. FALSE - String1 != String2
  1857. --*/
  1858. {
  1859. if (String1->Length == String2->Length) {
  1860. USHORT numChars = String1->Length / sizeof(*String1->Buffer);
  1861. PWSTR buf1 = String1->Buffer;
  1862. PWSTR buf2 = String2->Buffer;
  1863. while (numChars) {
  1864. if (*buf1++ == *buf2++) {
  1865. --numChars;
  1866. } else {
  1867. return FALSE;
  1868. }
  1869. }
  1870. return TRUE;
  1871. }
  1872. return FALSE;
  1873. }
  1874. VOID
  1875. PurgeLlcEventQueue(
  1876. IN PBINDING_CONTEXT pBindingContext
  1877. )
  1878. /*++
  1879. Routine Description:
  1880. If there are any outstanding events on the adapter context waiting to be
  1881. indicated to the client of the current binding, they are removed
  1882. Arguments:
  1883. pBindingContext - pointer to BINDING_CONTEXT about to be deleted
  1884. Return Value:
  1885. None.
  1886. --*/
  1887. {
  1888. PADAPTER_CONTEXT pAdapterContext = pBindingContext->pAdapterContext;
  1889. ASSUME_IRQL(DISPATCH_LEVEL);
  1890. if (!IsListEmpty(&pAdapterContext->QueueEvents)) {
  1891. PEVENT_PACKET pEventPacket;
  1892. PEVENT_PACKET nextEventPacket;
  1893. for (pEventPacket = (PEVENT_PACKET)pAdapterContext->QueueEvents.Flink;
  1894. pEventPacket != (PEVENT_PACKET)&pAdapterContext->QueueEvents;
  1895. pEventPacket = nextEventPacket) {
  1896. nextEventPacket = pEventPacket->pNext;
  1897. if (pEventPacket->pBinding == pBindingContext) {
  1898. RemoveEntryList((PLIST_ENTRY)&pEventPacket->pNext);
  1899. #if DBG
  1900. DbgPrint("PurgeLlcEventQueue: BC=%x PKT=%x\n", pBindingContext, pEventPacket);
  1901. #endif
  1902. DEALLOCATE_PACKET_LLC_PKT(pAdapterContext->hPacketPool, pEventPacket);
  1903. }
  1904. }
  1905. }
  1906. }
  1907. #ifdef NDIS40
  1908. PADAPTER_CONTEXT
  1909. AllocateAdapterContext(
  1910. PNDIS_STRING pAdapterName
  1911. )
  1912. {
  1913. PADAPTER_CONTEXT pAdapterContext;
  1914. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  1915. DEBUGMSG(DBG_NDIS_BIND,
  1916. (TEXT("+AllocateAdapterContext(%#x)\n"), pAdapterName));
  1917. pAdapterContext = (PADAPTER_CONTEXT) ALLOCATE_ZEROMEMORY_DRIVER(
  1918. sizeof(ADAPTER_CONTEXT));
  1919. if (pAdapterContext == NULL)
  1920. {
  1921. NdisStatus = NDIS_STATUS_RESOURCES;
  1922. goto done;
  1923. }
  1924. //
  1925. // New PnP structure members.
  1926. //
  1927. REFINIT(
  1928. &pAdapterContext->AdapterRefCnt,
  1929. pAdapterContext,
  1930. CloseAdapter,
  1931. 'tpdA');
  1932. KeInitializeEvent(&pAdapterContext->CloseAdapterEvent, NotificationEvent, FALSE);
  1933. pAdapterContext->BindState = BIND_STATE_UNBOUND;
  1934. #if DBG
  1935. //
  1936. // record who owns this memory usage structure and add it to the
  1937. // list of all memory usages created in the driver
  1938. //
  1939. pAdapterContext->MemoryUsage.Owner = (PVOID)pAdapterContext;
  1940. pAdapterContext->MemoryUsage.OwnerObjectId = AdapterContextObject;
  1941. pAdapterContext->StringUsage.Owner = (PVOID)pAdapterContext;
  1942. pAdapterContext->StringUsage.OwnerObjectId = AdapterContextObject;
  1943. LinkMemoryUsage(&pAdapterContext->MemoryUsage);
  1944. LinkMemoryUsage(&pAdapterContext->StringUsage);
  1945. #endif
  1946. //
  1947. // We must allocate all spinlocks immediately after the
  1948. // adapter context has been allocated, because
  1949. // they can also deallocated simultaneously.
  1950. //
  1951. ALLOCATE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1952. ALLOCATE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  1953. //
  1954. // allocate space for the adapter name string from non-paged pool
  1955. // and initialize the name in the adapter context structure
  1956. //
  1957. NdisStatus = LlcInitUnicodeString(
  1958. &pAdapterContext->Name,
  1959. pAdapterName);
  1960. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1961. {
  1962. goto done;
  1963. }
  1964. pAdapterContext->OpenCompleteStatus = NDIS_STATUS_PENDING;
  1965. //
  1966. // We must initialize the list heads before we open the adapter!!!
  1967. //
  1968. InitializeListHead(&pAdapterContext->QueueEvents);
  1969. InitializeListHead(&pAdapterContext->QueueCommands);
  1970. InitializeListHead(&pAdapterContext->NextSendTask);
  1971. pAdapterContext->OpenErrorStatus = NDIS_STATUS_PENDING;
  1972. KeInitializeEvent(&pAdapterContext->Event, NotificationEvent, FALSE);
  1973. done:
  1974. if (NdisStatus != NDIS_STATUS_SUCCESS &&
  1975. pAdapterContext)
  1976. {
  1977. FreeAdapterContext(pAdapterContext);
  1978. pAdapterContext = NULL;
  1979. }
  1980. DEBUGMSG(DBG_NDIS_BIND, (TEXT("-AllocateAdapterContext [%#x]\n"), NdisStatus));
  1981. return (pAdapterContext);
  1982. }
  1983. VOID
  1984. FreeAdapterContext(
  1985. PADAPTER_CONTEXT pAdapterContext
  1986. )
  1987. {
  1988. ASSERT(pAdapterContext);
  1989. DEBUGMSG(DBG_NDIS_BIND, (TEXT("+FreeAdapterContext(%#x)\n"), pAdapterContext));
  1990. if (pAdapterContext->hNdisPacketPool)
  1991. {
  1992. //
  1993. // Free MDLs for each NDIS packet.
  1994. //
  1995. while (pAdapterContext->pNdisPacketPool)
  1996. {
  1997. PLLC_NDIS_PACKET pNdisPacket;
  1998. pNdisPacket = PopFromList(((PLLC_PACKET)pAdapterContext->pNdisPacketPool));
  1999. IoFreeMdl(pNdisPacket->pMdl);
  2000. NdisFreePacket((PNDIS_PACKET)pNdisPacket);
  2001. DBG_INTERLOCKED_DECREMENT(AllocatedMdlCount);
  2002. }
  2003. NdisFreePacketPool(pAdapterContext->hNdisPacketPool);
  2004. }
  2005. if (pAdapterContext->Name.Buffer)
  2006. {
  2007. FREE_STRING_DRIVER(pAdapterContext->Name.Buffer);
  2008. }
  2009. if (pAdapterContext->hLinkPool)
  2010. {
  2011. DELETE_PACKET_POOL_ADAPTER(&pAdapterContext->hLinkPool);
  2012. }
  2013. if (pAdapterContext->hPacketPool)
  2014. {
  2015. DELETE_PACKET_POOL_ADAPTER(&pAdapterContext->hPacketPool);
  2016. }
  2017. CHECK_MEMORY_RETURNED_ADAPTER();
  2018. CHECK_STRING_RETURNED_ADAPTER();
  2019. UNLINK_MEMORY_USAGE(pAdapterContext);
  2020. UNLINK_STRING_USAGE(pAdapterContext);
  2021. FREE_MEMORY_DRIVER(pAdapterContext);
  2022. DEBUGMSG(DBG_NDIS_BIND, (TEXT("-FreeAdapterContext\n")));
  2023. return;
  2024. }
  2025. NDIS_STATUS
  2026. OpenAdapter(
  2027. PADAPTER_CONTEXT pAdapterContext,
  2028. BOOLEAN fFirstOpen
  2029. )
  2030. /*++
  2031. Routine Description:
  2032. Arguments:
  2033. pAdapterContext - Context describing the adapter to open.
  2034. fFirstOpen - On first time opening the adapter, need to configure some
  2035. ADAPTER_CONTEXT data members.
  2036. Return Value:
  2037. NDIS_STATUS_SUCCESS - Successfully opened the adapter and configured.
  2038. --*/
  2039. {
  2040. NDIS_STATUS NdisStatus;
  2041. NTSTATUS NtStatus;
  2042. UINT MediumIndex;
  2043. LONG BindState;
  2044. LLC_NDIS_REQUEST Request;
  2045. DEBUGMSG(DBG_NDIS_BIND, (TEXT("OpenAdapter(%#x) %ws\n"),
  2046. pAdapterContext,
  2047. pAdapterContext->Name.Buffer)); // This buffer is null terminated.
  2048. KeClearEvent(&pAdapterContext->Event);
  2049. pAdapterContext->OpenErrorStatus = NDIS_STATUS_PENDING;
  2050. // Initialize the event for the request.
  2051. KeInitializeEvent(&Request.SyncEvent, NotificationEvent, FALSE);
  2052. NdisOpenAdapter(
  2053. &NdisStatus,
  2054. &pAdapterContext->OpenErrorStatus,
  2055. &pAdapterContext->NdisBindingHandle,
  2056. &MediumIndex,
  2057. (PNDIS_MEDIUM)&LlcMediumArray[0],
  2058. sizeof(LlcMediumArray),
  2059. (NDIS_HANDLE) LlcProtocolHandle,
  2060. (NDIS_HANDLE) pAdapterContext,
  2061. &pAdapterContext->Name,
  2062. NDIS_OPEN_RECEIVE_NOT_REENTRANT,
  2063. NULL); // No addressing info.
  2064. if (NdisStatus == NDIS_STATUS_PENDING)
  2065. {
  2066. ASSUME_IRQL(PASSIVE_LEVEL);
  2067. DEBUGMSG(DBG_NDIS_BIND, (TEXT("OpenAdapter - NdisOpenAdapter pending.\n")));
  2068. do
  2069. {
  2070. NtStatus = KeWaitForSingleObject(
  2071. &pAdapterContext->Event,
  2072. Executive,
  2073. KernelMode,
  2074. TRUE, // Alertable.
  2075. (PLARGE_INTEGER) NULL);
  2076. }
  2077. while (NtStatus == STATUS_ALERTED);
  2078. //
  2079. // Get the open return status.
  2080. //
  2081. NdisStatus = pAdapterContext->AsyncOpenStatus;
  2082. KeResetEvent(&pAdapterContext->Event);
  2083. }
  2084. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2085. {
  2086. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - NdisOpenAdapter failure.\n")));
  2087. pAdapterContext->NdisBindingHandle = NULL;
  2088. goto done;
  2089. }
  2090. //
  2091. // Reference count the NDIS binding handle.
  2092. //
  2093. REFADD(&pAdapterContext->AdapterRefCnt, 'dniB');
  2094. //
  2095. // On the first time opening adapter, we need to initialize some members
  2096. // of the ADAPTER_CONTEXT.
  2097. //
  2098. if (fFirstOpen == TRUE)
  2099. {
  2100. pAdapterContext->NdisMedium = LlcMediumArray[MediumIndex];
  2101. DEBUGMSG(DBG_NDIS_BIND,
  2102. (TEXT("OpenAdapter - adapter %ws open, medium = %s (%d)\n"),
  2103. pAdapterContext->Name.Buffer,
  2104. pAdapterContext->NdisMedium == NdisMedium802_5 ? TEXT("802_5") :
  2105. pAdapterContext->NdisMedium == NdisMedium802_3 ? TEXT("802_3") :
  2106. pAdapterContext->NdisMedium == NdisMediumFddi ? TEXT("Fddi") :
  2107. TEXT("Unknown!!"),
  2108. pAdapterContext->NdisMedium));
  2109. //
  2110. // fill-in some medium-specific fields
  2111. //
  2112. switch (pAdapterContext->NdisMedium)
  2113. {
  2114. case NdisMedium802_5:
  2115. pAdapterContext->cbMaxFrameHeader = 32; // 6 + 6 + 2 + 18
  2116. //
  2117. // the top bit of the destination address signifies a broadcast
  2118. // frame. On Token Ring, the top bit is bit 7
  2119. //
  2120. pAdapterContext->IsBroadcast = 0x80;
  2121. //
  2122. // functional address starts C0-00-... The top 2 bytes are compared
  2123. // as a USHORT = 0x00C0
  2124. //
  2125. pAdapterContext->usHighFunctionalBits = 0x00C0;
  2126. pAdapterContext->AddressTranslationMode = LLC_SEND_802_5_TO_802_5;
  2127. break;
  2128. case NdisMedium802_3:
  2129. pAdapterContext->cbMaxFrameHeader = 14; // 6 + 6 + 2
  2130. //
  2131. // the top bit of the destination address signifies a broadcast
  2132. // frame. On Ethernet, the top bit is bit 0
  2133. //
  2134. pAdapterContext->IsBroadcast = 0x01;
  2135. //
  2136. // functional address starts 03-00-... The top 2 bytes are compared as
  2137. // a USHORT = 0x0003
  2138. //
  2139. pAdapterContext->usHighFunctionalBits = 0x0003;
  2140. pAdapterContext->AddressTranslationMode = LLC_SEND_802_3_TO_802_3;
  2141. break;
  2142. case NdisMediumFddi:
  2143. pAdapterContext->cbMaxFrameHeader = 13; // 1 + 6 + 6
  2144. //
  2145. // bits are in same order as for ethernet
  2146. //
  2147. pAdapterContext->IsBroadcast = 0x01;
  2148. pAdapterContext->usHighFunctionalBits = 0x0003;
  2149. pAdapterContext->AddressTranslationMode = LLC_SEND_FDDI_TO_FDDI;
  2150. break;
  2151. }
  2152. //
  2153. // allocate the ndis packets. The NDIS packet must have space
  2154. // for the maximum number frame header and the maximum LLC response
  2155. // and its information field (quite small)
  2156. //
  2157. NdisAllocatePacketPool(
  2158. &NdisStatus,
  2159. &pAdapterContext->hNdisPacketPool,
  2160. MAX_NDIS_PACKETS + 1,
  2161. sizeof(LLC_NDIS_PACKET) - sizeof(NDIS_MAC_PACKET));
  2162. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2163. {
  2164. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - NdisAllocatePacketPool failure.\n")));
  2165. goto done;
  2166. }
  2167. NdisStatus = InitNdisPackets(
  2168. &pAdapterContext->pNdisPacketPool,
  2169. pAdapterContext->hNdisPacketPool);
  2170. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2171. {
  2172. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - InitNdisPackets failure.\n")));
  2173. goto done;
  2174. }
  2175. //
  2176. // Initialize the LLC packet pool
  2177. //
  2178. pAdapterContext->hPacketPool = CREATE_PACKET_POOL_ADAPTER(
  2179. LlcPacketPoolObject,
  2180. sizeof(UNITED_PACKETS),
  2181. 8);
  2182. if (pAdapterContext->hPacketPool == NULL)
  2183. {
  2184. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - CREATE_PACKET_POOL_ADAPTER hPacketPool failure.\n")));
  2185. NdisStatus = NDIS_STATUS_RESOURCES;
  2186. goto done;
  2187. }
  2188. pAdapterContext->hLinkPool = CREATE_PACKET_POOL_ADAPTER(
  2189. LlcLinkPoolObject,
  2190. pAdapterContext->cbMaxFrameHeader + sizeof(DATA_LINK),
  2191. 2);
  2192. if (pAdapterContext->hLinkPool == NULL)
  2193. {
  2194. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - CREATE_PACKET_POOL_ADAPTER hLinkPool failure.\n")));
  2195. NdisStatus = NDIS_STATUS_RESOURCES;
  2196. goto done;
  2197. }
  2198. //
  2199. // Read the current node address and maximum frame size
  2200. //
  2201. // Can't use GetNdisParameter since it checks to see if adapter is bound,
  2202. // which is isn't since we don't want anyone to use it until we are done
  2203. // initialization.
  2204. Request.Ndis.RequestType = NdisRequestQueryInformation;
  2205. Request.Ndis.DATA.QUERY_INFORMATION.Oid =
  2206. (pAdapterContext->NdisMedium == NdisMedium802_3) ? OID_802_3_CURRENT_ADDRESS :
  2207. (pAdapterContext->NdisMedium == NdisMediumFddi) ? OID_FDDI_LONG_CURRENT_ADDR :
  2208. OID_802_5_CURRENT_ADDRESS;
  2209. Request.Ndis.DATA.QUERY_INFORMATION.InformationBuffer = pAdapterContext->NodeAddress;
  2210. Request.Ndis.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(pAdapterContext->NodeAddress);;
  2211. Request.AsyncStatus = NDIS_STATUS_PENDING;
  2212. NdisRequest(&NdisStatus, pAdapterContext->NdisBindingHandle, &Request.Ndis);
  2213. NdisStatus = WaitAsyncOperation(
  2214. &Request.SyncEvent,
  2215. &Request.AsyncStatus,
  2216. NdisStatus);
  2217. // NdisStatus = GetNdisParameter(
  2218. // pAdapterContext,
  2219. // (pAdapterContext->NdisMedium == NdisMedium802_3) ? OID_802_3_CURRENT_ADDRESS :
  2220. // (pAdapterContext->NdisMedium == NdisMediumFddi) ? OID_FDDI_LONG_CURRENT_ADDR :
  2221. // OID_802_5_CURRENT_ADDRESS,
  2222. // pAdapterContext->NodeAddress,
  2223. // sizeof(pAdapterContext->NodeAddress));
  2224. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2225. {
  2226. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - GetNdisParm CURR_ADDRESS failure %#x.\n"),
  2227. NdisStatus));
  2228. goto done;
  2229. }
  2230. Request.Ndis.RequestType = NdisRequestQueryInformation;
  2231. Request.Ndis.DATA.QUERY_INFORMATION.Oid =
  2232. (pAdapterContext->NdisMedium == NdisMedium802_3) ? OID_802_3_PERMANENT_ADDRESS :
  2233. (pAdapterContext->NdisMedium == NdisMediumFddi) ? OID_FDDI_LONG_PERMANENT_ADDR :
  2234. OID_802_5_PERMANENT_ADDRESS;
  2235. Request.Ndis.DATA.QUERY_INFORMATION.InformationBuffer = pAdapterContext->PermanentAddress;
  2236. Request.Ndis.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(pAdapterContext->PermanentAddress);;
  2237. Request.AsyncStatus = NDIS_STATUS_PENDING;
  2238. NdisRequest(&NdisStatus, pAdapterContext->NdisBindingHandle, &Request.Ndis);
  2239. NdisStatus = WaitAsyncOperation(
  2240. &Request.SyncEvent,
  2241. &Request.AsyncStatus,
  2242. NdisStatus);
  2243. // NdisStatus = GetNdisParameter(
  2244. // pAdapterContext,
  2245. // (pAdapterContext->NdisMedium == NdisMedium802_3) ? OID_802_3_PERMANENT_ADDRESS :
  2246. // (pAdapterContext->NdisMedium == NdisMediumFddi) ? OID_FDDI_LONG_PERMANENT_ADDR :
  2247. // OID_802_5_PERMANENT_ADDRESS,
  2248. // pAdapterContext->PermanentAddress,
  2249. // sizeof(pAdapterContext->PermanentAddress));
  2250. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2251. {
  2252. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - GetNdisParm PERM_ADDRESS failure.\n")));
  2253. goto done;
  2254. }
  2255. {
  2256. //
  2257. // Mod RLF 07/10/92
  2258. //
  2259. // apparently, TR adapter does not support NDIS_PACKET_TYPE_MULTICAST
  2260. // as a filter. Up to now, it seems to have been reasonably happy
  2261. // with this type. However, we're not going to include it from now on
  2262. //
  2263. //
  2264. // Mod RLF 01/13/93
  2265. //
  2266. // Similarly, Ethernet doesn't support FUNCTIONAL addresses (Token
  2267. // Ring's functional address is equivalent to Ethernet's multicast
  2268. // address)
  2269. //
  2270. ULONG PacketFilter =
  2271. NDIS_PACKET_TYPE_DIRECTED |
  2272. NDIS_PACKET_TYPE_BROADCAST |
  2273. (((pAdapterContext->NdisMedium == NdisMedium802_3) || (pAdapterContext->NdisMedium == NdisMediumFddi))
  2274. ? NDIS_PACKET_TYPE_MULTICAST
  2275. : NDIS_PACKET_TYPE_FUNCTIONAL);
  2276. //
  2277. // EndMod
  2278. //
  2279. Request.Ndis.RequestType = NdisRequestSetInformation;
  2280. Request.Ndis.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  2281. Request.Ndis.DATA.SET_INFORMATION.InformationBuffer = &PacketFilter;
  2282. Request.Ndis.DATA.SET_INFORMATION.InformationBufferLength = sizeof(PacketFilter);
  2283. Request.AsyncStatus = NDIS_STATUS_PENDING;
  2284. NdisRequest(&NdisStatus, pAdapterContext->NdisBindingHandle, &Request.Ndis);
  2285. NdisStatus = WaitAsyncOperation(
  2286. &Request.SyncEvent,
  2287. &Request.AsyncStatus,
  2288. NdisStatus);
  2289. // NdisStatus = SetNdisParameter(
  2290. // pAdapterContext,
  2291. // OID_GEN_CURRENT_PACKET_FILTER,
  2292. // &PacketFilter,
  2293. // sizeof(PacketFilter));
  2294. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2295. {
  2296. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - SetNdisParm PACKET_FILTER failure.\n")));
  2297. ASSERT(FALSE);
  2298. goto done;
  2299. }
  2300. }
  2301. LlcMemCpy(
  2302. pAdapterContext->Adapter.Node.auchAddress,
  2303. pAdapterContext->NodeAddress,
  2304. 6);
  2305. Request.Ndis.RequestType = NdisRequestQueryInformation;
  2306. Request.Ndis.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
  2307. Request.Ndis.DATA.QUERY_INFORMATION.InformationBuffer = &pAdapterContext->MaxFrameSize;
  2308. Request.Ndis.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(pAdapterContext->MaxFrameSize);
  2309. Request.AsyncStatus = NDIS_STATUS_PENDING;
  2310. NdisRequest(&NdisStatus, pAdapterContext->NdisBindingHandle, &Request.Ndis);
  2311. NdisStatus = WaitAsyncOperation(
  2312. &Request.SyncEvent,
  2313. &Request.AsyncStatus,
  2314. NdisStatus);
  2315. // NdisStatus = GetNdisParameter(
  2316. // pAdapterContext,
  2317. // OID_GEN_MAXIMUM_TOTAL_SIZE,
  2318. // &pAdapterContext->MaxFrameSize,
  2319. // sizeof(pAdapterContext->MaxFrameSize));
  2320. if (NdisStatus == STATUS_SUCCESS)
  2321. {
  2322. Request.Ndis.RequestType = NdisRequestQueryInformation;
  2323. Request.Ndis.DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
  2324. Request.Ndis.DATA.QUERY_INFORMATION.InformationBuffer = &pAdapterContext->LinkSpeed;
  2325. Request.Ndis.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(pAdapterContext->LinkSpeed);
  2326. Request.AsyncStatus = NDIS_STATUS_PENDING;
  2327. NdisRequest(&NdisStatus, pAdapterContext->NdisBindingHandle, &Request.Ndis);
  2328. NdisStatus = WaitAsyncOperation(
  2329. &Request.SyncEvent,
  2330. &Request.AsyncStatus,
  2331. NdisStatus);
  2332. // NdisStatus = GetNdisParameter(
  2333. // pAdapterContext,
  2334. // OID_GEN_LINK_SPEED,
  2335. // &pAdapterContext->LinkSpeed,
  2336. // sizeof(pAdapterContext->LinkSpeed));
  2337. }
  2338. if (NdisStatus != STATUS_SUCCESS)
  2339. {
  2340. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - GetNdisParm MAX_SIZE/LINK_SPEED failure.\n")));
  2341. goto done;
  2342. }
  2343. //
  2344. // RLF 04/12/93
  2345. //
  2346. // Here we used to load the LLC_TICKS array from TimerTicks - a global
  2347. // array of timer tick values.
  2348. // Instead, we get any per-adapter configuration information stored in
  2349. // the registry
  2350. //
  2351. LoadAdapterConfiguration(
  2352. &pAdapterContext->Name,
  2353. &pAdapterContext->ConfigInfo);
  2354. //
  2355. // RLF 04/02/94
  2356. //
  2357. // if this is not a Token Ring card then check the MaxFrameSize retrieved
  2358. // above. If the UseEthernetFrameSize parameter was set in the registry
  2359. // then we use the smaller of the ethernet size (1514) and the value
  2360. // reported by the MAC. If the parameter was not set then we just use
  2361. // the value already retrieved. If the card is Token Ring then we use
  2362. // the value already retrieved
  2363. //
  2364. if (pAdapterContext->NdisMedium != NdisMedium802_5 &&
  2365. pAdapterContext->ConfigInfo.UseEthernetFrameSize &&
  2366. pAdapterContext->MaxFrameSize > MAX_ETHERNET_FRAME_LENGTH)
  2367. {
  2368. pAdapterContext->MaxFrameSize = MAX_ETHERNET_FRAME_LENGTH;
  2369. }
  2370. pAdapterContext->QueueI.pObject = (PVOID)GetI_Packet;
  2371. InitializeListHead(&pAdapterContext->QueueI.ListHead);
  2372. pAdapterContext->QueueDirAndU.pObject = (PVOID)BuildDirOrU_Packet;
  2373. InitializeListHead(&pAdapterContext->QueueDirAndU.ListHead);
  2374. pAdapterContext->QueueExpidited.pObject = (PVOID)GetLlcCommandPacket;
  2375. InitializeListHead(&pAdapterContext->QueueExpidited.ListHead);
  2376. pAdapterContext->OpenCompleteStatus = STATUS_SUCCESS;
  2377. }
  2378. else
  2379. {
  2380. //
  2381. // Re-opening adapter. Don't really need to do much configuration.
  2382. // Need to set packet filter.
  2383. //
  2384. // Still should be same medium for the adapter.
  2385. ASSERT(pAdapterContext->NdisMedium == LlcMediumArray[MediumIndex]);
  2386. {
  2387. //
  2388. // Mod RLF 07/10/92
  2389. //
  2390. // apparently, TR adapter does not support NDIS_PACKET_TYPE_MULTICAST
  2391. // as a filter. Up to now, it seems to have been reasonably happy
  2392. // with this type. However, we're not going to include it from now on
  2393. //
  2394. //
  2395. // Mod RLF 01/13/93
  2396. //
  2397. // Similarly, Ethernet doesn't support FUNCTIONAL addresses (Token
  2398. // Ring's functional address is equivalent to Ethernet's multicast
  2399. // address)
  2400. //
  2401. ULONG PacketFilter =
  2402. NDIS_PACKET_TYPE_DIRECTED |
  2403. NDIS_PACKET_TYPE_BROADCAST |
  2404. (((pAdapterContext->NdisMedium == NdisMedium802_3) || (pAdapterContext->NdisMedium == NdisMediumFddi))
  2405. ? NDIS_PACKET_TYPE_MULTICAST
  2406. : NDIS_PACKET_TYPE_FUNCTIONAL);
  2407. //
  2408. // EndMod
  2409. //
  2410. Request.Ndis.RequestType = NdisRequestSetInformation;
  2411. Request.Ndis.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  2412. Request.Ndis.DATA.SET_INFORMATION.InformationBuffer = &PacketFilter;
  2413. Request.Ndis.DATA.SET_INFORMATION.InformationBufferLength = sizeof(PacketFilter);
  2414. Request.AsyncStatus = NDIS_STATUS_PENDING;
  2415. NdisRequest(&NdisStatus, pAdapterContext->NdisBindingHandle, &Request.Ndis);
  2416. NdisStatus = WaitAsyncOperation(
  2417. &Request.SyncEvent,
  2418. &Request.AsyncStatus,
  2419. NdisStatus);
  2420. // NdisStatus = SetNdisParameter(
  2421. // pAdapterContext,
  2422. // OID_GEN_CURRENT_PACKET_FILTER,
  2423. // &PacketFilter,
  2424. // sizeof(PacketFilter));
  2425. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2426. {
  2427. DEBUGMSG(DBG_ERROR, (TEXT("OpenAdapter - SetNdisParm PACKET_FILTER failure.\n")));
  2428. ASSERT(FALSE);
  2429. goto done;
  2430. }
  2431. }
  2432. }
  2433. //
  2434. // Adapter can now be used, so put state to bound. Sends and requests
  2435. // will fail if the state is not BIND_STATE_BOUND.
  2436. //
  2437. BindState = InterlockedExchange(&pAdapterContext->BindState, BIND_STATE_BOUND);
  2438. ASSERT(BindState == BIND_STATE_UNBOUND);
  2439. done:
  2440. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2441. {
  2442. if (pAdapterContext->NdisBindingHandle != NULL)
  2443. {
  2444. NDIS_STATUS CloseNdisStatus;
  2445. pAdapterContext->AsyncCloseResetStatus = NDIS_STATUS_PENDING;
  2446. NdisCloseAdapter(
  2447. &CloseNdisStatus,
  2448. pAdapterContext->NdisBindingHandle);
  2449. WaitAsyncOperation(
  2450. &pAdapterContext->Event,
  2451. &pAdapterContext->AsyncCloseResetStatus,
  2452. CloseNdisStatus);
  2453. pAdapterContext->NdisBindingHandle = NULL;
  2454. REFDEL(&pAdapterContext->AdapterRefCnt, 'dniB');
  2455. }
  2456. }
  2457. DEBUGMSG(DBG_NDIS_BIND, (TEXT("-OpenAdapter - Adapter %#x [%#x]\n"),
  2458. pAdapterContext, NdisStatus));
  2459. return (NdisStatus);
  2460. }
  2461. VOID
  2462. CloseAdapter(
  2463. PVOID pv_pAdapterContext
  2464. )
  2465. /*++
  2466. Routine Description:
  2467. This function is called when the reference count on the NdisBindingHandle
  2468. for the AdapterContext goes to zero. The CloseAdapterEvent is set to
  2469. indicate to the unbind handler that all references to the adapter are
  2470. removed and it can complete the unbind/close adapter.
  2471. Arguments:
  2472. pv_pAdapterContext - Context describing open adapter.
  2473. Return Value:
  2474. None.
  2475. --*/
  2476. {
  2477. PADAPTER_CONTEXT pAdapterContext = (PADAPTER_CONTEXT) pv_pAdapterContext;
  2478. KeSetEvent(&pAdapterContext->CloseAdapterEvent, 0L, FALSE);
  2479. }
  2480. VOID
  2481. LlcBindAdapterHandler(
  2482. OUT PNDIS_STATUS pStatus,
  2483. IN NDIS_HANDLE BindContext,
  2484. IN PNDIS_STRING pDeviceName,
  2485. IN PVOID SystemSpecific1,
  2486. IN PVOID SystemSpecific2
  2487. )
  2488. /*++
  2489. Routine Description:
  2490. Protocol bind adapter handler. This is called by NDIS to bind
  2491. to an adapter.
  2492. Arguments:
  2493. pStatus - The status to returned by this bind adapter call.
  2494. BindContext - Handle used when indicating completion using
  2495. NdisCompleteBindAdapter.
  2496. pDeviceName - Zero-terminated Unicode string with the name of the
  2497. underlying NIC to bind to.
  2498. SystemSpecific1 - Registry path used by NdisOpenProtocolConfiguration.
  2499. SystemSpecific2 - Reserved.
  2500. Return Value:
  2501. None.
  2502. Notes:
  2503. Runs at IRQL_PASSIVE_LEVEL.
  2504. This function creates an ADAPTER_CONTEXT, initializes it and opens the
  2505. adapter. This adapter is stored in a global adapter list so that DLC
  2506. can find and use the adapter context.
  2507. --*/
  2508. {
  2509. PADAPTER_CONTEXT pAdapterContext = NULL;
  2510. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  2511. BOOLEAN fNewAdapter = FALSE;
  2512. DEBUGMSG(DBG_NDIS_BIND,
  2513. (TEXT("+LlcBindAdapterHandler(%#x, %#x, %#x, %#x %#x)\n"),
  2514. pStatus, BindContext, pDeviceName,
  2515. SystemSpecific1, SystemSpecific2));
  2516. KeWaitForSingleObject((PVOID)&OpenAdapterSemaphore,
  2517. Executive,
  2518. KernelMode,
  2519. FALSE, // not alertable
  2520. NULL // wait until object is signalled
  2521. );
  2522. //
  2523. // Check for re-bind case.
  2524. //
  2525. for (pAdapterContext = pAdapters;
  2526. pAdapterContext != NULL;
  2527. pAdapterContext = pAdapterContext->pNext)
  2528. {
  2529. if (UnicodeStringCompare(pDeviceName, &pAdapterContext->Name))
  2530. {
  2531. // Found the adapter.
  2532. break;
  2533. }
  2534. }
  2535. if (pAdapterContext == NULL)
  2536. {
  2537. pAdapterContext = AllocateAdapterContext(pDeviceName);
  2538. if (pAdapterContext == NULL)
  2539. {
  2540. NdisStatus = NDIS_STATUS_RESOURCES;
  2541. goto done;
  2542. }
  2543. fNewAdapter = TRUE;
  2544. }
  2545. else
  2546. {
  2547. //
  2548. // ADAPTER_CONTEXT already exists. This must be the re-bind scenario.
  2549. //
  2550. ASSERT(pAdapterContext->BindState == BIND_STATE_UNBOUND);
  2551. }
  2552. //
  2553. // Open the NDIS adapter. OpenAdapter should not return pending.
  2554. //
  2555. NdisStatus = OpenAdapter(pAdapterContext, fNewAdapter);
  2556. ASSERT(NdisStatus != NDIS_STATUS_PENDING);
  2557. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2558. {
  2559. DEBUGMSG(DBG_ERROR, (TEXT("LlcBindAdapterHandler - OpenAdapter failure.\n")));
  2560. goto done;
  2561. }
  2562. //
  2563. // If we just created this adapter context, then put in global adapter
  2564. // list.
  2565. //
  2566. if (fNewAdapter == TRUE)
  2567. {
  2568. pAdapterContext->pNext = pAdapters;
  2569. pAdapters = pAdapterContext;
  2570. }
  2571. done:
  2572. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  2573. // All above requests were serialized.
  2574. ASSERT(NdisStatus != NDIS_STATUS_PENDING);
  2575. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2576. {
  2577. if (pAdapterContext && fNewAdapter == TRUE)
  2578. {
  2579. ASSERT(pAdapterContext->pNext == NULL);
  2580. FreeAdapterContext(pAdapterContext);
  2581. }
  2582. }
  2583. DEBUGMSG(DBG_NDIS_BIND, (TEXT("-LlcBindAdapter [%#x]\n"), NdisStatus));
  2584. *pStatus = NdisStatus;
  2585. return;
  2586. }
  2587. VOID
  2588. LlcUnbindAdapterHandler(
  2589. OUT PNDIS_STATUS pStatus,
  2590. IN NDIS_HANDLE ProtocolBindingContext,
  2591. IN NDIS_HANDLE UnbindContext
  2592. )
  2593. /*++
  2594. Routine Description:
  2595. This is called by NDIS to unbind an adapter.
  2596. Arguments:
  2597. pStatus - The status to be returned by this unbind adapter call.
  2598. ProtocolBindingContext - Protocol allocated binding context to the adapter
  2599. to unbind to.
  2600. UnbindContext - Handle used when indicating completion using
  2601. NdisCompleteUnbindAdapter.
  2602. Return Value:
  2603. None.
  2604. Notes:
  2605. Runs at IRQL_PASSIVE_LEVEL.
  2606. --*/
  2607. {
  2608. PADAPTER_CONTEXT pAdapterContext = (PADAPTER_CONTEXT) ProtocolBindingContext;
  2609. LONG BindState;
  2610. NDIS_STATUS NdisStatus;
  2611. DEBUGMSG(DBG_NDIS_BIND,
  2612. (TEXT("+LlcUnbindAdapterHandler(%#x, %#x, %#x)\n"),
  2613. pStatus, ProtocolBindingContext, UnbindContext));
  2614. KeWaitForSingleObject((PVOID)&OpenAdapterSemaphore,
  2615. Executive,
  2616. KernelMode,
  2617. FALSE, // not alertable
  2618. NULL // wait until object is signalled
  2619. );
  2620. //
  2621. // Update bind state.
  2622. //
  2623. BindState = InterlockedExchange(
  2624. &pAdapterContext->BindState,
  2625. BIND_STATE_UNBINDING);
  2626. ASSERT(BindState == BIND_STATE_BOUND);
  2627. //
  2628. // Remove the reference count that NDIS has on the adapter handle since we
  2629. // will close the adapter.
  2630. //
  2631. KeResetEvent(&pAdapterContext->CloseAdapterEvent);
  2632. REFDEL(&pAdapterContext->AdapterRefCnt, 'dniB');
  2633. //
  2634. // Wait until the reference goes to zero, then we are signalled. The above
  2635. // REFDEL would have signalled the event if this is the last reference.
  2636. //
  2637. KeWaitForSingleObject(
  2638. &pAdapterContext->CloseAdapterEvent,
  2639. Executive,
  2640. KernelMode,
  2641. FALSE,
  2642. NULL);
  2643. //
  2644. // Now we can safely close the NdisBindingHandle.
  2645. //
  2646. pAdapterContext->AsyncCloseResetStatus = NDIS_STATUS_PENDING;
  2647. ASSERT(pAdapterContext->NdisBindingHandle);
  2648. NdisCloseAdapter(
  2649. &NdisStatus,
  2650. pAdapterContext->NdisBindingHandle);
  2651. NdisStatus = WaitAsyncOperation(
  2652. &pAdapterContext->Event,
  2653. &(pAdapterContext->AsyncCloseResetStatus),
  2654. NdisStatus);
  2655. ASSERT(NdisStatus != NDIS_STATUS_PENDING);
  2656. pAdapterContext->NdisBindingHandle = NULL;
  2657. //
  2658. // Update state.
  2659. //
  2660. BindState = InterlockedExchange(
  2661. &pAdapterContext->BindState,
  2662. BIND_STATE_UNBOUND);
  2663. ASSERT(BindState == BIND_STATE_UNBINDING);
  2664. //
  2665. // Clean up and save status before completing.
  2666. //
  2667. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  2668. *pStatus = NdisStatus;
  2669. DEBUGMSG(DBG_NDIS_BIND, (TEXT("-LlcUnbindAdapterHandler [%#x]\n"), NdisStatus));
  2670. return;
  2671. }
  2672. NDIS_STATUS
  2673. LlcPnPEventHandler(
  2674. IN NDIS_HANDLE ProtocolBindingContext,
  2675. IN PNET_PNP_EVENT pNetPnPEvent
  2676. )
  2677. /*++
  2678. Routine Description:
  2679. PnP events indicated to the protocol. Currently, we are only interested
  2680. in the binds complete event.
  2681. Arguments:
  2682. ProtocolBindingContext - Protocol allocated binding context to the adapter.
  2683. This can be NULL for some events.
  2684. pNetPnPEvent - Describes PnP event.
  2685. Return Value:
  2686. NDIS_STATUS_SUCCESS - Always return success, even for those PnP events
  2687. which are not supported.
  2688. --*/
  2689. {
  2690. switch (pNetPnPEvent->NetEvent)
  2691. {
  2692. case NetEventBindsComplete:
  2693. //
  2694. // Block all LlcOpenAdapter requests until we are sure all adapters
  2695. // have been indicated to the protocol.
  2696. //
  2697. NdisSetEvent(&PnPBindsComplete);
  2698. break;
  2699. }
  2700. return (NDIS_STATUS_SUCCESS);
  2701. }
  2702. VOID
  2703. CloseAllAdapters(
  2704. )
  2705. /*++
  2706. Routine Description:
  2707. Closes all adapters. This should only be called from the unload
  2708. routine.
  2709. Arguments:
  2710. None.
  2711. Return Value:
  2712. None.
  2713. --*/
  2714. {
  2715. PADAPTER_CONTEXT pAdapterContext;
  2716. PADAPTER_CONTEXT pNextAdapter;
  2717. LONG BindState;
  2718. NDIS_STATUS NdisStatus;
  2719. DEBUGMSG(DBG_NDIS_OPEN, (TEXT("+CloseAllAdapters()\n")));
  2720. KeWaitForSingleObject((PVOID)&OpenAdapterSemaphore,
  2721. Executive,
  2722. KernelMode,
  2723. FALSE, // not alertable
  2724. NULL // wait until object is signalled
  2725. );
  2726. pAdapterContext = pAdapters;
  2727. while (pAdapterContext)
  2728. {
  2729. // Save next adapter since we are going to free memory.
  2730. pNextAdapter = pAdapterContext->pNext;
  2731. //
  2732. // Update bind state.
  2733. //
  2734. BindState = InterlockedExchange(
  2735. &pAdapterContext->BindState,
  2736. BIND_STATE_UNBINDING);
  2737. if (BindState == BIND_STATE_BOUND)
  2738. {
  2739. //
  2740. // Poll to see if any objects are still attached to adapter.
  2741. //
  2742. DEBUGMSG(DBG_WARN && pAdapterContext,
  2743. (TEXT("CloseAllAdapters - waiting for adapter LLC objects to close...\n")));
  2744. while (pAdapterContext->ObjectCount)
  2745. {
  2746. DEBUGMSG(DBG_WARN && DBG_VERBOSE,
  2747. (TEXT("CloseAllAdapters - still waiting...\n")));
  2748. LlcSleep(1000L); // 1ms
  2749. }
  2750. //
  2751. // Remove the reference count that NDIS has on the adapter handle since we
  2752. // will close the adapter.
  2753. //
  2754. KeResetEvent(&pAdapterContext->CloseAdapterEvent);
  2755. REFDEL(&pAdapterContext->AdapterRefCnt, 'dniB');
  2756. //
  2757. // Wait until the reference goes to zero, then we are signalled. The above
  2758. // REFDEL would have signalled the event if this is the last reference.
  2759. //
  2760. KeWaitForSingleObject(
  2761. &pAdapterContext->CloseAdapterEvent,
  2762. Executive,
  2763. KernelMode,
  2764. FALSE,
  2765. NULL);
  2766. //
  2767. // Now we can safely close the NdisBindingHandle.
  2768. //
  2769. pAdapterContext->AsyncCloseResetStatus = NDIS_STATUS_PENDING;
  2770. ASSERT(pAdapterContext->NdisBindingHandle);
  2771. NdisCloseAdapter(
  2772. &NdisStatus,
  2773. pAdapterContext->NdisBindingHandle);
  2774. NdisStatus = WaitAsyncOperation(
  2775. &pAdapterContext->Event,
  2776. &(pAdapterContext->AsyncCloseResetStatus),
  2777. NdisStatus);
  2778. ASSERT(NdisStatus != NDIS_STATUS_PENDING);
  2779. pAdapterContext->NdisBindingHandle = NULL;
  2780. //
  2781. // Update state.
  2782. //
  2783. BindState = InterlockedExchange(
  2784. &pAdapterContext->BindState,
  2785. BIND_STATE_UNBOUND);
  2786. ASSERT(BindState == BIND_STATE_UNBINDING);
  2787. }
  2788. // Remove adapter from the list.
  2789. RemoveFromLinkList((PVOID *)&pAdapters, pAdapterContext);
  2790. FreeAdapterContext(pAdapterContext);
  2791. // Adjust pointer.
  2792. pAdapterContext = pNextAdapter;
  2793. }
  2794. KeReleaseSemaphore(&OpenAdapterSemaphore, 0, 1, FALSE);
  2795. DEBUGMSG(DBG_NDIS_OPEN, (TEXT("-CloseAllAdapters\n")));
  2796. return;
  2797. }
  2798. #endif // NDIS40