?? callback.c
字號:
//===========================================================================
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996 - 2000 Microsoft Corporation. All Rights Reserved.
//
//===========================================================================
/*++
Module Name:
dcampkt.c
Abstract:
This file contains code to handle callback from the bus/class driver.
They might be running in DISPATCH level.
Author:
Yee J. Wu 15-Oct-97
Environment:
Kernel mode only
Revision History:
--*/
#include "strmini.h"
#include "ksmedia.h"
#include "1394.h"
#include "wdm.h" // for DbgBreakPoint() defined in dbg.h
#include "dbg.h"
#include "dcamdef.h"
#include "dcampkt.h"
#include "sonydcam.h"
#include "capprop.h"
NTSTATUS
DCamToInitializeStateCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PDCAM_IO_CONTEXT pDCamIoContext
)
/*++
Routine Description:
Completion routine called after the device is initialize to a known state.
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.
--*/
{
PDCAM_EXTENSION pDevExt;
PSTREAMEX pStrmEx;
PIRB pIrb;
if(!pDCamIoContext) {
return STATUS_MORE_PROCESSING_REQUIRED;
}
pIrb = pDCamIoContext->pIrb;
pDevExt = pDCamIoContext->pDevExt;
DbgMsg2(("\'DCamToInitializeStateCompletionRoutine: completed DeviceState=%d; pIrp->IoStatus.Status=%x\n",
pDCamIoContext->DeviceState, pIrp->IoStatus.Status));
// Free MDL
if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
DbgMsg3(("DCamToInitializeStateCompletionRoutine: IoFreeMdl\n"));
IoFreeMdl(pIrb->u.AsyncWrite.Mdl);
}
// CAUTION:
// Do we need to retry if the return is STATUS_TIMEOUT or invalid generation number ?
//
if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
ERROR_LOG(("DCamToInitializeStateCompletionRoutine: Status=%x != STATUS_SUCCESS; cannot restart its state.\n", pIrp->IoStatus.Status));
if(pDCamIoContext->pSrb) {
pDCamIoContext->pSrb->Status = STATUS_UNSUCCESSFUL;
StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
}
DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
//
// Done here if we are in STOP or PAUSE state;
// else setting to RUN state.
//
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
//
// No stream is open, job is done.
//
if(!pStrmEx) {
if(pDCamIoContext->pSrb) {
pDCamIoContext->pSrb->Status = STATUS_SUCCESS;
StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
switch(pStrmEx->KSStateFinal) {
case KSSTATE_STOP:
case KSSTATE_PAUSE:
pStrmEx->KSState = pStrmEx->KSStateFinal;
if(pDCamIoContext->pSrb) {
pDCamIoContext->pSrb->Status = STATUS_SUCCESS;
StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
}
DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
break;
case KSSTATE_RUN:
if(pDCamIoContext->pSrb) {
pDCamIoContext->pSrb->Status = STATUS_SUCCESS;
StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
}
// Restart the stream.
DCamSetKSStateRUN(pDevExt, pDCamIoContext->pSrb);
// Need pDCamIoContext->pSrb; so free it after DCamSetKSStateRUN().
DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
break;
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
DCamSetKSStateInitialize(
PDCAM_EXTENSION pDevExt
)
/*++
Routine Description:
Set KSSTATE to KSSTATE_RUN.
Arguments:
pDevExt -
Return Value:
Nothing
--*/
{
PSTREAMEX pStrmEx;
PIRB pIrb;
PIRP pIrp;
PDCAM_IO_CONTEXT pDCamIoContext;
PIO_STACK_LOCATION NextIrpStack;
NTSTATUS Status;
ASSERT(pDevExt);
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Initialize the device to a known state
// may need to do this due to power down??
//
pDCamIoContext->DeviceState = DCAM_SET_INITIALIZE; // Keep track of device state that we just set.
pDCamIoContext->pDevExt = pDevExt;
pDCamIoContext->RegisterWorkArea.AsULONG = 0;
pDCamIoContext->RegisterWorkArea.Initialize.Initialize = TRUE;
pDCamIoContext->RegisterWorkArea.AsULONG = bswap(pDevExt->RegisterWorkArea.AsULONG);
pIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
pIrb->Flags = 0;
pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, Initialize);
pIrb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(ULONG);
pIrb->u.AsyncWrite.nBlockSize = 0;
pIrb->u.AsyncWrite.fulFlags = 0;
InterlockedExchange(&pIrb->u.AsyncWrite.ulGeneration, pDevExt->CurrentGeneration);
pIrb->u.AsyncWrite.Mdl =
IoAllocateMdl(&pDCamIoContext->RegisterWorkArea, sizeof(ULONG), FALSE, FALSE, NULL);
MmBuildMdlForNonPagedPool(pIrb->u.AsyncWrite.Mdl);
NextIrpStack = IoGetNextIrpStackLocation(pIrp);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pIrb;
IoSetCompletionRoutine(
pIrp,
DCamToInitializeStateCompletionRoutine,
pDCamIoContext,
TRUE,
TRUE,
TRUE
);
Status =
IoCallDriver(
pDevExt->BusDeviceObject,
pIrp
);
return STATUS_SUCCESS;
}
VOID
DCamBusResetNotification(
IN PVOID Context
)
/*++
Routine Description:
We receive this callback notification after a bus reset and if the device is still attached.
This can happen when a new device is plugged in or an existing one is removed, or due to
awaken from sleep state. We will restore the device to its original streaming state by
(1) Initialize the device to a known state and then
(2) launch a state machine to restart streaming.
We will stop the state machine if previous state has failed. This can happen if the generation
count is changed before the state mahcine is completed.
The freeing and realocation of isoch bandwidth and channel are done in the bus reset irp.
It is passed down by stream class in SRB_UNKNOWN_DEVICE_COMMAND. This IRP is guarantee to
call after this bus reset notification has returned and while the state machine is going on.
This is a callback at IRQL_DPC level; there are many 1394 APIs cannot be called at this level
if it does blocking using KeWaitFor*Object(). Consult 1394 docuement for the list.
Arguments:
Context - Pointer to the context of this registered notification.
Return Value:
Nothing
--*/
{
PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Context;
PSTREAMEX pStrmEx;
NTSTATUS Status;
PIRP pIrp;
PIRB pIrb;
if(!pDevExt) {
ERROR_LOG(("DCamBusResetNotification:pDevExt is 0.\n\n"));
ASSERT(pDevExt);
return;
}
//
// Check a field in the context that must be valid to make sure that it is Ok to continue.
//
if(!pDevExt->BusDeviceObject) {
ERROR_LOG(("DCamBusResetNotification:pDevExtBusDeviceObject is 0.\n\n"));
ASSERT(pDevExt->BusDeviceObject);
return;
}
DbgMsg2(("DCamBusResetNotification: pDevExt %x, pDevExt->pStrmEx %x, pDevExt->BusDeviceObject %x\n",
pDevExt, pDevExt->pStrmEx, pDevExt->BusDeviceObject));
//
//
// Get the current generation count first
//
// CAUTION:
// not all 1394 APIs can be called in DCamSubmitIrpSynch() if in DISPATCH_LEVEL;
// Getting generation count require no blocking so it is OK.
if(!DCamAllocateIrbAndIrp(&pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
ERROR_LOG(("DCamBusResetNotification: DcamAllocateIrbAndIrp has failed!!\n\n\n"));
ASSERT(FALSE);
return;
}
pIrb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
pIrb->Flags = 0;
Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
if(Status) {
ERROR_LOG(("\'DCamBusResetNotification: Status=%x while trying to get generation number\n", Status));
// Done with them; free resources.
DCamFreeIrbIrpAndContext(0, pIrb, pIrp);
return;
}
ERROR_LOG(("DCamBusResetNotification: Generation number from %d to %d\n",
pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount));
InterlockedExchange(&pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount);
// Done with them; free resources.
DCamFreeIrbIrpAndContext(0, pIrb, pIrp);
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
DbgMsg2(("\'%d:%s) DCamBusResetNotification: !!! pDevExt, %x; pStrmEx, %x !!!\n",
pDevExt->idxDev, pDevExt->pchVendorName, pDevExt, pStrmEx));
//
// If the stream was open (pStrmEx != NULL && pStrmEx->pVideoInfoHeader != NULL),
// then we need to restore its streaming state.
//
if (pStrmEx &&
pStrmEx->pVideoInfoHeader != NULL) {
DbgMsg2(("\'%d:%s) DCamBusResetNotification: Stream was open; Try allocate them again.\n", pDevExt->idxDev, pDevExt->pchVendorName));
} else {
DbgMsg2(("DCamBusResetNotification:Stream has not open on this device. Done!\n"));
return;
}
//
// Save the original state as the final state.
//
if(pStrmEx)
pStrmEx->KSStateFinal = pStrmEx->KSState;
//
// Initialize the device, and restore to its original streaming state.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -