windows-nt/Source/XPSP1/NT/drivers/wdm/capture/mini/mstape/mstpuppr.c
2020-09-26 16:20:57 +08:00

928 lines
28 KiB
C

/*++
Copyright (C) Microsoft Corporation, 1999 - 2000
Module Name:
MSTpUppr.c
Abstract:
Interface code with stream class driver.
Last changed by:
Author: Yee J. Wu
Environment:
Kernel mode only
Revision History:
$Revision:: $
$Date:: $
--*/
#include "strmini.h"
#include "ksmedia.h"
#include "1394.h"
#include "61883.h"
#include "avc.h"
#include "dbg.h"
#include "MsTpFmt.h"
#include "MsTpDef.h"
#include "MsTpGuts.h" // Function prototypes
#include "MsTpAvc.h"
#include "EDevCtrl.h"
#ifdef TIME_BOMB
#include "..\..\inc\timebomb.c"
#endif
#if DBG
LONG MSDVCRMutextUseCount = 0;
#endif
// global flag for debugging. Inlines are defined in dbg.h. The debug level is set for
// minimal amount of messages.
#if DBG
#define TraceMaskCheckIn TL_PNP_ERROR | TL_STRM_ERROR
#define TraceMaskDefault TL_PNP_ERROR | TL_PNP_WARNING \
| TL_61883_ERROR | TL_61883_WARNING \
| TL_CIP_ERROR \
| TL_FCP_ERROR \
| TL_STRM_ERROR | TL_STRM_WARNING \
| TL_CLK_ERROR
#define TraceMaskDebug TL_PNP_ERROR | TL_PNP_WARNING \
| TL_61883_ERROR| TL_61883_WARNING \
| TL_CIP_ERROR \
| TL_FCP_ERROR | TL_FCP_WARNING \
| TL_STRM_ERROR | TL_STRM_WARNING \
| TL_CLK_ERROR
ULONG TapeTraceMask = TraceMaskCheckIn;
ULONG TapeAssertLevel = 1;
#endif
extern AVCSTRM_FORMAT_INFO AVCStrmFormatInfoTable[];
//
// Function prototypes
//
VOID
DVRcvStreamDevicePacket(
IN PHW_STREAM_REQUEST_BLOCK pSrb
);
VOID
DVSRBRead(
IN PKSSTREAM_HEADER pStrmHeader,
IN ULONG ulFrameSize,
IN PDVCR_EXTENSION pDevExt,
IN PSTREAMEX pStrmExt,
IN PHW_STREAM_REQUEST_BLOCK pSrb // needs Srb->Status
);
BOOL
DVSignalEOStream(
IN PHW_STREAM_REQUEST_BLOCK pSrb,
IN PSTREAMEX pStrmExt,
IN FMT_INDEX ulVideoFormatIndex,
IN ULONG ulOptionFlags
);
NTSTATUS
DVAttachWriteFrame(
IN PSTREAMEX pStrmExt
);
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
#if 0 // Enable later
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DVRcvStreamDevicePacket)
#pragma alloc_text(PAGE, AVCTapeRcvControlPacket)
#pragma alloc_text(PAGE, AVCTapeRcvDataPacket)
// #pragma alloc_text(INIT, DriverEntry)
#endif
#endif
VOID
DVRcvStreamDevicePacket(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
/*++
Routine Description:
This is where most of the interesting Stream requests come to us
--*/
{
PDVCR_EXTENSION pDevExt;
PAV_61883_REQUEST pAVReq;
PIO_STACK_LOCATION pIrpStack;
PAGED_CODE();
//
// Get these extensions from a SRB
//
pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
pAVReq = (PAV_61883_REQUEST) pSrb->SRBExtension; // Use in IrpSync is OK,
#if DBG
if(pSrb->Command != SRB_INITIALIZE_DEVICE && // PowerState is initialize in this SRB so ignore it.
pDevExt->PowerState != PowerDeviceD0) {
TRACE(TL_PNP_WARNING,("RcvDevPkt; pSrb:%x; Cmd:%x; Dev is OFF state\n", pSrb, pSrb->Command));
}
#endif
TRACE(TL_PNP_TRACE,("StreamDevicePacket: pSrb %x, Cmd %d, pdevExt %x\n", pSrb, pSrb->Command, pDevExt));
//
// Assume success
//
pSrb->Status = STATUS_SUCCESS;
switch (pSrb->Command) {
case SRB_INITIALIZE_DEVICE:
ASSERT(((PPORT_CONFIGURATION_INFORMATION) pSrb->CommandData.ConfigInfo)->HwDeviceExtension == pDevExt);
pSrb->Status =
AVCTapeInitialize(
(PDVCR_EXTENSION) ((PPORT_CONFIGURATION_INFORMATION)pSrb->CommandData.ConfigInfo)->HwDeviceExtension,
pSrb->CommandData.ConfigInfo,
pAVReq
);
break;
case SRB_INITIALIZATION_COMPLETE:
//
// Stream class has finished initialization.
// Now create DShow Medium interface BLOBs.
// This needs to be done at low priority since it uses the registry, so use a callback
//
pSrb->Status =
AVCTapeInitializeCompleted(
pDevExt
);
break;
case SRB_GET_STREAM_INFO:
//
// this is a request for the driver to enumerate requested streams
//
pSrb->Status =
AVCTapeGetStreamInfo(
pDevExt,
pSrb->NumberOfBytesToTransfer,
&pSrb->CommandData.StreamBuffer->StreamHeader,
&pSrb->CommandData.StreamBuffer->StreamInfo
);
break;
case SRB_GET_DATA_INTERSECTION:
pSrb->Status =
AVCTapeGetDataIntersection(
pDevExt->NumOfPins,
pSrb->CommandData.IntersectInfo->StreamNumber,
pSrb->CommandData.IntersectInfo->DataRange,
pSrb->CommandData.IntersectInfo->DataFormatBuffer,
pSrb->CommandData.IntersectInfo->SizeOfDataFormatBuffer,
AVCStrmFormatInfoTable[pDevExt->VideoFormatIndex].FrameSize,
&pSrb->ActualBytesTransferred,
pDevExt->pStreamInfoObject
#ifdef SUPPORT_NEW_AVC
,
pDevExt->hPlugLocalOut,
pDevExt->hPlugLocalIn
#endif
);
break;
case SRB_OPEN_STREAM:
//
// Serialize SRB_OPEN_STREAMs
//
KeWaitForMutexObject(&pDevExt->hMutex, Executive, KernelMode, FALSE, NULL);
pSrb->Status =
AVCTapeOpenStream(
pSrb->StreamObject,
pSrb->CommandData.OpenFormat,
pAVReq
);
KeReleaseMutex(&pDevExt->hMutex, FALSE);
break;
case SRB_CLOSE_STREAM:
KeWaitForMutexObject(&pDevExt->hMutex, Executive, KernelMode, FALSE, NULL);
pSrb->Status =
AVCTapeCloseStream(
pSrb->StreamObject,
pSrb->CommandData.OpenFormat,
pAVReq
);
KeReleaseMutex(&pDevExt->hMutex, FALSE);
break;
case SRB_GET_DEVICE_PROPERTY:
pSrb->Status =
AVCTapeGetDeviceProperty(
pDevExt,
pSrb->CommandData.PropertyInfo,
&pSrb->ActualBytesTransferred
);
break;
case SRB_SET_DEVICE_PROPERTY:
pSrb->Status =
AVCTapeSetDeviceProperty(
pDevExt,
pSrb->CommandData.PropertyInfo,
&pSrb->ActualBytesTransferred
);
break;
case SRB_CHANGE_POWER_STATE:
pIrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
if(pIrpStack->MinorFunction == IRP_MN_SET_POWER) {
pSrb->Status =
DVChangePower(
(PDVCR_EXTENSION) pSrb->HwDeviceExtension,
pAVReq,
pSrb->CommandData.DeviceState
);
} else
if(pIrpStack->MinorFunction == IRP_MN_QUERY_POWER) {
TRACE(TL_PNP_WARNING,("IRP_MN_QUERY_POWER: PwrSt:%d\n", pDevExt->PowerState));
pSrb->Status = STATUS_SUCCESS;
}
else {
TRACE(TL_PNP_WARNING,("Not Supported POWER_STATE MinorFunc:%d\n", pIrpStack->MinorFunction));
pSrb->Status = STATUS_NOT_IMPLEMENTED; // STATUS_NOT_SUPPORTED;
}
break;
case SRB_UNKNOWN_DEVICE_COMMAND:
//
// We might be interested in unknown commands if they pertain
// to bus resets. Bus resets are important cuz we need to know
// what the current generation count is.
//
pIrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
if(pIrpStack->MajorFunction == IRP_MJ_PNP) {
if(pIrpStack->MinorFunction == IRP_MN_BUS_RESET) {
AVCTapeProcessPnPBusReset(
pDevExt
);
// Always success
pSrb->Status = STATUS_SUCCESS;
}
else {
TRACE(TL_PNP_TRACE,("StreamDevicePacket: NOT_IMPL; IRP_MJ_PNP Min:%x\n",
pIrpStack->MinorFunction
));
pSrb->Status = STATUS_NOT_IMPLEMENTED; // SUPPORTED;
}
}
else
pSrb->Status = STATUS_NOT_IMPLEMENTED; // SUPPORTED;
break;
case SRB_SURPRISE_REMOVAL:
TRACE(TL_PNP_WARNING,("#SURPRISE_REMOVAL# pSrb %x, pDevExt %x\n", pSrb, pDevExt));
pSrb->Status =
AVCTapeSurpriseRemoval(
pDevExt,
pAVReq
);
break;
case SRB_UNINITIALIZE_DEVICE:
TRACE(TL_PNP_WARNING,("#UNINITIALIZE_DEVICE# pSrb %x, pDevExt %x\n", pSrb, pDevExt));
pSrb->Status =
AVCTapeUninitialize(
(PDVCR_EXTENSION) pSrb->HwDeviceExtension
);
break;
default:
TRACE(TL_PNP_WARNING,("StreamDevicePacket: Unknown or unprocessed SRB cmd %x\n", pSrb->Command));
//
// this is a request that we do not understand. Indicate invalid
// command and complete the request
//
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
//
// NOTE:
//
// all of the commands that we do, or do not understand can all be completed
// synchronously at this point, so we can use a common callback routine here.
// If any of the above commands require asynchronous processing, this will
// have to change
//
#if DBG
if (pSrb->Status != STATUS_SUCCESS &&
pSrb->Status != STATUS_NOT_SUPPORTED &&
pSrb->Status != STATUS_NOT_IMPLEMENTED &&
pSrb->Status != STATUS_BUFFER_TOO_SMALL &&
pSrb->Status != STATUS_BUFFER_OVERFLOW &&
pSrb->Status != STATUS_NO_MATCH
) {
TRACE(TL_PNP_WARNING,("StreamDevicePacket:pSrb->Command(0x%x) does not return STATUS_SUCCESS or NOT_IMPLEMENTED but 0x%x\n", pSrb->Command, pSrb->Status));
}
#endif
if(STATUS_PENDING != pSrb->Status) {
StreamClassDeviceNotification(
DeviceRequestComplete,
pSrb->HwDeviceExtension,
pSrb
);
}
else {
// Pending pSrb which will be completed asynchronously
TRACE(TL_PNP_WARNING,("ReceiveDevicePacket:Pending pSrb %x\n", pSrb));
}
}
VOID
AVCTapeRcvControlPacket(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
/*++
Routine Description:
Called with packet commands that control the video stream
--*/
{
PAV_61883_REQUEST pAVReq;
PSTREAMEX pStrmExt;
PDVCR_EXTENSION pDevExt;
PAGED_CODE();
//
// Get these three extension from SRB
//
pAVReq = (PAV_61883_REQUEST) pSrb->SRBExtension; // This is OK to be used us IrpSync operation
pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
pStrmExt = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension; // Only valid in SRB_OPEN/CLOSE_STREAM
ASSERT(pStrmExt && pDevExt && pAVReq);
//
// Default to success
//
pSrb->Status = STATUS_SUCCESS;
switch (pSrb->Command) {
case SRB_GET_STREAM_STATE:
pSrb->Status =
AVCTapeGetStreamState(
pStrmExt,
pDevExt->pBusDeviceObject,
&(pSrb->CommandData.StreamState),
&(pSrb->ActualBytesTransferred)
);
break;
case SRB_SET_STREAM_STATE:
pSrb->Status =
AVCTapeSetStreamState(
pStrmExt,
pDevExt,
pAVReq,
pSrb->CommandData.StreamState // Target KSSTATE
);
break;
case SRB_GET_STREAM_PROPERTY:
pSrb->Status =
DVGetStreamProperty(
pSrb
);
break;
case SRB_SET_STREAM_PROPERTY:
pSrb->Status =
DVSetStreamProperty(
pSrb
);
break;
case SRB_OPEN_MASTER_CLOCK:
case SRB_CLOSE_MASTER_CLOCK:
//
// This stream is being selected to provide a Master clock.
//
pSrb->Status =
AVCTapeOpenCloseMasterClock(
pStrmExt,
pSrb->Command == SRB_OPEN_MASTER_CLOCK ? pSrb->CommandData.MasterClockHandle: NULL);
break;
case SRB_INDICATE_MASTER_CLOCK:
//
// Assigns a clock to a stream.
//
pSrb->Status =
AVCTapeIndicateMasterClock(
pStrmExt,
pSrb->CommandData.MasterClockHandle);
break;
case SRB_PROPOSE_DATA_FORMAT:
//
// The SRB_PROPOSE_DATA_FORMAT command queries the minidriver
// to determine if the minidriver can change the format of a
// particular stream. If the minidriver is able to switch the
// stream to the specified format, STATUS_SUCCESS is returned.
// Note that this function only proposes a new format, but does
// not change it.
//
// The CommandData.OpenFormat passes the format to validate.
// If the minidriver is able to accept the new format, at some
// later time the class driver may send the minidriver a format
// change, which is indicated by an OptionsFlags flag in a
// KSSTREAM_HEADER structure.
//
if(!AVCTapeVerifyDataFormat(
pDevExt->NumOfPins,
pSrb->CommandData.OpenFormat,
pSrb->StreamObject->StreamNumber,
AVCStrmFormatInfoTable[pDevExt->VideoFormatIndex].FrameSize,
pDevExt->pStreamInfoObject
)) {
TRACE(TL_PNP_WARNING,("RcvControlPacket: AdapterVerifyFormat failed.\n"));
pSrb->Status = STATUS_NO_MATCH;
}
break;
default:
//
// invalid / unsupported command. Fail it as such
//
TRACE(TL_PNP_WARNING,("RcvControlPacket: unknown cmd = %x\n",pSrb->Command));
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
TRACE(TL_PNP_TRACE,("RcvControlPacket: pSrb:%x, Command %x, ->Status %x, ->CommandData %x\n",
pSrb, pSrb->Command, pSrb->Status, &(pSrb->CommandData.StreamState) ));
StreamClassStreamNotification(
StreamRequestComplete,
pSrb->StreamObject,
pSrb);
}
VOID
AVCTapeRcvDataPacket(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
/*++
Routine Description:
Called with video data packet commands
--*/
{
PSTREAMEX pStrmExt;
PDVCR_EXTENSION pDevExt;
PAVC_STREAM_REQUEST_BLOCK pAVCStrmReq;
PIRP pIrpReq;
PIO_STACK_LOCATION NextIrpStack;
NTSTATUS Status;
PDRIVER_REQUEST pDriverReq;
KIRQL oldIrql;
PAGED_CODE();
pStrmExt = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
pDevExt = (PDVCR_EXTENSION) pSrb->HwDeviceExtension;
#if DBG
if(pDevExt->PowerState != PowerDeviceD0) {
TRACE(TL_PNP_WARNING,("SRB_READ/WRITE; PowerSt:OFF; pSrb:%x\n", pSrb));
}
#endif
// The stream has to be open before we can do anything.
if (pStrmExt == NULL) {
TRACE(TL_STRM_TRACE,("RcvDataPacket: stream not opened for SRB %x. kicking out...\n", pSrb->Command));
pSrb->Status = STATUS_UNSUCCESSFUL;
pSrb->CommandData.DataBufferArray->DataUsed = 0;
StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
return;
}
TRACE(TL_PNP_TRACE,("XXX_DATA(%d, %d);Srb:%x;Flg:%x;FExt:%d:%d\n",
(DWORD) pStrmExt->cntSRBReceived,
(DWORD) pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000,
pSrb,
pSrb->CommandData.DataBufferArray->OptionsFlags,
pSrb->CommandData.DataBufferArray->FrameExtent,
AVCStrmFormatInfoTable[pDevExt->VideoFormatIndex].FrameSize
));
// If we has asked to stopped, we should not receive data request.
ASSERT(pStrmExt->StreamState != KSSTATE_STOP);
//
// determine the type of packet.
//
pSrb->Status = STATUS_SUCCESS;
switch (pSrb->Command) {
case SRB_WRITE_DATA:
// ********************************
// Take care of some special cases:
// ********************************
// Can signal this when the last is transmitted or sigal it immediately like
// what is done here.
if(pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM) {
// Optional, wait a fix time and can be signalled when the last one has returned.
// And then signal the completion.
TRACE(TL_STRM_WARNING,("RcvDataPacket: EndOfStream is signalled!\n"));
pSrb->CommandData.DataBufferArray->DataUsed = 0;
pSrb->Status = STATUS_SUCCESS;
//
// Send this flag down to AVCStrm.sys so it will wait until
// all attach buffers are completed.
//
} else if (pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) {
TRACE(TL_PNP_WARNING,("RcvDataPacket:KSSTREAM_HEADER_OPTIONSF_TYPECHANGED.\n"));
pSrb->CommandData.DataBufferArray->DataUsed = 0;
// May need to compare the data format; instead of return STATUS_SUCCESS??
pSrb->Status = STATUS_SUCCESS; // May need to check the format when dynamic format change is allowed.
break;
}
case SRB_READ_DATA:
//
// If removed, cancel the request with STATUS_DEVICE_REMOVED.
// (apply to both SRB_READ_DATA and SRB_WRITE_DATA)
//
if(pDevExt->bDevRemoved) {
TRACE(TL_STRM_WARNING,("SRB_READ/WRITE; DevRemoved!\n", pSrb));
pSrb->Status = STATUS_DEVICE_REMOVED;
pSrb->CommandData.DataBufferArray->DataUsed = 0;
break;
}
//
// A true data request must has a MdlAddress unless it is a know
// optional flag.
//
if(pSrb->Irp->MdlAddress == NULL) {
if((pSrb->CommandData.DataBufferArray->OptionsFlags &
(KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM | KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) )) {
//
// Known optional flags
//
} else {
TRACE(TL_STRM_ERROR,("pSrb:%x, unknown OptionsFlags:%x\n",pSrb, pSrb->CommandData.DataBufferArray->OptionsFlags));
ASSERT(pSrb->Irp->MdlAddress);
break;
//
// We do not know how to handle this option flag so we will quit on this data request.
//
}
}
//
// Serialize with setting state
//
EnterAVCStrm(pStrmExt->hMutexReq);
//
// Get a context to send this request down
//
KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
pStrmExt->cntSRBReceived++;
if(IsListEmpty(&pStrmExt->DataDetachedListHead)) {
TRACE(TL_STRM_ERROR,("**** DataDetachList is empty! ****\n"));
ASSERT(!IsListEmpty(&pStrmExt->DataDetachedListHead));
//
// Note: The alternative to the failure is to expand the pre-allocated list.
//
KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
LeaveAVCStrm(pStrmExt->hMutexReq);
pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
pSrb->CommandData.DataBufferArray->DataUsed = 0;
break;
} else {
pDriverReq = (PDRIVER_REQUEST) RemoveHeadList(&pStrmExt->DataDetachedListHead); pStrmExt->cntDataDetached--;
#if DBG
pDriverReq->cntDataRequestReceived = pStrmExt->cntSRBReceived; // For verification
#endif
InsertTailList(&pStrmExt->DataAttachedListHead, &pDriverReq->ListEntry); pStrmExt->cntDataAttached++;
pAVCStrmReq = &pDriverReq->AVCStrmReq;
pIrpReq = pDriverReq->pIrp;
KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
}
RtlZeroMemory(pAVCStrmReq, sizeof(AVC_STREAM_REQUEST_BLOCK));
INIT_AVCSTRM_HEADER(pAVCStrmReq, (pSrb->Command == SRB_READ_DATA) ? AVCSTRM_READ : AVCSTRM_WRITE);
pAVCStrmReq->AVCStreamContext = pStrmExt->AVCStreamContext;
// Need these context when this IRP is completed.
pDriverReq->Context1 = (PVOID) pSrb;
pDriverReq->Context2 = (PVOID) pStrmExt;
// We are the clock provide if hMasterClock is not NULL.
pAVCStrmReq->CommandData.BufferStruct.ClockProvider = (pStrmExt->hMasterClock != NULL);
pAVCStrmReq->CommandData.BufferStruct.ClockHandle = pStrmExt->hClock; // Used only if !ClockProvider
pAVCStrmReq->CommandData.BufferStruct.StreamHeader = pSrb->CommandData.DataBufferArray;
//
// This could be a data or just flag that need to be processed.
// Get its system address only if there is an MdlAddress.
//
if(pSrb->Irp->MdlAddress) {
pAVCStrmReq->CommandData.BufferStruct.FrameBuffer =
#ifdef USE_WDM110 // Win2000, XP
MmGetSystemAddressForMdlSafe(pSrb->Irp->MdlAddress, NormalPagePriority);
if(!pAVCStrmReq->CommandData.BufferStruct.FrameBuffer) {
//
// Reclaim the data entry from attach (busy) to detach (free)
//
KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
RemoveEntryList(&pDriverReq->ListEntry); pStrmExt->cntDataAttached--;
InsertHeadList(&pStrmExt->DataAttachedListHead, &pDriverReq->ListEntry); pStrmExt->cntDataAttached++;
KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
pSrb->CommandData.DataBufferArray->DataUsed = 0;
ASSERT(pAVCStrmReq->CommandData.BufferStruct.FrameBuffer);
break;
}
#else // Win9x
MmGetSystemAddressForMdl (pSrb->Irp->MdlAddress);
#endif
}
// This is a Async command
NextIrpStack = IoGetNextIrpStackLocation(pIrpReq);
NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_AVCSTRM_CLASS;
NextIrpStack->Parameters.Others.Argument1 = pAVCStrmReq;
// Not cancellable!
IoSetCancelRoutine(
pIrpReq,
NULL
);
IoSetCompletionRoutine(
pIrpReq,
AVCTapeReqReadDataCR,
pDriverReq,
TRUE, // Success
TRUE, // Error
TRUE // or Cancel
);
pSrb->Status = STATUS_PENDING;
pStrmExt->cntDataSubmitted++;
Status =
IoCallDriver(
pDevExt->pBusDeviceObject,
pIrpReq
);
LeaveAVCStrm(pStrmExt->hMutexReq);
if(Status == STATUS_PENDING) {
// Normal case.
return; // Will complete asychronousely (Success, Error, or Cancel)
} else {
//
// Complete the data request synchronousely (no pending)
//
if(pDriverReq->Context1 == NULL || pDriverReq->Context2 == NULL) {
TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("pSrb:%x; SRB_READ_DATA/WRITE IRP completed with Status;%x\n", pSrb, Status));
return;
} else {
TRACE(TL_STRM_WARNING,("AVCSTRM_READ/WRITE: pSrb %x; failed or completed with ST:%x; pAVCStrmReq:%x\n", pSrb, Status, pAVCStrmReq));
ASSERT(FALSE);
// Complete the SRB if not pending
pSrb->Status = pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_UNSUCCESSFUL;
pSrb->CommandData.DataBufferArray->DataUsed = 0;
}
}
break;
default:
//
// invalid / unsupported command. Fail it as such
//
pSrb->Status = STATUS_NOT_SUPPORTED;
break;
}
ASSERT(pSrb->Status != STATUS_PENDING);
// Finally, send the srb back up ...
StreamClassStreamNotification(
StreamRequestComplete,
pSrb->StreamObject,
pSrb );
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This where life begins for a driver. The stream class takes care
of alot of stuff for us, but we still need to fill in an initialization
structure for the stream class and call it.
Arguments:
Context1 - DriverObject
Context2 - RegistryPath
Return Value:
The function value is the final status from the initialization operation.
--*/
{
HW_INITIALIZATION_DATA HwInitData;
TRACE(TL_PNP_ERROR,("<<<<<<< MSTape.sys: %s; %s; %x %x >>>>>>>>\n",
__DATE__, __TIME__, DriverObject, RegistryPath));
#ifdef TIME_BOMB
if (HasEvaluationTimeExpired()) {
TRACE(TL_PNP_ERROR, ("Evaluation period expired!") );
return STATUS_EVALUATION_EXPIRATION;
}
#endif
TRACE(TL_PNP_ERROR,("===================================================================\n"));
TRACE(TL_PNP_ERROR,("TapeTraceMask=0x%.8x = 0x[7][6][5][4][3][2][1][0] where\n", TapeTraceMask));
TRACE(TL_PNP_ERROR,("\n"));
TRACE(TL_PNP_ERROR,("PNP: [0]:Loading, power state, surprise removal, device SRB..etc.\n"));
TRACE(TL_PNP_ERROR,("61883: [1]:Plugs, connection, CMP info and call to 61883.\n"));
TRACE(TL_PNP_ERROR,("CIP: [2]:Isoch data transfer.\n"));
TRACE(TL_PNP_ERROR,("AVC: [3]:AVC commands.\n"));
TRACE(TL_PNP_ERROR,("Stream:[4]:Data intersec, open/close,.state, property etc.\n"));
TRACE(TL_PNP_ERROR,("Clock: [5]:Clock (event and signal)etc.\n"));
TRACE(TL_PNP_ERROR,("===================================================================\n"));
TRACE(TL_PNP_ERROR,("dd mstape!TapeTraceMask L1\n"));
TRACE(TL_PNP_ERROR,("e mstape!TapeTraceMask <new value> <enter>\n"));
TRACE(TL_PNP_ERROR,("<for each nibble: ERROR:8, WARNING:4, TRACE:2, INFO:1, MASK:f>\n"));
TRACE(TL_PNP_ERROR,("===================================================================\n\n"));
//
// Fill in the HwInitData structure
//
RtlZeroMemory( &HwInitData, sizeof(HW_INITIALIZATION_DATA) );
HwInitData.HwInitializationDataSize = sizeof(HwInitData);
HwInitData.HwInterrupt = NULL;
HwInitData.HwReceivePacket = DVRcvStreamDevicePacket;
HwInitData.HwRequestTimeoutHandler = DVTimeoutHandler;
HwInitData.HwCancelPacket = DVCRCancelOnePacket;
HwInitData.DeviceExtensionSize = sizeof(DVCR_EXTENSION) +
sizeof(AVC_DEV_PLUGS) * 2;
//
// The ULONG is used in SRB_WRITE_DATA to keep track of
// number of times the same SRB was attached for transmit.
//
// Data SRB: ULONG is used (< sizeof(AV_61883_REQ)
// DeviceControl or StreamControl Srb: AV_61883_REQ is used.
HwInitData.PerRequestExtensionSize = sizeof(AV_61883_REQUEST); // Per SRB
HwInitData.PerStreamExtensionSize = sizeof(STREAMEX); // Per pin/stream
HwInitData.FilterInstanceExtensionSize = 0;
HwInitData.BusMasterDMA = FALSE;
HwInitData.Dma24BitAddresses = FALSE;
HwInitData.BufferAlignment = sizeof(ULONG) - 1;
HwInitData.TurnOffSynchronization = TRUE;
HwInitData.DmaBufferSize = 0;
return StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData);
}