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.

1870 lines
49 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Copyright (c) 1991 Nokia Data Systems AB
  4. Module Name:
  5. dlcreq.c
  6. Abstract:
  7. This module handles the miscellaneous DLC requests (set & query information)
  8. Contents:
  9. DlcBufferFree
  10. DlcBufferGet
  11. DlcBufferCreate
  12. DlcConnectStation
  13. DlcFlowControl
  14. ResetLocalBusyBufferStates
  15. DlcReallocate
  16. DlcReset
  17. DirSetExceptionFlags
  18. CompleteAsyncCommand
  19. GetLinkStation
  20. GetSapStation
  21. GetStation
  22. DlcReadCancel
  23. DirOpenAdapter
  24. DirCloseAdapter
  25. CompleteDirCloseAdapter
  26. DlcCompleteCommand
  27. Author:
  28. Antti Saarenheimo 22-Jul-1991 (o-anttis)
  29. Environment:
  30. Kernel mode
  31. Revision History:
  32. --*/
  33. #include <dlc.h>
  34. #include "dlcdebug.h"
  35. #if 0
  36. //
  37. // if DLC and LLC share the same driver then we can use macros to access fields
  38. // in the BINDING_CONTEXT and ADAPTER_CONTEXT structures
  39. //
  40. #if DLC_AND_LLC
  41. #ifndef i386
  42. #define LLC_PRIVATE_PROTOTYPES
  43. #endif
  44. #include "llcdef.h"
  45. #include "llctyp.h"
  46. #include "llcapi.h"
  47. #endif
  48. #endif
  49. NTSTATUS
  50. DlcBufferFree(
  51. IN PIRP pIrp,
  52. IN PDLC_FILE_CONTEXT pFileContext,
  53. IN PNT_DLC_PARMS pDlcParms,
  54. IN ULONG InputBufferLength,
  55. IN ULONG OutputBufferLength
  56. )
  57. /*++
  58. Routine Description:
  59. Procedure simply releases the given user buffers.
  60. Arguments:
  61. pIrp - current io request packet
  62. pFileContext - DLC address object
  63. pDlcParms - the current parameter block
  64. InputBufferLength - the length of input parameters
  65. OutputBufferLength -
  66. Return Value:
  67. NTSTATUS:
  68. STATUS_SUCCESS
  69. DLC_STATUS_INADEQUATE_BUFFERS - buffer pool does not exist
  70. DLC_STATUS_INVALID_STATION_ID -
  71. DLC_STATUS_INVALID_BUFFER_LENGTH -
  72. NOTE!!! BUFFER.FREE does not return error, if the
  73. given buffer is invalid, or released twice!!!
  74. --*/
  75. {
  76. NTSTATUS status = STATUS_SUCCESS;
  77. UNREFERENCED_PARAMETER(pIrp);
  78. UNREFERENCED_PARAMETER(OutputBufferLength);
  79. ASSUME_IRQL(DISPATCH_LEVEL);
  80. if (!pFileContext->hBufferPool) {
  81. return DLC_STATUS_INADEQUATE_BUFFERS;
  82. }
  83. //
  84. // The parameter list is a DLC desriptor array.
  85. // Get the number of descriptor elements in the array.
  86. //
  87. if (InputBufferLength != (sizeof(NT_DLC_BUFFER_FREE_PARMS)
  88. - sizeof(LLC_TRANSMIT_DESCRIPTOR)
  89. + pDlcParms->BufferFree.BufferCount
  90. * sizeof(LLC_TRANSMIT_DESCRIPTOR))) {
  91. return DLC_STATUS_INVALID_BUFFER_LENGTH;
  92. }
  93. //
  94. // We refernce the buffer pool, because otherwise it may disappear
  95. // immeadiately after DLC_LEAVE (when the adapter is closed)
  96. //
  97. ReferenceBufferPool(pFileContext);
  98. //
  99. // Don't try to allocate 0 buffers, it will fail.
  100. //
  101. if (pDlcParms->BufferFree.BufferCount) {
  102. LEAVE_DLC(pFileContext);
  103. RELEASE_DRIVER_LOCK();
  104. status = BufferPoolDeallocate(pFileContext->hBufferPool,
  105. pDlcParms->BufferFree.BufferCount,
  106. pDlcParms->BufferFree.DlcBuffer
  107. );
  108. ACQUIRE_DRIVER_LOCK();
  109. ENTER_DLC(pFileContext);
  110. //
  111. // Reset the local busy states, if there is now enough
  112. // buffers the receive the expected stuff.
  113. //
  114. if (!IsListEmpty(&pFileContext->FlowControlQueue)
  115. && BufGetUncommittedSpace(pFileContext->hBufferPool) >= 0) {
  116. ResetLocalBusyBufferStates(pFileContext);
  117. }
  118. #if LLC_DBG
  119. cFramesReleased++;
  120. #endif
  121. }
  122. pDlcParms->BufferFree.cBuffersLeft = (USHORT)BufferPoolCount(pFileContext->hBufferPool);
  123. DereferenceBufferPool(pFileContext);
  124. return status;
  125. }
  126. NTSTATUS
  127. DlcBufferGet(
  128. IN PIRP pIrp,
  129. IN PDLC_FILE_CONTEXT pFileContext,
  130. IN PNT_DLC_PARMS pDlcParms,
  131. IN ULONG InputBufferLength,
  132. IN ULONG OutputBufferLength
  133. )
  134. /*++
  135. Routine Description:
  136. Procedure allocates the requested number or size of DLC buffers
  137. and returns them back to user in a single entry link list..
  138. Arguments:
  139. pIrp - current io request packet
  140. pFileContext - DLC adapter context
  141. pDlcParms - the current parameter block
  142. InputBufferLength - the length of input parameters
  143. OutputBufferLength -
  144. Return Value:
  145. NTSTATUS:
  146. STATUS_SUCCESS
  147. --*/
  148. {
  149. NTSTATUS Status = STATUS_SUCCESS;
  150. UINT SegmentSize;
  151. UINT SizeIndex;
  152. UINT BufferSize;
  153. UINT PrevBufferSize;
  154. UINT cBuffersToGet;
  155. PDLC_BUFFER_HEADER pBufferHeader = NULL;
  156. UNREFERENCED_PARAMETER(pIrp);
  157. UNREFERENCED_PARAMETER(InputBufferLength);
  158. UNREFERENCED_PARAMETER(OutputBufferLength);
  159. ASSUME_IRQL(DISPATCH_LEVEL);
  160. if (pFileContext->hBufferPool == NULL) {
  161. return DLC_STATUS_INADEQUATE_BUFFERS;
  162. }
  163. //
  164. // If the segment size is 0, then we return the optimal mix
  165. // of buffer for the requested size. Non null buffer count defines
  166. // how many buffers having the requested size is returned.
  167. //
  168. cBuffersToGet = pDlcParms->BufferGet.cBuffersToGet;
  169. /*******************************************************************************
  170. #if PAGE_SIZE == 8192
  171. if (cBuffersToGet == 0) {
  172. cBuffersToGet = 1;
  173. SegmentSize = pDlcParms->BufferGet.cbBufferSize;
  174. SizeIndex = (UINT)(-1);
  175. } else if (pDlcParms->BufferGet.cbBufferSize <= 256) {
  176. SegmentSize = 256 - sizeof(NEXT_DLC_SEGMENT);
  177. SizeIndex = 5;
  178. } else if (pDlcParms->BufferGet.cbBufferSize <= 512) {
  179. SegmentSize = 512 - sizeof(NEXT_DLC_SEGMENT);
  180. SizeIndex = 4;
  181. } else if (pDlcParms->BufferGet.cbBufferSize <= 1024) {
  182. SegmentSize = 1024 - sizeof(NEXT_DLC_SEGMENT);
  183. SizeIndex = 3;
  184. } else if (pDlcParms->BufferGet.cbBufferSize <= 2048) {
  185. SegmentSize = 2048 - sizeof(NEXT_DLC_SEGMENT);
  186. SizeIndex = 2;
  187. } else if (pDlcParms->BufferGet.cbBufferSize <= 4096) {
  188. SegmentSize = 4096 - sizeof(NEXT_DLC_SEGMENT);
  189. SizeIndex = 1;
  190. } else if (pDlcParms->BufferGet.cbBufferSize <= 8192) {
  191. SegmentSize = 8192 - sizeof(NEXT_DLC_SEGMENT);
  192. SizeIndex = 0;
  193. } else {
  194. return DLC_STATUS_INVALID_BUFFER_LENGTH;
  195. }
  196. #elif PAGE_SIZE == 4096
  197. if (cBuffersToGet == 0) {
  198. cBuffersToGet = 1;
  199. SegmentSize = pDlcParms->BufferGet.cbBufferSize;
  200. SizeIndex = (UINT)(-1);
  201. } else if (pDlcParms->BufferGet.cbBufferSize <= 256) {
  202. SegmentSize = 256 - sizeof(NEXT_DLC_SEGMENT);
  203. SizeIndex = 4;
  204. } else if (pDlcParms->BufferGet.cbBufferSize <= 512) {
  205. SegmentSize = 512 - sizeof(NEXT_DLC_SEGMENT);
  206. SizeIndex = 3;
  207. } else if (pDlcParms->BufferGet.cbBufferSize <= 1024) {
  208. SegmentSize = 1024 - sizeof(NEXT_DLC_SEGMENT);
  209. SizeIndex = 2;
  210. } else if (pDlcParms->BufferGet.cbBufferSize <= 2048) {
  211. SegmentSize = 2048 - sizeof(NEXT_DLC_SEGMENT);
  212. SizeIndex = 1;
  213. } else if (pDlcParms->BufferGet.cbBufferSize <= 4096) {
  214. SegmentSize = 4096 - sizeof(NEXT_DLC_SEGMENT);
  215. SizeIndex = 0;
  216. } else {
  217. return DLC_STATUS_INVALID_BUFFER_LENGTH;
  218. }
  219. #else
  220. #error "Target machine page size not 4096 or 8192"
  221. #endif
  222. *******************************************************************************/
  223. #if defined(ALPHA)
  224. if (cBuffersToGet == 0) {
  225. cBuffersToGet = 1;
  226. SegmentSize = pDlcParms->BufferGet.cbBufferSize;
  227. SizeIndex = (UINT)(-1);
  228. } else if (pDlcParms->BufferGet.cbBufferSize <= 256) {
  229. SegmentSize = 256 - sizeof(NEXT_DLC_SEGMENT);
  230. SizeIndex = 5;
  231. } else if (pDlcParms->BufferGet.cbBufferSize <= 512) {
  232. SegmentSize = 512 - sizeof(NEXT_DLC_SEGMENT);
  233. SizeIndex = 4;
  234. } else if (pDlcParms->BufferGet.cbBufferSize <= 1024) {
  235. SegmentSize = 1024 - sizeof(NEXT_DLC_SEGMENT);
  236. SizeIndex = 3;
  237. } else if (pDlcParms->BufferGet.cbBufferSize <= 2048) {
  238. SegmentSize = 2048 - sizeof(NEXT_DLC_SEGMENT);
  239. SizeIndex = 2;
  240. } else if (pDlcParms->BufferGet.cbBufferSize <= 4096) {
  241. SegmentSize = 4096 - sizeof(NEXT_DLC_SEGMENT);
  242. SizeIndex = 1;
  243. } else if (pDlcParms->BufferGet.cbBufferSize <= 8192) {
  244. SegmentSize = 8192 - sizeof(NEXT_DLC_SEGMENT);
  245. SizeIndex = 0;
  246. } else {
  247. return DLC_STATUS_INVALID_BUFFER_LENGTH;
  248. }
  249. #else
  250. if (cBuffersToGet == 0) {
  251. cBuffersToGet = 1;
  252. SegmentSize = pDlcParms->BufferGet.cbBufferSize;
  253. SizeIndex = (UINT)(-1);
  254. } else if (pDlcParms->BufferGet.cbBufferSize <= 256) {
  255. SegmentSize = 256 - sizeof(NEXT_DLC_SEGMENT);
  256. SizeIndex = 4;
  257. } else if (pDlcParms->BufferGet.cbBufferSize <= 512) {
  258. SegmentSize = 512 - sizeof(NEXT_DLC_SEGMENT);
  259. SizeIndex = 3;
  260. } else if (pDlcParms->BufferGet.cbBufferSize <= 1024) {
  261. SegmentSize = 1024 - sizeof(NEXT_DLC_SEGMENT);
  262. SizeIndex = 2;
  263. } else if (pDlcParms->BufferGet.cbBufferSize <= 2048) {
  264. SegmentSize = 2048 - sizeof(NEXT_DLC_SEGMENT);
  265. SizeIndex = 1;
  266. } else if (pDlcParms->BufferGet.cbBufferSize <= 4096) {
  267. SegmentSize = 4096 - sizeof(NEXT_DLC_SEGMENT);
  268. SizeIndex = 0;
  269. } else {
  270. return DLC_STATUS_INVALID_BUFFER_LENGTH;
  271. }
  272. #endif
  273. //
  274. // We refernce the buffer pool, because otherwise it may disappear
  275. // immeadiately after DLC_LEAVE (when the adapter is closed)
  276. //
  277. ReferenceBufferPool(pFileContext);
  278. //
  279. // We don't need to initialize the LAN and DLC header sizes
  280. // in the buffer header and we allocate the requested
  281. // frame as a single buffer.
  282. //
  283. BufferSize = SegmentSize * cBuffersToGet;
  284. if (BufferSize != 0) {
  285. pBufferHeader = NULL;
  286. PrevBufferSize = 0;
  287. LEAVE_DLC(pFileContext);
  288. do {
  289. //
  290. // We must again do this interlocked to avoid the buffer
  291. // pool to be deleted while we are allocating buffers.
  292. //
  293. Status = BufferPoolAllocate(
  294. #if DBG
  295. pFileContext,
  296. #endif
  297. (PDLC_BUFFER_POOL)pFileContext->hBufferPool,
  298. BufferSize,
  299. 0, // FrameHeaderSize,
  300. 0, // UserDataSize,
  301. 0, // frame length
  302. SizeIndex, // fixed segment size set
  303. &pBufferHeader,
  304. &BufferSize
  305. );
  306. #if DBG
  307. BufferPoolExpand(pFileContext, (PDLC_BUFFER_POOL)pFileContext->hBufferPool);
  308. #else
  309. BufferPoolExpand((PDLC_BUFFER_POOL)pFileContext->hBufferPool);
  310. #endif
  311. //
  312. // Don't try to expand buffer pool any more, if it doesn't help!
  313. //
  314. if (BufferSize == PrevBufferSize) {
  315. break;
  316. }
  317. PrevBufferSize = BufferSize;
  318. } while (Status == DLC_STATUS_EXPAND_BUFFER_POOL);
  319. ENTER_DLC(pFileContext);
  320. if (pBufferHeader != NULL) {
  321. pBufferHeader->FrameBuffer.BufferState = BUF_USER;
  322. }
  323. if (Status == STATUS_SUCCESS) {
  324. pDlcParms->BufferGet.pFirstBuffer = (PLLC_XMIT_BUFFER)
  325. ((PUCHAR)pBufferHeader->FrameBuffer.pParent->Header.pLocalVa +
  326. MIN_DLC_BUFFER_SEGMENT * pBufferHeader->FrameBuffer.Index);
  327. } else {
  328. BufferPoolDeallocateList(pFileContext->hBufferPool, pBufferHeader);
  329. }
  330. }
  331. pDlcParms->BufferGet.cBuffersLeft = (USHORT)BufferPoolCount(pFileContext->hBufferPool);
  332. DereferenceBufferPool(pFileContext);
  333. return Status;
  334. }
  335. NTSTATUS
  336. DlcBufferCreate(
  337. IN PIRP pIrp,
  338. IN PDLC_FILE_CONTEXT pFileContext,
  339. IN PNT_DLC_PARMS pDlcParms,
  340. IN ULONG InputBufferLength,
  341. IN ULONG OutputBufferLength
  342. )
  343. /*++
  344. Routine Description:
  345. Procedure creates a new buffer pool and allocates the initial
  346. space for it.
  347. Arguments:
  348. pIrp - current io request packet
  349. pFileContext - DLC adapter context
  350. pDlcParms - the current parameter block
  351. InputBufferLength - the length of input parameters
  352. OutputBufferLength -
  353. Return Value:
  354. NTSTATUS:
  355. Success - STATUS_SUCCESS
  356. Failure - DLC_STATUS_DUPLICATE_COMMAND
  357. --*/
  358. {
  359. NTSTATUS status;
  360. PVOID newBufferAddress;
  361. ULONG newBufferSize;
  362. PVOID hExternalBufferPool;
  363. PVOID hBufferPool;
  364. UNREFERENCED_PARAMETER(pIrp);
  365. UNREFERENCED_PARAMETER(InputBufferLength);
  366. UNREFERENCED_PARAMETER(OutputBufferLength);
  367. ASSUME_IRQL(DISPATCH_LEVEL);
  368. //
  369. // if we already have a buffer pool defined for this handle, fail the
  370. // request
  371. //
  372. if (pFileContext->hBufferPool) {
  373. return DLC_STATUS_DUPLICATE_COMMAND;
  374. }
  375. hExternalBufferPool = pFileContext->hExternalBufferPool;
  376. LEAVE_DLC(pFileContext);
  377. #if DBG
  378. status = BufferPoolCreate(pFileContext,
  379. #else
  380. status = BufferPoolCreate(
  381. #endif
  382. pDlcParms->BufferCreate.pBuffer,
  383. pDlcParms->BufferCreate.cbBufferSize,
  384. pDlcParms->BufferCreate.cbMinimumSizeThreshold,
  385. &hExternalBufferPool,
  386. &newBufferAddress,
  387. &newBufferSize
  388. );
  389. ENTER_DLC(pFileContext);
  390. pFileContext->hExternalBufferPool = hExternalBufferPool;
  391. if (status == STATUS_SUCCESS) {
  392. //
  393. // The reference count keeps the buffer pool alive
  394. // when it is used (and simultaneously deleted by another
  395. // thread)
  396. //
  397. pFileContext->BufferPoolReferenceCount = 1;
  398. hBufferPool = pFileContext->hBufferPool;
  399. LEAVE_DLC(pFileContext);
  400. status = BufferPoolReference(hExternalBufferPool,
  401. &hBufferPool
  402. );
  403. ENTER_DLC(pFileContext);
  404. pFileContext->hBufferPool = hBufferPool;
  405. pDlcParms->BufferCreate.hBufferPool = pFileContext->hExternalBufferPool;
  406. }
  407. // ENTER_DLC(pFileContext);
  408. return status;
  409. }
  410. NTSTATUS
  411. DlcConnectStation(
  412. IN PIRP pIrp,
  413. IN PDLC_FILE_CONTEXT pFileContext,
  414. IN PNT_DLC_PARMS pDlcParms,
  415. IN ULONG InputBufferLength,
  416. IN ULONG OutputBufferLength
  417. )
  418. /*++
  419. Routine Description:
  420. Procedure connects an local link station to a remote node
  421. or accepts a remote connection request.
  422. Arguments:
  423. pIrp - current io request packet
  424. pFileContext - DLC adapter context
  425. pDlcParms - the current parameter block
  426. InputBufferLength - the length of input parameters
  427. OutputBufferLength -
  428. Return Value:
  429. NTSTATUS:
  430. STATUS_SUCCESS
  431. --*/
  432. {
  433. PDLC_OBJECT pLinkStation;
  434. NTSTATUS Status;
  435. PUCHAR pSourceRouting = NULL;
  436. PDLC_COMMAND pPacket;
  437. UNREFERENCED_PARAMETER(InputBufferLength);
  438. UNREFERENCED_PARAMETER(OutputBufferLength);
  439. //
  440. // Procedure checks the sap and link station ids and
  441. // returns the requested link station.
  442. // The error status indicates a wrong sap or station id.
  443. //
  444. Status = GetLinkStation(pFileContext,
  445. pDlcParms->Async.Parms.DlcConnectStation.StationId,
  446. &pLinkStation
  447. );
  448. if (Status != STATUS_SUCCESS) {
  449. return Status;
  450. }
  451. pPacket = ALLOCATE_PACKET_DLC_PKT(pFileContext->hPacketPool);
  452. if (pPacket == NULL) {
  453. return DLC_STATUS_NO_MEMORY;
  454. }
  455. pPacket->pIrp = pIrp;
  456. //
  457. // IBM LAN Tech. Ref p 3-48 (DLC.CONNECT.STATION) states that ROUTING_ADDR
  458. // field is ignored if the link was created due to receipt of a SABME from
  459. // the remote station, EVEN IF THE ADDRESS IS NON-ZERO
  460. //
  461. if (pDlcParms->Async.Parms.DlcConnectStation.RoutingInformationLength != 0) {
  462. pSourceRouting = pDlcParms->Async.Parms.DlcConnectStation.aRoutingInformation;
  463. }
  464. pLinkStation->PendingLlcRequests++;
  465. ReferenceLlcObject(pLinkStation);
  466. LEAVE_DLC(pFileContext);
  467. //
  468. // LlcConnect returns the maximum information field,
  469. // through the tr bridges!
  470. //
  471. LlcConnectStation(pLinkStation->hLlcObject,
  472. (PLLC_PACKET)pPacket,
  473. pSourceRouting,
  474. &pLinkStation->u.Link.MaxInfoFieldLength
  475. );
  476. ENTER_DLC(pFileContext);
  477. DereferenceLlcObject(pLinkStation);
  478. return STATUS_PENDING;
  479. }
  480. NTSTATUS
  481. DlcFlowControl(
  482. IN PIRP pIrp,
  483. IN PDLC_FILE_CONTEXT pFileContext,
  484. IN PNT_DLC_PARMS pDlcParms,
  485. IN ULONG InputBufferLength,
  486. IN ULONG OutputBufferLength
  487. )
  488. /*++
  489. Routine Description:
  490. Procedure sets or resets the loacl busy state on the given link station
  491. or on all link stations of a sap station.
  492. Arguments:
  493. pIrp - current io request packet
  494. pFileContext - DLC adapter context
  495. pDlcParms - the current parameter block
  496. InputBufferLength - the length of input parameters
  497. OutputBufferLength -
  498. Return Value:
  499. NTSTATUS:
  500. Success - STATUS_SUCCESS
  501. Failure - DLC_STATUS_NO_MEMORY
  502. --*/
  503. {
  504. NTSTATUS Status;
  505. PDLC_OBJECT pDlcObject;
  506. UNREFERENCED_PARAMETER(pIrp);
  507. UNREFERENCED_PARAMETER(InputBufferLength);
  508. UNREFERENCED_PARAMETER(OutputBufferLength);
  509. ASSUME_IRQL(DISPATCH_LEVEL);
  510. //
  511. // Procedure checks the sap and link station ids and
  512. // returns the requested link station.
  513. // The error status indicates a wrong sap or station id.
  514. //
  515. Status = GetStation(pFileContext,
  516. pDlcParms->DlcFlowControl.StationId,
  517. &pDlcObject
  518. );
  519. if (Status != STATUS_SUCCESS) {
  520. return Status;
  521. }
  522. //
  523. // We will queue all reset local busy buffer commands
  524. // given to the link stations
  525. //
  526. if (((pDlcParms->DlcFlowControl.FlowControlOption & LLC_RESET_LOCAL_BUSY_BUFFER) == LLC_RESET_LOCAL_BUSY_BUFFER)
  527. && (pDlcObject->Type == DLC_LINK_OBJECT)) {
  528. PDLC_RESET_LOCAL_BUSY_CMD pClearCmd;
  529. pClearCmd = (PDLC_RESET_LOCAL_BUSY_CMD)ALLOCATE_PACKET_DLC_PKT(pFileContext->hPacketPool);
  530. if (pClearCmd == NULL) {
  531. return DLC_STATUS_NO_MEMORY;
  532. }
  533. pClearCmd->StationId = pDlcParms->DlcFlowControl.StationId;
  534. pClearCmd->RequiredBufferSpace = 0;
  535. LlcInsertTailList(&pFileContext->FlowControlQueue, pClearCmd);
  536. ResetLocalBusyBufferStates(pFileContext);
  537. } else {
  538. ReferenceLlcObject(pDlcObject);
  539. LEAVE_DLC(pFileContext);
  540. Status = LlcFlowControl(pDlcObject->hLlcObject,
  541. pDlcParms->DlcFlowControl.FlowControlOption
  542. );
  543. ENTER_DLC(pFileContext);
  544. DereferenceLlcObject(pDlcObject);
  545. }
  546. return Status;
  547. }
  548. VOID
  549. ResetLocalBusyBufferStates(
  550. IN PDLC_FILE_CONTEXT pFileContext
  551. )
  552. /*++
  553. Routine Description:
  554. Procedure executes the pending busy state resets when there is
  555. enough memory in the buffer pool to receive the expected data.
  556. Arguments:
  557. pFileContext - DLC adapter context
  558. Return Value:
  559. None
  560. --*/
  561. {
  562. NTSTATUS Status;
  563. PDLC_OBJECT pDlcObject;
  564. PDLC_RESET_LOCAL_BUSY_CMD pClearCmd;
  565. ASSUME_IRQL(DISPATCH_LEVEL);
  566. //
  567. // We cannot reset anything, if the buffer pool is not yet
  568. // defined.
  569. //
  570. if (pFileContext->hBufferPool == NULL) {
  571. return;
  572. }
  573. ReferenceBufferPool(pFileContext);
  574. while (!IsListEmpty(&pFileContext->FlowControlQueue)) {
  575. pClearCmd = LlcRemoveHeadList(&pFileContext->FlowControlQueue);
  576. Status = GetLinkStation(pFileContext,
  577. pClearCmd->StationId,
  578. &pDlcObject
  579. );
  580. //
  581. // All commands having an invalid station id will be just removed
  582. // from the queue. The local busy state can be reset only
  583. // for the existing link stations
  584. //
  585. if (Status == STATUS_SUCCESS) {
  586. //
  587. // The required space is nul, when a mew packet is checked
  588. // in the first time, the non-null value just prevents
  589. // us to check the commited memory in the second time.
  590. //
  591. if (pClearCmd->RequiredBufferSpace == 0) {
  592. //
  593. // We must also remove the old uncommited space,
  594. // otherwise the same buffer size could be
  595. // committed several times, but uncommitted only once
  596. //
  597. if (pDlcObject->CommittedBufferSpace != 0) {
  598. BufUncommitBuffers(pFileContext->hBufferPool,
  599. pDlcObject->CommittedBufferSpace
  600. );
  601. }
  602. pDlcObject->CommittedBufferSpace =
  603. pClearCmd->RequiredBufferSpace = LlcGetCommittedSpace(pDlcObject->hLlcObject);
  604. BufCommitBuffers(pFileContext->hBufferPool,
  605. pDlcObject->CommittedBufferSpace
  606. );
  607. }
  608. //
  609. // We are be removing a local buffer busy state =>
  610. // we must expand the buffer pools before the local busy
  611. // is removed, but only if we are not calling this
  612. // from a DPC level.
  613. //
  614. if (BufGetUncommittedSpace(pFileContext->hBufferPool) < 0) {
  615. LEAVE_DLC(pFileContext);
  616. #if DBG
  617. BufferPoolExpand(pFileContext, pFileContext->hBufferPool);
  618. #else
  619. BufferPoolExpand(pFileContext->hBufferPool);
  620. #endif
  621. ENTER_DLC(pFileContext);
  622. }
  623. //
  624. // Now we have expanded the buffer pool for the new
  625. // flow control command, check if we have now enough
  626. // memory to receive the commited size of data.
  627. //
  628. if (BufGetUncommittedSpace(pFileContext->hBufferPool) >= 0
  629. && pDlcObject->hLlcObject != NULL) {
  630. ReferenceLlcObject(pDlcObject);
  631. LEAVE_DLC(pFileContext);
  632. Status = LlcFlowControl(pDlcObject->hLlcObject,
  633. LLC_RESET_LOCAL_BUSY_BUFFER
  634. );
  635. ENTER_DLC(pFileContext);
  636. DereferenceLlcObject(pDlcObject);
  637. } else {
  638. //
  639. // We must exit this loop when there is not enough available
  640. // space in the buffer pool, but we must return
  641. // the command back to the head of the list
  642. //
  643. LlcInsertHeadList(&pFileContext->FlowControlQueue, pClearCmd);
  644. break;
  645. }
  646. }
  647. DEALLOCATE_PACKET_DLC_PKT(pFileContext->hPacketPool, pClearCmd);
  648. }
  649. DereferenceBufferPool(pFileContext);
  650. }
  651. NTSTATUS
  652. DlcReallocate(
  653. IN PIRP pIrp,
  654. IN PDLC_FILE_CONTEXT pFileContext,
  655. IN PNT_DLC_PARMS pDlcParms,
  656. IN ULONG InputBufferLength,
  657. IN ULONG OutputBufferLength
  658. )
  659. /*++
  660. Routine Description:
  661. Procedure changes the number of link stations allocated to a SAP
  662. without closing or reopening the sap station.
  663. Arguments:
  664. pIrp - current io request packet
  665. pFileContext - DLC adapter context
  666. pDlcParms - the current parameter block
  667. InputBufferLength - the length of input parameters
  668. OutputBufferLength
  669. Return Value:
  670. NTSTATUS:
  671. STATUS_SUCCESS
  672. --*/
  673. {
  674. PDLC_OBJECT pSap;
  675. UCHAR ExtraStations;
  676. UCHAR StationCount;
  677. NTSTATUS Status;
  678. UNREFERENCED_PARAMETER(pIrp);
  679. UNREFERENCED_PARAMETER(InputBufferLength);
  680. UNREFERENCED_PARAMETER(OutputBufferLength);
  681. //
  682. // Procedure checks the sap and returns the requested sap station.
  683. // The error status indicates an invalid sap station id.
  684. //
  685. Status = GetSapStation(pFileContext,
  686. pDlcParms->DlcReallocate.usStationId,
  687. &pSap
  688. );
  689. if (Status != STATUS_SUCCESS) {
  690. return Status;
  691. }
  692. //
  693. // The new link station count must be more than current number
  694. // of open link stations but less than the available number
  695. // of link stations for the file context
  696. //
  697. StationCount = pDlcParms->DlcReallocate.uchStationCount;
  698. if (StationCount != 0 && Status == STATUS_SUCCESS) {
  699. //
  700. // Bit7 set in options => decrease the number of available
  701. // stations by the given station count. Otherwise we increase it.
  702. //
  703. if (pDlcParms->DlcReallocate.uchOption & 0x80) {
  704. ExtraStations = pSap->u.Sap.MaxStationCount - pSap->u.Sap.LinkStationCount;
  705. if (StationCount > ExtraStations) {
  706. StationCount = ExtraStations;
  707. Status = DLC_STATUS_INADEQUATE_LINKS;
  708. }
  709. pFileContext->LinkStationCount += StationCount;
  710. pSap->u.Sap.MaxStationCount -= StationCount;
  711. } else {
  712. if (pFileContext->LinkStationCount < StationCount) {
  713. StationCount = pFileContext->LinkStationCount;
  714. Status = DLC_STATUS_INADEQUATE_LINKS;
  715. }
  716. pFileContext->LinkStationCount -= StationCount;
  717. pSap->u.Sap.MaxStationCount += StationCount;
  718. }
  719. }
  720. //
  721. // Set the return parameters even if there would be an error
  722. // (inadequate stations is a non fatal error)
  723. //
  724. pDlcParms->DlcReallocate.uchStationsAvailOnAdapter = pFileContext->LinkStationCount;
  725. pDlcParms->DlcReallocate.uchStationsAvailOnSap = pSap->u.Sap.MaxStationCount - pSap->u.Sap.LinkStationCount;
  726. pDlcParms->DlcReallocate.uchTotalStationsOnAdapter = MAX_LINK_STATIONS;
  727. pDlcParms->DlcReallocate.uchTotalStationsOnSap = pSap->u.Sap.MaxStationCount;
  728. return Status;
  729. }
  730. NTSTATUS
  731. DlcReset(
  732. IN PIRP pIrp,
  733. IN PDLC_FILE_CONTEXT pFileContext,
  734. IN PNT_DLC_PARMS pDlcParms,
  735. IN ULONG InputBufferLength,
  736. IN ULONG OutputBufferLength
  737. )
  738. /*++
  739. Routine Description:
  740. Procedure closes immediately a sap and its all link stations or
  741. all saps and all link stations.
  742. Arguments:
  743. pIrp - current io request packet
  744. pFileContext - DLC adapter context
  745. pDlcParms - the current parameter block
  746. InputBufferLength - the length of input parameters
  747. OutputBufferLength -
  748. Return Value:
  749. NTSTATUS:
  750. STATUS_SUCCESS
  751. STATUS_PENDING
  752. DLC_STATUS_NO_MEMORY
  753. --*/
  754. {
  755. PDLC_OBJECT pDlcObject;
  756. PDLC_CLOSE_WAIT_INFO pClosingInfo;
  757. NTSTATUS Status;
  758. UNREFERENCED_PARAMETER(InputBufferLength);
  759. UNREFERENCED_PARAMETER(OutputBufferLength);
  760. ASSUME_IRQL(DISPATCH_LEVEL);
  761. //
  762. // Station id 0 resets the whole DLC
  763. //
  764. if (pDlcParms->Async.Ccb.u.dlc.usStationId == 0) {
  765. PDLC_CLOSE_WAIT_INFO pClosingInfo;
  766. pClosingInfo = ALLOCATE_PACKET_DLC_PKT(pFileContext->hPacketPool);
  767. if (pClosingInfo == NULL) {
  768. Status = DLC_STATUS_NO_MEMORY;
  769. } else {
  770. CloseAllStations(pFileContext,
  771. pIrp,
  772. DLC_COMMAND_COMPLETION,
  773. NULL,
  774. pDlcParms,
  775. pClosingInfo
  776. );
  777. Status = STATUS_PENDING;
  778. }
  779. } else {
  780. BOOLEAN allClosed;
  781. //
  782. // We have a specific sap station
  783. //
  784. Status = GetSapStation(pFileContext,
  785. pDlcParms->Async.Ccb.u.dlc.usStationId,
  786. &pDlcObject
  787. );
  788. if (Status != STATUS_SUCCESS) {
  789. return Status;
  790. }
  791. //
  792. // Allocate the close/reset command completion info,
  793. // the station count is the number of link stations and
  794. // the sap station itself
  795. //
  796. pClosingInfo = ALLOCATE_PACKET_DLC_PKT(pFileContext->hPacketPool);
  797. if (pClosingInfo == NULL) {
  798. return DLC_STATUS_NO_MEMORY;
  799. }
  800. pClosingInfo->pIrp = pIrp;
  801. pClosingInfo->Event = DLC_COMMAND_COMPLETION;
  802. pClosingInfo->CancelStatus = DLC_STATUS_CANCELLED_BY_USER;
  803. pClosingInfo->CloseCounter = 1; // keep command alive over sync path
  804. (USHORT)(pDlcObject->u.Sap.LinkStationCount + 1);
  805. CloseAnyStation(pDlcObject, pClosingInfo, FALSE);
  806. //
  807. // RLF 05/09/93
  808. //
  809. // PC/3270 (DOS program) is hanging forever when we try to quit.
  810. // It is doing this because we returned STATUS_PENDING to a DLC.RESET,
  811. // even though the reset completed; the DOS program spins forever on
  812. // the CCB.uchDlcStatus field, waiting for it to go non-0xFF, which it
  813. // will never do.
  814. //
  815. // If we determine that the station has been reset (all links closed)
  816. // then return success, else pending
  817. //
  818. allClosed = DecrementCloseCounters(pFileContext, pClosingInfo);
  819. //
  820. // RLF 07/21/92 Always return PENDING. Can't complete before return?
  821. //
  822. Status = allClosed ? STATUS_SUCCESS : STATUS_PENDING;
  823. }
  824. return Status;
  825. }
  826. NTSTATUS
  827. DirSetExceptionFlags(
  828. IN PIRP pIrp,
  829. IN PDLC_FILE_CONTEXT pFileContext,
  830. IN PNT_DLC_PARMS pDlcParms,
  831. IN ULONG InputBufferLength,
  832. IN ULONG OutputBufferLength
  833. )
  834. /*++
  835. Routine Description:
  836. Procedure sets the exception flags for the current adapter context.
  837. Arguments:
  838. pIrp - current io request packet
  839. pFileContext - DLC adapter context
  840. pDlcParms - the current parameter block
  841. InputBufferLength - the length of input parameters
  842. OutputBufferLength
  843. Return Value:
  844. NTSTATUS:
  845. STATUS_SUCCESS
  846. --*/
  847. {
  848. UNREFERENCED_PARAMETER(pIrp);
  849. UNREFERENCED_PARAMETER(InputBufferLength);
  850. UNREFERENCED_PARAMETER(OutputBufferLength);
  851. pFileContext->AdapterCheckFlag = pDlcParms->DirSetExceptionFlags.ulAdapterCheckFlag;
  852. pFileContext->NetworkStatusFlag = pDlcParms->DirSetExceptionFlags.ulNetworkStatusFlag;
  853. pFileContext->PcErrorFlag = pDlcParms->DirSetExceptionFlags.ulPcErrorFlag;
  854. pFileContext->SystemActionFlag = pDlcParms->DirSetExceptionFlags.ulSystemActionFlag;
  855. return STATUS_SUCCESS;
  856. }
  857. VOID
  858. CompleteAsyncCommand(
  859. IN PDLC_FILE_CONTEXT pFileContext,
  860. IN UINT Status,
  861. IN PIRP pIrp,
  862. IN PVOID pUserCcbPointer,
  863. IN BOOLEAN InCancel
  864. )
  865. /*++
  866. Routine Description:
  867. Procedure completes an asynchronous DLC command.
  868. It also copies the optional output parameters to user parameter
  869. table, if there is the second output buffer.
  870. Arguments:
  871. pFileContext - DLC driver client context.
  872. Status - status of the complete command.
  873. pIrp - the completed I/O request packet.
  874. pUserCcbPointer - the next CCB address to which the command will be linked.
  875. InCancel - TRUE if called on Irp cancel path
  876. Return Value:
  877. None.
  878. --*/
  879. {
  880. PNT_DLC_PARMS pDlcParms;
  881. UNREFERENCED_PARAMETER(pFileContext);
  882. ASSUME_IRQL(DISPATCH_LEVEL);
  883. DIAG_FUNCTION("CompleteAsyncCommand");
  884. pDlcParms = (PNT_DLC_PARMS)pIrp->AssociatedIrp.SystemBuffer;
  885. //
  886. // We first map the 32-bit DLC driver status code to 8- bit API status
  887. //
  888. if (Status == STATUS_SUCCESS) {
  889. pDlcParms->Async.Ccb.uchDlcStatus = (UCHAR)STATUS_SUCCESS;
  890. } else if (Status >= DLC_STATUS_ERROR_BASE && Status < DLC_STATUS_MAX_ERROR) {
  891. //
  892. // We can map the normal DLC error codes directly to the 8-bit
  893. // DLC API error codes.
  894. //
  895. pDlcParms->Async.Ccb.uchDlcStatus = (UCHAR)(Status - DLC_STATUS_ERROR_BASE);
  896. } else {
  897. //
  898. // we have an unknown NT error status => we will return it in the CCB
  899. //
  900. pDlcParms->Async.Ccb.uchDlcStatus = (UCHAR)(DLC_STATUS_NT_ERROR_STATUS & 0xff);
  901. }
  902. pDlcParms->Async.Ccb.pCcbAddress = pUserCcbPointer;
  903. //
  904. // We always return success status to the I/O system. The actual status is
  905. // copied to the CCB (= the dafault output buffer)
  906. //
  907. LEAVE_DLC(pFileContext);
  908. RELEASE_DRIVER_LOCK();
  909. DlcCompleteIoRequest(pIrp, InCancel);
  910. ACQUIRE_DRIVER_LOCK();
  911. ENTER_DLC(pFileContext);
  912. DereferenceFileContext(pFileContext);
  913. }
  914. NTSTATUS
  915. GetLinkStation(
  916. IN PDLC_FILE_CONTEXT pFileContext,
  917. IN USHORT StationId,
  918. OUT PDLC_OBJECT *ppLinkStation
  919. )
  920. /*++
  921. Routine Description:
  922. Procedure checks and returns link station
  923. Arguments:
  924. pFileContext - DLC driver client context
  925. StationId - DLC station id (ssnn, where ss = sap and nn = link station id
  926. ppDlcObject - the returned link station
  927. Return Value:
  928. NTSTATUS:
  929. STATUS_SUCCESS
  930. DLC_STATUS_INVALID_SAP_VALUE
  931. DLC_STATUS_INVALID_STATION_ID
  932. --*/
  933. {
  934. if ((StationId & 0xff) == 0 || (StationId & 0xff00) == 0) {
  935. return DLC_STATUS_INVALID_STATION_ID;
  936. }
  937. return GetStation(pFileContext, StationId, ppLinkStation);
  938. }
  939. NTSTATUS
  940. GetSapStation(
  941. IN PDLC_FILE_CONTEXT pFileContext,
  942. IN USHORT StationId,
  943. OUT PDLC_OBJECT *ppStation
  944. )
  945. /*++
  946. Routine Description:
  947. Procedure checks and returns link station
  948. Arguments:
  949. pFileContext - DLC driver client context
  950. StationId - DLC station id (ssnn, where ss = sap and nn = link station id
  951. ppDlcObject - the returned link station
  952. Return Value:
  953. NTSTATUS:
  954. STATUS_SUCCESS
  955. DLC_STATUS_INVALID_SAP_VALUE
  956. DLC_STATUS_INVALID_STATION_ID
  957. --*/
  958. {
  959. UINT SapId = StationId >> 9;
  960. if (SapId >= MAX_SAP_STATIONS
  961. || SapId == 0
  962. || (StationId & GROUP_SAP_BIT)
  963. || (*ppStation = pFileContext->SapStationTable[SapId]) == NULL
  964. || (*ppStation)->State != DLC_OBJECT_OPEN) {
  965. return DLC_STATUS_INVALID_SAP_VALUE;
  966. }
  967. return STATUS_SUCCESS;
  968. }
  969. NTSTATUS
  970. GetStation(
  971. IN PDLC_FILE_CONTEXT pFileContext,
  972. IN USHORT StationId,
  973. OUT PDLC_OBJECT *ppStation
  974. )
  975. /*++
  976. Routine Description:
  977. Procedure checks the given station id and returns a pointer to
  978. sap, direct or link station object.
  979. Arguments:
  980. pFileContext - DLC driver client context
  981. StationId - DLC station id (ssnn, where ss = sap and nn = link station id
  982. ppStation - the returned station object
  983. Return Value:
  984. NTSTATUS:
  985. STATUS_SUCCESS
  986. DLC_STATUS_INVALID_STATION_ID
  987. --*/
  988. {
  989. UINT SapId = StationId >> 9;
  990. //
  991. // Check if the sap or direct station exists,
  992. // but check also the link station, if we found a valid sap id.
  993. //
  994. if (SapId >= MAX_SAP_STATIONS
  995. || (StationId & GROUP_SAP_BIT)
  996. || (*ppStation = pFileContext->SapStationTable[SapId]) == NULL
  997. || (*ppStation)->State != DLC_OBJECT_OPEN) {
  998. if (SapId == 0) {
  999. return DLC_STATUS_DIRECT_STATIONS_NOT_AVAILABLE;
  1000. } else {
  1001. return DLC_STATUS_INVALID_STATION_ID;
  1002. }
  1003. }
  1004. //
  1005. // The link station table will never be read, if we have found
  1006. // a valid sap or direct station. Link station must exist and
  1007. // it must be opened.
  1008. //
  1009. if (SapId != 0
  1010. && (StationId & 0xff) != 0
  1011. && (*ppStation = pFileContext->LinkStationTable[((StationId & 0xff) - 1)]) == NULL
  1012. || (*ppStation)->State != DLC_OBJECT_OPEN) {
  1013. return DLC_STATUS_INVALID_STATION_ID;
  1014. }
  1015. return STATUS_SUCCESS;
  1016. }
  1017. NTSTATUS
  1018. DlcReadCancel(
  1019. IN PIRP pIrp,
  1020. IN PDLC_FILE_CONTEXT pFileContext,
  1021. IN PNT_DLC_PARMS pDlcParms,
  1022. IN ULONG InputBufferLength,
  1023. IN ULONG OutputBufferLength
  1024. )
  1025. /*++
  1026. Routine Description:
  1027. This primitive cancels a READ command, that have the given CCB pointer.
  1028. Arguments:
  1029. pIrp - current io request packet
  1030. pFileContext - DLC process specific adapter context
  1031. pDlcParms - the current parameter block
  1032. InputBufferLength - the length of input parameters
  1033. OutputBufferLength -
  1034. Return Value:
  1035. DLC_STATUS:
  1036. STATUS_SUCCESS
  1037. --*/
  1038. {
  1039. PVOID pCcbAddress = NULL;
  1040. UNREFERENCED_PARAMETER(pIrp);
  1041. UNREFERENCED_PARAMETER(InputBufferLength);
  1042. UNREFERENCED_PARAMETER(OutputBufferLength);
  1043. DLC_TRACE('Q');
  1044. return AbortCommand(pFileContext,
  1045. (USHORT)DLC_IGNORE_STATION_ID,
  1046. (USHORT)DLC_STATION_MASK_SPECIFIC,
  1047. pDlcParms->DlcCancelCommand.CcbAddress,
  1048. &pCcbAddress,
  1049. DLC_STATUS_CANCELLED_BY_USER,
  1050. TRUE // Suppress completion
  1051. );
  1052. }
  1053. NTSTATUS
  1054. DirOpenAdapter(
  1055. IN PIRP pIrp,
  1056. IN PDLC_FILE_CONTEXT pFileContext,
  1057. IN PNT_DLC_PARMS pDlcParms,
  1058. IN ULONG InputBufferLength,
  1059. IN ULONG OutputBufferLength
  1060. )
  1061. /*++
  1062. Routine Description:
  1063. This primitive binds the DLC API driver to an adapter context of
  1064. the LLC module. The LLC mode may also bind to the given NDIS driver
  1065. and open it, if this is the first reference to the driver from DLC.
  1066. Arguments:
  1067. pIrp - current io request packet
  1068. pFileContext - DLC process specific adapter context
  1069. pDlcParms - the current parameter block
  1070. InputBufferLength - the length of input parameters
  1071. OutputBufferLength -
  1072. Return Value:
  1073. DLC_STATUS:
  1074. STATUS_SUCCESS
  1075. --*/
  1076. {
  1077. NTSTATUS Status;
  1078. UINT OpenErrorCode;
  1079. UNREFERENCED_PARAMETER(pIrp);
  1080. UNREFERENCED_PARAMETER(InputBufferLength);
  1081. UNREFERENCED_PARAMETER(OutputBufferLength);
  1082. ASSUME_IRQL(DISPATCH_LEVEL);
  1083. if (pDlcParms->DirOpenAdapter.NtDlcIoctlVersion != NT_DLC_IOCTL_VERSION) {
  1084. return DLC_STATUS_INVALID_VERSION;
  1085. }
  1086. //
  1087. // This makes the DirOpenAdapter safe, even if there were two adapter
  1088. // opens going on simultaneously
  1089. //
  1090. //
  1091. // RLF 04/22/94
  1092. //
  1093. // this only protects against 2 threads in the same process performing
  1094. // simultaneous opens on the same adapter
  1095. //
  1096. if (pFileContext->pBindingContext) {
  1097. return DLC_STATUS_DUPLICATE_COMMAND;
  1098. }
  1099. pFileContext->pBindingContext = (PVOID)-1;
  1100. //
  1101. // if a buffer pool handle was supplied (i.e. the app already created a
  1102. // buffer pool or is otherwise sharing one) then reference it for this
  1103. // file context
  1104. //
  1105. if (pDlcParms->DirOpenAdapter.hBufferPoolHandle) {
  1106. Status = BufferPoolReference(pDlcParms->DirOpenAdapter.hBufferPoolHandle,
  1107. &pFileContext->hBufferPool
  1108. );
  1109. if (Status == STATUS_SUCCESS) {
  1110. pFileContext->BufferPoolReferenceCount = 1;
  1111. pFileContext->hExternalBufferPool = pDlcParms->DirOpenAdapter.hBufferPoolHandle;
  1112. } else {
  1113. //
  1114. // Invalid buffer pool handle, hopefully this status
  1115. // code indicates correctly, that the buffer pool
  1116. // handle is not valid.
  1117. //
  1118. pFileContext->pBindingContext = NULL;
  1119. return DLC_STATUS_INVALID_BUFFER_LENGTH;
  1120. }
  1121. }
  1122. LEAVE_DLC(pFileContext);
  1123. //
  1124. // XXXXXXX: BringUpDiagnostics are still missing!!!
  1125. //
  1126. //
  1127. // RLF 04/19/93
  1128. //
  1129. // The string we pass to LlcOpenAdapter is a pointer to a zero terminated
  1130. // wide character string, NOT a pointer to a UNICODE_STRING structure. The
  1131. // string MUST be in system memory space, i.e. copied across the kernel
  1132. // interface by NtDeviceIoControlFile
  1133. //
  1134. Status = LlcOpenAdapter(&pDlcParms->DirOpenAdapter.Buffer[0],
  1135. (PVOID)pFileContext,
  1136. LlcCommandCompletion,
  1137. LlcReceiveIndication,
  1138. LlcEventIndication,
  1139. NdisMedium802_5, // Always token-ring!
  1140. pDlcParms->DirOpenAdapter.LlcEthernetType,
  1141. pDlcParms->DirOpenAdapter.AdapterNumber,
  1142. &pFileContext->pBindingContext,
  1143. &OpenErrorCode,
  1144. &pFileContext->MaxFrameLength,
  1145. &pFileContext->ActualNdisMedium
  1146. );
  1147. //
  1148. // make sure LlcOpenAdapter didn't return with lowered IRQL
  1149. //
  1150. ASSUME_IRQL(DISPATCH_LEVEL);
  1151. //
  1152. // IBM LAN Tech. Ref. defines the open error code as a 16-bit value, the
  1153. // high 8 bits of which are 0. The MAC inclusive-ORs the open error code
  1154. // into the NDIS status. Extract it
  1155. //
  1156. pDlcParms->DirOpenAdapter.Adapter.usOpenErrorCode = (USHORT)(UCHAR)OpenErrorCode;
  1157. if (Status != STATUS_SUCCESS) {
  1158. ENTER_DLC(pFileContext);
  1159. //
  1160. // It does not matter, if we have null buffer pool handle!
  1161. //
  1162. #if DBG
  1163. BufferPoolDereference(pFileContext,
  1164. (PDLC_BUFFER_POOL*)&pFileContext->hBufferPool
  1165. );
  1166. #else
  1167. BufferPoolDereference((PDLC_BUFFER_POOL*)&pFileContext->hBufferPool);
  1168. #endif
  1169. //
  1170. // set the BINDING_CONTEXT pointer back to NULL - other routines check
  1171. // for this value, like CloseAdapterFileContext
  1172. //
  1173. pFileContext->pBindingContext = NULL;
  1174. //
  1175. // Probably the adapter was missing or it was installed improperly
  1176. //
  1177. Status = DLC_STATUS_ADAPTER_NOT_INSTALLED;
  1178. } else {
  1179. //
  1180. // Set the optional timer tick one/two values
  1181. // (if they have been set in registry)
  1182. //
  1183. LlcSetInformation(pFileContext->pBindingContext,
  1184. DLC_INFO_CLASS_DLC_TIMERS,
  1185. (PLLC_SET_INFO_BUFFER)&(pDlcParms->DirOpenAdapter.LlcTicks),
  1186. sizeof(LLC_TICKS)
  1187. );
  1188. LlcQueryInformation(pFileContext->pBindingContext,
  1189. DLC_INFO_CLASS_DIR_ADAPTER,
  1190. (PLLC_QUERY_INFO_BUFFER)pDlcParms->DirOpenAdapter.Adapter.auchNodeAddress,
  1191. sizeof(LLC_ADAPTER_INFO)
  1192. );
  1193. ENTER_DLC(pFileContext);
  1194. //
  1195. // take the missing parameters from the hat
  1196. //
  1197. pDlcParms->DirOpenAdapter.Adapter.usOpenOptions = 0;
  1198. pDlcParms->DirOpenAdapter.Adapter.usMaxFrameSize = (USHORT)(pFileContext->MaxFrameLength + 6);
  1199. pDlcParms->DirOpenAdapter.Adapter.usBringUps = 0;
  1200. pDlcParms->DirOpenAdapter.Adapter.InitWarnings = 0;
  1201. pFileContext->AdapterNumber = pDlcParms->DirOpenAdapter.AdapterNumber;
  1202. pFileContext->LinkStationCount = 255;
  1203. pFileContext->pSecurityDescriptor = pDlcParms->DirOpenAdapter.pSecurityDescriptor;
  1204. //
  1205. // Read the most recent cumulative NDIS error counters
  1206. // to the file context. DLC error counters will be counted
  1207. // from 0 and they may be reset.
  1208. //
  1209. GetDlcErrorCounters(pFileContext, NULL);
  1210. pFileContext->State = DLC_FILE_CONTEXT_OPEN;
  1211. }
  1212. //
  1213. // We may directly return whatever the LLC binding primitive gives us
  1214. //
  1215. return Status;
  1216. }
  1217. NTSTATUS
  1218. DirCloseAdapter(
  1219. IN PIRP pIrp,
  1220. IN PDLC_FILE_CONTEXT pFileContext,
  1221. IN PNT_DLC_PARMS pDlcParms,
  1222. IN ULONG InputBufferLength,
  1223. IN ULONG OutputBufferLength
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. This primitive initializes the close adapter operation.
  1228. It first closes all open link and sap stations and
  1229. then optionally chains the canceled commands and
  1230. receive buffers to a READ command. If no read commands
  1231. was found, then the CCBs are linked to the CCB pointer
  1232. of this command.
  1233. The actual file close should only delete the file
  1234. object, except, if the application exits, when it still has
  1235. open dlc api handles. In that case the file close routine
  1236. will call this procedure to shut down the dlc file context.
  1237. Arguments:
  1238. pIrp - current io request packet
  1239. pFileContext - DLC process specific adapter context
  1240. pDlcParms - the current parameter block
  1241. InputBufferLength - the length of input parameters
  1242. OutputBufferLength -
  1243. Return Value:
  1244. NTSTATUS
  1245. STATUS_PENDING
  1246. The adapter is being closed
  1247. DLC_STATUS_ADAPTER_CLOSED
  1248. The adapter is already closed
  1249. NOTE: This is a SYNCHRONOUS return code! And will cause the IRP
  1250. to be completed
  1251. --*/
  1252. {
  1253. UNREFERENCED_PARAMETER(pDlcParms);
  1254. UNREFERENCED_PARAMETER(InputBufferLength);
  1255. UNREFERENCED_PARAMETER(OutputBufferLength);
  1256. ASSUME_IRQL(DISPATCH_LEVEL);
  1257. DIAG_FUNCTION("DirCloseAdapter");
  1258. DLC_TRACE('J');
  1259. if (pFileContext->State != DLC_FILE_CONTEXT_OPEN) {
  1260. return DLC_STATUS_ADAPTER_CLOSED;
  1261. }
  1262. #if LLC_DBG == 2
  1263. DbgPrint( "*** Top memory consumption (before adapter close) *** \n" );
  1264. PrintMemStatus();
  1265. #endif
  1266. //
  1267. // This disables any further commands (including DirCloseAdapter)
  1268. //
  1269. pFileContext->State = DLC_FILE_CONTEXT_CLOSE_PENDING;
  1270. //
  1271. // Remove first all functional, group or multicast addresses
  1272. // set in the adapter by the current DLC application process
  1273. //
  1274. if (pFileContext->pBindingContext) {
  1275. LEAVE_DLC(pFileContext);
  1276. LlcResetBroadcastAddresses(pFileContext->pBindingContext);
  1277. ENTER_DLC(pFileContext);
  1278. }
  1279. //
  1280. // We must use the static closing packet, because the adapter close
  1281. // must succeed even if we could not allocate any packets
  1282. //
  1283. CloseAllStations(pFileContext,
  1284. pIrp,
  1285. DLC_COMMAND_COMPLETION,
  1286. CompleteDirCloseAdapter,
  1287. pDlcParms,
  1288. &pFileContext->ClosingPacket
  1289. );
  1290. return STATUS_PENDING;
  1291. }
  1292. VOID
  1293. CompleteDirCloseAdapter(
  1294. IN PDLC_FILE_CONTEXT pFileContext,
  1295. IN PDLC_CLOSE_WAIT_INFO pClosingInfo,
  1296. IN PVOID pCcbLink
  1297. )
  1298. /*++
  1299. Routine Description:
  1300. Finishes DIR.CLOSE.ADAPTER command
  1301. Arguments:
  1302. pFileContext - DLC adapter open context
  1303. pClosingInfo - packet structure, that includes all data of this command
  1304. pCcbLink - the orginal user mode ccb address on the next CCB, that
  1305. will be chained to the completed command.
  1306. Return Value:
  1307. None
  1308. --*/
  1309. {
  1310. ASSUME_IRQL(DISPATCH_LEVEL);
  1311. DLC_TRACE('K');
  1312. //
  1313. // reference the file context to stop any of the dereferences below, or in
  1314. // functions called by this routine destroying it
  1315. //
  1316. ReferenceFileContext(pFileContext);
  1317. //
  1318. // Disconnect (or unbind) llc driver from us
  1319. //
  1320. if (pFileContext->pBindingContext) {
  1321. LEAVE_DLC(pFileContext);
  1322. LlcDisableAdapter(pFileContext->pBindingContext);
  1323. ENTER_DLC(pFileContext);
  1324. }
  1325. if (IoGetCurrentIrpStackLocation(pClosingInfo->pIrp)->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
  1326. CompleteAsyncCommand(pFileContext, STATUS_SUCCESS, pClosingInfo->pIrp, pCcbLink, FALSE);
  1327. } else {
  1328. //
  1329. // This is a normal FILE CLOSE !!! (IRP_MJ_CLEANUP)
  1330. //
  1331. ASSERT(IoGetCurrentIrpStackLocation(pClosingInfo->pIrp)->MajorFunction == IRP_MJ_CLEANUP);
  1332. //
  1333. // Dereference for the cleanup. This will allow cleanup to become
  1334. // unblocked.
  1335. //
  1336. DereferenceFileContext(pFileContext);
  1337. }
  1338. //
  1339. // We must delete the buffer pool now, because the dereference
  1340. // of the driver object starts the final process exit
  1341. // completion, that bug chekcs, if the number of the locked
  1342. // pages is non zero.
  1343. //
  1344. DereferenceBufferPool(pFileContext);
  1345. //
  1346. // We create two references for file context, when it is created
  1347. // the other is decremented here and the other when the synchronous
  1348. // part of command completion has been done
  1349. //
  1350. pFileContext->State = DLC_FILE_CONTEXT_CLOSED;
  1351. //
  1352. // This should be the last reference of the file context
  1353. // (if no IRPs operations are in execution or pending.
  1354. //
  1355. DereferenceFileContext(pFileContext);
  1356. }
  1357. NTSTATUS
  1358. DlcCompleteCommand(
  1359. IN PIRP pIrp,
  1360. IN PDLC_FILE_CONTEXT pFileContext,
  1361. IN PNT_DLC_PARMS pDlcParms,
  1362. IN ULONG InputBufferLength,
  1363. IN ULONG OutputBufferLength
  1364. )
  1365. /*++
  1366. Routine Description:
  1367. Procedure queues the given CCB to the completion list.
  1368. This routine is used to save the synchronous commands from
  1369. DLC API DLL to event queue. This must be done whenever a
  1370. synchronous command has a non null command completion flag.
  1371. Arguments:
  1372. pIrp - current io request packet
  1373. pFileContext - DLC address object
  1374. pDlcParms - the current parameter block
  1375. InputBufferLength - the length of input parameters
  1376. OutputBufferLength -
  1377. Return Value:
  1378. NTSTATUS:
  1379. STATUS_SUCCESS
  1380. --*/
  1381. {
  1382. UNREFERENCED_PARAMETER(pIrp);
  1383. UNREFERENCED_PARAMETER(InputBufferLength);
  1384. UNREFERENCED_PARAMETER(OutputBufferLength);
  1385. if (pDlcParms->CompleteCommand.CommandCompletionFlag == 0
  1386. || pDlcParms->CompleteCommand.pCcbPointer == NULL) {
  1387. //
  1388. // This is more likely an internal error!
  1389. //
  1390. return DLC_STATUS_INTERNAL_ERROR;
  1391. }
  1392. return MakeDlcEvent(pFileContext,
  1393. DLC_COMMAND_COMPLETION,
  1394. pDlcParms->CompleteCommand.StationId,
  1395. NULL,
  1396. pDlcParms->CompleteCommand.pCcbPointer,
  1397. pDlcParms->CompleteCommand.CommandCompletionFlag,
  1398. FALSE
  1399. );
  1400. }