/*++ 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 \n")); TRACE(TL_PNP_ERROR,("\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); }