📄 sonydcam.c
字号:
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 + -