📄 isochapi.c
字号:
ntStatus = ioStatus.Status;
}
}
else {
ntStatus = t1394_SubmitIrpSynch(deviceExtension->StackDeviceObject, Irp, pIrb);
}
if (!NT_SUCCESS(ntStatus)) {
TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus));
}
Exit_IsochStop:
if (pIrb)
{
ExFreePool(pIrb);
}
if (allocNewIrp)
{
Irp->IoStatus = ioStatus;
}
EXIT("t1394_IsochStop", ntStatus);
return(ntStatus);
} // t1394_IsochStop
NTSTATUS
t1394_IsochTalk(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN HANDLE hResource,
IN ULONG fulFlags,
CYCLE_TIME StartTime
)
{
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_IsochTalk");
TRACE(TL_TRACE, ("hResource = 0x%x\n", hResource));
TRACE(TL_TRACE, ("fulFlags = 0x%x\n", fulFlags));
TRACE(TL_TRACE, ("StartTime.CL_CycleOffset = 0x%x\n", StartTime.CL_CycleOffset));
TRACE(TL_TRACE, ("StartTime.CL_CycleCount = 0x%x\n", StartTime.CL_CycleCount));
TRACE(TL_TRACE, ("StartTime.CL_SecondCount = 0x%x\n", StartTime.CL_SecondCount));
//
// 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_IsochTalk;
}
allocNewIrp = TRUE;
}
pIrb = ExAllocatePool(NonPagedPool, sizeof(IRB));
if (!pIrb) {
TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochTalk;
} // if
RtlZeroMemory (pIrb, sizeof (IRB));
pIrb->FunctionNumber = REQUEST_ISOCH_TALK;
pIrb->Flags = 0;
pIrb->u.IsochTalk.hResource = hResource;
pIrb->u.IsochTalk.fulFlags = fulFlags;
pIrb->u.IsochTalk.StartTime = StartTime;
//
// 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));
}
Exit_IsochTalk:
if (pIrb)
{
ExFreePool(pIrb);
}
if (allocNewIrp)
{
Irp->IoStatus = ioStatus;
}
EXIT("t1394_IsochTalk", ntStatus);
return(ntStatus);
} // t1394_IsochTalk
void
t1394_IsochCallback(
IN PDEVICE_EXTENSION DeviceExtension,
IN PISOCH_DETACH_DATA IsochDetachData
)
{
KIRQL Irql;
ENTER("t1394_IsochCallback");
if (!IsochDetachData)
{
goto Exit_IsochCallback;
}
// make sure somebody else isn't already handling cleaning up for this request
KeAcquireSpinLock(&DeviceExtension->IsochSpinLock, &Irql);
if ((!DeviceExtension->bShutdown) &&
(t1394_IsOnList(&IsochDetachData->IsochDetachList, &DeviceExtension->IsochDetachData)))
{
RemoveEntryList(&IsochDetachData->IsochDetachList);
KeReleaseSpinLock(&DeviceExtension->IsochSpinLock, Irql);
KeCancelTimer(&IsochDetachData->Timer);
TRACE(TL_TRACE, ("IsochCallback: IsochDetachData = 0x%x\n", IsochDetachData));
TRACE(TL_TRACE, ("IsochCallback: IsochDetachData->Irp = 0x%x\n", IsochDetachData->Irp));
TRACE(TL_TRACE, ("IsochCallback: IsochDetachData->newIrp = 0x%x\n", IsochDetachData->newIrp));
// need to save the status of the attach
// we'll clean up in the same spot for success's and timeout's
IsochDetachData->AttachStatus = IsochDetachData->Irp->IoStatus.Status;
t1394_IsochCleanup(IsochDetachData);
}
else
{
TRACE(TL_TRACE, ("IsochCallback: Entry 0x%x not on List 0x%x\n",
IsochDetachData->IsochDetachList, DeviceExtension->IsochDetachData));
KeReleaseSpinLock(&DeviceExtension->IsochSpinLock, Irql);
}
Exit_IsochCallback:
EXIT("t1394_IsochCallback", 0);
} // t1394_IsochCallback
void
t1394_IsochTimeout(
IN PKDPC Dpc,
IN PISOCH_DETACH_DATA IsochDetachData,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
KIRQL Irql;
PDEVICE_EXTENSION DeviceExtension;
ENTER("t1394_IsochTimeout");
TRACE(TL_WARNING, ("Isoch Timeout!\n"));
//
// ISSUE: the device extension we are referencing comes from the IsochDetachData
// but it is possible this memory has been freed before we enter this function.
// The only way to check is to validate against our DeviceExtension->IsochDetachList
// but if the IsochDetachData has been freed then that won't be accessible
//
DeviceExtension = IsochDetachData->DeviceExtension;
if (DeviceExtension)
{
// make sure nobody else has already handled this request yet
KeAcquireSpinLock(&DeviceExtension->IsochSpinLock, &Irql);
if (t1394_IsOnList(&IsochDetachData->IsochDetachList, &DeviceExtension->IsochDetachData))
{
RemoveEntryList(&IsochDetachData->IsochDetachList);
KeReleaseSpinLock(&DeviceExtension->IsochSpinLock, Irql);
if(KeCancelTimer(&IsochDetachData->Timer))
{
TRACE(TL_TRACE, ("IsochTimeout: IsochDetachData = 0x%x\n", IsochDetachData));
TRACE(TL_TRACE, ("IsochTimeout: IsochDetachData->Irp = 0x%x\n", IsochDetachData->Irp));
TRACE(TL_TRACE, ("IsochTimeout: IsochDetachData->newIrp = 0x%x\n", IsochDetachData->newIrp));
// need to save the status of the attach
// we'll clean up in the same spot for success's and timeout's
IsochDetachData->AttachStatus = STATUS_TIMEOUT;
t1394_IsochCleanup(IsochDetachData);
}
}
else
{
KeReleaseSpinLock(&DeviceExtension->IsochSpinLock, Irql);
}
}
EXIT("t1394_IsochTimeout", 0);
} // t1394_IsochTimeout
void
t1394_IsochCleanup(
IN PISOCH_DETACH_DATA IsochDetachData
)
{
ULONG i;
PDEVICE_EXTENSION DeviceExtension;
ENTER("t1394_IsochCleanup");
DeviceExtension = IsochDetachData->DeviceExtension;
//
// see if we need to detach this buffer
//
if ((!IsochDetachData) || (!DeviceExtension))
{
goto Exit_IsochDetachBuffers;
}
if (IsochDetachData->bDetach) {
PIRB pIrb;
NTSTATUS ntStatus;
PIO_STACK_LOCATION NextIrpStack;
pIrb = ExAllocatePool(NonPagedPool, sizeof(IRB));
if (!pIrb) {
TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
TRACE(TL_WARNING, ("Can't detach buffer!\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_IsochDetachBuffers;
} // if
// save the irb in our detach data context
IsochDetachData->DetachIrb = pIrb;
RtlZeroMemory (pIrb, sizeof (IRB));
pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS;
pIrb->Flags = 0;
pIrb->u.IsochDetachBuffers.hResource = IsochDetachData->hResource;
pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = IsochDetachData->numIsochDescriptors;
pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDetachData->IsochDescriptor;
NextIrpStack = IoGetNextIrpStackLocation(IsochDetachData->newIrp);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pIrb;
IoSetCompletionRoutine( IsochDetachData->newIrp,
t1394_IsochDetachCompletionRoutine,
IsochDetachData,
TRUE,
TRUE,
TRUE
);
IoCallDriver(DeviceExtension->StackDeviceObject, IsochDetachData->newIrp);
}
else {
TRACE(TL_TRACE, ("Complete Irp.\n"));
if (IsochDetachData->AttachIrb)
{
ExFreePool(IsochDetachData->AttachIrb);
}
for (i=0; i<IsochDetachData->numIsochDescriptors; i++)
{
if (IsochDetachData->IsochDescriptor[i].Mdl)
{
IoFreeMdl(IsochDetachData->IsochDescriptor[i].Mdl);
}
}
ExFreePool(IsochDetachData->IsochDescriptor);
IsochDetachData->Irp->IoStatus.Status = IsochDetachData->AttachStatus;
// only set this if its a success...
if (NT_SUCCESS(IsochDetachData->AttachStatus))
{
IsochDetachData->Irp->IoStatus.Information = IsochDetachData->outputBufferLength;
}
//
// Complete original Irp and free the one we allocated in
// IsochAttachBuffers
//
IoCompleteRequest(IsochDetachData->Irp, IO_NO_INCREMENT);
IoFreeIrp (IsochDetachData->newIrp);
// all done with IsochDetachData, lets deallocate it...
ExFreePool(IsochDetachData);
}
Exit_IsochDetachBuffers:
EXIT("t1394_IsochCleanup", 0);
} // t1394_IsochCleanup
NTSTATUS
t1394_IsochDetachCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PISOCH_DETACH_DATA IsochDetachData
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG i;
ENTER("t1394_IsochDetachCompletionRoutine");
if (!IsochDetachData) {
TRACE(TL_WARNING, ("Invalid IsochDetachData\n"));
goto Exit_IsochDetachCompletionRoutine;
}
if (IsochDetachData->DetachIrb)
{
ExFreePool(IsochDetachData->DetachIrb);
}
TRACE(TL_TRACE, ("Now lets complete the Irp.\n"));
if (IsochDetachData->AttachIrb)
ExFreePool(IsochDetachData->AttachIrb);
for (i=0; i<IsochDetachData->numIsochDescriptors; i++)
{
if (IsochDetachData->IsochDescriptor[i].Mdl)
{
IoFreeMdl(IsochDetachData->IsochDescriptor[i].Mdl);
}
}
if (IsochDetachData->IsochDescriptor)
{
ExFreePool(IsochDetachData->IsochDescriptor);
}
// only set this if its a success...
if (NT_SUCCESS(IsochDetachData->AttachStatus))
{
IsochDetachData->Irp->IoStatus.Information = IsochDetachData->outputBufferLength;
}
IsochDetachData->Irp->IoStatus.Status = IsochDetachData->AttachStatus;
//
// Complete original Irp and free the one we allocated in
// IsochAttachBuffers
//
IoCompleteRequest(IsochDetachData->Irp, IO_NO_INCREMENT);
IoFreeIrp (IsochDetachData->newIrp);
// all done with IsochDetachData, lets deallocate it...
if (IsochDetachData)
{
ExFreePool(IsochDetachData);
}
Exit_IsochDetachCompletionRoutine:
EXIT(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -