📄 datapkt.c
字号:
//
// Set this to stop accepting incoming read.
//
pDevExt->bDevRemoved = TRUE;
//
// Wait for currect read to be attached so we cancel them all.
//
pStrmEx = pDevExt->pStrmEx;
if(pStrmEx) {
// Make sure that this structure is still valid.
if(pStrmEx->pVideoInfoHeader) {
StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );
KeReleaseMutex(&pStrmEx->hMutex, FALSE);
}
}
pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
if(!pIrp) {
ERROR_LOG(("DCamSurpriseRemovalPacket: faile to get resource; pIrb=%x, pDevExt=%x, pIrp\n", pIrb, pDevExt, pIrp));
pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
return;
}
//
// un-register a bus reset callback notification
//
pIrb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
pIrb->Flags = 0;
pIrb->u.BusResetNotification.fulFlags = DEREGISTER_NOTIFICATION_ROUTINE;
pIrb->u.BusResetNotification.ResetRoutine = (PBUS_BUS_RESET_NOTIFICATION) DCamBusResetNotification;
pIrb->u.BusResetNotification.ResetContext = 0;
Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
if(Status) {
ERROR_LOG(("DCamSurpriseRemoval: Status %x while trying to deregister bus reset notification.\n", Status));
}
//
// Get new generation number
//
pIrb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
pIrb->Flags = 0;
Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
if(Status) {
ERROR_LOG(("DCamSurpriseRemoval: Status %x while trying to get generation number.\n", Status));
} else {
DbgMsg1(("DCamSurpriseRemoval: pDevExt %x, Generation number from %d to %d\n",
pDevExt, pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount));
InterlockedExchange(&pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount);
}
if(pStrmEx) {
//
// Stop isoch transmission so we can detach buffers and cancel pending SRBs
//
pIrb->FunctionNumber = REQUEST_ISOCH_STOP;
pIrb->Flags = 0;
pIrb->u.IsochStop.hResource = pDevExt->hResource;
pIrb->u.IsochStop.fulFlags = 0;
Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
if(Status) {
ERROR_LOG(("DCamSurpriseRemoval: Status %x while trying to ISOCH_STOP.\n", Status));
}
IoFreeIrp(pIrp);
DCamCancelAllPackets(
pSrb,
pDevExt,
&pDevExt->PendingReadCount
);
} else {
IoFreeIrp(pIrp);
StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
}
}
NTSTATUS
DCamAttachBufferCR(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PISOCH_DESCRIPTOR IsochDescriptor
)
/*++
Routine Description:
This routine is the completion routine from attaching a bufffer to lower driver.
Arguments:
DriverObject - Pointer to driver object created by system.
pIrp - Irp that just completed
pDCamIoContext - A structure that contain the context of this IO completion routine.
Return Value:
None.
--*/
{
PHW_STREAM_REQUEST_BLOCK pSrb;
PDCAM_EXTENSION pDevExt;
PSTREAMEX pStrmEx;
NTSTATUS Status;
PIRB pIrb;
PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
KIRQL oldIrql;
pDevExt = (PDCAM_EXTENSION) IsochDescriptor->Context1;
ASSERT(pDevExt);
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
ASSERT(pStrmEx);
IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
ASSERT(IsochDescriptorReserved);
pSrb = IsochDescriptorReserved->Srb;
ASSERT(pSrb);
pIrb = (PIRB) pSrb->SRBExtension;
DbgMsg3(("\'DCamAttachBufferCR: completed KSSTATE=%d; pIrp->IoStatus.Status=%x; pSrb=%x\n",
pStrmEx->KSState, pIrp->IoStatus.Status, pSrb));
//
// Attaching a buffer return with error.
//
if(pIrp->IoStatus.Status) {
ERROR_LOG(("DCamAttachBufferCR: pIrp->IoStatus.Status=%x (STATUS_PENDING=%x); complete SRB with this status.\n",
pIrp->IoStatus.Status, STATUS_PENDING));
ASSERT(pIrp->IoStatus.Status == STATUS_SUCCESS);
if(!(IsochDescriptorReserved->Flags & STATE_SRB_IS_COMPLETE)) {
ASSERT(((IsochDescriptorReserved->Flags & STATE_SRB_IS_COMPLETE) != STATE_SRB_IS_COMPLETE));
IsochDescriptorReserved->Flags |= STATE_SRB_IS_COMPLETE;
pSrb->Status = pIrp->IoStatus.Status; // Read is completed with error status.
KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
RemoveEntryList(&IsochDescriptorReserved->DescriptorList); InterlockedDecrement(&pDevExt->PendingReadCount);
KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
ExFreePool(IsochDescriptor);
StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
KeAcquireSpinLock(&pDevExt->IsochWaitingLock, &oldIrql);
//
// If we failed to attach (rtn with failed status),
// removed this entry, and
// pull one out of the waiting list if not yet exceeded out limit.
//
if (!IsListEmpty(&pDevExt->IsochWaitingList) && pDevExt->PendingReadCount >= MAX_BUFFERS_SUPPLIED) {
//
// We had someone blocked waiting for us to complete. Pull
// them off the waiting list and get them running
//
DbgMsg3(("\'DCamAttachBufferCR: Dequeueing request - Read Count=%d\n", pDevExt->PendingReadCount));
IsochDescriptorReserved = \
(PISOCH_DESCRIPTOR_RESERVED) RemoveHeadList(
&pDevExt->IsochWaitingList
);
KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
IsochDescriptor = \
(PISOCH_DESCRIPTOR) (((PUCHAR) IsochDescriptorReserved) -
FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
DCamReadStreamWorker(IsochDescriptorReserved->Srb, IsochDescriptor);
} else {
KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
}
} else {
// Race condition ? or a valid error code?
ERROR_LOG(("DCamAttachBufferCR: IsochDescriptorReserved->Flags contain STATE_SRB_IS_COMPLETE\n"));
ASSERT(FALSE);
}
}
//
// Ealier when we set to RUN state, it might have failed with
// STATUS_INSUFFICIENT_RESOURCE due to no buffer attached;
// we have at least one now, ask controll to start listen and
// fill and return our buffer.
//
if(pDevExt->bNeedToListen) {
PIRB pIrb2;
PIRP pIrp2;
PDCAM_IO_CONTEXT pDCamIoContext;
PIO_STACK_LOCATION NextIrpStack;
if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb2, &pIrp2, pDevExt->BusDeviceObject->StackSize)) {
ERROR_LOG(("DCamAttachBufferCR: Want to stat Listening but no resource !!\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
pDevExt->bNeedToListen = FALSE;
DbgMsg2(("\'DCamAttachBufferCR: ##### pDevExt->bNeedToListen\n"));
pDCamIoContext->pDevExt = pDevExt;
pDCamIoContext->pIrb = pIrb2;
pIrb2->FunctionNumber = REQUEST_ISOCH_LISTEN;
pIrb2->Flags = 0;
pIrb2->u.IsochListen.hResource = pDevExt->hResource;
pIrb2->u.IsochListen.fulFlags = 0;
NextIrpStack = IoGetNextIrpStackLocation(pIrp2);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pIrb2;
pDevExt->lRetries = RETRY_COUNT;
IoSetCompletionRoutine(
pIrp2,
DCamStartListenCR,
pDCamIoContext,
TRUE,
TRUE,
TRUE
);
Status =
IoCallDriver(
pDevExt->BusDeviceObject,
pIrp2);
}
// No resource to freed.
// Resource (pIrb is from original SRB)
return STATUS_MORE_PROCESSING_REQUIRED;
//
// The attached SRB read will be completed in IoschCallback().
//
}
NTSTATUS
DCamReSubmitPacketCR(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PISOCH_DESCRIPTOR IsochDescriptor
)
/*++
Routine Description:
This routine is called after a packet is detach and
will be attached here to complete the resubmission of
packet after a isoch. resource change.
Arguments:
DriverObject - Pointer to driver object created by system.
pIrp - Irp that just completed
pDCamIoContext - A structure that contain the context of this IO completion routine.
Return Value:
None.
--*/
{
PIRB pIrb;
PIO_STACK_LOCATION NextIrpStack;
PDCAM_EXTENSION pDevExt;
PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
NTSTATUS Status;
pDevExt = IsochDescriptor->Context1;
ASSERT(pDevExt);
pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
ASSERT(pIrb);
IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
//
// Detached, so unmark it.
//
IsochDescriptorReserved->Flags &= ~STATE_DETACHING_BUFFERS;
DbgMsg2(("\'DCamReSubmitPacketCR: ReSubmit pDevExt %x, pIrb %x, hResource %x, IsochDescriptor %x, IsochDescriptorReserved %x\n",
pDevExt, pIrb, pDevExt->hResource, IsochDescriptor, IsochDescriptorReserved));
#if DBG
//
// Put signatures and use these count to track if the IsochDescriptor
// has been attached or detached unexpectely.
//
// When attach, [4]++ (DCamReadStreamWorker(), DCamReSumbitPacketCR())
// detach, [7]++ (DCamIsochcallback(), DCamCancelPacketCR(), DCamResubmitPacket())
//
IsochDescriptor->DeviceReserved[4] = 0x12345678;
IsochDescriptor->DeviceReserved[7] = 0x87654321;
#endif
//
// Attach descriptor onto our pending descriptor list
//
ExInterlockedInsertTailList(
&pDevExt->IsochDescriptorList,
&IsochDescriptorReserved->DescriptorList,
&pDevExt->IsochDescriptorLock
);
pIrb->FunctionNumber = REQUEST_ISOCH_ATTACH_BUFFERS;
pIrb->Flags = 0;
pIrb->u.IsochAttachBuffers.hResource = pDevExt->hResource;
pIrb->u.IsochAttachBuffers.nNumberOfDescriptors = 1;
pIrb->u.IsochAttachBuffers.pIsochDescriptor = IsochDescriptor;
NextIrpStack = IoGetNextIrpStackLocation(pIrp);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pIrb;
IoSetCompletionRoutine(
pIrp,
DCamAttachBufferCR,
IsochDescriptor,
TRUE,
TRUE,
TRUE
);
Status =
IoCallDriver(
pDevExt->BusDeviceObject,
pIrp
);
ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
return STATUS_MORE_PROCESSING_REQUIRED; // Complete Asynchronously in DCamAttachBufferCR
}
NTSTATUS
DCamReSubmitPacket(
HANDLE hStaleResource,
PDCAM_EXTENSION pDevExt,
PSTREAMEX pStrmEx,
LONG cntPendingRead
)
/*++
Routine Description:
Due to a bus reset, if a channel number has changed (subsequently, iso resource
change too), we must detach and re-attach pending packet(s).
While this function is executed, incoming SRB_READ is blocked and isoch callback
are returned and not processed (we are resubmiting them).
Arguments:
hStaleResource - staled isoch resource
pDevExt - Device's Extension
pStrmEx - Stremaing extension
cntPendingRead - Number of pending packets
Return Value:
NTSTATUS.
--*/
{
PIRB pIrb;
PIRP pIrp;
PIO_STACK_LOCATION NextIrpStack;
PISOCH_DESCRIPTOR IsochDescriptor;
PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
NTSTATUS Status = STATUS_SUCCESS;
KIRQL oldIrql;
DbgMsg1(("DCamReSubmitPacket: pDevExt %x, pStrmEx %x, PendingCount %d\n", pDevExt, pStrmEx, cntPendingRead));
for(; cntPendingRead > 0; cntPendingRead--) {
if(!IsListEmpty(&pDevExt->IsochDescriptorList)) {
//
// Synchronization note:
//
// We are competing with cancel packet routine in the
// event of device removal or setting to STOP state.
// which ever got the spin lock to set DEATCH_BUFFER
// flag take ownership completing the Irp/IsochDescriptor.
//
KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) RemoveHeadList(&pDevExt->IsochDescriptorList);
if((IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS))) {
ERROR_LOG(("DCamReSubmitPacket: Flags %x aleady mark STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS\n", IsochDescriptorReserved->Flags));
ASSERT(( !(IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS))));\
//Put it back since it has been detached.
InsertTailList(&pDevExt->IsochDescriptorList, &IsochDescriptorReserved->DescriptorList);
KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -