// // Differnt level of WDM supports may use different API // // e.g. MmGetSystemAddressForMdl (win9x) // Return NULL for Win9x; bugcheck for Win2000 if NULL would have returned. // // MmGetSystemAddressForMdlSafe (win2000) // Not supported in Win9x or Millen // // This is defined in SOURCES file. #define NUM_BUF_ATTACHED_THEN_ISOCH 4 // number of buffers attached before streaming and also as the water mark. // // These definition and macros are used to calculate the picture numbers. // With OHCI spec, the data is returned with the 16bit Cycle time, which includes // 3 bits of SecondCount and 13 bits of the CycleCount. This "timer" will wrap in 8 seconds. // #define TIME_PER_CYCLE 1250 // One 1394 cycle; unit = 100 nsec #define CYCLES_PER_SECOND 8000 #define MAX_SECOND_COUNTS 7 // The returned CycleTime contains 3 bits of SecondCount; that is 0..7 #define MAX_CYCLES (MAX_SECOND_COUNTS + 1) * CYCLES_PER_SECOND // 0..MAX_CYCLES-1 #define MAX_CYCLES_TIME (MAX_CYCLES * TIME_PER_CYCLE) // unit = 100nsec #define VALIDATE_CYCLE_COUNTS(CT) ASSERT(CT.CL_SecondCount <= 7 && CT.CL_CycleCount < CYCLES_PER_SECOND && CT.CL_CycleOffset == 0); #define CALCULATE_CYCLE_COUNTS(CT) (CT.CL_SecondCount * CYCLES_PER_SECOND + CT.CL_CycleCount); #define CALCULATE_DELTA_CYCLE_COUNT(prev, now) ((now > prev) ? now - prev : now + MAX_CYCLES - prev) // // Return avg time per frame in the unit of 100 nsec; // for calculation accuracy using only integer calculation, // we should do do multimplcation before division. // That is why the application can request to get numerator and denominator separately. // #define GET_AVG_TIME_PER_FRAME(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? (1001000/3) : FRAME_TIME_PAL) #define GET_AVG_TIME_PER_FRAME_NUM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 1001000 : 400000) #define GET_AVG_TIME_PER_FRAME_DENOM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 3 : 1) #define GET_NUM_PACKETS_PER_FRAME(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 4004/15 /* 100100/375 */ : MAX_SRC_PACKETS_PER_PAL_FRAME) #define GET_NUM_PACKETS_PER_FRAME_NUM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 4004 : MAX_SRC_PACKETS_PER_PAL_FRAME) #define GET_NUM_PACKETS_PER_FRAME_DENOM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 15 : 1) // // Structure used to keep track of and to perform stream data queuing // typedef struct _AVC_STREAM_DATA_STRUCT { ULONG SizeOfThisPacket; // // Frame size is calculated based on // CIP_DBS * 4 * (CIP_FN==0? 1 : (CIP_FN==1 ? 2 : (CIP_FN==2 ? 4 : 8))) // ULONG SourcePacketSize; // // Frame size is calculated based on // SourcePacketSize * SRC_PACKETS_PER_*** // ULONG FrameSize; // // Current stream time // LONGLONG CurrentStreamTime; ULONG LastCycleCount; // Used only for MPEG2TS stream // // Statistic of the frame information since last start stream // PictureNumber = FramesProcessed + FramesDropped + cndSRBCancelled. // LONGLONG PictureNumber; LONGLONG FramesProcessed; // Frame made it to 1394 serial bus. LONGLONG FramesDropped; #if DBG LONGLONG FramesAttached; #endif LONGLONG cntFrameCancelled; // // Count number of Data IRP received // LONGLONG cntDataReceived; // // Count and list for the attach list // LONG cntDataAttached; LIST_ENTRY DataAttachedListHead; // // Count and list for the SRB list // LONG cntDataQueued; // Used only with SRB_WRITE_DATA LIST_ENTRY DataQueuedListHead; // Used only with SRB_WRITE_DATA // // Count and list for the detach list // LONG cntDataDetached; LIST_ENTRY DataDetachedListHead; // // Lock to serialize attach and detach of list // KSPIN_LOCK DataListLock; // // Memory blocked allocated at passive level for queuing data IOs. // PBYTE pMemoryBlock; // // Signalled when there is no more attach frame; mainoy used to guarantee that all // data attached are transmitted before isoch is stopped for transmitting data // from PC to AVC device. // KEVENT hNoAttachEvent; } AVC_STREAM_DATA_STRUCT, * PAVC_STREAM_DATA_STRUCT; typedef struct DEVICE_EXTENSION; // // An AVC stream extension is created per stream opened. This will be returned to the caller, // when it will be used as the context (like a HANDLE) for subsequent call. // The allocation will include // // AVC_STREAM_EXTENSION // AV1394_FORMAT_INFO // AV_CLIENT_REQ // typedef struct _AVC_STREAM_EXTENSION { ULONG SizeOfThisPacket; // // This driver's device extension // struct DEVICE_EXTENSION * pDevExt; // // Data flow direction // KSPIN_DATAFLOW DataFlow; // Determine in or output pin // // Holds state // KSSTATE StreamState; // // This flag indicate if isoch is TALK/LISTEN or STOPPED // BOOLEAN IsochIsActive; // Close associated with StreamState // // Abstrction i/oPCR of an AVC device and PC itself as a plug handles // Connection handle is used when two plugs are connected. // HANDLE hPlugRemote; // Target (DVCR,D-VHS) device plug; HANDLE hPlugLocal; //.Local i/oPCR; HANDLE hConnect; // Connect two plugs // // Structure for specifing an AVC stream // PAVCSTRM_FORMAT_INFO pAVCStrmFormatInfo; // // Structure for data flow control (IsochActive, IOQueues..etc) // PAVC_STREAM_DATA_STRUCT pAVCStrmDataStruc; // // Synchronizing setting stream control and processing data // KMUTEX hMutexControl; // // Synchronize sharing the below AV_61883_REQUEST structure // Since all the stream control are synchronouse so we can use the same // AV61883Req structure to issue 61883 request // KMUTEX hMutexAVReq; PIRP pIrpAVReq; AV_61883_REQUEST AVReq; // // Counter used to indicate starting of an work item to cancel // LONG lAbortToken; // // Hold the work item // #ifdef USE_WDM110 // Win2000 code base PIO_WORKITEM pIoWorkItem; #else WORK_QUEUE_ITEM IoWorkItem; #endif // // TO signal that an work item is completed. // KEVENT hAbortDoneEvent; // // Cached plug state (these are dynamic values) // CMP_GET_PLUG_STATE RemotePlugState; #ifdef NT51_61883 // // Cyclic cycle count of last DV frame // ULONG CycleCount16bits; #endif // NT51_61883 // // Keep track of the last system time when the stream time was updated. // This is used to calibrate the current stream time when it is queries. // ULONGLONG LastSystemTime; // // Discontinuity is introduced when traistioning from RUN->PAUSE->RUN. // The stream time will not increment in PAUSE state but system time (1394 CycleTime) does. // BOOL b1stNewFrameFromPauseState; } AVC_STREAM_EXTENSION, *PAVC_STREAM_EXTENSION; // // Valid data entry states for a data request and they // can be Or'ed to show their code path. // // Examples of different possible code path: // // (A) Attached -> Pending -> Callback -> Completed // (B) Callback -> Attached -> Completed // (C) Attached -> Cancelled -> Completed // enum DATA_ENTRY_STATE { DE_PREPARED = 0x01, DE_IRP_LOWER_ATTACHED_COMPLETED = 0x02, DE_IRP_UPPER_PENDING_COMPLETED = 0x04, DE_IRP_LOWER_CALLBACK_COMPLETED = 0x08, DE_IRP_UPPER_COMPLETED = 0x10, DE_IRP_ERROR = 0x20, DE_IRP_CANCELLED = 0x40, }; #define IsStateSet(state, bitmask) ((state & (bitmask)) == bitmask) // // This is the data entry used to attach a frame // typedef struct _AVCSTRM_DATA_ENTRY { LIST_ENTRY ListEntry; // // Keep track of data entry state // enum DATA_ENTRY_STATE State; // // IRP from client of upper layer // PIRP pIrpUpper; // // Clock provider information // BOOL ClockProvider; // Client is a clock provider? HANDLE ClockHandle; // This is used only if !ClockProvider; it is possible that there is no clock used. // // Contain information about this streaming buffer // PKSSTREAM_HEADER StreamHeader; // // Frame buffer // PVOID FrameBuffer; // // Stream extension (Context) of the stream of this frame // PAVC_STREAM_EXTENSION pAVCStrmExt; #if DBG // // Add debug related info here // LONGLONG FrameNumber; #endif // // 61883 CIP frame structure // struct _CIP_FRAME * Frame; // // IRP used to send to 61883 (lower layer) for AV request, such as attach and release // PIRP pIrpLower; // // Use to send 61883 AV data request // AV_61883_REQUEST AVReq; } AVCSTRM_DATA_ENTRY, *PAVCSTRM_DATA_ENTRY; // // To open a stream. // A context is created and return to the caller. This context is need for all // stream operation. // NTSTATUS AVCStreamOpen( IN PIRP pIrp, // The Irp from its client IN struct DEVICE_EXTENSION * pDevExt, IN OUT AVCSTRM_OPEN_STRUCT * pOpenStruct ); // To Close a stram. NTSTATUS AVCStreamClose( IN PIRP pIrp, // The Irp from its client IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); // // Process stream control // NTSTATUS AVCStreamControlGetState( IN PIRP pIrp, // The Irp from its client IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, OUT KSSTATE * pKSState ); NTSTATUS AVCStreamControlSetState( IN PIRP pIrp, // The Irp from its client IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN KSSTATE KSState ); NTSTATUS AVCStreamControlGetProperty( IN PIRP pIrp, // The Irp from its client IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN PSTREAM_PROPERTY_DESCRIPTOR pSPD // BUGBUG StreamClass specific ); NTSTATUS AVCStreamControlSetProperty( IN PIRP pIrp, // The Irp from its client IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN PSTREAM_PROPERTY_DESCRIPTOR pSPD // BUGBUG StreamClass specific ); // Process SRB_READ/WRITE_DATA; this is the only IRPs that will operate asychronously // with. and STATUS_PENDING is returned. NTSTATUS AVCStreamRead( IN PIRP pIrpUpper, IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN AVCSTRM_BUFFER_STRUCT * pBufferStruct ); NTSTATUS AVCStreamWrite( IN PIRP pIrpUpper, IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN AVCSTRM_BUFFER_STRUCT * pBufferStruct ); /* This will stop streaming and cancel all pending data irps. This is typically used to cancel all Irps. To cancel a single Irp, use IoCancelIrp(). */ NTSTATUS AVCStreamAbortStreaming( IN PIRP pIrp, // The Irp from its client IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); /* Process surprise removal of a device */ NTSTATUS AVCStreamSurpriseRemoval( IN struct DEVICE_EXTENSION * pDevExt ); //////////////////////////////// // AvcUtil.c function prototypes //////////////////////////////// ULONGLONG GetSystemTime( ) ; NTSTATUS AVCStrmAttachFrameCR( IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp, IN PAVCSTRM_DATA_ENTRY pDataEntry ); VOID AVCStrmFormatAttachFrame( IN KSPIN_DATAFLOW DataFlow, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN AVCSTRM_FORMAT AVCStrmFormat, IN PAV_61883_REQUEST pAVReq, IN PAVCSTRM_DATA_ENTRY pDataEntry, IN ULONG ulSourcePacketSize, // Packet length in bytes IN ULONG ulFrameSize, // Buffer size; may contain one or multiple source packets IN PIRP pIrpUpper, IN PKSSTREAM_HEADER StreamHeader, IN PVOID FrameBuffer ); NTSTATUS AVCStrmGetPlugHandle( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmGetPlugState( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmGetConnectionProperty( IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, PSTREAM_PROPERTY_DESCRIPTOR pSPD, PULONG pulActualBytesTransferred ); NTSTATUS AVCStrmGetDroppedFramesProperty( IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, PSTREAM_PROPERTY_DESCRIPTOR pSPD, PULONG pulBytesTransferred ); NTSTATUS AVCStrmMakeConnection( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmBreakConnection( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmStartIsoch( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmStopIsoch( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); VOID AVCStrmWaitUntilAttachedAreCompleted( IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmAllocateQueues( IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN KSPIN_DATAFLOW DataFlow, IN PAVC_STREAM_DATA_STRUCT pDataStruc, PAVCSTRM_FORMAT_INFO pAVCStrmFormatInfo ); NTSTATUS AVCStrmFreeQueues( IN PAVC_STREAM_DATA_STRUCT pDataStruc ); NTSTATUS AVCStrmCancelIO( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmValidateFormat( PAVCSTRM_FORMAT_INFO pAVCFormatInfo ); void AVCStrmAbortStreamingWorkItemRoutine( #ifdef USE_WDM110 // Win2000 code base // Extra parameter if using WDM10 PDEVICE_OBJECT DeviceObject, #endif IN PAVC_STREAM_EXTENSION pAVCStrmExt );