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

📄 sonydcam.c

📁 1394 摄像头驱动程序源代码,学习驱动程序的人可以看看
💻 C
📖 第 1 页 / 共 2 页
字号:

    if (pIrb->u.GetConfigurationInformation.ModelLeafBufferSize) {

        pDevExt->ModelLeaf = ExAllocatePoolWithTag(NonPagedPool, pIrb->u.GetConfigurationInformation.ModelLeafBufferSize, 'macd');
        if (!pDevExt->ModelLeaf) {

            ERROR_LOG(("\'DCamHwInitialize: Couldn't allocate memory for the ModelLeaf\n"));
            status = STATUS_INSUFFICIENT_RESOURCES;
            goto AbortLoading;
        }
    }

    //
    // Now resubmit the pIrb with the appropriate pointers inside
    //

    pIrb->FunctionNumber = REQUEST_GET_CONFIGURATION_INFO;
    pIrb->Flags = 0;
    pIrb->u.GetConfigurationInformation.ConfigRom = pDevExt->ConfigRom;
    pIrb->u.GetConfigurationInformation.UnitDirectory = pDevExt->UnitDirectory;
    pIrb->u.GetConfigurationInformation.UnitDependentDirectory = pDevExt->UnitDependentDirectory;
    pIrb->u.GetConfigurationInformation.VendorLeaf = pDevExt->VendorLeaf;
    pIrb->u.GetConfigurationInformation.ModelLeaf = pDevExt->ModelLeaf;

    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);

    if (status) {

        ERROR_LOG(("DCamHwInitialize: Error %x while trying to get configuration info (2)\n", status));
        status = STATUS_UNSUCCESSFUL;
        goto AbortLoading;
    }

    //
    // We might be able to return strings about a Device
    //

    if (pDevExt->VendorLeaf) {

        //
        // bswap to get the actual leaf length (in quadlets)
        //

        *((PULONG) pDevExt->VendorLeaf) = bswap(*((PULONG) pDevExt->VendorLeaf));

        DbgMsg1(("\'DCamHwInitialize: BufSize %d (byte); VendorLeaf %x; Len %d (Quad)\n", 
            pIrb->u.GetConfigurationInformation.VendorLeafBufferSize, 
            pDevExt->VendorLeaf, 
            pDevExt->VendorLeaf->TL_Length));

        if(pDevExt->VendorLeaf->TL_Length >= 1) {
            pDevExt->pchVendorName = &pDevExt->VendorLeaf->TL_Data;

        } else {
            pDevExt->pchVendorName = szUnknownVendorName;
        }

        DbgMsg1(("\'DCamHwInitialize: VendorName %s, strLen %d\n", pDevExt->pchVendorName, strlen(pDevExt->pchVendorName)));
    }

    //
    // Now we chew thru the Unit Dependent Directory looking for our command
    // base register key.
    //

    DirectoryLength = pIrb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize >> 2;
    for (i=1; i < DirectoryLength; i++) {

        if ((*(((PULONG) pDevExt->UnitDependentDirectory)+i) & CONFIG_ROM_KEY_MASK) == COMMAND_BASE_KEY_SIGNATURE) {

            //
            // Found the command base offset.  This is a quadlet offset from
            // the initial register space.  (Should come out to 0xf0f00000)
            //

            pDevExt->BaseRegister = bswap(*(((PULONG) pDevExt->UnitDependentDirectory)+i) & CONFIG_ROM_OFFSET_MASK);
            pDevExt->BaseRegister <<= 2;
            pDevExt->BaseRegister |= INITIAL_REGISTER_SPACE_LO;
            break;

        }
        
    }

    ASSERT( pDevExt->BaseRegister );

    if(!DCamDeviceInUse(pIrb, pDevExt)) {
        //
        // Now let's actually do a write request to initialize the device
        //
        pDevExt->RegisterWorkArea.AsULONG = 0;
        pDevExt->RegisterWorkArea.Initialize.Initialize = TRUE;
        pDevExt->RegisterWorkArea.AsULONG = bswap(pDevExt->RegisterWorkArea.AsULONG);

        status = DCamWriteRegister ((PIRB) Srb->SRBExtension, pDevExt, 
                  FIELDOFFSET(CAMERA_REGISTER_MAP, Initialize), pDevExt->RegisterWorkArea.AsULONG);

        if(status) {

            ERROR_LOG(("DCamHwInitialize: Error %x while trying to write to Initialize register\n", status));
            status = STATUS_UNSUCCESSFUL;
            goto AbortLoading;   
        }
    }

    //
    // Now we initialize the size of stream descriptor information.
    // We have one stream descriptor, and we attempt to dword align the
    // structure.
    //

    ConfigInfo->StreamDescriptorSize = 
        1 * (sizeof (HW_STREAM_INFORMATION)) +      // 1 stream descriptor
        sizeof(HW_STREAM_HEADER);                   // and 1 stream header


    //
    // Construct the device property table from querying the device and registry
    //
    if(!NT_SUCCESS(status = DCamPrepareDevProperties(pDevExt))) {
        goto AbortLoading;
    }

    // Get the features of the properties as well as its persisted value.
    // It will also updated the table.
    // The return is ignored since the default values are set when there is a failure.
    DCamGetPropertyValuesFromRegistry(
        pDevExt
        );

    //
    // Query video mode supported, and then contruct the stream format table.
    //
    if(!DCamBuildFormatTable(pDevExt, pIrb)) {
        ERROR_LOG(("\'Failed to get Video Format and Mode information; return STATUS_NOT_SUPPORTED\n"));
        status = STATUS_NOT_SUPPORTED;    
        goto AbortLoading;
    }

    //
    // register a bus reset callback notification (as the last action in this function)
    //
    // The controller driver will call (at DPC level)
    // if and only if the device is STILL attached.
    //
    // The device that has been removed, its
    // driver will get SRB_SURPRISE_REMOVAL instead.
    //
    
    pIrb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
    pIrb->Flags = 0;
    pIrb->u.BusResetNotification.fulFlags = REGISTER_NOTIFICATION_ROUTINE;
    pIrb->u.BusResetNotification.ResetRoutine = (PBUS_BUS_RESET_NOTIFICATION) DCamBusResetNotification;
    pIrb->u.BusResetNotification.ResetContext = pDevExt;
    status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
    if (status) {

        ERROR_LOG(("DCamHwInitialize: Error (Status=%x) while trying to get local host info.\n", status));
        status = STATUS_UNSUCCESSFUL;
        goto AbortLoading;
    }

    // This Irp is used locally only.
    IoFreeIrp(pIrp);  pIrp = NULL;


    DbgMsg1(("#### %s DCam loaded. ClassDO %x, PhyDO %x, BusDO %x, pDevExt %x, Gen# %d\n", 
        pDevExt->pchVendorName, pDevExt->SharedDeviceObject, pDevExt->PhysicalDeviceObject, pDevExt->BusDeviceObject, pDevExt, pDevExt->CurrentGeneration));

    return (STATUS_SUCCESS);

AbortLoading:


    if(pIrp) {
        IoFreeIrp(pIrp); pIrp = NULL;
    }

    if(pDevExt->ConfigRom) {
        ExFreePool(pDevExt->ConfigRom); pDevExt->ConfigRom = NULL;
    }

    if(pDevExt->UnitDirectory) {
        ExFreePool(pDevExt->UnitDirectory); pDevExt->UnitDirectory = NULL;
    }

    if(pDevExt->UnitDependentDirectory) {
        ExFreePool(pDevExt->UnitDependentDirectory); pDevExt->UnitDependentDirectory = NULL;
    }

    if(pDevExt->VendorLeaf) {
        ExFreePool(pDevExt->VendorLeaf); pDevExt->VendorLeaf = NULL;
    }

    if(pDevExt->ModelLeaf) {
        ExFreePool(pDevExt->ModelLeaf); pDevExt->ModelLeaf = NULL;
    }

    return status;

}


NTSTATUS
DCamSubmitIrpSynch(
    PDCAM_EXTENSION pDevExt,
    PIRP pIrp,
    PIRB pIrb
    )

/*++

Routine Description:

    This routine submits an Irp synchronously to the bus driver.  We'll
    wait here til the Irp comes back

Arguments:

    pDevExt - Pointer to my local device extension

    pIrp - Pointer to Irp we're sending down to the port driver synchronously

    pIrb - Pointer to Irb we're submitting to the port driver

Return Value:

    Status is returned from Irp

--*/

{


    LONG Retries=RETRY_COUNT_IRP_SYNC;  // Take the worst case of 20 * 100 msec = 1sec
    KEVENT Event;
    NTSTATUS status;
    LARGE_INTEGER deltaTime;
    PIO_STACK_LOCATION NextIrpStack;
    BOOL bCanWait = KeGetCurrentIrql() < DISPATCH_LEVEL;
    BOOL bRetryStatus;
    PIRB pIrbRetry;
    NTSTATUS StatusRetry;
    ULONG ulGeneration;

    

    do {

        NextIrpStack = IoGetNextIrpStackLocation(pIrp);
        NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
        NextIrpStack->Parameters.Others.Argument1 = pIrb;

        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);

        IoSetCompletionRoutine(
            pIrp,
            DCamSynchCR,
           &Event,
            TRUE,
            TRUE,
            TRUE
            );

        status = IoCallDriver(
                    pDevExt->BusDeviceObject,
                    pIrp
                    );


        DbgMsg3(("\'DCamSubmitIrpSynch: pIrp is pending(%s); will wait(%s)\n", 
                   status == STATUS_PENDING?"Y":"N", bCanWait?"Y":"N"));

        if (bCanWait &&
            status == STATUS_PENDING) {

            //
            // Still pending, wait for the IRP to complete
            //

            KeWaitForSingleObject(  // Only in <= IRQL_DISPATCH_LEVEL; can only in DISPATCH if Timeout is 0
               &Event,
                Executive,
                KernelMode,
                FALSE,
                NULL
                );

        }

        // Will retry for any of these return status codes.
        bRetryStatus = 
             pIrp->IoStatus.Status == STATUS_TIMEOUT ||
             pIrp->IoStatus.Status == STATUS_IO_TIMEOUT ||
             pIrp->IoStatus.Status == STATUS_DEVICE_BUSY ||
             pIrp->IoStatus.Status == STATUS_INVALID_GENERATION;

        if (bCanWait && bRetryStatus && Retries > 0) {

            // Camera isn't fast enough to respond so delay this thread and try again.
            switch(pIrp->IoStatus.Status) {

            case STATUS_TIMEOUT: 
            case STATUS_IO_TIMEOUT: 
            case STATUS_DEVICE_BUSY: 

                deltaTime.LowPart = DCAM_DELAY_VALUE;
                deltaTime.HighPart = -1;
                KeDelayExecutionThread(KernelMode, TRUE, &deltaTime); 
                break;

            case STATUS_INVALID_GENERATION:

                // Cache obsolete ulGeneration and use it to detect its udpate in busreset callback.               
                if(pIrb->FunctionNumber == REQUEST_ASYNC_READ)
                    ulGeneration = pIrb->u.AsyncRead.ulGeneration;
                else if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE)
                    ulGeneration = pIrb->u.AsyncWrite.ulGeneration;
                else if(pIrb->FunctionNumber == REQUEST_ASYNC_LOCK)
                    ulGeneration = pIrb->u.AsyncLock.ulGeneration;
                else if(pIrb->FunctionNumber == REQUEST_ISOCH_FREE_BANDWIDTH) {
                    ERROR_LOG(("InvGen when free BW\n"));                    
                    // Special case that we do not need to retry since BW should be free
                    // and 1394 bus should just free the BW structure.
                    Retries = 0;  // no more retry and exit.
                    break;
                }
                else {
                    // Other REQUEST_* that depends on ulGeneration
                    ERROR_LOG(("Unexpected IRB function with InvGen:%d\n", pIrb->FunctionNumber));  
                    ASSERT(FALSE && "New REQUEST that requires ulGeneration");
                    Retries = 0;  // do not know what to do so no more retry and exit.
                    break;
                }
                
                pIrbRetry = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), 'macd');
                if (pIrbRetry) {

                    deltaTime.LowPart = DCAM_DELAY_VALUE_BUSRESET;  // Longer than the regular delay
                    deltaTime.HighPart = -1;

                    do {
                        KeDelayExecutionThread(KernelMode, TRUE, &deltaTime);

                        pIrbRetry->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
                        pIrbRetry->u.GetGenerationCount.GenerationCount = 0;
                        pIrbRetry->Flags = 0;
                        StatusRetry = DCamSubmitIrpSynch(pDevExt, pIrp, pIrbRetry);  // Recursive with differnt IRB but same IRP.

                        if(NT_SUCCESS(StatusRetry) && pIrbRetry->u.GetGenerationCount.GenerationCount > ulGeneration) {
                            InterlockedExchange(&pDevExt->CurrentGeneration, pIrbRetry->u.GetGenerationCount.GenerationCount);
                            // Update the generation count for the original IRB request and try again.
                            if(pIrb->FunctionNumber == REQUEST_ASYNC_READ)
                                InterlockedExchange(&pIrb->u.AsyncRead.ulGeneration, pDevExt->CurrentGeneration);
                            else if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE)
                                InterlockedExchange(&pIrb->u.AsyncWrite.ulGeneration, pDevExt->CurrentGeneration);
                            else if(pIrb->FunctionNumber == REQUEST_ASYNC_LOCK)
                                InterlockedExchange(&pIrb->u.AsyncLock.ulGeneration, pDevExt->CurrentGeneration);
                            else {
                                // Other (new) REQUEST_* that depends on ulGeneration
                            }                        
                        }

                        if(Retries)
                            Retries--;

                    } while (Retries && ulGeneration >= pDevExt->CurrentGeneration);

                    ERROR_LOG(("(%d) IrpSync: StautsRetry %x; Generation %d -> %d\n", 
                        Retries, StatusRetry, ulGeneration, pDevExt->CurrentGeneration));

                    ExFreePool(pIrbRetry); pIrbRetry = 0;
                }  // if
                break;                                            

            // All other status
            default:
                break;      
            }
        }

        if(Retries)
            Retries--;
 
    } while (bCanWait && bRetryStatus && (Retries > 0));

#if DBG
    if(!NT_SUCCESS(pIrp->IoStatus.Status)) {
        ERROR_LOG(("IrpSynch: IoCallDriver Status:%x; pIrp->IoStatus.Status (final):%x; Wait:%d; Retries:%d\n", status, pIrp->IoStatus.Status, bCanWait, Retries)); 
    }
#endif

    return (pIrp->IoStatus.Status);

}


NTSTATUS
DCamSynchCR(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP pIrp,
    IN PKEVENT Event
    )

/*++

Routine Description:

    This routine is for use with synchronous IRP processing.  
    All it does is signal an event, so the driver knows it
    can continue.

Arguments:

    DriverObject - Pointer to driver object created by system.

    pIrp - Irp that just completed

    Event - Event we'll signal to say Irp is done

Return Value:

    None.

--*/

{

    KeSetEvent((PKEVENT) Event, 0, FALSE);
    return (STATUS_MORE_PROCESSING_REQUIRED);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -