📄 datapkt.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:
DataPkt.c
Abstract:
Stream class based WDM driver for 1934 Desktop Camera.
This file contains code to handle the stream class packets.
Author:
Yee J. Wu 24-Jun-98
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"
extern CAMERA_ISOCH_INFO IsochInfoTable[];
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DCamSurpriseRemoval)
#pragma alloc_text(PAGE, DCamReceiveDataPacket)
#endif
NTSTATUS
DCamCancelOnePacketCR(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
PISOCH_DESCRIPTOR IsochDescriptor
)
/*++
Routine Description:
Completion routine for detach an isoch descriptor associate with a pending read SRB.
Will cancel the pending SRB here if detaching descriptor has suceeded.
Arguments:
DriverObject - Pointer to driver object created by system.
pIrp - Allocated locally, need to be free here.
IsochDescriptor - Isoch descriptor containing the SRB to be cancelled.
Return Value:
None.
--*/
{
PHW_STREAM_REQUEST_BLOCK pSrbToCancel;
PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
PDCAM_EXTENSION pDevExt;
if(STATUS_SUCCESS != pIrp->IoStatus.Status) {
ERROR_LOG(("DCamCancelOnePacketCR: Detach buffer failed with pIrp->IoStatus.Status= %x (! STATUS_SUCCESS) \n", pIrp->IoStatus.Status));
ASSERT(STATUS_SUCCESS == pIrp->IoStatus.Status);
} else {
IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
pSrbToCancel = IsochDescriptorReserved->Srb;
pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
IsochDescriptorReserved->Flags |= STATE_SRB_IS_COMPLETE;
pSrbToCancel->CommandData.DataBufferArray->DataUsed = 0;
pSrbToCancel->ActualBytesTransferred = 0;
pSrbToCancel->Status = pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED;
DbgMsg2(("DCamCancelOnePacketCR: SRB %x, Status %x, IsochDesc %x, Reserved %x cancelled\n",
pSrbToCancel, pSrbToCancel->Status, IsochDescriptor, IsochDescriptorReserved));
StreamClassStreamNotification(
StreamRequestComplete,
pSrbToCancel->StreamObject,
pSrbToCancel);
ExFreePool(IsochDescriptor);
}
// Allocated locally so free it.
IoFreeIrp(pIrp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID
DCamDetachAndCancelOnePacket(
IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel,
PISOCH_DESCRIPTOR IsochDescriptorToDetach,
HANDLE hResource,
PDEVICE_OBJECT pBusDeviceObject
)
/*++
Routine Description:
Detach an isoch descriptor and then cancel pending SRB in the completion routine.
Arguments:
pSrbToCancel - Pointer to SRB to cancel
IsochDescriptorToDetach - Iosch descriptor to detach
hResource - isoch resource allocated
hBusDeviceObject - bus device object
Return Value:
None.
--*/
{
PDCAM_EXTENSION pDevExt;
PIO_STACK_LOCATION NextIrpStack;
NTSTATUS Status;
PIRB pIrb;
PIRP pIrp;
DbgMsg2(("\'DCamDetachAndCancelOnePacket: pSrbTocancel %x, detaching IsochDescriptorToDetach %x\n", pSrbToCancel, IsochDescriptorToDetach));
pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
// Reuse cached IRP
pIrp = (PIRP) IsochDescriptorToDetach->DeviceReserved[5];
pIrb = pSrbToCancel->SRBExtension;
pIrb->Flags = 0;
pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS;
pIrb->u.IsochDetachBuffers.hResource = hResource;
pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = 1;
pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDescriptorToDetach;
NextIrpStack = IoGetNextIrpStackLocation(pIrp);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pIrb;
IoSetCompletionRoutine(
pIrp,
DCamCancelOnePacketCR,
IsochDescriptorToDetach,
TRUE,
TRUE,
TRUE
);
Status =
IoCallDriver(
pBusDeviceObject,
pIrp
);
ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING);
}
VOID
AbortWorkItem(
IN DEVICE_OBJECT *DeviceObject,
IN DCAM_EXTENSION *DevExt
)
/*++
Routine Description:
This work item routine aborts a stream at passive level.
Arguments:
DeviceObject - Device object
DevExt - Device extension
Return Value:
Success / failure
--*/
{
ERROR_LOG( ( "[%s] abort starting...\n", __FUNCTION__ ) );
DCamCancelAllPackets(
DevExt,
&DevExt->PendingReadCount );
}
VOID
DCamCancelOnePacket(
IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel
)
/*++
Routine Description:
This routine is called to cancel a pending streaming SRB. This is likely to
happen when transitioning from PAUSE to STOP state.
Note: This routine is called at DISPATCH_LEVEL !! so we queue a work item
to cancel pending requests at the passive level.
Arguments:
pSrbToCancel - Pointer to SRB to cancel
Return Value:
None.
--*/
{
PDCAM_EXTENSION pDevExt;
PSTREAMEX pStrmEx;
PIO_WORKITEM pIOWorkItem;
pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
ASSERT(pDevExt);
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
ASSERT(pStrmEx);
// Nothing to cancel
if(pStrmEx == NULL) {
return;
}
//
// Can cancel stream SRB as a result of aborting a stream.
//
if ( (pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) != SRB_HW_FLAGS_STREAM_REQUEST) {
ERROR_LOG(("DCamCancelOnePacket: Cannot cancel Device SRB %x\n", pSrbToCancel));
ASSERT( (pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) == SRB_HW_FLAGS_STREAM_REQUEST );
return;
}
//
// Abort only once so we must obtain the token first.
//
if( InterlockedExchange( &pStrmEx->CancelToken, 1 ) == 1 ) {
// Already in cancelling state!
ERROR_LOG( ( "Already cancelling...\n" ) );
return;
}
//
// Start a work item to cancel all pending request
//
pIOWorkItem = IoAllocateWorkItem( pDevExt ->PhysicalDeviceObject );
if( !pIOWorkItem ) {
// Could not do it, release the token.
InterlockedExchange( &pStrmEx->CancelToken, 0 );
return;
}
else {
IoQueueWorkItem( pIOWorkItem, AbortWorkItem, DelayedWorkQueue, pDevExt );
}
}
VOID
DCamCancelAllPackets(
PDCAM_EXTENSION pDevExt,
LONG *plPendingReadCount
)
/*++
Routine Description:
This routine is use to cancel all pending IRP.
Can be called at DISPATCH_LEVEL.
Arguments:
pSrbToCancel - Pointer to SRB to cancel
pDevExt - Device's contect
plPendingReadCount - Number of pending read
Return Value:
None.
--*/
{
HW_STREAM_REQUEST_BLOCK *pSrbToCancel;
ISOCH_DESCRIPTOR *IsochDescriptorToDetach;
LIST_ENTRY *pEntry;
KIRQL oldIrql;
STREAMEX *pStrmEx;
PAGED_CODE();
pStrmEx = pDevExt->pStrmEx;
// Nothing to cancel
if(pStrmEx == NULL) {
return;
}
//
// Sychronize with READ request so all request can be cancelled
//
KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );
//
// Loop through the linked list from the beginning to end,
// trying to find the SRB to cancel
//
KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
pEntry = pDevExt->IsochDescriptorList.Flink;
while (pEntry != &pDevExt->IsochDescriptorList) {
pSrbToCancel = ((PISOCH_DESCRIPTOR_RESERVED)pEntry)->Srb;
IsochDescriptorToDetach = \
(PISOCH_DESCRIPTOR) ( ((PUCHAR) pEntry) -
FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
if(((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) {
// Skip this one since it is already in detaching phase or completed.
ERROR_LOG(("DCamCancelAllPacket: pSrbToCancel %x, Descriptor %x, Reserved %x already detaching or completed\n",
pSrbToCancel, IsochDescriptorToDetach, pEntry));
ASSERT( FALSE && "Not ready to be cancelled!!!" );
pEntry = pEntry->Flink; // next
} else {
((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags |= STATE_DETACHING_BUFFERS;
#if DBG
// Should not have been detached.
ASSERT((IsochDescriptorToDetach->DeviceReserved[7] == 0x87654321));
IsochDescriptorToDetach->DeviceReserved[7]++;
#endif
RemoveEntryList(pEntry);
InterlockedDecrement(plPendingReadCount);
DbgMsg2(("DCamCancelAllPackets: pSrbToCancel %x, Descriptor %x, Reserved %x\n",
pSrbToCancel, IsochDescriptorToDetach, pEntry));
pEntry = pEntry->Flink; // pEntry is deleted in DCamDetachAndCancelOnePacket(); so get next here.
DCamDetachAndCancelOnePacket(
pSrbToCancel,
IsochDescriptorToDetach,
pDevExt->hResource,
pDevExt->BusDeviceObject);
}
}
KeReleaseSpinLock (&pDevExt->IsochDescriptorLock, oldIrql);
KeReleaseMutex(&pStrmEx->hMutex, FALSE);
}
VOID
DCamSurpriseRemoval(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
/*++
Routine Description:
Response to SRB_SURPRISE_REMOVAL.
Arguments:
pSrb - Pointer to the stream request block
Return Value:
None.
--*/
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -