📄 isochapi.c
字号:
TRACE(TL_TRACE, ("hResource = 0x%x\n", hResource));
TRACE(TL_TRACE, ("nNumberOfDescriptors = 0x%x\n", nNumberOfDescriptors));
TRACE(TL_TRACE, ("R3_IsochDescriptor = 0x%x\n", R3_IsochDescriptor));
if(!nNumberOfDescriptors)
{
TRACE(TL_WARNING, ("IsochAttachBuffers: Invalid nNumberOfDescriptors = 0x%x\n", nNumberOfDescriptors));
ntStatus = STATUS_INVALID_PARAMETER;
goto Exit_IsochAttachBuffers;
}
//
// Just assume that we are being passed a Irp that was created in UserMode
// and allocate one here, because we need to keep an Irp around for
// the callback routine. Must submit this asynchronously so use IoAllocateIrp
//
StackSize = deviceExtension->StackDeviceObject->StackSize;
newIrp = IoAllocateIrp (StackSize, FALSE);
if (!newIrp) {
TRACE(TL_ERROR, ("Failed to allocate newIrp!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochAttachBuffers;
}
//
// allocate the irb
//
pIrb = ExAllocatePool(NonPagedPool, sizeof(IRB));
if (!pIrb) {
TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochAttachBuffers;
} // if
//
// allocate our isoch descriptors
//
pIsochDescriptor = ExAllocatePool(NonPagedPool, sizeof(ISOCH_DESCRIPTOR)*nNumberOfDescriptors);
if (!pIsochDescriptor) {
TRACE(TL_ERROR, ("Failed to allocate pIsochDescriptor!\n"));
if (pIrb)
ExFreePool(pIrb);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochAttachBuffers;
}
pR3TempDescriptor = R3_IsochDescriptor;
for (i=0;i < nNumberOfDescriptors; i++) {
TRACE(TL_TRACE, ("pR3TempDescriptor = 0x%x\n", pR3TempDescriptor));
TRACE(TL_TRACE, ("pR3TempDescriptor->fulFlags = 0x%x\n", pR3TempDescriptor->fulFlags));
TRACE(TL_TRACE, ("pR3TempDescriptor->ulLength = 0x%x\n", pR3TempDescriptor->ulLength));
TRACE(TL_TRACE, ("pR3TempDescriptor->nMaxBytesPerFrame = 0x%x\n", pR3TempDescriptor->nMaxBytesPerFrame));
TRACE(TL_TRACE, ("pR3TempDescriptor->ulSynch = 0x%x\n", pR3TempDescriptor->ulSynch));
TRACE(TL_TRACE, ("pR3TempDescriptor->ulTag = 0x%x\n", pR3TempDescriptor->ulTag));
TRACE(TL_TRACE, ("pR3TempDescriptor->CycleTime.CL_CycleOffset = 0x%x\n", pR3TempDescriptor->CycleTime.CL_CycleOffset));
TRACE(TL_TRACE, ("pR3TempDescriptor->CycleTime.CL_CycleCount = 0x%x\n", pR3TempDescriptor->CycleTime.CL_CycleCount));
TRACE(TL_TRACE, ("pR3TempDescriptor->CycleTime.CL_SecondCount = 0x%x\n", pR3TempDescriptor->CycleTime.CL_SecondCount));
TRACE(TL_TRACE, ("pR3TempDescriptor->Data = 0x%x\n", &pR3TempDescriptor->Data));
TRACE(TL_TRACE, ("pIsochDescriptor[%x] = 0x%x\n", i, &pIsochDescriptor[i]));
// if we have a ulLength, create the Mdl. if not, Mdl=NULL
if (pR3TempDescriptor->ulLength) {
pIsochDescriptor[i].Mdl = IoAllocateMdl (pR3TempDescriptor->Data,
pR3TempDescriptor->ulLength,
FALSE,
FALSE,
NULL);
if (!pIsochDescriptor[i].Mdl)
{
// we failed to alloc our mdl for this descriptor, free the previosly alloc'd mdls, and exit
TRACE(TL_WARNING, ("Failed to allocate MDL for isoch descriptor num = 0x%x\n", i));
for (j = 0; j < i; j++)
{
if (pIsochDescriptor[j].Mdl)
{
IoFreeMdl (pIsochDescriptor[j].Mdl);
}
}
ExFreePool(pIsochDescriptor);
ntStatus = STATUS_INVALID_PARAMETER;
goto Exit_IsochAttachBuffers;
}
MmBuildMdlForNonPagedPool(pIsochDescriptor[i].Mdl);
pIsochDescriptor[i].ulLength = MmGetMdlByteCount(pIsochDescriptor[i].Mdl);
}
else {
pIsochDescriptor[i].Mdl = NULL;
pIsochDescriptor[i].ulLength = pR3TempDescriptor->ulLength;
}
pIsochDescriptor[i].fulFlags = pR3TempDescriptor->fulFlags;
pIsochDescriptor[i].nMaxBytesPerFrame = pR3TempDescriptor->nMaxBytesPerFrame;
pIsochDescriptor[i].ulSynch = pR3TempDescriptor->ulSynch;
pIsochDescriptor[i].ulTag = pR3TempDescriptor->ulTag;
pIsochDescriptor[i].CycleTime = pR3TempDescriptor->CycleTime;
if (pR3TempDescriptor->bUseCallback) {
//
// i'm hoping this is the last descriptor. they should have only set this in the
// last descriptor, since elsewhere it's not supported.
//
if (i != nNumberOfDescriptors-1) {
TRACE(TL_TRACE, ("Callback on descriptor prior to last!\n"));
// setting callback to NULL
pIsochDescriptor[i].Callback = NULL;
}
else {
// need to save hResource, numDescriptors and Irp to use when detaching.
// this needs to be done before we submit the irp, since the isoch callback
// can be called before the submitirpsynch call completes.
pIsochDetachData = ExAllocatePool(NonPagedPool, sizeof(ISOCH_DETACH_DATA));
if (!pIsochDetachData)
{
for (j = 0; j < i; j++)
{
if (pIsochDescriptor[j].Mdl)
{
IoFreeMdl (pIsochDescriptor[j].Mdl);
}
}
TRACE(TL_ERROR, ("Failed to allocate pIsochDetachData!\n"));
ExFreePool(pIsochDescriptor);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochAttachBuffers;
}
pIsochDetachData->AttachIrb = pIrb;
KeAcquireSpinLock(&deviceExtension->IsochSpinLock, &Irql);
InsertHeadList(&deviceExtension->IsochDetachData, &pIsochDetachData->IsochDetachList);
KeReleaseSpinLock(&deviceExtension->IsochSpinLock, Irql);
KeInitializeTimer(&pIsochDetachData->Timer);
KeInitializeDpc(&pIsochDetachData->TimerDpc, t1394_IsochTimeout, pIsochDetachData);
deltaTime.LowPart = ISOCH_DETACH_TIMEOUT_VALUE;
deltaTime.HighPart = -1;
KeSetTimer(&pIsochDetachData->Timer, deltaTime, &pIsochDetachData->TimerDpc);
pIsochDetachData->outputBufferLength = outputBufferLength;
pIsochDetachData->DeviceExtension = deviceExtension;
pIsochDetachData->hResource = hResource;
pIsochDetachData->numIsochDescriptors = nNumberOfDescriptors;
pIsochDetachData->IsochDescriptor = pIsochDescriptor;
pIsochDetachData->Irp = Irp;
pIsochDetachData->newIrp = newIrp;
pIsochDetachData->bDetach = pR3TempDescriptor->bAutoDetach;
pIsochDescriptor[i].Callback = t1394_IsochCallback;
pIsochDescriptor[i].Context1 = deviceExtension;
pIsochDescriptor[i].Context2 = pIsochDetachData;
TRACE(TL_TRACE, ("IsochAttachBuffers: pIsochDetachData = 0x%x\n", pIsochDetachData));
TRACE(TL_TRACE, ("IsochAttachBuffers: pIsochDetachData->Irp = 0x%x\n", pIsochDetachData->Irp));
}
}
else {
pIsochDescriptor[i].Callback = NULL;
}
TRACE(TL_TRACE, ("pIsochDescriptor[%x].fulFlags = 0x%x\n", i, pIsochDescriptor[i].fulFlags));
TRACE(TL_TRACE, ("pIsochDescriptor[%x].ulLength = 0x%x\n", i, pIsochDescriptor[i].ulLength));
TRACE(TL_TRACE, ("pIsochDescriptor[%x].nMaxBytesPerFrame = 0x%x\n", i, pIsochDescriptor[i].nMaxBytesPerFrame));
TRACE(TL_TRACE, ("pIsochDescriptor[%x].ulSynch = 0x%x\n", i, pIsochDescriptor[i].ulSynch));
TRACE(TL_TRACE, ("pIsochDescriptor[%x].ulTag = 0x%x\n", i, pIsochDescriptor[i].ulTag));
TRACE(TL_TRACE, ("pIsochDescriptor[%x].CycleTime.CL_CycleOffset = 0x%x\n", i, pIsochDescriptor[i].CycleTime.CL_CycleOffset));
TRACE(TL_TRACE, ("pIsochDescriptor[%x].CycleTime.CL_CycleCount = 0x%x\n", i, pIsochDescriptor[i].CycleTime.CL_CycleCount));
TRACE(TL_TRACE, ("pIsochDescriptor[%x].CycleTime.CL_SecondCount = 0x%x\n", i, pIsochDescriptor[i].CycleTime.CL_SecondCount));
pR3TempDescriptor =
(PRING3_ISOCH_DESCRIPTOR)((ULONG_PTR)pR3TempDescriptor +
pIsochDescriptor[i].ulLength +
sizeof(RING3_ISOCH_DESCRIPTOR));
} // for
// lets make sure the device is still around
// if it isn't, we free the irb and return, our pnp
// cleanup will take care of everything else
if (deviceExtension->bShutdown) {
TRACE(TL_TRACE, ("Shutdown!\n"));
ntStatus = STATUS_NO_SUCH_DEVICE;
goto Exit_IsochAttachBuffers;
}
RtlZeroMemory (pIrb, sizeof (IRB));
pIrb->FunctionNumber = REQUEST_ISOCH_ATTACH_BUFFERS;
pIrb->Flags = 0;
pIrb->u.IsochAttachBuffers.hResource = hResource;
pIrb->u.IsochAttachBuffers.nNumberOfDescriptors = nNumberOfDescriptors;
pIrb->u.IsochAttachBuffers.pIsochDescriptor = pIsochDescriptor;
// mark our original irp pending
IoMarkIrpPending(Irp);
//
// Submit the newIrp directly to the driver below us
//
NextIrpStack = IoGetNextIrpStackLocation(newIrp);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pIrb;
IoSetCompletionRoutine( newIrp,
t1394_IsochAttachCompletionRoutine,
pIsochDetachData,
TRUE,
TRUE,
TRUE
);
IoCallDriver(deviceExtension->StackDeviceObject, newIrp);
ntStatus = STATUS_PENDING;
Exit_IsochAttachBuffers:
EXIT("t1394_IsochAttachBuffers", ntStatus);
return(ntStatus);
} // t1394_IsochAttachBuffers
NTSTATUS
t1394_IsochDetachBuffers(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN HANDLE hResource,
IN ULONG nNumberOfDescriptors,
IN PISOCH_DESCRIPTOR IsochDescriptor
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIRB pIrb = NULL;
ULONG i;
PIRP newIrp = NULL;
BOOLEAN allocNewIrp = FALSE;
KEVENT Event;
IO_STATUS_BLOCK ioStatus;
ENTER("");
TRACE(TL_TRACE, ("hResource = 0x%x\n", hResource));
TRACE(TL_TRACE, ("nNumberOfDescriptors = 0x%x\n", nNumberOfDescriptors));
TRACE(TL_TRACE, ("IsochDescriptor = 0x%x\n", IsochDescriptor));
//
// If this is a UserMode request create a newIrp so that the request
// will be issued from KernelMode
//
if (Irp->RequestorMode == UserMode) {
newIrp = IoBuildDeviceIoControlRequest (IOCTL_1394_CLASS, deviceExtension->StackDeviceObject,
NULL, 0, NULL, 0, TRUE, &Event, &ioStatus);
if (!newIrp) {
TRACE(TL_ERROR, ("Failed to allocate newIrp!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochDetachBuffers;
}
allocNewIrp = TRUE;
}
pIrb = ExAllocatePool(NonPagedPool, sizeof(IRB));
if (!pIrb) {
TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochDetachBuffers;
} // if
RtlZeroMemory (pIrb, sizeof (IRB));
pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS;
pIrb->Flags = 0;
pIrb->u.IsochDetachBuffers.hResource = hResource;
pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = nNumberOfDescriptors;
pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDescriptor;
//
// If we allocated this irp, submit it asynchronously and wait for its
// completion event to be signaled. Otherwise submit it synchronously
//
if (allocNewIrp) {
KeInitializeEvent (&Event, NotificationEvent, FALSE);
ntStatus = t1394_SubmitIrpAsync (deviceExtension->StackDeviceObject, newIrp, pIrb);
if (ntStatus == STATUS_PENDING) {
KeWaitForSingleObject (&Event, Executive, KernelMode, FALSE, NULL);
ntStatus = ioStatus.Status;
}
}
else {
ntStatus = t1394_SubmitIrpSynch(deviceExtension->StackDeviceObject, Irp, pIrb);
}
if (!NT_SUCCESS(ntStatus)) {
TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus));
}
else
{
// if we detached the descriptor, free up the allocations
for (i=0; i<nNumberOfDescriptors; i++)
{
if (IsochDescriptor[i].Mdl)
{
IoFreeMdl(IsochDescriptor[i].Mdl);
}
}
ExFreePool(IsochDescriptor);
}
Exit_IsochDetachBuffers:
if (pIrb)
{
ExFreePool(pIrb);
}
if (allocNewIrp)
{
Irp->IoStatus = ioStatus;
}
EXIT("t1394_IsochDetachBuffers", ntStatus);
return(ntStatus);
} // t1394_IsochDetachBuffers
NTSTATUS
t1394_IsochFreeBandwidth(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN HANDLE hBandwidth
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIRB pIrb = NULL;
PIRP newIrp = NULL;
BOOLEAN allocNewIrp = FALSE;
KEVENT Event;
IO_STATUS_BLOCK ioStatus;
ENTER("t1394_IsochFreeBandwidth");
TRACE(TL_TRACE, ("hBandwidth = 0x%x\n", hBandwidth));
//
// If this is a UserMode request create a newIrp so that the request
// will be issued from KernelMode
//
if (Irp->RequestorMode == UserMode) {
newIrp = IoBuildDeviceIoControlRequest (IOCTL_1394_CLASS, deviceExtension->StackDeviceObject,
NULL, 0, NULL, 0, TRUE, &Event, &ioStatus);
if (!newIrp) {
TRACE(TL_ERROR, ("Failed to allocate newIrp!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochFreeBandwidth;
}
allocNewIrp = TRUE;
}
pIrb = ExAllocatePool(NonPagedPool, sizeof(IRB));
if (!pIrb) {
TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochFreeBandwidth;
} // if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -