|
|
/*++
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); }
|