2025-04-27 07:49:33 -04:00

3324 lines
76 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************
*******************************************************************
*******************************************************************
*******************************************************************
*******************************************************************
WARNING!!!!!! READ THIS FIRST!!!
This driver source is useful only as a model for implementing the DVD
specific properties and functions of streaming minidrivers.
There are several things in this driver that do not correspond to the optimal
stream minidriver architecture. PLEASE DO NOT COPY THESE BAD ELEMENTS
INTO YOUR DVD MINIDRIVER!!!!
The deviations in this driver are:
1) It uses a big DMA buffer to double buffer requests. DMA hardware should be
designed to support byte aligned scatter/gather DMA.
2) Global variables are used. This is a big no-no as multiple adapters
won't be supported.
3) This driver has video and audio extensions built into the device extension.
The per stream information should be kept in the stream extension.
4) IMPORTANT: this minidriver does PIO at raised IRQL, rather than calling
StreamClassCallAtNewPriority and switching to dispatch priority. Any
lengthy processing like PIO should be done at Dispatch priority. Ideally,
only DMA data xfer would be used, which may be set up at raised IRQL.
5) The code is poorly commented. Please use the commenting and header style
found in the generic sample.
Please see the generic stream minidriver sample code to see the correct way
to do these things.
*******************************************************************
*******************************************************************
*******************************************************************
*******************************************************************
*******************************************************************/
/*******************************************************************
*
* MPINIT.C
*
* Copyright (C) 1995 SGS-THOMSON Microelectronics.
*
*
* PORT/MINIPORT Interface init routines
*
*******************************************************************/
#include "strmini.h"
#include "ks.h"
#include <wingdi.h>
#include "ksmedia.h"
#include "mpinit.h"
#include "hwcodec.h"
#include "mpvideo.h"
#include "mpaudio.h"
//#include "dxapi.h"
#include "trace.h"
extern ULONG VidRate;
extern KS_AMVPDATAINFO VPFmt;
extern BOOLEAN fProgrammed;
extern BOOLEAN fStarted;
PHW_DEVICE_EXTENSION pDevEx;
//
// We allocate a large DMA buffer for Zoran chip
// in order to make sure that both writing into
// the dma buffer and reading from it for CD input
// can take place simultaniously.
// DO NOT REPLICATE THIS CODE IN OTHER DRIVERS!!!!!
//
#define DMA_BUFFER_SIZE 8192
GUID g_S3Guid = {DDVPTYPE_E_HREFL_VREFL};
void AudioPacketStub(PHW_STREAM_OBJECT pstrm);
//
// list of stream types for initialization
//
typedef enum tagStreamType {
strmVideo = 0,
strmAc3,
strmNTSCVideo,
strmSubpicture,
strmYUVVideo,
strmCCOut,
NUMBER_OF_STREAMS
} STREAMTYPES;
//
// some external variables
//
// WARNING!!!! DO NOT REPLICATE THIS IN YOUR DRIVER. Global variables
// will not work with multiple adapters.
//
PHW_STREAM_OBJECT pVideoStream;
HANDLE hClk;
HANDLE hMaster;
//
// define the data formats used by the pins in this minidriver
//
//
// MPEG2 video format definition
//
KSDATAFORMAT hwfmtiMpeg2Vid = {
sizeof(KSDATAFORMAT),// + sizeof(KS_MPEGVIDEOINFO2),
/* NOTE: MPEG2 video streams must support the KS_MPEGVIDEOINFO2 format
* block. This defines aspect ratios, and other stream properties */
0,
0,
0,
STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
// STATIC_KSDATAFORMAT_TYPE_MPEG2_PES,
STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO,
STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO
};
//
// define the events associated with the master clock
//
KSEVENT_ITEM ClockEventItm[] =
{
{
KSEVENT_CLOCK_POSITION_MARK, // position mark event supported
sizeof (KSEVENT_TIME_MARK), // requires this data as input
sizeof (KSEVENT_TIME_MARK), // allocate space to copy the data
NULL,
NULL,
NULL
},
{
KSEVENT_CLOCK_INTERVAL_MARK, // interval mark event supported
sizeof (KSEVENT_TIME_INTERVAL), // requires interval data as input
sizeof (MYTIME), // we use an additional workspace of
// size longlong for processing
// this event
NULL,
NULL,
NULL
}
};
KSEVENT_SET ClockEventSet[] =
{
{
&KSEVENTSETID_Clock,
SIZEOF_ARRAY(ClockEventItm),
ClockEventItm,
}
};
KSEVENT_ITEM VPEventItm[] =
{
{
KSEVENT_VPNOTIFY_FORMATCHANGE,
0,
0,
NULL,
NULL,
NULL
}
};
GUID MY_KSEVENTSETID_VPNOTIFY = {STATIC_KSEVENTSETID_VPNotify};
KSEVENT_SET VPEventSet[] =
{
{
&MY_KSEVENTSETID_VPNOTIFY,
SIZEOF_ARRAY(VPEventItm),
VPEventItm,
}
};
//
// AC3 audio format definition
//
KSDATAFORMAT hwfmtiMpeg2Aud
= {
sizeof(KSDATAFORMAT),
0,
0,
0,
STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
// STATIC_KSDATAFORMAT_TYPE_MPEG2_PES,
STATIC_KSDATAFORMAT_SUBTYPE_AC3_AUDIO,
STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
};
//
// define the NTSC output format
//
KSDATAFORMAT hwfmtiNTSCOut
= {
sizeof(KSDATAFORMAT),
0,
0,
0,
STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
// STATIC_KSDATAFORMAT_TYPE_MPEG2_PES,
STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO,
STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
};
//
// define the VP output pin format
//
KSDATAFORMAT hwfmtiVPOut
= {
sizeof(KSDATAFORMAT),
0,
0,
0,
STATIC_KSDATAFORMAT_TYPE_VIDEO,
STATIC_KSDATAFORMAT_TYPE_VIDEO,
STATIC_KSDATAFORMAT_TYPE_VIDEO
};
//
// define the Close Caption output pin format
//
KSDATAFORMAT hwfmtiCCOut
= {
sizeof(KSDATAFORMAT),
0,
200,
0,
STATIC_KSDATAFORMAT_TYPE_AUXLine21Data,
STATIC_KSDATAFORMAT_SUBTYPE_Line21_GOPPacket,
STATIC_KSDATAFORMAT_SPECIFIER_VIDEOINFO
};
//
// define the DVD subpicture decoder pin format
//
KSDATAFORMAT hwfmtiSubPic
= {
sizeof(KSDATAFORMAT),
0,
0,
0,
STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
// STATIC_KSDATAFORMAT_TYPE_MPEG2_PES,
STATIC_KSDATAFORMAT_SUBTYPE_SUBPICTURE,
STATIC_GUID_NULL
};
//
// define the arrays of supported formats pointers
//
PKSDATAFORMAT Mpeg2VidInfo[] = {
&hwfmtiMpeg2Vid // pointer to the MPEG 2 video format block
};
PKSDATAFORMAT SubPicInfo[] = {
&hwfmtiSubPic // pointer to the subpicture format block
};
PKSDATAFORMAT AC3AudioInfo[] = {
&hwfmtiMpeg2Aud // pointer to the AC-3 format block
};
PKSDATAFORMAT NtscInfo[] = { // ntsc output formats array
&hwfmtiNTSCOut
};
PKSDATAFORMAT VPInfo[] = { // VP output formats array
&hwfmtiVPOut
};
PKSDATAFORMAT CCInfo[] = { // CC output formats array
&hwfmtiCCOut
};
//
// define the Individual property items for the video property sets
//
static const KSPROPERTY_ITEM mpegVidPropItm[] = {
{KSPROPERTY_DVDSUBPIC_PALETTE, // subpicture palette property
FALSE, // get palette not supported
sizeof(KSPROPERTY),
sizeof(KSPROPERTY_SPPAL), // minimum size of data requested
(PFNKSHANDLER) FALSE, // set palette is supported
NULL,
0,
NULL,
NULL,
0
}
};
//
// define the subpicture property items supported
//
static const KSPROPERTY_ITEM spPropItm[] = {
{KSPROPERTY_DVDSUBPIC_PALETTE, // subpicture palette property
FALSE, // get palette not supported
sizeof(KSPROPERTY),
sizeof(KSPROPERTY_SPPAL), // minimum size of data requested
(PFNKSHANDLER) TRUE, // set palette is supported
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_DVDSUBPIC_HLI, // subpicture highlight property
FALSE, // get highlight not supported
sizeof(KSPROPERTY),
sizeof(KSPROPERTY_SPHLI), // minimum size of data requested
(PFNKSHANDLER) TRUE, // set highlight is supported
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_DVDSUBPIC_COMPOSIT_ON, // subpicture enable status property
FALSE, // get enable status not supported
sizeof(KSPROPERTY),
sizeof(KSPROPERTY_COMPOSIT_ON), // minimum size of data requested
(PFNKSHANDLER) TRUE, // set enable status is supported
NULL,
0,
NULL,
NULL,
0
}
};
static const KSPROPERTY_ITEM audPropItm[] = {
{KSPROPERTY_AUDDECOUT_MODES,// available audio decoder output formats
// property
(PFNKSHANDLER) TRUE, // get available modes is supported
sizeof(KSPROPERTY),
sizeof(ULONG), // minimum size of data requested
(PFNKSHANDLER) FALSE, // set available modes is not supported
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_AUDDECOUT_CUR_MODE, // current audio decoder output format
// property
(PFNKSHANDLER) TRUE, // get current mode is supported
sizeof(KSPROPERTY),
sizeof(ULONG), // minimum size of data requested
(PFNKSHANDLER) TRUE, // set current modes is supported
NULL,
0,
NULL,
NULL,
0
}
};
//
// define the copy protection property support
//
static const KSPROPERTY_ITEM CopyProtPropItm[] = {
{KSPROPERTY_DVDCOPY_CHLG_KEY,// DVD authentication challenge key
(PFNKSHANDLER)TRUE, // get property on challenge key requests the
// decoder to provide it's challenge key
sizeof(KSPROPERTY),
sizeof(KS_DVDCOPY_CHLGKEY), // minimum size of data requested
(PFNKSHANDLER) TRUE, // set palette is supported
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_DVDCOPY_DVD_KEY1,// DVD authentication DVD drive key property
FALSE, // get Key not supported
sizeof(KSPROPERTY),
sizeof(KS_DVDCOPY_BUSKEY),// minimum size of data requested
(PFNKSHANDLER) TRUE, // set key provides the key for the decoder
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_DVDCOPY_DEC_KEY2,// DVD authentication DVD decoder key property
(PFNKSHANDLER)TRUE, // get Key requests the decoder key, in
// response to a previous set challenge key
sizeof(KSPROPERTY),
sizeof(KS_DVDCOPY_BUSKEY), // minimum size of data requested
(PFNKSHANDLER)FALSE, // set key is not valid
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_DVDCOPY_REGION, // DVD region request
// the minidriver shall fit in exactly
// one region bit, corresponding to the region
// that the decoder is currently in
(PFNKSHANDLER)TRUE,
sizeof(KSPROPERTY),
sizeof(KS_DVDCOPY_REGION), // minimum size of data requested
(PFNKSHANDLER)FALSE, // set key is not valid
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_DVDCOPY_TITLE_KEY,// DVD authentication DVD title key property
FALSE, // get Key not supported
sizeof(KSPROPERTY),
sizeof(KS_DVDCOPY_TITLEKEY),// minimum size of data requested
(PFNKSHANDLER) TRUE, // set key provides the key for the decoder
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_DVDCOPY_DISC_KEY, // DVD authentication DVD disc key property
FALSE, // get Key not supported
sizeof(KSPROPERTY),
sizeof(KS_DVDCOPY_BUSKEY),// minimum size of data requested
(PFNKSHANDLER) TRUE, // set key provides the key for the decoder
NULL,
0,
NULL,
NULL,
0
}
};
//
// property set for Macrovision support
//
static const KSPROPERTY_ITEM MacroVisionPropItm[] = {
{
KSPROPERTY_COPY_MACROVISION, // support for setting macrovision level
(PFNKSHANDLER) FALSE, // get not supported
sizeof (KSPROPERTY),
sizeof (KS_COPY_MACROVISION),
(PFNKSHANDLER) TRUE, // set MACROVISION level supported
NULL,
0,
NULL,
NULL,
0
}
};
//
// property set for CC support
//
static const KSPROPERTY_ITEM CCPropItm[] = {
{
KSPROPERTY_CONNECTION_ALLOCATORFRAMING, // support for setting CC buffer size
(PFNKSHANDLER) TRUE, // get supported
sizeof (KSPROPERTY),
sizeof (KSALLOCATOR_FRAMING),
(PFNKSHANDLER) FALSE, // we only provide the allocator requirments
NULL,
0,
NULL,
NULL,
0
},
{
KSPROPERTY_CONNECTION_STATE, // support for setting CC buffer size
(PFNKSHANDLER) TRUE, // get supported
sizeof (KSPROPERTY),
sizeof (KSSTATE),
(PFNKSHANDLER) FALSE, // we only provide the allocator requirments
NULL,
0,
NULL,
NULL,
0
}
};
static const KSPROPERTY_ITEM VideoPortPropItm[] = {
{KSPROPERTY_VPCONFIG_NUMCONNECTINFO,
(PFNKSHANDLER) TRUE,
sizeof(KSPROPERTY),
sizeof(ULONG),
(PFNKSHANDLER) FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_NUMVIDEOFORMAT,
(PFNKSHANDLER) TRUE,
sizeof(KSPROPERTY),
sizeof(ULONG),
(PFNKSHANDLER) FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_GETCONNECTINFO,
(PFNKSHANDLER) TRUE,
sizeof (KSMULTIPLE_DATA_PROP), // minimum property input size
sizeof (ULONG),
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_SETCONNECTINFO,
(PFNKSHANDLER) FALSE,
sizeof (KSPROPERTY), // minimum property input size
sizeof (ULONG), // minimum buffer size
(PFNKSHANDLER)TRUE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_VPDATAINFO,
(PFNKSHANDLER) TRUE,
sizeof (KSPROPERTY),
sizeof (KS_AMVPDATAINFO),
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_MAXPIXELRATE,
(PFNKSHANDLER) TRUE,
sizeof (KSVPSIZE_PROP),
sizeof (KSVPMAXPIXELRATE),
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_INFORMVPINPUT,
(PFNKSHANDLER) TRUE,
sizeof (PKSPROPERTY),
sizeof (DDPIXELFORMAT), // could be 0 too
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_DDRAWHANDLE,
(PFNKSHANDLER)FALSE,
sizeof (PKSPROPERTY),
sizeof (ULONG), // could be 0 too
(PFNKSHANDLER) TRUE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_VIDEOPORTID,
(PFNKSHANDLER)FALSE,
sizeof (PKSPROPERTY),
sizeof (ULONG), // could be 0 too
(PFNKSHANDLER) TRUE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE,
(PFNKSHANDLER)FALSE,
sizeof (PKSPROPERTY),
sizeof (ULONG), // could be 0 too
(PFNKSHANDLER) TRUE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_GETVIDEOFORMAT,
(PFNKSHANDLER) TRUE,
sizeof (KSMULTIPLE_DATA_PROP), // for _GET; KSPROPERTY for _SET
sizeof (ULONG), // could be 4 or more
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_SETVIDEOFORMAT,
(PFNKSHANDLER) FALSE,
sizeof (KSPROPERTY), // minimum property input size
sizeof (ULONG), // minimum buffer size
(PFNKSHANDLER)TRUE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_INVERTPOLARITY,
(PFNKSHANDLER)TRUE,
sizeof (KSPROPERTY),
0,
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_DECIMATIONCAPABILITY,
(PFNKSHANDLER)TRUE,
sizeof (KSPROPERTY),
sizeof (BOOL),
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
},
{KSPROPERTY_VPCONFIG_SCALEFACTOR,
(PFNKSHANDLER)TRUE,
sizeof (KSPROPERTY),
sizeof (KS_AMVPSIZE),
(PFNKSHANDLER)FALSE,
NULL,
0,
NULL,
NULL,
0
}
};
//
// define the array of video property sets supported
//
static const KSPROPERTY_SET mpegVidPropSet[] = {
{
&KSPROPSETID_Mpeg2Vid,
SIZEOF_ARRAY(mpegVidPropItm),
(PKSPROPERTY_ITEM) mpegVidPropItm
},
{
&KSPROPSETID_CopyProt,
SIZEOF_ARRAY(CopyProtPropItm),
(PKSPROPERTY_ITEM) CopyProtPropItm
}
};
//
// define the array of subpicture property sets supported
//
static const KSPROPERTY_SET SPPropSet[] = {
{
&KSPROPSETID_DvdSubPic,
SIZEOF_ARRAY(spPropItm),
(PKSPROPERTY_ITEM) spPropItm
},
{
&KSPROPSETID_CopyProt,
SIZEOF_ARRAY(CopyProtPropItm),
(PKSPROPERTY_ITEM) CopyProtPropItm
}
};
//
// define the array of audio property sets supported
//
static const KSPROPERTY_SET audPropSet[] = {
{
&KSPROPSETID_AudioDecoderOut,
SIZEOF_ARRAY(audPropItm),
(PKSPROPERTY_ITEM) audPropItm
},
{
&KSPROPSETID_CopyProt,
SIZEOF_ARRAY(CopyProtPropItm),
(PKSPROPERTY_ITEM) CopyProtPropItm
}
};
//
// define the array of property sets for the video port pin
//
GUID VPPropSetid = {STATIC_KSPROPSETID_VPConfig};
static const KSPROPERTY_SET VideoPortPropSet[] = {
&VPPropSetid,
SIZEOF_ARRAY(VideoPortPropItm),
(PKSPROPERTY_ITEM) VideoPortPropItm
};
static const KSPROPERTY_SET NTSCPropSet[] = {
&KSPROPSETID_CopyProt,
SIZEOF_ARRAY(MacroVisionPropItm),
(PKSPROPERTY_ITEM) MacroVisionPropItm
};
static const KSPROPERTY_SET CCPropSet[] = {
&KSPROPSETID_Connection,
SIZEOF_ARRAY(CCPropItm),
(PKSPROPERTY_ITEM) CCPropItm
};
static const KSTOPOLOGY Topology = {
1,
(GUID *) & KSCATEGORY_DATADECOMPRESSOR,
0,
NULL,
0,
NULL
};
//
// Few globals here, should be put in the
// structure
// WARNING!!!! DO NOT REPLICATE THIS IN YOUR DRIVER. It will not work
// with multiple adapters.
//
BOOL bInitialized = FALSE;
VOID STREAMAPI StreamReceiveAudioPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb);
VOID HwProcessDataIntersection(PHW_STREAM_REQUEST_BLOCK pSrb);
extern PSP_STRM_EX pSPstrmex;
/*
** StreamReceiveFakeDataPacket ()
**
** dispatch routine for receiving a data packet. This routine will
** dispatch to the appropriate data handler initialized in the stream
** extension for this data stream
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID STREAMAPI
StreamReceiveFakeDataPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
pSrb->Status = STATUS_SUCCESS;
pSrb->ActualBytesTransferred = 0;
StreamClassStreamNotification(ReadyForNextStreamDataRequest,
pSrb->StreamObject);
StreamClassStreamNotification(StreamRequestComplete,
pSrb->StreamObject,
pSrb);
}
/*
** DriverEntry ()
**
** Initial load entry point into the driver. Initializes the key
** entry points to the mini driver, and registers with the stream class
** driver
**
** Arguments:
**
** Arg1 and Arg2, corresponding to the Context1 and Context2 arguments
** passed from the stream class driver
**
** Returns:
**
** The result of the registration call with the Stream Class driver
** This in turn will be the return from the SRB_INITIALIZE_DEVICE function
** call into the AdapterReceivePacket routine
**
** Side Effects:
*/
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
HW_INITIALIZATION_DATA HwInitData;
//
// all unused fields should be zero.
//
RtlZeroMemory(&HwInitData, sizeof(HW_INITIALIZATION_DATA));
MPTrace(mTraceDriverEntry);
DebugPrint((DebugLevelVerbose, "ST MPEG2 MiniDriver DriverEntry"));
HwInitData.HwInitializationDataSize = sizeof(HwInitData);
HwInitData.HwInterrupt = HwInterrupt;
HwInitData.HwReceivePacket = AdapterReceivePacket;
HwInitData.HwCancelPacket = AdapterCancelPacket;
HwInitData.HwRequestTimeoutHandler = AdapterTimeoutPacket;
HwInitData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
HwInitData.PerRequestExtensionSize = sizeof(MRP_EXTENSION);
HwInitData.FilterInstanceExtensionSize = 0;
HwInitData.PerStreamExtensionSize = sizeof(STREAMEX); // random size for code
// testing
HwInitData.BusMasterDMA = FALSE;
HwInitData.Dma24BitAddresses = FALSE;
HwInitData.BufferAlignment = 3;
HwInitData.TurnOffSynchronization = FALSE;
HwInitData.DmaBufferSize = DMA_BUFFER_SIZE;
DebugPrint((DebugLevelVerbose, "SGS: call to portinitialize"));
return (StreamClassRegisterAdapter((PVOID)DriverObject,
(PVOID)RegistryPath, &HwInitData));
}
/*
** AdapterCancelPacket ()
**
** routine to cancel a packet that may be in progress
**
** Arguments:
**
** pSrb points to the packet to be cancelled
**
** Returns:
**
** Side Effects:
** the mini driver must no longer access this packet after this call
** returns
*/
VOID
AdapterCancelPacket(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevex = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
MPTrace(mTraceCancelPacket);
//
// need to find this packet, pull it off our queues, and cancel it
//
//
// check the video queues to see if the packet is there
//
if (pdevex->VideoDeviceExt.pCurrentSRB == pSrb) {
//
// found the packet on the video queue, so, remove all references
// from the video processing, and clear any timers used to access
// this packet
//
MPTrace(mTraceLastVideoDone);
pdevex->VideoDeviceExt.pCurrentSRB = NULL;
StreamClassScheduleTimer(pSrb->StreamObject, pdevex,
0, VideoPacketStub, pSrb->StreamObject);
}
//
// check the audio queues for the packet
//
if (pdevex->AudioDeviceExt.pCurrentSRB == pSrb) {
TRAP
MPTrace(mTraceLastAudioDone);
pdevex->AudioDeviceExt.pCurrentSRB = NULL;
StreamClassScheduleTimer(pSrb->StreamObject, pdevex,
0, AudioPacketStub, pSrb->StreamObject);
}
if (pdevex->pCurSrb == pSrb) {
pdevex->pCurSrb = NULL;
}
pSrb->Status = STATUS_CANCELLED;
switch (pSrb->Flags & (SRB_HW_FLAGS_DATA_TRANSFER |
SRB_HW_FLAGS_STREAM_REQUEST)) {
//
// find all stream commands, and do stream notifications
//
case SRB_HW_FLAGS_STREAM_REQUEST | SRB_HW_FLAGS_DATA_TRANSFER:
StreamClassStreamNotification(ReadyForNextStreamDataRequest,
pSrb->StreamObject);
StreamClassStreamNotification(StreamRequestComplete,
pSrb->StreamObject,
pSrb);
break;
case SRB_HW_FLAGS_STREAM_REQUEST:
mpstCtrlCommandComplete(pSrb);
break;
default:
//
// must be a device request
//
AdapterCB(pSrb);
}
}
/*
** AdapterTimeoutPacket ()
**
** When this routine is called, a packet has spent too much time at the
** mindriver. Either the device is paused, and data packets are awaiting
** a play or stop, or something is wrong with the device. In a pause situation
** the timer should just be reset.
**
** If the system is not paused, the device should abort all outstanding
** requests and reset.
**
** Arguments:
**
** pSrb - points to the packet that timedout
**
** Returns:
**
** Side Effects:
*/
VOID
AdapterTimeoutPacket(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PSTREAMEX strm = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
PHW_DEVICE_EXTENSION pdevex = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
//
// if we are not playing, and this is a CTRL request, we still
// need to reset everything
//
MPTrace(mTraceTimeOut);
if (pdevex->VideoDeviceExt.DeviceState == KSSTATE_PAUSE ||
pdevex->AudioDeviceExt.DeviceState == KSSTATE_PAUSE) {
//
// reset the timeout counter, and continue
//
pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
return;
}
//
// this is a catastrophic timeout reset the device and prepare to
// continue
//
//
// eliminate all device queues
//
pdevex->VideoDeviceExt.pCurrentSRB = NULL;
pdevex->AudioDeviceExt.pCurrentSRB = NULL;
pSPstrmex->pSrbQ = NULL;
pdevex->pCurSrb = NULL;
CleanSPQueue(pSPstrmex);
CleanCCQueue();
//
// clear all pending timeouts on all streams that use them
//
if (pdevex->pstroVid) {
StreamClassScheduleTimer(pdevex->pstroVid, pdevex,
0, NULL, pdevex->pstroVid);
}
if (pdevex->pstroAud) {
StreamClassScheduleTimer(pdevex->pstroAud, pdevex,
0, NULL, pdevex->pstroAud);
}
//
// kill all outstanding requests for the entire device!
// NOTE: we don't need to call any requests back, they are all aborted
// at the stream class driver
//
StreamClassAbortOutstandingRequests(pSrb->HwDeviceExtension, NULL,
STATUS_CANCELLED);
}
/*
** AdapterOpenStream ()
**
** process open stream request blocks
**
** Arguments:
**
** pSrb -> request block for the open stream request
**
** Returns:
**
** status in the Srb
**
** Side Effects:
*/
VOID
AdapterOpenStream(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PSTREAMEX strm = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
PHW_DEVICE_EXTENSION pdevex = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
//
// for now, just return success
//
pSrb->Status = STATUS_SUCCESS;
//
// set up the sreamobject structure
//
//
// this mindriver uses a generic control routine, and pointers to
// functions
// for individual function dispatches. A minidriver could use an
// individual control routine for each stream if desired
//
pSrb->StreamObject->ReceiveControlPacket = (PVOID) StreamReceiveCtrlPacket;
//
// since this adapter double buffers all DMA, we indicate that the
// streams
// are PIO, as the minidriver is not interested in the physical dma
// addresses for the buffers that are passed to it, and the minidriver
// must read data from the buffer addresses passed in.
//
// This minidriver only uses the physical address of the DMA buffer that
// it allocates at initialization time.
//
// For hardware that can support byte aligned DMA, the Pio BOOLEAN should
// be set to TRUE, only if the minidriver will use the host processor
// to access the memory pointed to by data buffers passed to the stream
// Examples would be edge alignment of DMA transfers, or any code that
// might look for start codes, or end of streams within the data
//
pSrb->StreamObject->Pio = TRUE;
//
// the DMA BOOLEAN is set to true, only if the minidriver needs to be
// able to use DMA to DIRECTLY access the memory buffers passed in.
//
pSrb->StreamObject->Dma = FALSE;
//
// set up stream specific stream extension information
//
switch (pSrb->StreamObject->StreamNumber) {
case strmVideo:
//
// this is the video stream
//
//
// set up the control functions for AdapterReceiveCtrlPacket
//
strm->pfnWriteData = (PFN_WRITE_DATA) miniPortVideoPacket;
strm->pfnSetState = (PFN_WRITE_DATA) miniPortSetState;
strm->pfnGetProp = (PFN_WRITE_DATA) miniPortGetProperty;
strm->pfnSetProp = (PFN_WRITE_DATA) miniPortGetProperty;
strm->pfnQueryAccept = (PFN_WRITE_DATA) VideoQueryAccept;
//
// set up the receive data packet entry point
//
pSrb->StreamObject->ReceiveDataPacket = (PVOID) StreamReceiveDataPacket;
//
// set up some ugly globals.
//
pVideoStream = pSrb->StreamObject;
pdevex->pstroVid = pSrb->StreamObject;
//
// set up the initial video format, using the DATAFORMAT specifier
// passed in as part of this open command
//
ProcessVideoFormat(pSrb->CommandData.OpenFormat, pdevex);
EnableIT();
//
// call the DXAPI to get the version
//
//#pragma message ("fix before shipping")
// DxApiGetVersion();
break;
case strmAc3:
//
// this is the AC3 audio stream
//
//
// set up the flags indicating that this stream can be a master clock
// for syncronization purposes, also indicate the routine to call
// for current master clock value
//
pSrb->StreamObject->HwClockObject.HwClockFunction = StreamClockRtn;
pSrb->StreamObject->HwClockObject.ClockSupportFlags =
CLOCK_SUPPORT_CAN_SET_ONBOARD_CLOCK | CLOCK_SUPPORT_CAN_READ_ONBOARD_CLOCK |
CLOCK_SUPPORT_CAN_RETURN_STREAM_TIME;
//
// set up the control functions for AdapterReceiveCtrlPacket
//
strm->pfnWriteData = (PFN_WRITE_DATA) miniPortAudioPacket;
pSrb->StreamObject->ReceiveDataPacket = (PVOID) StreamReceiveDataPacket;
strm->pfnSetState = (PFN_WRITE_DATA) miniPortAudioSetState;
strm->pfnGetProp = (PFN_WRITE_DATA) miniPortAudioGetProperty;
strm->pfnSetProp = (PFN_WRITE_DATA) miniPortAudioSetProperty;
pSrb->StreamObject->HwEventRoutine = (PHW_EVENT_ROUTINE) AudioEvent;
//
// set up some more nasty Global references
//
pdevex->pstroAud = pSrb->StreamObject;
//
// ininitalise our clock information
//
fStarted = fProgrammed = FALSE;
EnableIT();
break;
case strmSubpicture:
//
// this is the subpicture stream
//
//
// set up the control functions for AdapterReceiveCtrlPacket
//
strm->pfnSetState = (PFN_WRITE_DATA) SPSetState;
strm->pfnGetProp = (PFN_WRITE_DATA) SPGetProp;
strm->pfnSetProp = (PFN_WRITE_DATA) SPSetProp;
//
// set up the subpicture datapacket routine
//
pSrb->StreamObject->ReceiveDataPacket = (PVOID) SPReceiveDataPacket;
//
// more cross referenced structures
//
strm->spstrmex.phwdevex = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
strm->spstrmex.phstrmo = pSrb->StreamObject;
EnableIT();
//
// the subpicture decoders needs memory buffers to double buffer
// the incoming data in a coherent form. Since the incoming call
// for the open stream is at interrupt priority, we need to allocate
// the memory at lower priority, so we will schedule a callback to
// accomplish this
//
StreamClassCallAtNewPriority(pSrb->StreamObject,
pSrb->HwDeviceExtension,
Low,
(PHW_PRIORITY_ROUTINE) OpenSubPicAlloc,
pSrb);
//
// note: we return without calling back the subpicture open stream
// SRB. We will call it back in the OpenSubPicAlloc routine
//
return;
case strmNTSCVideo:
//
// this is the anolog NTSC video stream. Not much to do yet, but
// it will soon handle NTSC macrovision properties
//
strm->pfnGetProp = (PFN_WRITE_DATA) NTSCGetProp;
strm->pfnSetProp = (PFN_WRITE_DATA) NTSCSetProp;
break;
case strmYUVVideo:
//
// this is the Video Port YUV Data stream. This pin only supports
// get and set properties
//
strm->pfnGetProp = (PFN_WRITE_DATA) VPEGetProp;
strm->pfnSetProp = (PFN_WRITE_DATA) VPESetProp;
pSrb->StreamObject->ReceiveDataPacket = (PVOID) StreamReceiveFakeDataPacket;
pdevex->pstroYUV = pSrb->StreamObject;
pSrb->StreamObject->HwEventRoutine = (PHW_EVENT_ROUTINE) CycEvent;
break;
case strmCCOut:
//
// this is the close caption stream
//
//
// set up the control functions for AdapterReceiveCtrlPacket
//
strm->pfnSetState = (PFN_WRITE_DATA) CCSetState;
strm->pfnGetProp = CCGetProp;
//
// set up the receive data packet entry point
//
pSrb->StreamObject->ReceiveDataPacket = (PVOID) CCReceiveDataPacket;
pdevex->pstroCC = pSrb->StreamObject;
break;
default:
//
// we should never get a call on a stream type that we didn't
// report in the first place!
//
TRAP
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
AdapterCB(pSrb);
}
/*
** OpenSubPicAlloc ()
**
** Routine to allocate memory for subpicture use
**
** Arguments:
**
** pSrb points to the subpicture open stream Srb
**
** Returns:
**
** returns status in the Srb
**
** Side Effects:
**
** the subpicture stream extension data pointer, pdata is initialized if the
** memory allocation is successful
*/
void OpenSubPicAlloc(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
PSTREAMEX strm = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
//
// attempt to allocate the locked memory area
//
if (!(strm->spstrmex.pdecctl.pData = (PVOID)
ExAllocatePool(NonPagedPool, SP_MAX_INPUT_BUF))) {
//
// could not allocate the memory, so fail the open
//
pSrb->Status = STATUS_NO_MEMORY;
}
//
// set some more ugly globals
//
pSPstrmex = &(strm->spstrmex);
//
// srb completions cannot be called back at low priority, so we need
// to change the priority back to high here
//
StreamClassCallAtNewPriority(pSrb->StreamObject,
pdevext,
LowToHigh,
(PHW_PRIORITY_ROUTINE) AdapterCB,
pSrb);
}
/*
** AdapterCB ()
**
** routine to callback adapter srbs
**
** Arguments:
**
** pSrb - request to callback
**
** Returns:
**
** Side Effects:
*/
void AdapterCB(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
StreamClassDeviceNotification(ReadyForNextDeviceRequest,
pSrb->HwDeviceExtension);
StreamClassDeviceNotification(DeviceRequestComplete,
pSrb->HwDeviceExtension,
pSrb);
}
/*
** AdapterReceivePacket ()
**
** main entry point for receiving an adapter based SRB
**
** Arguments:
**
** pSrb
**
** Returns:
**
** Side Effects:
*/
VOID STREAMAPI
AdapterReceivePacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
//
// determine the type of packet.
//
// Note: any command type that may require additional processing
// asyncronously
// must deal with the ready for next request, and request complete
// callbacks
// individually, and will return from the following case statement.
// All other cases will be called back automatically following.
//
switch (pSrb->Command) {
case SRB_OPEN_STREAM:
//
// this command requests the minidriver to prepare structures
// and initialize a stream instance
//
MPTrace(mTraceOpen);
AdapterOpenStream(pSrb);
return;
case SRB_GET_STREAM_INFO:
AdapterStreamInfo(pSrb);
MPTrace(mTraceInfo);
break;
case SRB_INITIALIZE_DEVICE:
MPTrace(mTraceInit);
HwInitialize(pSrb);
break;
case SRB_CLOSE_STREAM:
MPTrace(mTraceClose);
AdapterCloseStream(pSrb);
pSrb->Status = STATUS_SUCCESS;
break;
case SRB_CHANGE_POWER_STATE:
if (pSrb->CommandData.DeviceState == PowerDeviceD0) {
//
// bugbug - need to turn power back on here.
//
} else {
//
// bugbug - need to turn power off here, as well as disabling
// interrupts.
//
DisableIT();
}
pSrb->Status = STATUS_SUCCESS;
break;
case SRB_PAGING_OUT_DRIVER:
//
// ensure that the minidriver cannot receive interrupts while the
// interrupt handler is paged out!
//
DisableIT();
pSrb->Status = STATUS_SUCCESS;
break;
case SRB_GET_DATA_INTERSECTION:
HwProcessDataIntersection(pSrb);
break;
case SRB_UNINITIALIZE_DEVICE:
MPTrace(mTraceUnInit);
HwUnInitialize(pSrb->HwDeviceExtension);
pSrb->Status = STATUS_SUCCESS;
break;
default:
MPTrace(mTraceUnknown);
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
}
//
// callback the device request
//
AdapterCB(pSrb);
}
/*
** AdapterStreamInfo ()
**
** return the information on the stream types (number of pins) available
** in this hardware
**
** Arguments:
**
** pSrb -> command SRB
**
** Returns:
**
** Side Effects:
*/
VOID
AdapterStreamInfo(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
PHW_STREAM_INFORMATION pstrinfo = &(pSrb->CommandData.StreamBuffer->StreamInfo);
pSrb->CommandData.StreamBuffer->StreamHeader.NumberOfStreams =
NUMBER_OF_STREAMS;
pSrb->CommandData.StreamBuffer->StreamHeader.SizeOfHwStreamInformation =
sizeof(HW_STREAM_INFORMATION);
//
// store a pointer to the topology for the device
//
pSrb->CommandData.StreamBuffer->StreamHeader.Topology = (PKSTOPOLOGY) & Topology;
//
// set up the stream info structures for the MPEG2 video
//
pstrinfo->NumberOfPossibleInstances = 1;
// stream can be opened only once
pstrinfo->DataFlow = KSPIN_DATAFLOW_IN;
// indicates data flows into this stream from an external
// source
pstrinfo->DataAccessible = TRUE;
pstrinfo->NumberOfFormatArrayEntries = 1;
// number of formats supported
pstrinfo->StreamFormatsArray = Mpeg2VidInfo;
pstrinfo->NumStreamPropArrayEntries = 2;
// number of property SETS that are supported (each set
// may have more than one property supported within it
pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) mpegVidPropSet;
pstrinfo++;
//
// set up the stream info structures for the MPEG2 audio
//
pstrinfo->NumberOfPossibleInstances = 1;
pstrinfo->DataFlow = KSPIN_DATAFLOW_IN;
pstrinfo->DataAccessible = TRUE;
pstrinfo->NumberOfFormatArrayEntries = 1;
pstrinfo->StreamFormatsArray = AC3AudioInfo;
pstrinfo->NumStreamPropArrayEntries = 2;
pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) audPropSet;
pstrinfo->StreamEventsArray = ClockEventSet;
pstrinfo->NumStreamEventArrayEntries = SIZEOF_ARRAY(ClockEventSet);
pstrinfo++;
//
// set up the stream info structures for the MPEG2 NTSC stream
//
pstrinfo->NumberOfPossibleInstances = 1;
pstrinfo->DataFlow = KSPIN_DATAFLOW_OUT;
pstrinfo->DataAccessible = FALSE;
pstrinfo->NumberOfFormatArrayEntries = 1;
pstrinfo->StreamFormatsArray = NtscInfo;
pstrinfo->NumStreamPropArrayEntries = 0;
pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) NTSCPropSet;
pstrinfo++;
//
// set up the stream info structures for the MPEG2 subpicture
//
pstrinfo->NumberOfPossibleInstances = 1;
pstrinfo->DataFlow = KSPIN_DATAFLOW_IN;
pstrinfo->DataAccessible = TRUE;
pstrinfo->NumberOfFormatArrayEntries = 1;
pstrinfo->StreamFormatsArray = SubPicInfo;
pstrinfo->NumStreamPropArrayEntries = 2;
pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) SPPropSet;
pstrinfo++;
//
// set up the stream info structures for the Video Port
//
pstrinfo->NumberOfPossibleInstances = 1;
pstrinfo->DataFlow = KSPIN_DATAFLOW_OUT;
pstrinfo->DataAccessible = TRUE;
pstrinfo->NumberOfFormatArrayEntries = 1;
pstrinfo->StreamFormatsArray = VPInfo;
pstrinfo->NumStreamPropArrayEntries = 1;
pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) VideoPortPropSet;
pstrinfo->StreamEventsArray = VPEventSet;
pstrinfo->NumStreamEventArrayEntries = SIZEOF_ARRAY(VPEventSet);
pstrinfo++;
//
// set up the stream info structures for the Close Caption stream
//
pstrinfo->NumberOfPossibleInstances = 1;
pstrinfo->DataFlow = KSPIN_DATAFLOW_OUT;
pstrinfo->DataAccessible = TRUE;
pstrinfo->NumberOfFormatArrayEntries = 1;
pstrinfo->StreamFormatsArray = CCInfo;
pstrinfo->NumStreamPropArrayEntries = 1;
pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) CCPropSet;
pSrb->Status = STATUS_SUCCESS;
}
/*
** StreamReceiveDataPacket ()
**
** dispatch routine for receiving a data packet. This routine will
** dispatch to the appropriate data handler initialized in the stream
** extension for this data stream
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID STREAMAPI
StreamReceiveDataPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
//
// determine the type of packet.
//
switch (pSrb->Command) {
case SRB_WRITE_DATA:
//
// This is a write data function. Call the appropriate handler
// if it exists, otherwise fall through
//
if (((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)
->pfnWriteData) {
((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)
->pfnWriteData(pSrb);
break;
}
//
// NOTE: falls through to default!
//
default:
//
// invalid / unsupported command. Fail it as such
//
TRAP
pSrb->Status = STATUS_NOT_IMPLEMENTED;
StreamClassStreamNotification(ReadyForNextStreamDataRequest,
pSrb->StreamObject);
StreamClassStreamNotification(StreamRequestComplete,
pSrb->StreamObject,
pSrb);
}
}
/*
** CycEvent ()
**
** receives notification for stream event enable/ disable
**
** Arguments:}
**
**
**
** Returns:
**
** Side Effects:
*/
STREAMAPI
CycEvent (PHW_EVENT_DESCRIPTOR pEvent)
{
PSTREAMEX pstrm=(PSTREAMEX)(pEvent->StreamObject->HwStreamExtension);
if (pEvent->Enable)
{
pstrm->EventCount++;
}
else
{
pstrm->EventCount--;
}
return (STATUS_SUCCESS);
}
/*
** StreamReceiveCtrlPacket ()
**
** main dispatch routine for stream control requests
**
** Arguments:
**
** pSrb - control request to dispatch
**
** Returns:
**
** Side Effects:
*/
VOID STREAMAPI
StreamReceiveCtrlPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
PSTREAMEX pstrm = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
//
// set default status
//
pSrb->Status = STATUS_SUCCESS;
//
// determine the type of packet. All calls here use the pointers
// to the individual stream functions initialised at open time
//
switch (pSrb->Command) {
case SRB_SET_STREAM_STATE:
//
// change the stream state (i.e. play or pause)
//
if (((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)->pfnSetState) {
((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)
->pfnSetState(pSrb);
}
break;
case SRB_GET_STREAM_PROPERTY:
if (((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)->pfnGetProp) {
((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)
->pfnGetProp(pSrb);
}
break;
case SRB_OPEN_MASTER_CLOCK:
case SRB_CLOSE_MASTER_CLOCK:
//
// BUGBUG - these should be stored individually on a per stream basis,
// not in a global variable!!
hMaster = pSrb->CommandData.MasterClockHandle;
break;
case SRB_INDICATE_MASTER_CLOCK:
//
// BUGBUG - these should be stored individually on a per stream basis,
// not in a global variable!!
//
hClk = pSrb->CommandData.MasterClockHandle;
break;
case SRB_SET_STREAM_PROPERTY:
if (((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)->pfnSetProp) {
((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)
->pfnSetProp(pSrb);
}
break;
case SRB_PROPOSE_DATA_FORMAT:
if (((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)->pfnQueryAccept) {
((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)
->pfnQueryAccept(pSrb);
}
break;
/* video rate stuff */
case SRB_SET_STREAM_RATE:
//
// rates should be set on an individual stream basis
//
VidRate = 1000; /* set the rate from the packet here */
break;
/* end video rate stuff */
default:
//
// invalid / unsupported command. Fail it as such
//
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
}
mpstCtrlCommandComplete(pSrb);
}
/*
** mpstCtrlCommandComplete ()
**
** calls back a stream control command, and indicates ready for next
** request
**
** Arguments:
**
** pSrb - Request to commplete
**
** Returns:
**
** Side Effects:
*/
VOID
mpstCtrlCommandComplete(PHW_STREAM_REQUEST_BLOCK pSrb)
{
StreamClassStreamNotification(
ReadyForNextStreamControlRequest,
pSrb->StreamObject);
StreamClassStreamNotification(StreamRequestComplete,
pSrb->StreamObject,
pSrb);
}
/*
** AdapterCloseStream ()
**
** Free up any structures used for a stream, and indicate that it is
** no longer in use
**
** Arguments:
**
** pSrb - command for stream to close
** StreamObject->StreamNumber - indicates the stream number from the
** streaminfo call to be closed
** StreamObject->HwStreamExtension - should indicate which instance is
** being closed
**
** Returns:
**
** Side Effects:
*/
VOID
AdapterCloseStream(PHW_STREAM_REQUEST_BLOCK pSrb)
{
extern void HwCodecReset(void);
PSTREAMEX strm = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
PHW_DEVICE_EXTENSION pdevex = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
//
// NOTE:
// the whole object will go away, we don't need to clear up any fields
// from
// the streamextension, such as all of the pfn functions
//
pSrb->Status = STATUS_SUCCESS;
switch (pSrb->StreamObject->StreamNumber) {
case strmVideo:
pdevex->pstroVid = NULL;
break;
case strmAc3:
pdevex->pstroAud = NULL;
break;
case strmSubpicture:
//
// this is the subpicture stream, free up any allocated buffers
//
if (strm->spstrmex.pdecctl.pData) {
ExFreePool(strm->spstrmex.pdecctl.pData);
}
if (strm->spstrmex.pdecctl.pTopWork) {
ExFreePool(strm->spstrmex.pdecctl.pTopWork);
}
strm->spstrmex.pdecctl.cDecod = 0;
strm->spstrmex.pdecctl.pData = 0;
strm->spstrmex.pdecctl.pTopWork = 0;
pSPstrmex = 0;
break;
case strmYUVVideo:
pdevex->pstroYUV = NULL;
break;
case strmCCOut:
CleanCCQueue();
pdevex->pstroCC = NULL;
break;
}
}
DWORD CDMAadr;
/*
** HwInitialize ()
**
** Performs all board, IRQ and structure initialization for this instance
** of the adapter
**
** Arguments:
**
** pSrb -> command block
** pSrb->CommandData.ConfigInfo -> points to configuration information structure
**
** Returns:
** pSrb->Status set to status of intialization
**
** Side Effects:
*/
NTSTATUS
HwInitialize(
IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
STREAM_PHYSICAL_ADDRESS adr;
ULONG Size;
PUCHAR pDmaBuf;
PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
PHW_DEVICE_EXTENSION pHwDevExt =
(PHW_DEVICE_EXTENSION) ConfigInfo->HwDeviceExtension;
RtlZeroMemory(pHwDevExt, sizeof (PHW_DEVICE_EXTENSION));
//
// this board requires at least one memory access range
//
if (ConfigInfo->NumberOfAccessRanges < 1) {
DebugPrint((DebugLevelVerbose, "ST3520: illegal config info"));
pSrb->Status = STATUS_NO_SUCH_DEVICE;
return (FALSE);
}
DebugPrint((DebugLevelVerbose, "No of access ranges = %lx", ConfigInfo->NumberOfAccessRanges));
//
// the first access range according to this boards inf will be the
// main PIO address base
//
pHwDevExt->ioBaseLocal = (PUSHORT) (ULONG_PTR) (ConfigInfo->AccessRanges[0].RangeStart.LowPart);
DebugPrint((DebugLevelVerbose, "Memory Range = %lx\n", pHwDevExt->ioBaseLocal));
DebugPrint((DebugLevelVerbose, "IRQ = %lx\n", ConfigInfo->BusInterruptLevel));
//
// pick up the irq level
//
pHwDevExt->Irq = (USHORT) (ConfigInfo->BusInterruptLevel);
//
// intiialize some stuff in the hwdevice extension here
//
pHwDevExt->VideoDeviceExt.videoSTC = 0;
pHwDevExt->AudioDeviceExt.audioSTC = 0;
pHwDevExt->AudioDeviceExt.pCurrentSRB = NULL;
pHwDevExt->VideoDeviceExt.pCurrentSRB = NULL;
pHwDevExt->AudioDeviceExt.pCurrentSRB = NULL;
pHwDevExt->VideoDeviceExt.pCurrentSRB = NULL;
pHwDevExt->VideoDeviceExt.pCurrentSRB = NULL;
pHwDevExt->AudioDeviceExt.pCurrentSRB = NULL;
pHwDevExt->VideoDeviceExt.DeviceState = KSSTATE_PAUSE;
pHwDevExt->AudioDeviceExt.DeviceState = KSSTATE_PAUSE;
//
// indicate the size of the structure necessary to descrive all streams
// that are supported by this hardware
//
ConfigInfo->StreamDescriptorSize =
NUMBER_OF_STREAMS * sizeof(HW_STREAM_INFORMATION) +
sizeof(HW_STREAM_HEADER);
//
// allocate the DMA buffer here
//
pDmaBuf = StreamClassGetDmaBuffer(pHwDevExt);
//
// pick up the physical address for the DMA buffer
//
adr = StreamClassGetPhysicalAddress(pHwDevExt, NULL, pDmaBuf, DmaBuffer, &Size);
CDMAadr = adr.LowPart; // chieh for HwCodecReset
bInitialized = TRUE;
//
// make sure the hardware seems to be working ...
//
if (HwCodecOpen((ULONG_PTR) (pHwDevExt->ioBaseLocal), pDmaBuf, (ULONG) (adr.LowPart)))
{
pSrb->Status = STATUS_SUCCESS;
pDevEx = pHwDevExt;
}
else
pSrb->Status = STATUS_NO_SUCH_DEVICE;
DebugPrint((DebugLevelVerbose, "Exit : HwInitialize()\n"));
return TRUE;
}
/*
** HwUnInitialize ()
**
** prepare this instance of the adapter to be removed by plug and play
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
BOOLEAN
HwUnInitialize(IN PVOID DeviceExtension)
{
HwCodecClose();
return TRUE;
}
/*
** HwInterrupt ()
**
** entry point for hardware interrupts
**
** Arguments:
**
** pointer to the device extension for this instance of the adapter
**
** Returns:
**
** TRUE if this interrupt was for this adapter, and was handled by this
** routine
** FALSE if this interrupt was not generated by the device represented
** by this hardware device extension
**
** Side Effects:
*/
BOOLEAN
HwInterrupt(IN PVOID pDeviceExtension)
{
BOOLEAN bRetValue;
PHW_DEVICE_EXTENSION pdevext = (PHW_DEVICE_EXTENSION) pDeviceExtension;
if (!bInitialized)
return FALSE;
//
// this hardware needs to ensure that additional interrupts are not
// generated at the hardware while interrupts are being processed,
// so it enables and disables interrupts around the processing
//
HwCodecDisableIRQ();
bRetValue = (BOOLEAN)HwCodecInterrupt();
HwCodecEnableIRQ();
//
// NOTE: this next code restarts DMA of Video data if there is any
// room available.
//
if (pdevext->VideoDeviceExt.pCurrentSRB)
VideoPacketStub(pdevext->VideoDeviceExt.pCurrentSRB->StreamObject);
if (pdevext->AudioDeviceExt.pCurrentSRB)
AudioPacketStub(pdevext->AudioDeviceExt.pCurrentSRB->StreamObject);
return bRetValue;
}
static fEnabled = FALSE;
/*
** DisableIT ()
**
** disable board interrupts
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID
DisableIT(VOID)
{
HwCodecDisableIRQ();
fEnabled = FALSE;
}
/*
** EnableIT ()
**
** enable board interrupts
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID
EnableIT(VOID)
{
if (!fEnabled) {
HwCodecEnableIRQ();
}
fEnabled = TRUE;
}
/*
** HostDisableIT ()
**
** null routine at the moment
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID
HostDisableIT(VOID)
{
}
/*
** HostEnableIT ()
**
** equally null routine
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID
HostEnableIT(VOID)
{
}
/*
** NTSCSetProp ()
**
** Set property handling routine for the NTSC encoder pin
**
** Arguments:
**
** pSrb -> property command block
** pSrb->CommandData.PropertyInfo describes the requested property
**
** Returns:
**
** Side Effects:
*/
void
NTSCSetProp(PHW_STREAM_REQUEST_BLOCK pSrb)
{
if (pSrb->CommandData.PropertyInfo->PropertySetID) {
// invalid property
pSrb->Status = STATUS_NOT_IMPLEMENTED;
return;
}
switch(pSrb->CommandData.PropertyInfo->Property->Id)
{
case KSPROPERTY_COPY_MACROVISION:
//
// pick up the macrovision level, and set the level accordingly
//
// SetMacroVisionLevel(
// pSrb->CommandData.PropertyInfo->PropertyInfo);
//
pSrb->Status = STATUS_SUCCESS;
break;
default:
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
/*
** NTSCGetProp ()
**
** get property handling routine for the NTSC encoder pin
**
** Arguments:
**
** pSrb -> property command block
** pSrb->CommandData.PropertyInfo describes the requested property
**
** Returns:
**
** Side Effects:
*/
void
NTSCGetProp(PHW_STREAM_REQUEST_BLOCK pSrb)
{
if (pSrb->CommandData.PropertyInfo->PropertySetID) {
// invalid property
pSrb->Status = STATUS_NOT_IMPLEMENTED;
return;
}
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
/*
** CCGetProp ()
**
** get property handling routine for the Close caption pin
**
** Arguments:
**
** pSrb -> property command block
** pSrb->CommandData.PropertyInfo describes the requested property
**
** Returns:
**
** Side Effects:
*/
void
CCGetProp(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevex =
((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
PKSALLOCATOR_FRAMING pfrm = (PKSALLOCATOR_FRAMING)
pSrb->CommandData.PropertyInfo->PropertyInfo;
PKSSTATE State;
pSrb->Status = STATUS_NOT_IMPLEMENTED;
if (pSrb->CommandData.PropertyInfo->PropertySetID) {
// invalid property
return;
}
switch(pSrb->CommandData.PropertyInfo->Property->Id)
{
case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
pfrm->OptionsFlags = 0;
pfrm->PoolType = 0;
pfrm->Frames = 10;
pfrm->FrameSize = 200;
pfrm->FileAlignment = 0;
pfrm->Reserved = 0;
pSrb->ActualBytesTransferred = sizeof(KSALLOCATOR_FRAMING);
pSrb->Status = STATUS_SUCCESS;
break;
case KSPROPERTY_CONNECTION_STATE:
State= (PKSSTATE) pSrb->CommandData.PropertyInfo->PropertyInfo;
pSrb->ActualBytesTransferred = sizeof (State);
// A very odd rule:
// When transitioning from stop to pause, DShow tries to preroll
// the graph. Capture sources can't preroll, and indicate this
// by returning VFW_S_CANT_CUE in user mode. To indicate this
// condition from drivers, they must return ERROR_NO_DATA_DETECTED
*State = ((PSTREAMEX)(pdevex->pstroCC->HwStreamExtension))->state;
if (((PSTREAMEX)pdevex->pstroCC->HwStreamExtension)->state == KSSTATE_PAUSE)
{
//
// wierd stuff for capture type state change. When you transition
// from stop to pause, we need to indicate that this device cannot
// preroll, and has no data to send.
//
pSrb->Status = STATUS_NO_DATA_DETECTED;
return;
}
pSrb->Status = STATUS_SUCCESS;
break;
default:
TRAP
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
}
/*
** VPESetProp ()
**
** Set property handling routine for the Video Port Extensions pin
**
** Arguments:
**
** pSrb -> property command block
** pSrb->CommandData.PropertyInfo describes the requested property
**
** Returns:
**
** Side Effects:
*/
void
VPESetProp(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevex = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
DWORD dwInputBufferSize;
DWORD dwOutputBufferSize;
DWORD *lpdwOutputBufferSize;
PKS_AMVPSIZE pDim;
dwInputBufferSize = pSrb->CommandData.PropertyInfo->PropertyInputSize;
dwOutputBufferSize = pSrb->CommandData.PropertyInfo->PropertyOutputSize;
lpdwOutputBufferSize = &(pSrb->ActualBytesTransferred);
pSrb->Status = STATUS_SUCCESS;
switch(pSrb->CommandData.PropertyInfo->Property->Id)
{
case KSPROPERTY_VPCONFIG_SETCONNECTINFO:
//
// pSrb->CommandData.PropertInfo->PropertyInfo
// points to a ULONG which is an index into the array of
// connectinfo structs returned to the caller from the
// Get call to ConnectInfo.
//
// Since the sample only supports one connection type right
// now, we will ensure that the requested index is 0.
//
switch (*(PULONG)pSrb->CommandData.PropertyInfo->PropertyInfo)
{
case 0:
//
// at this point, we would program the hardware to use
// the right connection information for the videoport.
// since we are only supporting one connection, we don't
// need to do anything, so we will just indicate success
//
break;
default:
pSrb->Status = STATUS_NO_MATCH;
break;
}
break;
case KSPROPERTY_VPCONFIG_DDRAWHANDLE:
pdevex->ddrawHandle =
(*(PULONG)pSrb->CommandData.PropertyInfo->PropertyInfo);
break;
case KSPROPERTY_VPCONFIG_VIDEOPORTID:
pdevex->VidPortID =
(*(PULONG)pSrb->CommandData.PropertyInfo->PropertyInfo);
break;
case KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE:
pdevex->SurfaceHandle =
(*(PULONG)pSrb->CommandData.PropertyInfo->PropertyInfo);
break;
case KSPROPERTY_VPCONFIG_SETVIDEOFORMAT:
//
// pSrb->CommandData.PropertInfo->PropertyInfo
// points to a ULONG which is an index into the array of
// VIDEOFORMAT structs returned to the caller from the
// Get call to FORMATINFO
//
// Since the sample only supports one FORMAT type right
// now, we will ensure that the requested index is 0.
//
switch (*(PULONG)pSrb->CommandData.PropertyInfo->PropertyInfo)
{
case 0:
//
// at this point, we would program the hardware to use
// the right connection information for the videoport.
// since we are only supporting one connection, we don't
// need to do anything, so we will just indicate success
//
break;
default:
pSrb->Status = STATUS_NO_MATCH;
break;
}
break;
case KSPROPERTY_VPCONFIG_INFORMVPINPUT:
//
// These are the preferred formats for the VPE client
//
// they are multiple properties passed in, return success
//
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case KSPROPERTY_VPCONFIG_INVERTPOLARITY:
//
// Toggles the global polarity flag, telling the output
// of the VPE port to be inverted. Since this hardware
// does not support this feature, we will just return
// success for now, although this should be returning not
// implemented
//
break;
case KSPROPERTY_VPCONFIG_SCALEFACTOR:
//
// the sizes for the scaling factor are passed in, and the
// image dimensions should be scaled appropriately
//
//
// if there is a horizontal scaling available, do it here.
//
TRAP
pDim =(PKS_AMVPSIZE)(pSrb->CommandData.PropertyInfo->PropertyInfo);
if (pDim->dwWidth != VPFmt.amvpDimInfo.dwFieldWidth - 63)
{
TRAP
DbgPrint("CYCLO: setting scaling to %d, %d\n",
VPFmt.amvpDimInfo.dwFieldWidth - 63,pDim->dwWidth);
VideoSetSRC(VPFmt.amvpDimInfo.dwFieldWidth - 63,pDim->dwWidth);
VideoSwitchSRC(TRUE);
}
else
{
TRAP
VideoSwitchSRC(FALSE);
}
break;
default:
TRAP
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
/*
** VPEGetProp ()
**
** function to handle any of the Get property calls for the VPE
** pin
**
** Arguments:
**
** pSrb - packet for Getting the property
** pSrb->CommandData.PropertyInfo -> describes the property
**
** Returns:
**
** Side Effects:
*/
void VPEGetProp(PHW_STREAM_REQUEST_BLOCK pSrb)
{
DWORD dwInputBufferSize;
DWORD dwOutputBufferSize;
DWORD dwNumConnectInfo = 1;
DWORD dwNumVideoFormat = 1;
unsigned long ulFourCC = MKFOURCC('Y', 'U', 'Y', '2');
DWORD dwFieldWidth = 783;
DWORD dwFieldHeight = 258;
ULONG lc;
// the pointers to which the input buffer will be cast to
LPDDVIDEOPORTCONNECT pConnectInfo;
LPDDPIXELFORMAT pVideoFormat;
PKSVPMAXPIXELRATE pMaxPixelRate;
PKS_AMVPDATAINFO pVpdata;
// LPAMSCALINGINFO pScaleFactor;
//
// NOTE: ABSOLUTELY DO NOT use pmulitem, until it is determined that
// the stream property descriptor describes a multiple item, or you will
// pagefault.
//
PKSMULTIPLE_ITEM pmulitem =
&(((PKSMULTIPLE_DATA_PROP)pSrb->CommandData.PropertyInfo->Property)->MultipleItem);
//
// NOTE: same goes for this one as above.
//
PKS_AMVPSIZE pdim =
&(((PKSVPSIZE_PROP)pSrb->CommandData.PropertyInfo->Property)->Size);
if(pSrb->CommandData.PropertyInfo->PropertySetID)
{
// invalid property
pSrb->Status = STATUS_NOT_IMPLEMENTED;
return;
}
dwInputBufferSize = pSrb->CommandData.PropertyInfo->PropertyInputSize;
dwOutputBufferSize = pSrb->CommandData.PropertyInfo->PropertyOutputSize;
pSrb->Status = STATUS_SUCCESS;
switch(pSrb->CommandData.PropertyInfo->Property->Id)
{
case KSPROPERTY_VPCONFIG_NUMCONNECTINFO:
//
// specify the number of bytes written
//
pSrb->ActualBytesTransferred = sizeof(DWORD);
*(PULONG) pSrb->CommandData.PropertyInfo->PropertyInfo
= dwNumConnectInfo;
break;
case KSPROPERTY_VPCONFIG_NUMVIDEOFORMAT:
//
// specify the number of bytes written
//
pSrb->ActualBytesTransferred = sizeof(DWORD);
*(PULONG) pSrb->CommandData.PropertyInfo->PropertyInfo
= dwNumVideoFormat;
break;
case KSPROPERTY_VPCONFIG_GETCONNECTINFO:
//
// check that the size of the output buffer is correct
//
if (pmulitem->Count > dwNumConnectInfo ||
pmulitem->Size != sizeof (DDVIDEOPORTCONNECT) ||
dwOutputBufferSize <
(pmulitem->Count * sizeof (DDVIDEOPORTCONNECT)))
{
TRAP
//
// buffer size is invalid, so error the call
//
pSrb->Status = STATUS_INVALID_BUFFER_SIZE;
return;
}
//
// specify the number of bytes written
//
pSrb->ActualBytesTransferred = pmulitem->Count*sizeof(DDVIDEOPORTCONNECT);
for (lc = 0,
pConnectInfo = (LPDDVIDEOPORTCONNECT)(pSrb->CommandData.
PropertyInfo->PropertyInfo);
lc <pmulitem->Count;
lc++,
pConnectInfo++)
{
//
// fill in the values
//
pConnectInfo->dwSize = sizeof (DDVIDEOPORTCONNECT);
pConnectInfo->guidTypeID = g_S3Guid; //DDVPTYPE_E_HREFL_VREFL;
pConnectInfo->dwPortWidth = 8;
pConnectInfo->dwFlags = 0x3F;
}
break;
case KSPROPERTY_VPCONFIG_VPDATAINFO:
//
// specify the number of bytes written
//
pSrb->ActualBytesTransferred = sizeof(KS_AMVPDATAINFO);
//
// cast the buffer to the porper type
//
pVpdata = (PKS_AMVPDATAINFO)pSrb->CommandData.PropertyInfo->PropertyInfo;
pVpdata->dwSize = sizeof (KS_AMVPDATAINFO);
//
// set up the current region
//
*pVpdata = VPFmt;
// fill in the values
pVpdata->dwMicrosecondsPerField = 17;
pVpdata->bEnableDoubleClock = FALSE;
pVpdata->bEnableVACT = FALSE;
pVpdata->bDataIsInterlaced = TRUE;
pVpdata->lHalfLinesOdd = 1;
pVpdata->lHalfLinesEven = 0;
pVpdata->bFieldPolarityInverted = FALSE;
break ;
case KSPROPERTY_VPCONFIG_MAXPIXELRATE:
//
// NOTE:
// this property is special. And has another different
// input property!
//
if (dwInputBufferSize < sizeof (KSVPSIZE_PROP))
{
TRAP
pSrb->Status = STATUS_INVALID_BUFFER_SIZE;
return;
}
//
// note: pdim specfies the dimensions requested for
// the output image pixel rate. Please use these to
// determine your real rate. It's late Sunday night, and
// we don't have time to actually look at these in this
// sample code ... :-)
//
//
// specify the number of bytes written
//
pSrb->ActualBytesTransferred = sizeof(KSVPMAXPIXELRATE);
//
// cast the buffer to the porper type
//
pMaxPixelRate = (PKSVPMAXPIXELRATE)pSrb->CommandData.PropertyInfo->PropertyInfo;
// tell the app that the pixel rate is valid for these dimensions
pMaxPixelRate->Size.dwWidth = dwFieldWidth;
pMaxPixelRate->Size.dwHeight = dwFieldHeight;
pMaxPixelRate->MaxPixelsPerSecond = 1300;
break;
case KSPROPERTY_VPCONFIG_INFORMVPINPUT:
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break ;
case KSPROPERTY_VPCONFIG_GETVIDEOFORMAT:
//
// check that the size of the output buffer is correct
//
if (pmulitem->Count > dwNumConnectInfo ||
pmulitem->Size != sizeof (DDPIXELFORMAT) ||
dwOutputBufferSize <
(pmulitem->Count * sizeof (DDPIXELFORMAT)))
{
TRAP
//
// buffer size is invalid, so error the call
//
pSrb->Status = STATUS_INVALID_BUFFER_SIZE;
return;
}
//
// specify the number of bytes written
//
pSrb->ActualBytesTransferred = pmulitem->Count*sizeof(DDPIXELFORMAT);
for (lc = 0,
pVideoFormat = (LPDDPIXELFORMAT)(pSrb->CommandData.
PropertyInfo->PropertyInfo);
lc <pmulitem->Count;
lc++,
pVideoFormat++)
{
//
// fill in the values
//
pVideoFormat->dwFlags = DDPF_FOURCC;
pVideoFormat->dwYUVBitCount = 16;
pVideoFormat->dwSize= sizeof (DDPIXELFORMAT);
pVideoFormat->dwFourCC = ulFourCC;
}
break;
case KSPROPERTY_VPCONFIG_DECIMATIONCAPABILITY:
//
// indicate that we can decimate anything, especially if it's late.
//
pSrb->ActualBytesTransferred = sizeof (BOOL);
*((PBOOL)pSrb->CommandData.PropertyInfo->PropertyInfo) = TRUE;
break;
default:
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
/*
** HwProcessDataIntersection ()
**
**
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID
HwProcessDataIntersection(PHW_STREAM_REQUEST_BLOCK pSrb)
{
NTSTATUS Status = STATUS_SUCCESS;
PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
PKSDATARANGE DataRange;
PKSDATAFORMAT pFormat = NULL;
ULONG formatSize;
//
// BUGBUG - this is a tempory implementation. We need to compare
// the data types passed in and error if the ranges don't overlap.
// we also need to return valid format blocks, not just the data range.
//
IntersectInfo = pSrb->CommandData.IntersectInfo;
switch (IntersectInfo->StreamNumber) {
/*
case strmVideo:
pFormat = &hwfmtiMpeg2Vid;
formatSize = sizeof hwfmtiMpeg2Vid;
break;
case strmAc3:
pFormat = &hwfmtiMpeg2Aud;
formatSize = sizeof hwfmtiMpeg2Aud;
break;
case strmNTSCVideo:
pFormat = &hwfmtiNTSCOut;
formatSize = sizeof hwfmtiNTSCOut;
break;
case strmSubpicture:
pFormat = &hwfmtiSubPic;
formatSize = sizeof hwfmtiSubPic;
break;
*/
case strmYUVVideo:
pFormat = &hwfmtiVPOut;
formatSize = sizeof hwfmtiVPOut;
break;
case strmCCOut:
pFormat = &hwfmtiCCOut;
formatSize = sizeof hwfmtiCCOut;
break;
default:
pSrb->Status = STATUS_NOT_IMPLEMENTED;
return;
TRAP;
} // end streamnumber switch
if (pFormat) {
//
// do a minimal compare of the dataranges to at least verify
// that the guids are the same.
// BUGBUG - this is woefully incomplete.
//
DataRange = IntersectInfo->DataRange;
if (!(IsEqualGUID(&DataRange->MajorFormat,
&pFormat->MajorFormat) &&
IsEqualGUID(&DataRange->Specifier,
&pFormat->Specifier))) {
Status = STATUS_NO_MATCH;
} else { // if guids are equal
//
// check to see if the size of the passed in buffer is a ULONG.
// if so, this indicates that we are to return only the size
// needed, and not return the actual data.
//
if (IntersectInfo->SizeOfDataFormatBuffer != sizeof(ULONG)) {
//
// we are to copy the data, not just return the size
//
if (IntersectInfo->SizeOfDataFormatBuffer < formatSize) {
Status = STATUS_BUFFER_TOO_SMALL;
} else { // if too small
RtlCopyMemory(IntersectInfo->DataFormatBuffer,
pFormat,
formatSize);
pSrb->ActualBytesTransferred = formatSize;
Status = STATUS_SUCCESS;
} // if too small
} else { // if sizeof ULONG specified
//
// caller wants just the size of the buffer. Get that.
//
*(PULONG) IntersectInfo->DataFormatBuffer = formatSize;
pSrb->ActualBytesTransferred = sizeof(ULONG);
} // if sizeof ULONG
} // if guids are equal
} else { // if pFormat
Status = STATUS_NOT_SUPPORTED;
} // if pFormat
pSrb->Status = Status;
return;
}
/*
** CCReceiveDataPacket ()
**
** Receive the data packets to send to the close-caption decoder
**
** Arguments:}
**
**
**
** Returns:
**
** Side Effects:
*/
extern ULONG cCCRec;
extern ULONG cCCDeq;
extern ULONG cCCCB;
ULONG cCCRec = 0;
ULONG cCCDeq = 0;
ULONG cCCCB = 0;
VOID STREAMAPI
CCReceiveDataPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevex =
((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
//
// determine the type of packet.
//
switch (pSrb->Command) {
case SRB_READ_DATA:
//
// This is a write data function. Call the appropriate handler
// if it exists, otherwise fall through
//
cCCRec++;
CCEnqueue(pSrb);
StreamClassStreamNotification(ReadyForNextStreamDataRequest,
pSrb->StreamObject);
pSrb->TimeoutOriginal = 0;
pSrb->TimeoutCounter = 0;
break;
default:
//
// invalid / unsupported command. Fail it as such
//
TRAP
pSrb->Status = STATUS_NOT_IMPLEMENTED;
StreamClassStreamNotification(ReadyForNextStreamDataRequest,
pSrb->StreamObject);
StreamClassStreamNotification(StreamRequestComplete,
pSrb->StreamObject,
pSrb);
}
}
/*
** CCSetState ()
**
** set up the state for the current stream
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
VOID STREAMAPI
CCSetState(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevex =
((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
((PSTREAMEX)(pdevex->pstroCC->HwStreamExtension))->state = pSrb->CommandData.StreamState;
pSrb->Status = STATUS_SUCCESS;
}
extern ULONG cCCQ;
ULONG cCCQ =0;
void CCEnqueue(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_STREAM_REQUEST_BLOCK pSrbTmp;
ULONG cSrb;
//
// enqueue the given SRB on the device extension queue
//
for (cSrb =0,
pSrbTmp = CONTAINING_RECORD((&(pDevEx->pSrbQ)),
HW_STREAM_REQUEST_BLOCK, NextSRB);
pSrbTmp->NextSRB;
pSrbTmp = pSrbTmp->NextSRB, cSrb++);
pSrbTmp->NextSRB = pSrb;
pSrb->NextSRB = NULL;
cCCQ++;
}
PHW_STREAM_REQUEST_BLOCK CCDequeue(void)
{
PHW_STREAM_REQUEST_BLOCK pRet = NULL;
if (pDevEx->pSrbQ)
{
cCCDeq++;
pRet = pDevEx->pSrbQ;
pDevEx->pSrbQ = pRet->NextSRB;
cCCQ--;
}
return(pRet);
}
void CleanCCQueue()
{
PHW_STREAM_REQUEST_BLOCK pSrb;
while (pSrb = CCDequeue())
{
CallBackError(pSrb);
}
}