Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1006 lines
26 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Copyright (c) 1991 Nokia Data Systems Ab
  4. Module Name:
  5. llcobj.c
  6. Abstract:
  7. The module implements the open and close primitives
  8. for all data link driver objects.
  9. Contents:
  10. LlcOpenStation
  11. LlcCloseStation
  12. CompleteClose
  13. CancelTransmitCommands
  14. CancelTransmitsInQueue
  15. LlcSetDirectOpenOptions
  16. CompleteObjectDelete
  17. CompletePendingLlcCommand
  18. LlcDereferenceObject
  19. LlcReferenceObject
  20. LlcGetReceivedLanHeaderLength
  21. LlcGetEthernetType
  22. LlcGetCommittedSpace
  23. Author:
  24. Antti Saarenheimo (o-anttis) 29-MAY-1991
  25. Revision History:
  26. --*/
  27. #if DBG
  28. #ifndef i386
  29. #define LLC_PRIVATE_PROTOTYPES
  30. #endif
  31. #include "dlc.h" // need DLC_FILE_CONTEXT for memory charged to file handle
  32. #endif
  33. #include <llc.h>
  34. static USHORT ObjectSizes[] = {
  35. sizeof(LLC_STATION_OBJECT), // direct station
  36. sizeof(LLC_SAP ), // SAP station
  37. sizeof(LLC_STATION_OBJECT), // group SAP
  38. (USHORT)(-1), // link station
  39. sizeof(LLC_STATION_OBJECT) // DIX station
  40. };
  41. DLC_STATUS
  42. LlcOpenStation(
  43. IN PBINDING_CONTEXT pBindingContext,
  44. IN PVOID hClientHandle,
  45. IN USHORT ObjectAddress,
  46. IN UCHAR ObjectType,
  47. IN USHORT OpenOptions,
  48. OUT PVOID* phStation
  49. )
  50. /*++
  51. Routine Description:
  52. The primitive opens a LLC SAP exclusively for the upper protocol
  53. driver. The upper protocol must provide the storage for the
  54. SAP object. The correct size of the object has been defined in the
  55. characteristics table of the LLC driver.
  56. The first call to a new adapter initializes also the NDIS interface
  57. and allocates internal data structures for the new adapter.
  58. Arguments:
  59. pBindingContext - binding context of the llc client
  60. hClientHandle - The client protocol gets this handle in all indications
  61. of the SAP
  62. ObjectAddress - LLC SAP number or dix
  63. ObjectType - type of the created object
  64. OpenOptions - various open options set for the new object
  65. phStation - returned opaque handle
  66. Special: Must be called IRQL < DPC (at least when direct station opened)
  67. Return Value:
  68. DLC_STATUS
  69. Success - STATUS_SUCCESS
  70. Failure - DLC_STATUS_NO_MEMORY
  71. DLC_STATUS_INVALID_SAP_VALUE
  72. DLC_STATUS_INVALID_OPTION
  73. DLC_STATUS_INVALID_STATION_ID
  74. --*/
  75. {
  76. PADAPTER_CONTEXT pAdapterContext;
  77. PLLC_OBJECT pStation;
  78. DLC_STATUS LlcStatus = STATUS_SUCCESS;
  79. PVOID* ppListBase;
  80. ULONG PacketFilter;
  81. #if DBG
  82. PDLC_FILE_CONTEXT pFileContext = (PDLC_FILE_CONTEXT)(pBindingContext->hClientContext);
  83. #endif
  84. pAdapterContext = pBindingContext->pAdapterContext;
  85. //
  86. // Allocate and initialize the SAP, but do not yet connect
  87. // it to the adapter
  88. //
  89. ASSERT(ObjectSizes[ObjectType] != (USHORT)(-1));
  90. pStation = (PLLC_OBJECT)ALLOCATE_ZEROMEMORY_FILE(ObjectSizes[ObjectType]);
  91. if (pStation == NULL) {
  92. return DLC_STATUS_NO_MEMORY;
  93. }
  94. if (ObjectType == LLC_SAP_OBJECT && (ObjectAddress & 1)) {
  95. ObjectType = LLC_GROUP_SAP_OBJECT;
  96. ASSERT(phStation);
  97. }
  98. pStation->Gen.hClientHandle = hClientHandle;
  99. pStation->Gen.pLlcBinding = pBindingContext;
  100. pStation->Gen.pAdapterContext = pAdapterContext;
  101. pStation->Gen.ObjectType = (UCHAR)ObjectType;
  102. //
  103. // The LLC objects must be referenced whenever they should be kept alive
  104. // over a long operation, that opens the spin locks (especially async
  105. // operations)
  106. // The first reference is for open/close
  107. //
  108. ReferenceObject(pStation);
  109. //
  110. // These values are common for SAP, direct (and DIX objects)
  111. //
  112. pStation->Sap.OpenOptions = OpenOptions;
  113. pStation->Dix.ObjectAddress = ObjectAddress;
  114. ACQUIRE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  115. switch (pStation->Gen.ObjectType) {
  116. case LLC_SAP_OBJECT:
  117. //
  118. // RLF 05/13/93
  119. //
  120. // don't allow multiple applications to open the same SAP. This is
  121. // incompatible with OS/2 DLC
  122. //
  123. if (pAdapterContext->apSapBindings[ObjectAddress] == NULL) {
  124. ppListBase = (PVOID*)&(pAdapterContext->apSapBindings[ObjectAddress]);
  125. LlcMemCpy(&pStation->Sap.DefaultParameters,
  126. &DefaultParameters,
  127. sizeof(DefaultParameters)
  128. );
  129. ALLOCATE_SPIN_LOCK(&pStation->Sap.FlowControlLock);
  130. } else {
  131. FREE_MEMORY_FILE(pStation);
  132. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  133. return DLC_STATUS_INVALID_SAP_VALUE;
  134. }
  135. break;
  136. case LLC_GROUP_SAP_OBJECT:
  137. ppListBase = (PVOID*)&(pAdapterContext->apSapBindings[ObjectAddress]);
  138. //
  139. // All members of the same group/individual SAP muust have set
  140. // the same XID handling option
  141. //
  142. if (pAdapterContext->apSapBindings[ObjectAddress] != NULL) {
  143. if ((OpenOptions & LLC_EXCLUSIVE_ACCESS)
  144. || (pAdapterContext->apSapBindings[ObjectAddress]->OpenOptions
  145. & LLC_EXCLUSIVE_ACCESS)) {
  146. LlcStatus = DLC_STATUS_INVALID_SAP_VALUE;
  147. } else if ((pAdapterContext->apSapBindings[ObjectAddress]->OpenOptions &
  148. LLC_HANDLE_XID_COMMANDS) != (OpenOptions & LLC_HANDLE_XID_COMMANDS)) {
  149. LlcStatus = DLC_STATUS_INVALID_OPTION;
  150. }
  151. }
  152. ALLOCATE_SPIN_LOCK(&pStation->Sap.FlowControlLock);
  153. break;
  154. case LLC_DIRECT_OBJECT:
  155. ppListBase = (PVOID*)&pAdapterContext->pDirectStation;
  156. break;
  157. case LLC_DIX_OBJECT:
  158. if (pAdapterContext->NdisMedium != NdisMedium802_3) {
  159. LlcStatus = DLC_STATUS_INVALID_STATION_ID;
  160. } else {
  161. ppListBase = (PVOID*)&(pAdapterContext->aDixStations[ObjectAddress % MAX_DIX_TABLE]);
  162. }
  163. break;
  164. #if LLC_DBG
  165. default:
  166. LlcInvalidObjectType();
  167. break;
  168. #endif
  169. }
  170. if (LlcStatus == STATUS_SUCCESS) {
  171. pStation->Gen.pNext = *ppListBase;
  172. *phStation = *ppListBase = pStation;
  173. pAdapterContext->ObjectCount++;
  174. } else {
  175. FREE_MEMORY_FILE(pStation);
  176. }
  177. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  178. if (LlcStatus == STATUS_SUCCESS
  179. && pStation->Gen.ObjectType == LLC_DIRECT_OBJECT
  180. && OpenOptions & DLC_RCV_MAC_FRAMES
  181. && !(pAdapterContext->OpenOptions & DLC_RCV_MAC_FRAMES)) {
  182. //
  183. // We enable the MAC frames, if they have once been enabled,
  184. // but they will never be disabled again. The receiving
  185. // of MAC frames is quite exceptional case, and it is
  186. // not really worth of it to maintain local and global
  187. // Ndis flag states just because of it
  188. //
  189. PacketFilter = NDIS_PACKET_TYPE_DIRECTED
  190. | NDIS_PACKET_TYPE_MULTICAST
  191. | NDIS_PACKET_TYPE_FUNCTIONAL
  192. | NDIS_PACKET_TYPE_MAC_FRAME;
  193. pAdapterContext->OpenOptions |= DLC_RCV_MAC_FRAMES;
  194. LlcStatus = SetNdisParameter(pAdapterContext,
  195. OID_GEN_CURRENT_PACKET_FILTER,
  196. &PacketFilter,
  197. sizeof(PacketFilter)
  198. );
  199. }
  200. return LlcStatus;
  201. }
  202. DLC_STATUS
  203. LlcCloseStation(
  204. IN PLLC_OBJECT pStation,
  205. IN PLLC_PACKET pCompletionPacket
  206. )
  207. /*++
  208. Routine Description:
  209. The primitive closes a direct, sap or link station object.
  210. All pending transmit commands are terminated.
  211. This primitive does not support graceful termination, but
  212. the upper level must wait the pending transmit commands, if
  213. it want to make a clean close (without deleting the transmit queue).
  214. For a link station this primitive releases a disconnected link
  215. station or discards a remote connection request.
  216. Arguments:
  217. pStation - handle of a link, sap or direct station
  218. pCompletionPacket - returned context, when the command is complete
  219. Return Value:
  220. DLC_STATUS
  221. Success - STATUS_SUCCESS
  222. Failure - DLC_STATUS_INVALID_PARAMETERS
  223. the SAP has still active link stations. All active link
  224. stations must be closed before sap can be closed.
  225. --*/
  226. {
  227. PADAPTER_CONTEXT pAdapterContext = pStation->Gen.pAdapterContext;
  228. PBINDING_CONTEXT pOldBinding;
  229. PDATA_LINK* ppLink;
  230. PVOID* ppLinkListBase;
  231. PEVENT_PACKET pEvent;
  232. if (pStation->Gen.ObjectType == LLC_LINK_OBJECT) {
  233. //
  234. // The remote connection requests are routed through all
  235. // SAP station reqistered on a SAP until someone accepts
  236. // the connection request or it has been routed to all
  237. // clients having opened the sap station.
  238. //
  239. if (pStation->Link.Flags & DLC_ACTIVE_REMOTE_CONNECT_REQUEST) {
  240. ACQUIRE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  241. pOldBinding = pStation->Gen.pLlcBinding;
  242. if (pStation->Link.pSap->Gen.pNext != NULL) {
  243. pStation->Gen.pLlcBinding = pStation->Link.pSap->Gen.pNext->Gen.pLlcBinding;
  244. }
  245. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  246. //
  247. // Complete the close command immediately, if
  248. // the connect request was redirected to another
  249. // SAP station
  250. //
  251. if (pStation->Gen.pLlcBinding != pOldBinding) {
  252. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  253. pEvent = ALLOCATE_PACKET_LLC_PKT(pAdapterContext->hPacketPool);
  254. if (pEvent != NULL) {
  255. LlcInsertTailList(&pAdapterContext->QueueEvents, pEvent);
  256. pEvent->pBinding = pStation->Gen.pLlcBinding;
  257. pEvent->hClientHandle = pStation->Link.pSap->Gen.hClientHandle;
  258. pEvent->Event = LLC_STATUS_CHANGE_ON_SAP;
  259. pEvent->pEventInformation = &pStation->Link.DlcStatus;
  260. pEvent->SecondaryInfo = INDICATE_CONNECT_REQUEST;
  261. }
  262. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  263. if (pEvent != NULL) {
  264. return STATUS_SUCCESS;
  265. }
  266. } else {
  267. //
  268. // Nobody accepted this connect request, we must discard it.
  269. //
  270. RunInterlockedStateMachineCommand((PDATA_LINK)pStation, SET_ADM);
  271. }
  272. }
  273. }
  274. ACQUIRE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  275. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  276. DLC_TRACE('C');
  277. switch (pStation->Gen.ObjectType) {
  278. case LLC_DIRECT_OBJECT:
  279. //
  280. // This Direct must be in the linked list of Directs (having
  281. // the same source Direct).
  282. //
  283. ppLinkListBase = (PVOID*)&pAdapterContext->pDirectStation;
  284. DLC_TRACE('b');
  285. break;
  286. case LLC_DIX_OBJECT:
  287. //
  288. // This Direct must be in the linked list of Directs (having
  289. // the same source Direct).
  290. //
  291. ppLinkListBase = (PVOID*)&pAdapterContext->aDixStations[pStation->Dix.ObjectAddress % MAX_DIX_TABLE];
  292. DLC_TRACE('a');
  293. break;
  294. case LLC_SAP_OBJECT:
  295. #if LLC_DBG
  296. if (pStation->Sap.pActiveLinks != NULL) {
  297. DbgPrint("Closing SAP before link stations!!!\n");
  298. DbgBreakPoint();
  299. //
  300. // Open the spin locks and return thge error status
  301. //
  302. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  303. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  304. return DLC_STATUS_LINK_STATIONS_OPEN;
  305. }
  306. #endif
  307. DLC_TRACE('d');
  308. case LLC_GROUP_SAP_OBJECT:
  309. //
  310. // This SAP must be in the linked list of SAPs (having
  311. // the same source SAP).
  312. //
  313. ppLinkListBase = (PVOID*)&pAdapterContext->apSapBindings[pStation->Sap.SourceSap];
  314. DEALLOCATE_SPIN_LOCK(&pStation->Sap.FlowControlLock);
  315. break;
  316. case LLC_LINK_OBJECT:
  317. //
  318. // Only a disconnected link station can be deactivated.
  319. // If this fails, then we must disconnect the link station,
  320. // if it is not already disconnected.
  321. //
  322. if (RunStateMachineCommand((PDATA_LINK)pStation, DEACTIVATE_LS) != STATUS_SUCCESS
  323. && pStation->Link.State != DISCONNECTING) {
  324. //
  325. // We must disconnect the link station immediately.
  326. // We don't care if we are at the moment in
  327. // a checkpoint state, that would delay the disconnection
  328. // until the other side has acknowledged it.
  329. // The link station must be killed now!
  330. //
  331. SendLlcFrame((PDATA_LINK)pStation, DLC_DISC_TOKEN | 1);
  332. DisableSendProcess((PDATA_LINK)pStation);
  333. }
  334. pStation->Link.State = LINK_CLOSED;
  335. ppLinkListBase = (PVOID *)&pStation->Link.pSap->pActiveLinks;
  336. ppLink = SearchLinkAddress(pAdapterContext, pStation->Link.LinkAddr);
  337. *ppLink = pStation->Link.pNextNode;
  338. TerminateTimer(pAdapterContext, &pStation->Link.T1);
  339. TerminateTimer(pAdapterContext, &pStation->Link.T2);
  340. TerminateTimer(pAdapterContext, &pStation->Link.Ti);
  341. DLC_TRACE('c');
  342. break;
  343. #if LLC_DBG
  344. default:
  345. LlcInvalidObjectType();
  346. break;
  347. #endif
  348. }
  349. RemoveFromLinkList(ppLinkListBase, pStation);
  350. //
  351. // Queue the asynchronous close command. Group sap and
  352. // disabling of non-existing link station may use
  353. // a null packet, because those commands are executed
  354. // synchronously (they cannot have pending packets)
  355. //
  356. if (pCompletionPacket != NULL) {
  357. AllocateCompletionPacket(pStation, LLC_CLOSE_COMPLETION, pCompletionPacket);
  358. }
  359. //
  360. // OK. Everything has been processed =>
  361. // now we can decrement the object counter.
  362. //
  363. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  364. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  365. //
  366. // Delete the object NOW, if this was the last reference to it
  367. //
  368. LlcDereferenceObject(pStation);
  369. return STATUS_PENDING;
  370. }
  371. VOID
  372. CompleteClose(
  373. IN PLLC_OBJECT pLlcObject,
  374. IN UINT CancelStatus
  375. )
  376. /*++
  377. Routine Description:
  378. Procedure cancel all pending commands of llc object and
  379. deletes the object.
  380. The procedure returns a pending status as far the object
  381. has pending transmits in NDIS.
  382. Arguments:
  383. pLlcObject - LLC object
  384. CancelStatus - the status returned in the cancelled (completed) commands
  385. Return Value:
  386. None.
  387. --*/
  388. {
  389. PADAPTER_CONTEXT pAdapterContext = pLlcObject->Gen.pAdapterContext;
  390. UINT Status;
  391. #if DBG
  392. PDLC_FILE_CONTEXT pFileContext = (PDLC_FILE_CONTEXT)(pLlcObject->Gen.pLlcBinding->hClientContext);
  393. #endif
  394. if (pLlcObject->Gen.ReferenceCount != 0) {
  395. return;
  396. }
  397. //
  398. // Cancel the queue transmit commands
  399. //
  400. CancelTransmitCommands(pLlcObject, CancelStatus);
  401. //
  402. // Queue also all commands queued in the link stations
  403. // (actually only LlcConnect and LlcDisconnect),
  404. // Note: the queue command eats the list of completion packets.
  405. //
  406. while (pLlcObject->Gen.pCompletionPackets != NULL) {
  407. Status = CancelStatus;
  408. if (pLlcObject->Gen.pCompletionPackets->Data.Completion.CompletedCommand == LLC_CLOSE_COMPLETION) {
  409. Status = STATUS_SUCCESS;
  410. }
  411. QueueCommandCompletion(pLlcObject,
  412. (UINT)pLlcObject->Gen.pCompletionPackets->Data.Completion.CompletedCommand,
  413. Status
  414. );
  415. }
  416. //
  417. // release link station specific resources
  418. //
  419. if (pLlcObject->Gen.ObjectType == LLC_LINK_OBJECT) {
  420. //
  421. // The link may have been closed because of an error
  422. // or timeout (eg. somebody has turned the power off in the
  423. // other side). We must complete all pending transmits with
  424. // an error. We assume, that the link has not any more
  425. // any packets in NDIS queues, but is does not matter,
  426. // because NDIS packets of a link station will never be
  427. // directly indicated to the user (they may not exist any
  428. // more). Thus nothing fatal can happen, if we simply
  429. // complete all packets and return them to the main
  430. // packet storage.
  431. //
  432. DEALLOCATE_PACKET_LLC_LNK(pAdapterContext->hLinkPool, pLlcObject);
  433. } else {
  434. FREE_MEMORY_FILE(pLlcObject);
  435. }
  436. pAdapterContext->ObjectCount--;
  437. }
  438. VOID
  439. CancelTransmitCommands(
  440. IN PLLC_OBJECT pLlcObject,
  441. IN UINT Status
  442. )
  443. /*++
  444. Routine Description:
  445. Procedure removes the transmit commands of the given LLC client
  446. from the transmit queue. This cannot cancel those dir/sap transmit
  447. already queued in NDIS, but the caller must first wait that the
  448. object has no commands in the NDIS queue.
  449. Arguments:
  450. pLlcObject - LLC object
  451. Status - status to set in cancelled transmit commands
  452. Return Value:
  453. None.
  454. --*/
  455. {
  456. PADAPTER_CONTEXT pAdapterContext = pLlcObject->Gen.pAdapterContext;
  457. //
  458. // We can (and must) cancel all pending transmits on a link
  459. // without any global locks, when the station has first
  460. // been removed from all global data structures,
  461. //
  462. if (pLlcObject->Gen.ObjectType == LLC_LINK_OBJECT) {
  463. CancelTransmitsInQueue(pLlcObject,
  464. Status,
  465. &((PDATA_LINK)pLlcObject)->SendQueue.ListHead,
  466. NULL
  467. );
  468. CancelTransmitsInQueue(pLlcObject,
  469. Status,
  470. &((PDATA_LINK)pLlcObject)->SentQueue,
  471. NULL
  472. );
  473. StopSendProcess(pAdapterContext, (PDATA_LINK)pLlcObject);
  474. //
  475. // We cannot leave any S- commands with a reference to the
  476. // link lan header.
  477. //
  478. CancelTransmitsInQueue(pLlcObject,
  479. Status,
  480. &pAdapterContext->QueueExpidited.ListHead,
  481. &pAdapterContext->QueueExpidited
  482. );
  483. } else {
  484. CancelTransmitsInQueue(pLlcObject,
  485. Status,
  486. &pAdapterContext->QueueDirAndU.ListHead,
  487. &pAdapterContext->QueueDirAndU
  488. );
  489. }
  490. }
  491. VOID
  492. CancelTransmitsInQueue(
  493. IN PLLC_OBJECT pLlcObject,
  494. IN UINT Status,
  495. IN PLIST_ENTRY pQueue,
  496. IN PLLC_QUEUE pLlcQueue OPTIONAL
  497. )
  498. /*++
  499. Routine Description:
  500. Procedure removes the transmit commands of the given LLC client
  501. from the transmit queue. This cannot cancel those dir/sap transmit
  502. already queued in NDIS, but the caller must first wait that the
  503. object has no commands in the NDIS queue.
  504. Arguments:
  505. pLlcObject - LLC object
  506. Status - the status returned by the completed transmit commands
  507. pQueue - a data links transmit queue
  508. pLlcQueue - an optional LLC queue, that is disconnected from the send
  509. task if the subqueue becomes empty.
  510. Return Value:
  511. None.
  512. --*/
  513. {
  514. PLLC_PACKET pPacket;
  515. PLLC_PACKET pNextPacket;
  516. PADAPTER_CONTEXT pAdapterContext = pLlcObject->Gen.pAdapterContext;
  517. //
  518. // Cancel all pending transmit commands in LLC queues,
  519. // check first, if the transmit queue is empty.
  520. //
  521. if (IsListEmpty(pQueue)) {
  522. return;
  523. }
  524. for (pPacket = (PLLC_PACKET)pQueue->Flink; pPacket != (PLLC_PACKET)pQueue; pPacket = pNextPacket) {
  525. pNextPacket = pPacket->pNext;
  526. //
  527. // Complete the packet only if it has a correct binding handle
  528. // and it belongs the given client object. Note: if binding
  529. // handle is null, then client object handle may be garbage!
  530. //
  531. if (pPacket->CompletionType > LLC_MAX_RESPONSE_PACKET
  532. && pPacket->Data.Xmit.pLlcObject == pLlcObject) {
  533. LlcRemoveEntryList(pPacket);
  534. //
  535. // We MUST NOT cancel those transmit commands, that are
  536. // still in the NDIS queue!!!! The command completion would
  537. // make the MDLs in NDIS packet invalid => system would crash.
  538. //
  539. if (((pPacket->CompletionType) & LLC_I_PACKET_PENDING_NDIS) == 0) {
  540. if (pPacket->pBinding != NULL) {
  541. LlcInsertTailList(&pAdapterContext->QueueCommands, pPacket);
  542. pPacket->Data.Completion.CompletedCommand = LLC_SEND_COMPLETION;
  543. pPacket->Data.Completion.Status = Status;
  544. pPacket->Data.Completion.hClientHandle = pLlcObject->Gen.hClientHandle;
  545. } else {
  546. DEALLOCATE_PACKET_LLC_PKT(pAdapterContext->hPacketPool, pPacket);
  547. }
  548. } else {
  549. //
  550. // The I-frames must be discarded by the link protocol, because
  551. // the link is now dead, and we will complete them immediately
  552. // when NdisSend the completes.
  553. //
  554. pPacket->CompletionType &= ~LLC_I_PACKET_UNACKNOWLEDGED;
  555. pPacket->Data.Completion.CompletedCommand = LLC_SEND_COMPLETION;
  556. pPacket->Data.Completion.Status = Status;
  557. pPacket->Data.Completion.hClientHandle = pLlcObject->Gen.hClientHandle;
  558. }
  559. }
  560. }
  561. //
  562. // Disconnect the list from the send task, if is now empty,
  563. // We don't use this check with the I- frame queues
  564. // (StopSendProcess does the same thing for them).
  565. //
  566. if (pLlcQueue != NULL
  567. && IsListEmpty(&pLlcQueue->ListHead)
  568. && pLlcQueue->ListEntry.Flink != NULL) {
  569. LlcRemoveEntryList(&pLlcQueue->ListEntry);
  570. pLlcQueue->ListEntry.Flink = NULL;
  571. }
  572. }
  573. //
  574. // Procedure sets new open options (receive mask) for a direct station.
  575. // The MAC frames must have been enabled, when the direct
  576. // object was opened on data link.
  577. // This is called whenever DLC receive command is issued for direct station.
  578. //
  579. VOID
  580. LlcSetDirectOpenOptions(
  581. IN PLLC_OBJECT pDirect,
  582. IN USHORT OpenOptions
  583. )
  584. {
  585. pDirect->Dir.OpenOptions = OpenOptions;
  586. }
  587. VOID
  588. CompleteObjectDelete(
  589. IN PLLC_OBJECT pStation
  590. )
  591. /*++
  592. Routine Description:
  593. The function completes the delete operation for a llc object.
  594. Arguments:
  595. pStation - link, sap or direct station handle
  596. Return Value:
  597. None.
  598. --*/
  599. {
  600. PADAPTER_CONTEXT pAdapterContext = pStation->Gen.pAdapterContext;
  601. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  602. if (pStation->Gen.ReferenceCount == 0) {
  603. CompletePendingLlcCommand(pStation);
  604. BackgroundProcessAndUnlock(pAdapterContext);
  605. } else {
  606. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  607. }
  608. }
  609. VOID
  610. CompletePendingLlcCommand(
  611. PLLC_OBJECT pLlcObject
  612. )
  613. /*++
  614. Routine Description:
  615. The routines cleans up all commands and event of a llc object
  616. from the the data link driver.
  617. Arguments:
  618. pLlObject - a data link object handle (opeque pointer)
  619. Return Value:
  620. None.
  621. --*/
  622. {
  623. //
  624. // The reference count is zero only if the object is deleted,
  625. // otherwise this is just a reset for a link station.
  626. //
  627. if (pLlcObject->Gen.ReferenceCount == 0) {
  628. CompleteClose(pLlcObject, DLC_STATUS_CANCELLED_BY_SYSTEM_ACTION);
  629. } else {
  630. CancelTransmitCommands(pLlcObject, DLC_STATUS_LINK_NOT_TRANSMITTING);
  631. }
  632. }
  633. VOID
  634. LlcDereferenceObject(
  635. IN PVOID pStation
  636. )
  637. /*++
  638. Routine Description:
  639. The function dereferences any LLC object.
  640. THIS ROUTINE MUST BE CALLED ALL SPIN LOCKS UNLOCKED,
  641. BECAUSE IT MAY CALL BACK !!!!
  642. Arguments:
  643. pStation - link, sap or direct station handle
  644. Return Value:
  645. None.
  646. --*/
  647. {
  648. DLC_TRACE('L');
  649. DLC_TRACE((UCHAR)((PLLC_OBJECT)pStation)->Gen.ReferenceCount - 1);
  650. if (InterlockedDecrement((PLONG)&(((PLLC_OBJECT)(pStation))->Gen.ReferenceCount)) == 0) {
  651. CompleteObjectDelete(pStation);
  652. }
  653. /* pStation might have been freed by now
  654. DLC_TRACE('L');
  655. DLC_TRACE((UCHAR)((PLLC_OBJECT)pStation)->Gen.ReferenceCount); */
  656. }
  657. VOID
  658. LlcReferenceObject(
  659. IN PVOID pStation
  660. )
  661. /*++
  662. Routine Description:
  663. The function references any LLC object. The non-zero
  664. reference counter keeps LLC objects alive.
  665. Arguments:
  666. pStation - link, sap or direct station handle
  667. Return Value:
  668. None.
  669. --*/
  670. {
  671. InterlockedIncrement((PLONG)&(((PLLC_OBJECT)pStation)->Gen.ReferenceCount));
  672. DLC_TRACE('M');
  673. DLC_TRACE((UCHAR)((PLLC_OBJECT)pStation)->Gen.ReferenceCount);
  674. }
  675. #if !DLC_AND_LLC
  676. //
  677. // the following routines can be used as macros if DLC and LLC live in the same
  678. // driver and the one knows about the other's structures
  679. //
  680. UINT
  681. LlcGetReceivedLanHeaderLength(
  682. IN PVOID pBinding
  683. )
  684. /*++
  685. Routine Description:
  686. Returns the length of the LAN header of the frame last received from NDIS.
  687. The size is 14 for all Ethernet types except direct Ethernet frames, and
  688. whatever we stored in the RcvLanHeaderLength field of the ADAPTER_CONTEXT
  689. for Token Ring (can contain source routing)
  690. Arguments:
  691. pBinding - pointer to BINDING_CONTEXT structure describing adapter
  692. on which frame of interest was received
  693. Return Value:
  694. UINT
  695. --*/
  696. {
  697. return (((PBINDING_CONTEXT)pBinding)->pAdapterContext->NdisMedium == NdisMedium802_3)
  698. ? (((PBINDING_CONTEXT)pBinding)->pAdapterContext->FrameType == LLC_DIRECT_ETHERNET_TYPE)
  699. ? 12
  700. : 14
  701. : ((PBINDING_CONTEXT)pBinding)->pAdapterContext->RcvLanHeaderLength;
  702. }
  703. USHORT
  704. LlcGetEthernetType(
  705. IN PVOID hContext
  706. )
  707. /*++
  708. Routine Description:
  709. Returns the Ethernet type set in the adapter context
  710. Arguments:
  711. hContext - handle of/pointer to BINDING_CONTEXT structure
  712. Return Value:
  713. USHORT
  714. --*/
  715. {
  716. return ((PBINDING_CONTEXT)hContext)->pAdapterContext->EthernetType;
  717. }
  718. UINT
  719. LlcGetCommittedSpace(
  720. IN PVOID hLink
  721. )
  722. /*++
  723. Routine Description:
  724. Returns the amount of committed buffer space
  725. Arguments:
  726. hLink -
  727. Return Value:
  728. UINT
  729. --*/
  730. {
  731. return ((PDATA_LINK)hLink)->BufferCommitment;
  732. }
  733. #endif