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.

1083 lines
25 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. This module contains the ioctl interface to this driver
  7. Author:
  8. Anil Francis Thomas (10/98)
  9. Environment:
  10. Kernel
  11. Revision History:
  12. DChen 092499 Bug fixes
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #define MODULE_ID MODULE_IOCTL
  17. NTSTATUS AtmSmDispatch(
  18. IN PDEVICE_OBJECT pDeviceObject,
  19. IN PIRP pIrp
  20. )
  21. /*++
  22. Routine Description:
  23. This is the common dispath routine for user Ioctls
  24. Arguments:
  25. Return Value:
  26. None
  27. --*/
  28. {
  29. NTSTATUS Status;
  30. ULONG ulBytesWritten = 0;
  31. PIO_STACK_LOCATION pIrpSp;
  32. TraceIn(AtmSmDispatch);
  33. //
  34. // Get current Irp stack location
  35. //
  36. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  37. pIrp->IoStatus.Information = 0;
  38. switch(pIrpSp->MajorFunction)
  39. {
  40. case IRP_MJ_CREATE: {
  41. DbgLoud(("IRP_MJ_CREATE\n"));
  42. InterlockedIncrement(&AtmSmGlobal.ulNumCreates);
  43. Status = STATUS_SUCCESS;
  44. break;
  45. }
  46. case IRP_MJ_CLOSE: {
  47. DbgLoud(("IRP_MJ_CLOSE\n"));
  48. Status = STATUS_SUCCESS;
  49. break;
  50. }
  51. case IRP_MJ_CLEANUP: {
  52. DbgLoud(("IRP_MJ_CLEANUP\n"));
  53. Status = STATUS_SUCCESS;
  54. InterlockedDecrement(&AtmSmGlobal.ulNumCreates);
  55. break;
  56. }
  57. case IRP_MJ_DEVICE_CONTROL: {
  58. ULONG ulControlCode;
  59. ULONG ulControlFunc;
  60. ulControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
  61. ulControlFunc = IoGetFunctionCodeFromCtlCode(ulControlCode);
  62. // verify the IOCTL codes
  63. if(DEVICE_TYPE_FROM_CTL_CODE(ulControlCode) == FILE_DEVICE_ATMSM &&
  64. ulControlFunc < ATMSM_NUM_IOCTLS &&
  65. AtmSmIoctlTable[ulControlFunc] == ulControlCode)
  66. {
  67. // set the status to PENDING by default
  68. pIrp->IoStatus.Status = STATUS_PENDING;
  69. Status = (*AtmSmFuncProcessIoctl[ulControlFunc])(pIrp, pIrpSp);
  70. }
  71. else
  72. {
  73. DbgErr(("Unknown IRP_MJ_DEVICE_CONTROL code - %x\n",
  74. ulControlCode));
  75. Status = STATUS_INVALID_PARAMETER;
  76. }
  77. break;
  78. }
  79. default: {
  80. DbgErr(("Unknown IRP_MJ_XX - %x\n",pIrpSp->MajorFunction));
  81. Status = STATUS_INVALID_PARAMETER;
  82. break;
  83. }
  84. }
  85. if(STATUS_PENDING != Status)
  86. {
  87. pIrp->IoStatus.Status = Status;
  88. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  89. }
  90. TraceOut(AtmSmDispatch);
  91. return Status;
  92. }
  93. NTSTATUS AtmSmIoctlEnumerateAdapters(
  94. PIRP pIrp,
  95. PIO_STACK_LOCATION pIrpSp
  96. )
  97. /*++
  98. Routine Description:
  99. This routine is called to enumerate the adapters that we are bound to.
  100. NOTE! This uses buffered I/O
  101. Arguments:
  102. Return Value:
  103. Status - doesn't pend
  104. --*/
  105. {
  106. NTSTATUS Status = STATUS_SUCCESS;
  107. ULONG ulNum, ulOutputBufLen, ulNeededSize;
  108. PADAPTER_INFO pAdaptInfo = (PADAPTER_INFO)
  109. pIrp->AssociatedIrp.SystemBuffer;
  110. PATMSM_ADAPTER pAdapt;
  111. TraceIn(AtmSmIoctlEnumerateAdapters);
  112. ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  113. ACQUIRE_GLOBAL_LOCK();
  114. ulNeededSize = sizeof(ADAPTER_INFO) +
  115. (sizeof(UCHAR) * NSAP_ADDRESS_LEN *
  116. (AtmSmGlobal.ulAdapterCount - 1));
  117. if(ulOutputBufLen < ulNeededSize)
  118. {
  119. DbgErr(("Output length is not sufficient\n"));
  120. RELEASE_GLOBAL_LOCK();
  121. TraceOut(AtmSmIoctlEnumerateAdapters);
  122. return STATUS_BUFFER_TOO_SMALL;
  123. }
  124. pAdaptInfo->ulNumAdapters = 0;
  125. ulNum = 0;
  126. for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt &&
  127. ulNum < AtmSmGlobal.ulAdapterCount;
  128. pAdapt = pAdapt->pAdapterNext)
  129. {
  130. if(AtmSmReferenceAdapter(pAdapt))
  131. {
  132. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  133. if(0 == (pAdapt->ulFlags & ADAPT_ADDRESS_INVALID))
  134. {
  135. // this is a good adapter
  136. RtlCopyMemory(pAdaptInfo->ucLocalATMAddr[ulNum],
  137. pAdapt->ConfiguredAddress.Address,
  138. (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
  139. pAdaptInfo->ulNumAdapters++;
  140. ulNum++;
  141. }
  142. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  143. AtmSmDereferenceAdapter(pAdapt);
  144. }
  145. }
  146. RELEASE_GLOBAL_LOCK();
  147. pIrp->IoStatus.Information = ulOutputBufLen;
  148. TraceOut(AtmSmIoctlEnumerateAdapters);
  149. return Status;
  150. }
  151. NTSTATUS AtmSmIoctlOpenForRecv(
  152. PIRP pIrp,
  153. PIO_STACK_LOCATION pIrpSp
  154. )
  155. /*++
  156. Routine Description:
  157. This routine is used to open an adapter for receiving all the packets that
  158. come to our SAP. We allow only 1 user to open the adapter for recvs.
  159. NOTE! This uses buffered I/O
  160. Arguments:
  161. Return Value:
  162. Status - doesn't Pend
  163. --*/
  164. {
  165. NTSTATUS Status = STATUS_SUCCESS;
  166. ULONG ulInputBufLen, ulOutputBufLen, ulCompareLength;
  167. POPEN_FOR_RECV_INFO pOpenInfo = (POPEN_FOR_RECV_INFO)
  168. pIrp->AssociatedIrp.SystemBuffer;
  169. PATMSM_ADAPTER pAdapt;
  170. #if DBG
  171. ATM_ADDRESS AtmAddr;
  172. #endif
  173. TraceIn(AtmSmIoctlOpenForRecv);
  174. ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  175. ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  176. if(ulInputBufLen < sizeof(OPEN_FOR_RECV_INFO))
  177. {
  178. DbgErr(("Input length is invalid\n"));
  179. TraceOut(AtmSmIoctlOpenForRecv);
  180. return STATUS_INVALID_PARAMETER;
  181. }
  182. if(ulOutputBufLen < sizeof(HANDLE))
  183. {
  184. DbgErr(("Output length is not sufficient\n"));
  185. TraceOut(AtmSmIoctlOpenForRecv);
  186. return STATUS_BUFFER_TOO_SMALL;
  187. }
  188. #if DBG
  189. AtmAddr.AddressType = ATM_NSAP;
  190. AtmAddr.NumberOfDigits = ATM_ADDRESS_LENGTH;
  191. RtlCopyMemory(AtmAddr.Address, pOpenInfo->ucLocalATMAddr,
  192. (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
  193. DumpATMAddress(ATMSMD_INFO, "Recv Open - Local AtmAddress - ", &AtmAddr);
  194. #endif
  195. do
  196. { // break off loop
  197. //
  198. // grab the global lock and find out which adapter is being refered to.
  199. //
  200. ACQUIRE_GLOBAL_LOCK();
  201. // we don't compare the selector byte
  202. ulCompareLength = sizeof(UCHAR) * (ATM_ADDRESS_LENGTH - 1);
  203. for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt;
  204. pAdapt = pAdapt->pAdapterNext)
  205. {
  206. if(ulCompareLength == RtlCompareMemory(
  207. pOpenInfo->ucLocalATMAddr,
  208. pAdapt->ConfiguredAddress.Address,
  209. ulCompareLength))
  210. break;
  211. }
  212. if(NULL == pAdapt)
  213. {
  214. RELEASE_GLOBAL_LOCK();
  215. DbgErr(("Specified adapter address not found.\n"));
  216. Status = STATUS_OBJECT_NAME_INVALID;
  217. break;
  218. }
  219. // we have found the adapter put a reference on it
  220. if(!AtmSmReferenceAdapter(pAdapt))
  221. {
  222. RELEASE_GLOBAL_LOCK();
  223. DbgErr(("Couldn't put a reference on the adapter.\n"));
  224. Status = STATUS_UNSUCCESSFUL;
  225. break;
  226. }
  227. RELEASE_GLOBAL_LOCK();
  228. // we have a reference on the adapter now
  229. // check if it is already opened for recv's . We allow only
  230. // one receiver.
  231. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  232. if(pAdapt->fAdapterOpenedForRecv)
  233. {
  234. // we already have an open for recv
  235. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  236. AtmSmDereferenceAdapter(pAdapt);
  237. DbgErr(("Already opened for recvs.\n"));
  238. Status = STATUS_UNSUCCESSFUL;
  239. break;
  240. }
  241. pAdapt->fAdapterOpenedForRecv = TRUE;
  242. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  243. // now set the opencontext
  244. *(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer) = (HANDLE)pAdapt;
  245. pIrp->IoStatus.Information = sizeof(HANDLE);
  246. DbgInfo(("Success! Recv Open Context - 0x%x\n", pAdapt));
  247. // remove the reference added when opening for recvs
  248. AtmSmDereferenceAdapter(pAdapt);
  249. } while(FALSE);
  250. TraceOut(AtmSmIoctlOpenForRecv);
  251. return Status;
  252. }
  253. NTSTATUS AtmSmIoctlRecvData(
  254. PIRP pIrp,
  255. PIO_STACK_LOCATION pIrpSp
  256. )
  257. /*++
  258. Routine Description:
  259. This routine is used to transfer data from network packets into the user
  260. buffers. If a packet is queued up, then we will immediately complete
  261. this reuqest.
  262. NOTE! This uses Direct I/O for buffer to recv data
  263. Arguments:
  264. Return Value:
  265. Status - Success, Pending or error
  266. --*/
  267. {
  268. NTSTATUS Status = STATUS_SUCCESS;
  269. ULONG ulInputBufLen, ulOutputBufLen;
  270. PATMSM_ADAPTER pAdapt;
  271. ULONG ulControlCode;
  272. TraceIn(AtmSmIoctlRecvData);
  273. ulControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
  274. ASSERT(METHOD_OUT_DIRECT == (ulControlCode & 0x3));
  275. ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  276. if(ulInputBufLen < sizeof(HANDLE))
  277. {
  278. DbgErr(("Input length is invalid\n"));
  279. TraceOut(AtmSmIoctlRecvData);
  280. return STATUS_INVALID_PARAMETER;
  281. }
  282. ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  283. if(0 == ulOutputBufLen)
  284. {
  285. DbgErr(("Output buffer length is 0!\n"));
  286. TraceOut(AtmSmIoctlRecvData);
  287. return STATUS_INVALID_PARAMETER;
  288. }
  289. DbgLoud(("Recv - Output buffer length = %u\n", ulOutputBufLen));
  290. pAdapt = (PATMSM_ADAPTER)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
  291. DbgLoud(("Recv Context is 0x%x\n", pAdapt));
  292. // Note - VerifyRecvOpenContext adds a reference to the adapter
  293. // if successful, which we remove when we are done
  294. if(STATUS_SUCCESS != (Status = VerifyRecvOpenContext(pAdapt)))
  295. {
  296. TraceOut(AtmSmIoctlRecvData);
  297. return Status;
  298. }
  299. // we have a valid RecvContext - check if a recv is already queued
  300. do
  301. { // break off loop
  302. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  303. if(pAdapt->pRecvIrp)
  304. {
  305. // there is already an Irp pending
  306. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  307. Status = STATUS_UNSUCCESSFUL;
  308. DbgErr(("There is already a recv pending\n"));
  309. break;
  310. }
  311. // No irps pending, check if a queued packets is there, if so copy
  312. // else queue ourselves
  313. if(pAdapt->pRecvPktNext)
  314. {
  315. PPROTO_RSVD pPRsvd;
  316. PNDIS_PACKET pPkt;
  317. pPkt = pAdapt->pRecvPktNext;
  318. pPRsvd = GET_PROTO_RSVD(pPkt);
  319. pAdapt->pRecvPktNext = pPRsvd->pPktNext;
  320. if(pAdapt->pRecvLastPkt == pPkt)
  321. pAdapt->pRecvLastPkt = NULL;
  322. pAdapt->ulRecvPktsCount--;
  323. // release the recv queue lock
  324. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  325. // Copy the packet to the Irp buffer
  326. // Note this may be partial if the Irp buffer is not large enough
  327. pIrp->IoStatus.Information =
  328. CopyPacketToIrp(pIrp, pPkt);
  329. // return the packet to the miniport
  330. NdisReturnPackets(&pPkt, 1);
  331. // Status success
  332. }
  333. else
  334. {
  335. // no packets available, queue this Irp
  336. pAdapt->pRecvIrp = pIrp;
  337. // release the recv queue lock
  338. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  339. IoMarkIrpPending(pIrp);
  340. Status = STATUS_PENDING;
  341. }
  342. }while(FALSE);
  343. // remove the reference added while verifying
  344. AtmSmDereferenceAdapter(pAdapt);
  345. TraceOut(AtmSmIoctlRecvData);
  346. return Status;
  347. }
  348. NTSTATUS AtmSmIoctlCloseRecvHandle(
  349. PIRP pIrp,
  350. PIO_STACK_LOCATION pIrpSp
  351. )
  352. /*++
  353. Routine Description:
  354. This routine is used to close a handle that was obtained when the adapter
  355. was opened for recvs.
  356. NOTE! This uses buffered I/O
  357. Arguments:
  358. Return Value:
  359. Status - doesn't pend
  360. --*/
  361. {
  362. NTSTATUS Status = STATUS_SUCCESS;
  363. ULONG ulInputBufLen;
  364. PATMSM_ADAPTER pAdapt;
  365. TraceIn(AtmSmIoctlCloseRecvHandle);
  366. ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  367. if(ulInputBufLen < sizeof(HANDLE))
  368. {
  369. DbgErr(("Input length is invalid\n"));
  370. TraceOut(AtmSmIoctlCloseRecvHandle);
  371. return STATUS_INVALID_PARAMETER;
  372. }
  373. pAdapt = (PATMSM_ADAPTER)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
  374. DbgLoud(("Recv Context is 0x%x\n", pAdapt));
  375. // Note - VerifyRecvOpenContext adds a reference to the adapter
  376. // if successful, which we remove when we are done
  377. if(STATUS_SUCCESS != (Status = VerifyRecvOpenContext(pAdapt)))
  378. {
  379. DbgInfo(("Couldn't put a reference on the adapter - pAdapt - 0x%x\n",
  380. pAdapt));
  381. TraceOut(AtmSmIoctlCloseRecvHandle);
  382. return Status;
  383. }
  384. // we have a valid RecvContext
  385. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  386. if(pAdapt->pRecvIrp)
  387. {
  388. PIRP pRecvIrp = pAdapt->pRecvIrp;
  389. pAdapt->pRecvIrp = NULL;
  390. // there is an Irp pending, complete it
  391. pRecvIrp->IoStatus.Status = STATUS_CANCELLED;
  392. pRecvIrp->Cancel = TRUE;
  393. pRecvIrp->IoStatus.Information = 0;
  394. IoCompleteRequest(pRecvIrp, IO_NETWORK_INCREMENT);
  395. }
  396. pAdapt->fAdapterOpenedForRecv = FALSE;
  397. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  398. // remove the reference added while verifying
  399. AtmSmDereferenceAdapter(pAdapt);
  400. pIrp->IoStatus.Information = 0;
  401. TraceOut(AtmSmIoctlCloseRecvHandle);
  402. return Status;
  403. }
  404. NTSTATUS AtmSmIoctlConnectToDsts(
  405. PIRP pIrp,
  406. PIO_STACK_LOCATION pIrpSp
  407. )
  408. /*++
  409. Routine Description:
  410. This routine is used to initiate a connection to 1 (P-P) or more (PMP)
  411. destinations.
  412. NOTE! This uses buffered I/O
  413. Arguments:
  414. Return Value:
  415. Status - Pending or error
  416. --*/
  417. {
  418. NTSTATUS Status = STATUS_SUCCESS;
  419. PCONNECT_INFO pConnectInfo = (PCONNECT_INFO)
  420. pIrp->AssociatedIrp.SystemBuffer;
  421. ULONG ul, ulInputBufLen, ulOutputBufLen, ulCompareLength;
  422. PATMSM_ADAPTER pAdapt;
  423. PATMSM_VC pVc;
  424. #if DBG
  425. ATM_ADDRESS AtmAddr;
  426. #endif
  427. TraceIn(AtmSmIoctlConnectToDsts);
  428. ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  429. ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  430. if(ulInputBufLen < sizeof(CONNECT_INFO))
  431. {
  432. DbgErr(("Input length < sizeof(CONNECT_INFO)\n"));
  433. TraceOut(AtmSmIoctlConnectToDsts);
  434. return STATUS_INVALID_PARAMETER;
  435. }
  436. if(pConnectInfo->ulNumDsts == 0)
  437. {
  438. DbgErr(("Number of destinations is zero\n"));
  439. TraceOut(AtmSmIoctlConnectToDsts);
  440. return STATUS_INVALID_PARAMETER;
  441. }
  442. if((ulInputBufLen - (sizeof(CONNECT_INFO))/(sizeof(UCHAR)*ATM_ADDRESS_LENGTH))
  443. < pConnectInfo->ulNumDsts -1)
  444. {
  445. DbgErr(("Input length is invalid\n"));
  446. TraceOut(AtmSmIoctlConnectToDsts);
  447. return STATUS_INVALID_PARAMETER;
  448. }
  449. if(ulOutputBufLen < sizeof(HANDLE))
  450. {
  451. DbgErr(("Output length is not sufficient\n"));
  452. TraceOut(AtmSmIoctlConnectToDsts);
  453. return STATUS_BUFFER_TOO_SMALL;
  454. }
  455. #if DBG
  456. AtmAddr.AddressType = ATM_NSAP;
  457. AtmAddr.NumberOfDigits = ATM_ADDRESS_LENGTH;
  458. RtlCopyMemory(AtmAddr.Address, pConnectInfo->ucLocalATMAddr,
  459. (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
  460. DumpATMAddress(ATMSMD_INFO, "Connect to Dsts - Local AtmAddress - ",
  461. &AtmAddr);
  462. DbgInfo(("No of destinations - %u\n", pConnectInfo->ulNumDsts));
  463. for(ul = 0; ul < pConnectInfo->ulNumDsts; ul++)
  464. {
  465. RtlCopyMemory(AtmAddr.Address, pConnectInfo->ucDstATMAddrs[ul],
  466. (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
  467. DumpATMAddress(ATMSMD_INFO, " Destination AtmAddress - ", &AtmAddr);
  468. }
  469. #endif
  470. do
  471. { // break off loop
  472. // initialize
  473. Status = STATUS_OBJECT_NAME_INVALID;
  474. //
  475. // grab the global lock and find out which adapter is being refered to.
  476. //
  477. ACQUIRE_GLOBAL_LOCK();
  478. // we don't compare the selector byte
  479. ulCompareLength = sizeof(UCHAR) * (ATM_ADDRESS_LENGTH - 1);
  480. for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt;
  481. pAdapt = pAdapt->pAdapterNext)
  482. {
  483. if(ulCompareLength == RtlCompareMemory(
  484. pConnectInfo->ucLocalATMAddr,
  485. pAdapt->ConfiguredAddress.Address,
  486. ulCompareLength))
  487. {
  488. // create a VC structure
  489. Status = AtmSmAllocVc(pAdapt,
  490. &pVc,
  491. (pConnectInfo->bPMP?
  492. VC_TYPE_PMP_OUTGOING :
  493. VC_TYPE_PP_OUTGOING),
  494. NULL);
  495. if(NDIS_STATUS_SUCCESS != Status)
  496. {
  497. DbgErr(("Failed to create ougoing VC. Status - 0x%X.\n", Status));
  498. Status = STATUS_NO_MEMORY;
  499. }
  500. break;
  501. }
  502. }
  503. RELEASE_GLOBAL_LOCK();
  504. if(Status != NDIS_STATUS_SUCCESS)
  505. {
  506. break;
  507. }
  508. // no need to add reference here since the allocation of VC
  509. // will add a reference to the Adapter
  510. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  511. if(!pConnectInfo->bPMP)
  512. {
  513. // this is P-P
  514. // copy the destination address
  515. PATM_ADDRESS pAtmAddr = &pVc->HwAddr.Address;
  516. pAtmAddr->AddressType = ATM_NSAP;
  517. pAtmAddr->NumberOfDigits = ATM_ADDRESS_LENGTH;
  518. RtlCopyMemory(pAtmAddr->Address, pConnectInfo->ucDstATMAddrs[0],
  519. (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
  520. // Note: we don't get the correct selector byte from user mode
  521. // we assume the selector byte used by the destination is
  522. // the same.
  523. pAtmAddr->Address[ATM_ADDRESS_LENGTH-1] = pAdapt->SelByte;
  524. }
  525. else
  526. {
  527. for(ul = 0; ul < pConnectInfo->ulNumDsts; ul++)
  528. {
  529. PATMSM_PMP_MEMBER pMember;
  530. PATM_ADDRESS pAtmAddr;
  531. AtmSmAllocMem(&pMember, PATMSM_PMP_MEMBER,
  532. sizeof(ATMSM_PMP_MEMBER));
  533. if(NULL == pMember)
  534. {
  535. DbgErr(("Failed to allocate member. No resources\n"));
  536. // cleanup the members and VC
  537. while(NULL != (pMember = pVc->pPMPMembers))
  538. {
  539. AtmSmFreeMem(pMember);
  540. pVc->ulRefCount--;
  541. }
  542. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  543. AtmSmDereferenceVc(pVc);
  544. Status = STATUS_NO_MEMORY;
  545. break;
  546. }
  547. NdisZeroMemory(pMember, sizeof(ATMSM_PMP_MEMBER));
  548. pMember->ulSignature = atmsm_member_signature;
  549. pMember->pVc = pVc;
  550. ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_IDLE);
  551. pAtmAddr = &pMember->HwAddr.Address;
  552. pAtmAddr->AddressType = ATM_NSAP;
  553. pAtmAddr->NumberOfDigits = ATM_ADDRESS_LENGTH;
  554. RtlCopyMemory(pAtmAddr->Address,
  555. pConnectInfo->ucDstATMAddrs[ul],
  556. (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
  557. // Note: we don't get the correct selector byte from user mode
  558. // we assume the selector byte used by the destination is
  559. // the same.
  560. pAtmAddr->Address[ATM_ADDRESS_LENGTH-1] = pAdapt->SelByte;
  561. pMember->pNext = pVc->pPMPMembers;
  562. pVc->pPMPMembers = pMember;
  563. pVc->ulNumTotalMembers++;
  564. // Also add a reference for each members
  565. pVc->ulRefCount++;
  566. }
  567. }
  568. pVc->pConnectIrp = pIrp;
  569. IoMarkIrpPending(pIrp);
  570. // we will return pending
  571. Status = STATUS_PENDING;
  572. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  573. DbgInfo(("Initiated a VC connection - Adapter 0x%x VC - 0x%x\n",
  574. pAdapt, pVc));
  575. if(!pConnectInfo->bPMP)
  576. {
  577. AtmSmConnectPPVC(pVc);
  578. }
  579. else
  580. {
  581. AtmSmConnectToPMPDestinations(pVc);
  582. }
  583. } while(FALSE);
  584. TraceOut(AtmSmIoctlConnectToDsts);
  585. return Status;
  586. }
  587. NTSTATUS AtmSmIoctlSendToDsts(
  588. PIRP pIrp,
  589. PIO_STACK_LOCATION pIrpSp
  590. )
  591. /*++
  592. Routine Description:
  593. This routine is used to send a packet to destination(s) for which we
  594. already have a connection.
  595. NOTE! This uses Direct I/O for buffer to send data
  596. Arguments:
  597. Return Value:
  598. Status - Pending or error
  599. --*/
  600. {
  601. NTSTATUS Status = STATUS_SUCCESS;
  602. ULONG ulInputBufLen, ulOutputBufLen;
  603. PATMSM_VC pVc;
  604. ULONG ulControlCode;
  605. TraceIn(AtmSmIoctlSendToDsts);
  606. ulControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
  607. ASSERT(METHOD_IN_DIRECT == (ulControlCode & 0x3));
  608. ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  609. if(sizeof(HANDLE) != ulInputBufLen)
  610. {
  611. DbgErr(("Input buffer length is invalid!\n"));
  612. ASSERT(FALSE);
  613. TraceOut(AtmSmIoctlSendToDsts);
  614. return STATUS_INVALID_PARAMETER;
  615. }
  616. ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  617. if(0 == ulOutputBufLen)
  618. {
  619. DbgErr(("Output buffer length is 0!\n"));
  620. ASSERT(FALSE);
  621. TraceOut(AtmSmIoctlRecvData);
  622. return STATUS_INVALID_PARAMETER;
  623. }
  624. DbgLoud(("Send - Output buffer length = %u\n", ulOutputBufLen));
  625. pVc = (PATMSM_VC)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
  626. DbgLoud(("Connect Context is 0x%x\n", pVc));
  627. // Note - VerifyConnectContext adds a reference to the VC
  628. // if successful, which we remove when we are done
  629. if(STATUS_SUCCESS != (Status = VerifyConnectContext(pVc)))
  630. {
  631. TraceOut(AtmSmIoctlSendToDsts);
  632. return Status;
  633. }
  634. // we have a valid ConnectContext
  635. do
  636. { // break off loop
  637. PNDIS_PACKET pPacket;
  638. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  639. //
  640. // Try to get a packet
  641. //
  642. NdisAllocatePacket(
  643. &Status,
  644. &pPacket,
  645. pAdapt->PacketPoolHandle
  646. );
  647. if(NDIS_STATUS_SUCCESS != Status)
  648. {
  649. //
  650. // No free packets
  651. //
  652. Status = STATUS_UNSUCCESSFUL;
  653. break;
  654. }
  655. (GET_PROTO_RSVD(pPacket))->pSendIrp=pIrp;
  656. #ifdef BUG_IN_NEW_DMA
  657. {
  658. PNDIS_BUFFER pBuffer;
  659. PVOID pSrcVA =
  660. MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
  661. UINT uiBufSize =
  662. MmGetMdlByteCount(pIrp->MdlAddress);
  663. if (pSrcVA == NULL)
  664. {
  665. Status = NDIS_STATUS_RESOURCES;
  666. break;
  667. }
  668. // allocate the Buffer Descriptor
  669. NdisAllocateBuffer(&Status,
  670. &pBuffer,
  671. pAdapt->BufferPoolHandle,
  672. pSrcVA,
  673. uiBufSize);
  674. if(NDIS_STATUS_SUCCESS != Status)
  675. {
  676. NdisFreePacket(pPacket);
  677. break;
  678. }
  679. // add the buffer to the packet
  680. NdisChainBufferAtFront(pPacket,
  681. pBuffer);
  682. }
  683. #else // BUG_IN_NEW_DMA
  684. //
  685. // Attach the send buffer to the packet
  686. //
  687. NdisChainBufferAtFront(pPacket, pIrp->MdlAddress);
  688. #endif // BUG_IN_NEW_DMA
  689. IoMarkIrpPending(pIrp);
  690. Status = STATUS_PENDING;
  691. // send the packet on the VC
  692. AtmSmSendPacketOnVc(pVc, pPacket);
  693. }while(FALSE);
  694. // remove the reference added to the VC while verifying
  695. AtmSmDereferenceVc(pVc);
  696. TraceOut(AtmSmIoctlSendToDsts);
  697. return Status;
  698. }
  699. NTSTATUS AtmSmIoctlCloseSendHandle(
  700. PIRP pIrp,
  701. PIO_STACK_LOCATION pIrpSp
  702. )
  703. /*++
  704. Routine Description:
  705. This routine is used to close a handle that was obtained when we established
  706. a connection to destinations.
  707. NOTE! This uses buffered I/O
  708. Arguments:
  709. Return Value:
  710. Status - doesn't pend
  711. --*/
  712. {
  713. NTSTATUS Status = STATUS_SUCCESS;
  714. ULONG ulInputBufLen;
  715. PATMSM_VC pVc;
  716. TraceIn(AtmSmIoctlCloseSendHandle);
  717. ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  718. if(ulInputBufLen < sizeof(HANDLE))
  719. {
  720. DbgErr(("Input length is invalid\n"));
  721. TraceOut(AtmSmIoctlCloseSendHandle);
  722. return STATUS_INVALID_PARAMETER;
  723. }
  724. pVc = (PATMSM_VC)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
  725. DbgLoud(("Connect Context is 0x%x\n", pVc));
  726. // Note - VerifyConnectContext adds a reference to the VC
  727. // if successful, which we remove when we are done
  728. if(STATUS_SUCCESS != (Status = VerifyConnectContext(pVc)))
  729. {
  730. TraceOut(AtmSmIoctlCloseSendHandle);
  731. return Status;
  732. }
  733. // we have a valid Connect Context - disconnect it
  734. AtmSmDisconnectVc(pVc);
  735. // remove the reference added to the VC while verifying
  736. AtmSmDereferenceVc(pVc);
  737. TraceOut(AtmSmIoctlCloseSendHandle);
  738. return Status;
  739. }