?? 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;
pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
ASSERT(pIrp);
if(!pIrp)
return;
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
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 !!
Arguments:
pSrbToCancel - Pointer to SRB to cancel
Return Value:
None.
--*/
{
PHW_STREAM_REQUEST_BLOCK pSrbInQ;
PISOCH_DESCRIPTOR IsochDescriptorToDetach;
PDCAM_EXTENSION pDevExt;
PSTREAMEX pStrmEx;
PLIST_ENTRY pEntry; // Pointer to an isoch decriptor reserved structure
KIRQL oldIrql;
BOOL Found;
pDevExt = (PDCAM_EXTENSION) pSrbToCancel->HwDeviceExtension;
ASSERT(pDevExt);
pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
ASSERT(pStrmEx);
// Nothing to cancel
if(pStrmEx == NULL) {
return;
}
//
// We only expect stream SRB, but not device SRB.
//
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;
}
//
// Loop through the linked list from the beginning to end,
// trying to find the SRB to cancel
//
KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
Found = FALSE;
pEntry = pDevExt->IsochDescriptorList.Flink;
while (pEntry != &pDevExt->IsochDescriptorList) {
pSrbInQ = ((PISOCH_DESCRIPTOR_RESERVED)pEntry)->Srb;
IsochDescriptorToDetach = \
(PISOCH_DESCRIPTOR) ( ((PUCHAR) pEntry) -
FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
if(pSrbToCancel == pSrbInQ) {
// If we are in RUN state, we could be competing with IsochCallback;
// Whichever grabs and change STATE_DETACHING_BUFFERS will detach.
if(((PISOCH_DESCRIPTOR_RESERVED) pEntry)->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) {
Found = FALSE; // IsochCallback are detaching it (we lost our chance).
ERROR_LOG(("DCamCancelOnePacket: pSrbToCancel %x, Descriptor %x, Reserved %x already detaching or completed\n",
pSrbToCancel, IsochDescriptorToDetach, pEntry));
} 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(&pDevExt->PendingReadCount);
Found = TRUE;
}
break;
}
pEntry = pEntry->Flink; // Next
}
KeReleaseSpinLock (&pDevExt->IsochDescriptorLock, oldIrql);
//
// Since we are in DISPATCH level, we cannot do sync operation;
// so we will complete this asynchronously in the completion routine.
//
if (Found) {
DCamDetachAndCancelOnePacket(
pSrbToCancel,
IsochDescriptorToDetach,
pDevExt->hResource,
pDevExt->BusDeviceObject);
} else {
ERROR_LOG(("DCamCancelOnePacket: pSrbToCancel %x is not in our list!\n", pSrbToCancel));
ASSERT(Found);
}
}
VOID
DCamCancelAllPackets(
PHW_STREAM_REQUEST_BLOCK pSrb,
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.
--*/
{
PHW_STREAM_REQUEST_BLOCK pSrbToCancel;
PISOCH_DESCRIPTOR IsochDescriptorToDetach;
PLIST_ENTRY pEntry;
KIRQL oldIrql;
PSTREAMEX pStrmEx;
pStrmEx = pDevExt->pStrmEx;
// Nothing to cancel
if(pStrmEx == NULL) {
return;
}
//
// 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));
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);
pSrb->Status = STATUS_SUCCESS;
DbgMsg1(("DCamCancelAllPackets: Complete pSrb %x, Status %x\n", pSrb, pSrb->Status));
COMPLETE_SRB(pSrb)
}
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.
--*/
{
PIRP pIrp;
PIRB pIrb;
PDCAM_EXTENSION pDevExt;
PSTREAMEX pStrmEx;
NTSTATUS Status, StatusWait;
PAGED_CODE();
pIrb = (PIRB) pSrb->SRBExtension;
ASSERT(pIrb);
pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
ASSERT(pDevExt);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -