3324 lines
76 KiB
C
3324 lines
76 KiB
C
/******************************************************************
|
||
*******************************************************************
|
||
*******************************************************************
|
||
*******************************************************************
|
||
*******************************************************************
|
||
|
||
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);
|
||
}
|
||
|
||
}
|
||
|