⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datapkt.c

📁 a sample WDM stream class video capture driver that supports two IEEE 1394 digital cameras. The sam
💻 C
📖 第 1 页 / 共 3 页
字号:

    //
    // 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 + -