📄 dcampkt.c
字号:
#ifdef SUPPORT_YUV800
case FOURCC_Y800:
ModeIndex = VMODE5_YUV800;
break;
#endif
default:
Status = STATUS_NOT_IMPLEMENTED;;
return Status;;
}
DbgMsg1(("\'DCamAllocateIsochResource: ModeIndex=%d, AvgTimePerFrame=%d, FrameRate=%d\n",
ModeIndex, dwAvgTimePerFrame, pDevExt->FrameRate));
//
// Get an Irp so we can send some allocation commands down
//
StackSize = pDevExt->BusDeviceObject->StackSize;
Irp = IoAllocateIrp(StackSize, FALSE);
if (!Irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Calculate the index to use to reference the ISOCH table
//
pStrmEx->idxIsochTable = ModeIndex * NUM_POSSIBLE_RATES + pDevExt->FrameRate;
ASSERT(pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage == IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize);
DbgMsg2(("\'DCamAllocateIsochResource: ModeIndex=%d, idxIsochTable=%d, biSizeImage=%d, CompletePictureSize=%d\n",
ModeIndex, pStrmEx->idxIsochTable, pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage, IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize));
//
// 0. Determine the MAX_SPEED and not use the speed defined in the static table.
//
Irb->FunctionNumber = REQUEST_GET_SPEED_BETWEEN_DEVICES;
Irb->Flags = 0;
Irb->u.GetMaxSpeedBetweenDevices.fulFlags = USE_LOCAL_NODE;
Irb->u.GetMaxSpeedBetweenDevices.ulNumberOfDestinations = 0;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
if(Status) {
ERROR_LOG(("\'DCamAllocateIsochResource: Error %x while trying to get maximun speed between devices.\n", Status));
IoFreeIrp(Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
fulSpeed = Irb->u.GetMaxSpeedBetweenDevices.fulSpeed;
//
// The max speed between devices should be within supported speed range, and
// must be equal or greater than the required speed for the chosen format.
//
if(
( fulSpeed != SPEED_FLAGS_100
&& fulSpeed != SPEED_FLAGS_200
&& fulSpeed != SPEED_FLAGS_400
)
|| fulSpeed < IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired
) {
ASSERT(fulSpeed == SPEED_FLAGS_100 || fulSpeed == SPEED_FLAGS_200 || fulSpeed == SPEED_FLAGS_400);
ASSERT(fulSpeed >= IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired);
IoFreeIrp(Irp);
return STATUS_UNSUCCESSFUL;
}
pDevExt->SpeedCode = fulSpeed >> 1; // Safe for S100, 200 and 400 (is checked above).
DbgMsg2(("\'GetMaxSpeedBetweenDevices.fulSpeed=%x; SpeedCode:%x\n", fulSpeed, pDevExt->SpeedCode));
//
// 1. Allocate CHANNEL
// First try to re-allocate the same channel
// If it is used, try to get any channel. 1394DCam can only be on channel 0..15
//
Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
Irb->Flags = 0;
//
// ULONG nRequestedChannel; // Need a specific channel
// ULONG Channel; // Returned channel
// LARGE_INTEGER ChannelsAvailable; // Channels available
// Instead of hardcoded '0'; use -1 to ask the bus driver to get the next available channel for us.
// -1 (any channel) or an existing channel
Irb->u.IsochAllocateChannel.nRequestedChannel = pDevExt->IsochChannel;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
if(Status) {
//
// Due to channel change,
// all Pending read will be either resubmitted,
// or cancelled (if out of resource).
//
pDevExt->bStopIsochCallback = TRUE; // Set back to FALSE after pending buffer are attached.
//
// If this is an initial request and no channel available,
// free all resource and abort.
//
if(pDevExt->IsochChannel == ISOCH_ANY_CHANNEL)
goto NoResource_abort;
DbgMsg1(("DCamAllocateIsochResource: last allocated channel %d is not available; pending count %d.\n",
pDevExt->IsochChannel, pDevExt->PendingReadCount));
// Try gettting any channel.
Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
Irb->Flags = 0;
Irb->u.IsochAllocateChannel.nRequestedChannel = ISOCH_ANY_CHANNEL;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
if(Status) {
ERROR_LOG(("DCamAllocateIsochResource: allocate any channel failed, status %x!\n", Status));
goto NoResource_abort;
}
//
// Channel changed, we MUST reallocate resource.
// The "stale" resrouce will be free later when
// pending packet are detached.
//
bAllocateResource = TRUE;
}
DbgMsg1(("**IsochAlloc: Channel(Old) %d, requested %d, got %d, HiLo(0x%x:%x), PendingRead %d\n",
pDevExt->IsochChannel,
Irb->u.IsochAllocateChannel.nRequestedChannel,
Irb->u.IsochAllocateChannel.Channel,
Irb->u.IsochAllocateChannel.ChannelsAvailable.u.HighPart,
Irb->u.IsochAllocateChannel.ChannelsAvailable.u.LowPart,
pDevExt->PendingReadCount));
// New channel
pDevExt->IsochChannel = Irb->u.IsochAllocateChannel.Channel; // Used in allocating iso. resource and reallocation
//
// 2. Allocate BANDWIDTH
//
Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_BANDWIDTH;
Irb->Flags = 0;
Irb->u.IsochAllocateBandwidth.nMaxBytesPerFrameRequested = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
Irb->u.IsochAllocateBandwidth.fulSpeed = fulSpeed;
Irb->u.IsochAllocateBandwidth.hBandwidth = 0;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
if(Status) {
ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch bandwidth\n", Status));
goto NoResource_abort;
}
pDevExt->hBandwidth = Irb->u.IsochAllocateBandwidth.hBandwidth;
DbgMsg2(("**IsochAlloc: nMaxBytesPerFrameRequested %d, fulSpeed %d; hBandWidth 0x%x\n",
IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2, fulSpeed, pDevExt->hBandwidth));
//
// 3. Allocate RESOURCES
// Note: after a bus reset, we need not free and re-allocate this resoruce again.
//
if(bAllocateResource) {
Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_RESOURCES;
Irb->Flags = 0;
Irb->u.IsochAllocateResources.fulSpeed = fulSpeed;
Irb->u.IsochAllocateResources.nChannel = pDevExt->IsochChannel;
Irb->u.IsochAllocateResources.nMaxBytesPerFrame = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
// For slower frame rate use smaller quadlets
// smaller frame size will use more packet to fill the same amount of data
// this is why smaller frame rate actually demand more resource !!
Irb->u.IsochAllocateResources.nNumberOfBuffers = MAX_BUFFERS_SUPPLIED + 1; // "+1" as a "safety"
Irb->u.IsochAllocateResources.nMaxBufferSize = IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize;
if (pDevExt->HostControllerInfomation.HostCapabilities & HOST_INFO_SUPPORTS_RETURNING_ISO_HDR) {
Irb->u.IsochAllocateResources.nQuadletsToStrip = 1;
Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING | RESOURCE_STRIP_ADDITIONAL_QUADLETS;
} else {
Irb->u.IsochAllocateResources.nQuadletsToStrip = 0;
Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING;
}
Irb->u.IsochAllocateResources.hResource = 0;
DbgMsg2(("\'DCamAllocateIsochResource: fullSpeed(%d), nMaxBytesPerFrame(%d), nMaxBufferSize(%d)\n",
Irb->u.IsochAllocateResources.fulSpeed,
Irb->u.IsochAllocateResources.nMaxBytesPerFrame,
Irb->u.IsochAllocateResources.nMaxBufferSize));
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
if(Status) {
ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch resources\n", Status));
goto NoResource_abort;
}
pDevExt->hResource = Irb->u.IsochAllocateResources.hResource;
}
pDevExt->CurrentModeIndex = ModeIndex;
DbgMsg2(("**IsochAlloc: hResource = %x\n", pDevExt->hResource));
IoFreeIrp(Irp);
return STATUS_SUCCESS;
NoResource_abort:
// Free bandwidth
if(pDevExt->hBandwidth != NULL) {
Irb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
Irb->Flags = 0;
Irb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
pDevExt->hBandwidth = NULL;
if(Status) {
ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to free Isoch bandwidth\n", Status));
}
}
// Free channel
if (pDevExt->IsochChannel != ISOCH_ANY_CHANNEL) {
Irb->FunctionNumber = REQUEST_ISOCH_FREE_CHANNEL;
Irb->Flags = 0;
Irb->u.IsochFreeChannel.nChannel = pDevExt->IsochChannel;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
pDevExt->IsochChannel = ISOCH_ANY_CHANNEL; // Reset it.
if(Status) {
ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to free Isoch channel\n", Status));
}
}
IoFreeIrp(Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
NTSTATUS
DCamFreeIsochResource (
PDCAM_EXTENSION pDevExt,
PIRB Irb,
BOOL bFreeResource
)
/*++
Routine Description:
Free resource allocated in DCamAllocateIsochResource().
Arguments:
Srb - Pointer to Stream request block
Return Value:
Nothing
--*/
{
PIRP Irp;
CCHAR StackSize;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DbgMsg2(("\'DCamFreeIsochResource: enter; DevExt=%x, Irb=%x\n", pDevExt, Irb));
ASSERT(pDevExt);
ASSERT(Irb);
if(Irb == 0 ||
pDevExt == 0) {
DbgMsg2(("\'DCamFreeIsochResource: ABORTED!\n"));
return STATUS_SUCCESS;
}
//
// Get an Irp so we can send some free commands down
//
StackSize = pDevExt->BusDeviceObject->StackSize;
Irp = IoAllocateIrp(StackSize, FALSE);
if (!Irp) {
ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to allocate an Irp\n\n", Status));
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// 1. Free Resource
//
if (pDevExt->hResource && bFreeResource) {
DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->hResource\n"));
Irb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES;
Irb->Flags = 0;
Irb->u.IsochFreeResources.hResource = pDevExt->hResource;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
pDevExt->hResource = NULL;
if (Status) {
ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch resources\n\n", Status));
}
}
//
// 2. Free Channel
//
if (pDevExt->IsochChannel != ISOCH_ANY_CHANNEL) {
DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->IsochChannel\n"));
Irb->FunctionNumber = REQUEST_ISOCH_FREE_CHANNEL;
Irb->Flags = 0;
Irb->u.IsochFreeChannel.nChannel = pDevExt->IsochChannel;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
pDevExt->IsochChannel = ISOCH_ANY_CHANNEL;
if(Status) {
ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch channel\n\n", Status));
}
}
//
// 3. Free Bandwidth
//
if (pDevExt->hBandwidth) {
DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->hBandwidth\n"));
Irb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
Irb->Flags = 0;
Irb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
pDevExt->hBandwidth = NULL;
if (Status) {
ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch bandwidth\n", Status));
}
}
DbgMsg2(("\'DCamFreeIsochResource: hResource = %x\n", pDevExt->hResource));
IoFreeIrp(Irp);
return STATUS_SUCCESS;
}
VOID
InitializeStreamExtension(
PDCAM_EXTENSION pDevExt,
PHW_STREAM_OBJECT pStreamObject,
PSTREAMEX pStrmEx
)
{
PAGED_CODE();
pStrmEx->hMasterClock = 0;
pStrmEx->FrameInfo.ExtendedHeaderSize = sizeof(KS_FRAME_INFO);
pStrmEx->FrameInfo.PictureNumber = 0;
pStrmEx->FrameInfo.DropCount = 0;
pStrmEx->FrameInfo.dwFrameFlags = 0;
pStrmEx->FirstFrameTime = 0;
pStrmEx->pVideoInfoHeader = 0;
pStrmEx->KSState = KSSTATE_STOP;
pStrmEx->KSSavedState = KSSTATE_STOP;
KeInitializeMutex( &pStrmEx->hMutex, 0); // Level 0 and in Signal state
}
BOOL
DCamDeviceInUse(
PIRB pIrb,
PDCAM_EXTENSION pDevExt
)
/*++
Routine Description:
See if this device is in used.
We check ISO_ENABLE since this is the only register
in a 1394DCam that we can set/get and 99%+ of time
this bit is set by its owner.
Arguments:
pIrb - Pointer to IEEE 1394 Request Block definition (IRB)
pDevExt - this device extension
Return Value:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -