|
|
/*++
Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
Module Name:
ioctl.c
Abstract:
This module contains the ioctl interface to this driver
Author:
Anil Francis Thomas (10/98)
Environment:
Kernel
Revision History: DChen 092499 Bug fixes
--*/ #include "precomp.h"
#pragma hdrstop
#define MODULE_ID MODULE_IOCTL
NTSTATUS AtmSmDispatch( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) /*++
Routine Description:
This is the common dispath routine for user Ioctls
Arguments:
Return Value:
None
--*/ { NTSTATUS Status; ULONG ulBytesWritten = 0; PIO_STACK_LOCATION pIrpSp;
TraceIn(AtmSmDispatch);
//
// Get current Irp stack location
//
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
pIrp->IoStatus.Information = 0;
switch(pIrpSp->MajorFunction) {
case IRP_MJ_CREATE: {
DbgLoud(("IRP_MJ_CREATE\n"));
InterlockedIncrement(&AtmSmGlobal.ulNumCreates); Status = STATUS_SUCCESS;
break; }
case IRP_MJ_CLOSE: {
DbgLoud(("IRP_MJ_CLOSE\n"));
Status = STATUS_SUCCESS;
break; }
case IRP_MJ_CLEANUP: {
DbgLoud(("IRP_MJ_CLEANUP\n"));
Status = STATUS_SUCCESS;
InterlockedDecrement(&AtmSmGlobal.ulNumCreates);
break; }
case IRP_MJ_DEVICE_CONTROL: {
ULONG ulControlCode; ULONG ulControlFunc;
ulControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode; ulControlFunc = IoGetFunctionCodeFromCtlCode(ulControlCode);
// verify the IOCTL codes
if(DEVICE_TYPE_FROM_CTL_CODE(ulControlCode) == FILE_DEVICE_ATMSM && ulControlFunc < ATMSM_NUM_IOCTLS && AtmSmIoctlTable[ulControlFunc] == ulControlCode) { // set the status to PENDING by default
pIrp->IoStatus.Status = STATUS_PENDING; Status = (*AtmSmFuncProcessIoctl[ulControlFunc])(pIrp, pIrpSp); } else { DbgErr(("Unknown IRP_MJ_DEVICE_CONTROL code - %x\n", ulControlCode)); Status = STATUS_INVALID_PARAMETER; }
break; }
default: {
DbgErr(("Unknown IRP_MJ_XX - %x\n",pIrpSp->MajorFunction));
Status = STATUS_INVALID_PARAMETER;
break; } }
if(STATUS_PENDING != Status) { pIrp->IoStatus.Status = Status;
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT); }
TraceOut(AtmSmDispatch);
return Status; }
NTSTATUS AtmSmIoctlEnumerateAdapters( PIRP pIrp, PIO_STACK_LOCATION pIrpSp ) /*++
Routine Description:
This routine is called to enumerate the adapters that we are bound to. NOTE! This uses buffered I/O
Arguments:
Return Value:
Status - doesn't pend
--*/ { NTSTATUS Status = STATUS_SUCCESS; ULONG ulNum, ulOutputBufLen, ulNeededSize; PADAPTER_INFO pAdaptInfo = (PADAPTER_INFO) pIrp->AssociatedIrp.SystemBuffer; PATMSM_ADAPTER pAdapt;
TraceIn(AtmSmIoctlEnumerateAdapters);
ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
ACQUIRE_GLOBAL_LOCK();
ulNeededSize = sizeof(ADAPTER_INFO) + (sizeof(UCHAR) * NSAP_ADDRESS_LEN * (AtmSmGlobal.ulAdapterCount - 1));
if(ulOutputBufLen < ulNeededSize) {
DbgErr(("Output length is not sufficient\n"));
RELEASE_GLOBAL_LOCK();
TraceOut(AtmSmIoctlEnumerateAdapters); return STATUS_BUFFER_TOO_SMALL; }
pAdaptInfo->ulNumAdapters = 0;
ulNum = 0; for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt && ulNum < AtmSmGlobal.ulAdapterCount; pAdapt = pAdapt->pAdapterNext) {
if(AtmSmReferenceAdapter(pAdapt)) {
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
if(0 == (pAdapt->ulFlags & ADAPT_ADDRESS_INVALID)) { // this is a good adapter
RtlCopyMemory(pAdaptInfo->ucLocalATMAddr[ulNum], pAdapt->ConfiguredAddress.Address, (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
pAdaptInfo->ulNumAdapters++; ulNum++; }
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
AtmSmDereferenceAdapter(pAdapt); }
}
RELEASE_GLOBAL_LOCK();
pIrp->IoStatus.Information = ulOutputBufLen;
TraceOut(AtmSmIoctlEnumerateAdapters);
return Status; }
NTSTATUS AtmSmIoctlOpenForRecv( PIRP pIrp, PIO_STACK_LOCATION pIrpSp ) /*++
Routine Description:
This routine is used to open an adapter for receiving all the packets that come to our SAP. We allow only 1 user to open the adapter for recvs. NOTE! This uses buffered I/O
Arguments:
Return Value:
Status - doesn't Pend
--*/ { NTSTATUS Status = STATUS_SUCCESS; ULONG ulInputBufLen, ulOutputBufLen, ulCompareLength; POPEN_FOR_RECV_INFO pOpenInfo = (POPEN_FOR_RECV_INFO) pIrp->AssociatedIrp.SystemBuffer; PATMSM_ADAPTER pAdapt;
#if DBG
ATM_ADDRESS AtmAddr; #endif
TraceIn(AtmSmIoctlOpenForRecv);
ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength; ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if(ulInputBufLen < sizeof(OPEN_FOR_RECV_INFO)) {
DbgErr(("Input length is invalid\n")); TraceOut(AtmSmIoctlOpenForRecv); return STATUS_INVALID_PARAMETER; }
if(ulOutputBufLen < sizeof(HANDLE)) {
DbgErr(("Output length is not sufficient\n")); TraceOut(AtmSmIoctlOpenForRecv); return STATUS_BUFFER_TOO_SMALL; }
#if DBG
AtmAddr.AddressType = ATM_NSAP; AtmAddr.NumberOfDigits = ATM_ADDRESS_LENGTH; RtlCopyMemory(AtmAddr.Address, pOpenInfo->ucLocalATMAddr, (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
DumpATMAddress(ATMSMD_INFO, "Recv Open - Local AtmAddress - ", &AtmAddr); #endif
do { // break off loop
//
// grab the global lock and find out which adapter is being refered to.
//
ACQUIRE_GLOBAL_LOCK();
// we don't compare the selector byte
ulCompareLength = sizeof(UCHAR) * (ATM_ADDRESS_LENGTH - 1);
for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt; pAdapt = pAdapt->pAdapterNext) {
if(ulCompareLength == RtlCompareMemory( pOpenInfo->ucLocalATMAddr, pAdapt->ConfiguredAddress.Address, ulCompareLength)) break; }
if(NULL == pAdapt) { RELEASE_GLOBAL_LOCK();
DbgErr(("Specified adapter address not found.\n")); Status = STATUS_OBJECT_NAME_INVALID; break; }
// we have found the adapter put a reference on it
if(!AtmSmReferenceAdapter(pAdapt)) { RELEASE_GLOBAL_LOCK();
DbgErr(("Couldn't put a reference on the adapter.\n")); Status = STATUS_UNSUCCESSFUL; break; }
RELEASE_GLOBAL_LOCK();
// we have a reference on the adapter now
// check if it is already opened for recv's . We allow only
// one receiver.
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
if(pAdapt->fAdapterOpenedForRecv) { // we already have an open for recv
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
AtmSmDereferenceAdapter(pAdapt); DbgErr(("Already opened for recvs.\n")); Status = STATUS_UNSUCCESSFUL; break; }
pAdapt->fAdapterOpenedForRecv = TRUE;
RELEASE_ADAPTER_GEN_LOCK(pAdapt); // now set the opencontext
*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer) = (HANDLE)pAdapt; pIrp->IoStatus.Information = sizeof(HANDLE);
DbgInfo(("Success! Recv Open Context - 0x%x\n", pAdapt));
// remove the reference added when opening for recvs
AtmSmDereferenceAdapter(pAdapt);
} while(FALSE);
TraceOut(AtmSmIoctlOpenForRecv);
return Status; }
NTSTATUS AtmSmIoctlRecvData( PIRP pIrp, PIO_STACK_LOCATION pIrpSp ) /*++
Routine Description: This routine is used to transfer data from network packets into the user buffers. If a packet is queued up, then we will immediately complete this reuqest.
NOTE! This uses Direct I/O for buffer to recv data
Arguments:
Return Value:
Status - Success, Pending or error
--*/ { NTSTATUS Status = STATUS_SUCCESS; ULONG ulInputBufLen, ulOutputBufLen; PATMSM_ADAPTER pAdapt; ULONG ulControlCode;
TraceIn(AtmSmIoctlRecvData);
ulControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
ASSERT(METHOD_OUT_DIRECT == (ulControlCode & 0x3));
ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
if(ulInputBufLen < sizeof(HANDLE)) {
DbgErr(("Input length is invalid\n")); TraceOut(AtmSmIoctlRecvData); return STATUS_INVALID_PARAMETER; }
ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if(0 == ulOutputBufLen) { DbgErr(("Output buffer length is 0!\n")); TraceOut(AtmSmIoctlRecvData); return STATUS_INVALID_PARAMETER; }
DbgLoud(("Recv - Output buffer length = %u\n", ulOutputBufLen));
pAdapt = (PATMSM_ADAPTER)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
DbgLoud(("Recv Context is 0x%x\n", pAdapt));
// Note - VerifyRecvOpenContext adds a reference to the adapter
// if successful, which we remove when we are done
if(STATUS_SUCCESS != (Status = VerifyRecvOpenContext(pAdapt))) {
TraceOut(AtmSmIoctlRecvData); return Status; }
// we have a valid RecvContext - check if a recv is already queued
do { // break off loop
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt); if(pAdapt->pRecvIrp) {
// there is already an Irp pending
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
Status = STATUS_UNSUCCESSFUL; DbgErr(("There is already a recv pending\n"));
break; }
// No irps pending, check if a queued packets is there, if so copy
// else queue ourselves
if(pAdapt->pRecvPktNext) {
PPROTO_RSVD pPRsvd; PNDIS_PACKET pPkt;
pPkt = pAdapt->pRecvPktNext; pPRsvd = GET_PROTO_RSVD(pPkt);
pAdapt->pRecvPktNext = pPRsvd->pPktNext;
if(pAdapt->pRecvLastPkt == pPkt) pAdapt->pRecvLastPkt = NULL;
pAdapt->ulRecvPktsCount--;
// release the recv queue lock
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
// Copy the packet to the Irp buffer
// Note this may be partial if the Irp buffer is not large enough
pIrp->IoStatus.Information = CopyPacketToIrp(pIrp, pPkt);
// return the packet to the miniport
NdisReturnPackets(&pPkt, 1);
// Status success
} else {
// no packets available, queue this Irp
pAdapt->pRecvIrp = pIrp;
// release the recv queue lock
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
IoMarkIrpPending(pIrp);
Status = STATUS_PENDING; }
}while(FALSE);
// remove the reference added while verifying
AtmSmDereferenceAdapter(pAdapt);
TraceOut(AtmSmIoctlRecvData);
return Status; }
NTSTATUS AtmSmIoctlCloseRecvHandle( PIRP pIrp, PIO_STACK_LOCATION pIrpSp ) /*++
Routine Description:
This routine is used to close a handle that was obtained when the adapter was opened for recvs. NOTE! This uses buffered I/O
Arguments:
Return Value:
Status - doesn't pend
--*/ { NTSTATUS Status = STATUS_SUCCESS; ULONG ulInputBufLen; PATMSM_ADAPTER pAdapt;
TraceIn(AtmSmIoctlCloseRecvHandle);
ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
if(ulInputBufLen < sizeof(HANDLE)) {
DbgErr(("Input length is invalid\n")); TraceOut(AtmSmIoctlCloseRecvHandle); return STATUS_INVALID_PARAMETER; }
pAdapt = (PATMSM_ADAPTER)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
DbgLoud(("Recv Context is 0x%x\n", pAdapt));
// Note - VerifyRecvOpenContext adds a reference to the adapter
// if successful, which we remove when we are done
if(STATUS_SUCCESS != (Status = VerifyRecvOpenContext(pAdapt))) {
DbgInfo(("Couldn't put a reference on the adapter - pAdapt - 0x%x\n", pAdapt)); TraceOut(AtmSmIoctlCloseRecvHandle); return Status; }
// we have a valid RecvContext
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
if(pAdapt->pRecvIrp) {
PIRP pRecvIrp = pAdapt->pRecvIrp;
pAdapt->pRecvIrp = NULL;
// there is an Irp pending, complete it
pRecvIrp->IoStatus.Status = STATUS_CANCELLED; pRecvIrp->Cancel = TRUE; pRecvIrp->IoStatus.Information = 0; IoCompleteRequest(pRecvIrp, IO_NETWORK_INCREMENT);
}
pAdapt->fAdapterOpenedForRecv = FALSE;
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
// remove the reference added while verifying
AtmSmDereferenceAdapter(pAdapt);
pIrp->IoStatus.Information = 0;
TraceOut(AtmSmIoctlCloseRecvHandle);
return Status; }
NTSTATUS AtmSmIoctlConnectToDsts( PIRP pIrp, PIO_STACK_LOCATION pIrpSp ) /*++
Routine Description: This routine is used to initiate a connection to 1 (P-P) or more (PMP) destinations. NOTE! This uses buffered I/O
Arguments:
Return Value:
Status - Pending or error
--*/ { NTSTATUS Status = STATUS_SUCCESS; PCONNECT_INFO pConnectInfo = (PCONNECT_INFO) pIrp->AssociatedIrp.SystemBuffer; ULONG ul, ulInputBufLen, ulOutputBufLen, ulCompareLength; PATMSM_ADAPTER pAdapt; PATMSM_VC pVc;
#if DBG
ATM_ADDRESS AtmAddr; #endif
TraceIn(AtmSmIoctlConnectToDsts);
ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength; ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if(ulInputBufLen < sizeof(CONNECT_INFO)) { DbgErr(("Input length < sizeof(CONNECT_INFO)\n")); TraceOut(AtmSmIoctlConnectToDsts); return STATUS_INVALID_PARAMETER; } if(pConnectInfo->ulNumDsts == 0) { DbgErr(("Number of destinations is zero\n")); TraceOut(AtmSmIoctlConnectToDsts); return STATUS_INVALID_PARAMETER; }
if((ulInputBufLen - (sizeof(CONNECT_INFO))/(sizeof(UCHAR)*ATM_ADDRESS_LENGTH)) < pConnectInfo->ulNumDsts -1) { DbgErr(("Input length is invalid\n")); TraceOut(AtmSmIoctlConnectToDsts); return STATUS_INVALID_PARAMETER; }
if(ulOutputBufLen < sizeof(HANDLE)) { DbgErr(("Output length is not sufficient\n")); TraceOut(AtmSmIoctlConnectToDsts); return STATUS_BUFFER_TOO_SMALL; }
#if DBG
AtmAddr.AddressType = ATM_NSAP; AtmAddr.NumberOfDigits = ATM_ADDRESS_LENGTH; RtlCopyMemory(AtmAddr.Address, pConnectInfo->ucLocalATMAddr, (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
DumpATMAddress(ATMSMD_INFO, "Connect to Dsts - Local AtmAddress - ", &AtmAddr);
DbgInfo(("No of destinations - %u\n", pConnectInfo->ulNumDsts));
for(ul = 0; ul < pConnectInfo->ulNumDsts; ul++) {
RtlCopyMemory(AtmAddr.Address, pConnectInfo->ucDstATMAddrs[ul], (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
DumpATMAddress(ATMSMD_INFO, " Destination AtmAddress - ", &AtmAddr); }
#endif
do { // break off loop
// initialize
Status = STATUS_OBJECT_NAME_INVALID;
//
// grab the global lock and find out which adapter is being refered to.
//
ACQUIRE_GLOBAL_LOCK();
// we don't compare the selector byte
ulCompareLength = sizeof(UCHAR) * (ATM_ADDRESS_LENGTH - 1);
for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt; pAdapt = pAdapt->pAdapterNext) {
if(ulCompareLength == RtlCompareMemory( pConnectInfo->ucLocalATMAddr, pAdapt->ConfiguredAddress.Address, ulCompareLength)) { // create a VC structure
Status = AtmSmAllocVc(pAdapt, &pVc, (pConnectInfo->bPMP? VC_TYPE_PMP_OUTGOING : VC_TYPE_PP_OUTGOING), NULL); if(NDIS_STATUS_SUCCESS != Status) { DbgErr(("Failed to create ougoing VC. Status - 0x%X.\n", Status)); Status = STATUS_NO_MEMORY; }
break; } }
RELEASE_GLOBAL_LOCK();
if(Status != NDIS_STATUS_SUCCESS) { break; }
// no need to add reference here since the allocation of VC
// will add a reference to the Adapter
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
if(!pConnectInfo->bPMP) {
// this is P-P
// copy the destination address
PATM_ADDRESS pAtmAddr = &pVc->HwAddr.Address;
pAtmAddr->AddressType = ATM_NSAP; pAtmAddr->NumberOfDigits = ATM_ADDRESS_LENGTH; RtlCopyMemory(pAtmAddr->Address, pConnectInfo->ucDstATMAddrs[0], (sizeof(UCHAR) * ATM_ADDRESS_LENGTH)); // Note: we don't get the correct selector byte from user mode
// we assume the selector byte used by the destination is
// the same.
pAtmAddr->Address[ATM_ADDRESS_LENGTH-1] = pAdapt->SelByte;
} else {
for(ul = 0; ul < pConnectInfo->ulNumDsts; ul++) {
PATMSM_PMP_MEMBER pMember; PATM_ADDRESS pAtmAddr;
AtmSmAllocMem(&pMember, PATMSM_PMP_MEMBER, sizeof(ATMSM_PMP_MEMBER));
if(NULL == pMember) {
DbgErr(("Failed to allocate member. No resources\n"));
// cleanup the members and VC
while(NULL != (pMember = pVc->pPMPMembers)) { AtmSmFreeMem(pMember); pVc->ulRefCount--; }
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
AtmSmDereferenceVc(pVc);
Status = STATUS_NO_MEMORY; break; }
NdisZeroMemory(pMember, sizeof(ATMSM_PMP_MEMBER));
pMember->ulSignature = atmsm_member_signature; pMember->pVc = pVc; ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_IDLE); pAtmAddr = &pMember->HwAddr.Address;
pAtmAddr->AddressType = ATM_NSAP; pAtmAddr->NumberOfDigits = ATM_ADDRESS_LENGTH; RtlCopyMemory(pAtmAddr->Address, pConnectInfo->ucDstATMAddrs[ul], (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
// Note: we don't get the correct selector byte from user mode
// we assume the selector byte used by the destination is
// the same.
pAtmAddr->Address[ATM_ADDRESS_LENGTH-1] = pAdapt->SelByte;
pMember->pNext = pVc->pPMPMembers; pVc->pPMPMembers = pMember; pVc->ulNumTotalMembers++;
// Also add a reference for each members
pVc->ulRefCount++; }
}
pVc->pConnectIrp = pIrp;
IoMarkIrpPending(pIrp);
// we will return pending
Status = STATUS_PENDING;
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
DbgInfo(("Initiated a VC connection - Adapter 0x%x VC - 0x%x\n", pAdapt, pVc)); if(!pConnectInfo->bPMP) {
AtmSmConnectPPVC(pVc);
} else {
AtmSmConnectToPMPDestinations(pVc); }
} while(FALSE);
TraceOut(AtmSmIoctlConnectToDsts);
return Status; }
NTSTATUS AtmSmIoctlSendToDsts( PIRP pIrp, PIO_STACK_LOCATION pIrpSp ) /*++
Routine Description: This routine is used to send a packet to destination(s) for which we already have a connection. NOTE! This uses Direct I/O for buffer to send data
Arguments:
Return Value:
Status - Pending or error --*/ { NTSTATUS Status = STATUS_SUCCESS; ULONG ulInputBufLen, ulOutputBufLen; PATMSM_VC pVc; ULONG ulControlCode;
TraceIn(AtmSmIoctlSendToDsts);
ulControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
ASSERT(METHOD_IN_DIRECT == (ulControlCode & 0x3));
ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
if(sizeof(HANDLE) != ulInputBufLen) { DbgErr(("Input buffer length is invalid!\n")); ASSERT(FALSE); TraceOut(AtmSmIoctlSendToDsts); return STATUS_INVALID_PARAMETER; }
ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if(0 == ulOutputBufLen) { DbgErr(("Output buffer length is 0!\n")); ASSERT(FALSE); TraceOut(AtmSmIoctlRecvData); return STATUS_INVALID_PARAMETER; }
DbgLoud(("Send - Output buffer length = %u\n", ulOutputBufLen));
pVc = (PATMSM_VC)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
DbgLoud(("Connect Context is 0x%x\n", pVc));
// Note - VerifyConnectContext adds a reference to the VC
// if successful, which we remove when we are done
if(STATUS_SUCCESS != (Status = VerifyConnectContext(pVc))) {
TraceOut(AtmSmIoctlSendToDsts); return Status; }
// we have a valid ConnectContext
do { // break off loop
PNDIS_PACKET pPacket; PATMSM_ADAPTER pAdapt = pVc->pAdapt; //
// Try to get a packet
//
NdisAllocatePacket( &Status, &pPacket, pAdapt->PacketPoolHandle );
if(NDIS_STATUS_SUCCESS != Status) {
//
// No free packets
//
Status = STATUS_UNSUCCESSFUL; break; }
(GET_PROTO_RSVD(pPacket))->pSendIrp=pIrp;
#ifdef BUG_IN_NEW_DMA
{ PNDIS_BUFFER pBuffer; PVOID pSrcVA = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); UINT uiBufSize = MmGetMdlByteCount(pIrp->MdlAddress);
if (pSrcVA == NULL) { Status = NDIS_STATUS_RESOURCES; break; }
// allocate the Buffer Descriptor
NdisAllocateBuffer(&Status, &pBuffer, pAdapt->BufferPoolHandle, pSrcVA, uiBufSize);
if(NDIS_STATUS_SUCCESS != Status) { NdisFreePacket(pPacket); break; }
// add the buffer to the packet
NdisChainBufferAtFront(pPacket, pBuffer);
}
#else // BUG_IN_NEW_DMA
//
// Attach the send buffer to the packet
//
NdisChainBufferAtFront(pPacket, pIrp->MdlAddress);
#endif // BUG_IN_NEW_DMA
IoMarkIrpPending(pIrp);
Status = STATUS_PENDING;
// send the packet on the VC
AtmSmSendPacketOnVc(pVc, pPacket);
}while(FALSE);
// remove the reference added to the VC while verifying
AtmSmDereferenceVc(pVc);
TraceOut(AtmSmIoctlSendToDsts);
return Status; }
NTSTATUS AtmSmIoctlCloseSendHandle( PIRP pIrp, PIO_STACK_LOCATION pIrpSp ) /*++
Routine Description:
This routine is used to close a handle that was obtained when we established a connection to destinations. NOTE! This uses buffered I/O
Arguments:
Return Value:
Status - doesn't pend
--*/ { NTSTATUS Status = STATUS_SUCCESS; ULONG ulInputBufLen; PATMSM_VC pVc;
TraceIn(AtmSmIoctlCloseSendHandle);
ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
if(ulInputBufLen < sizeof(HANDLE)) {
DbgErr(("Input length is invalid\n")); TraceOut(AtmSmIoctlCloseSendHandle); return STATUS_INVALID_PARAMETER; }
pVc = (PATMSM_VC)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));
DbgLoud(("Connect Context is 0x%x\n", pVc));
// Note - VerifyConnectContext adds a reference to the VC
// if successful, which we remove when we are done
if(STATUS_SUCCESS != (Status = VerifyConnectContext(pVc))) {
TraceOut(AtmSmIoctlCloseSendHandle); return Status; }
// we have a valid Connect Context - disconnect it
AtmSmDisconnectVc(pVc);
// remove the reference added to the VC while verifying
AtmSmDereferenceVc(pVc);
TraceOut(AtmSmIoctlCloseSendHandle);
return Status; }
|