#include "strmini.h"
#include "stdefs.h"
#include "ks.h"

#include "ls220.h"

#ifdef WINDOWS2000
	#include "wdm.h"
#else
	#include "ntddk.h" // Windows 98 DDK use this ??! , we need to use newr 98 DDK !
#endif

#include <wingdi.h>
#include <mmreg.h>
#include "ksmedia.h"
#include "mpinit.h"
#include "mpvideo.h"
#include "mpaudio.h"
#include "lssubp.h"
#include "dxapi.h"
#include "dvhw32.h"
#include "video.h"
#include "audio.h"
#include "luxksprop.h"

//#define MAPPER	//Code added to export Functions to a VxD Interface

#ifdef MAPPER	
	#include <wdm.h>
		
	#define WANTVXDWRAPS
	#define INITGUID
	#define DllExport    __declspec( dllexport )

	//Global Variable Declaration
	PHYSICAL_ADDRESS phys_addr;

	//Function Declaration
	void LuxGetPhysAddr(PHW_DEVICE_EXTENSION pHwDevExt);

	//Exports
	NTSTATUS DllExport _stdcall LUXGetBase(OUT ULONG *pLinBase );
	NTSTATUS DllExport _stdcall OpenDriver();
	NTSTATUS DllExport _stdcall CloseClose();

	//external functions
	extern NTKERNELAPI PHYSICAL_ADDRESS MmGetPhysicalAddress(IN PVOID BaseAddress);

#endif

#define LINE21

//provide flexibility to remove CC and VPE pins
#define CCOUT
#define VPE

#define DDVPTYPE_E_HREFH_VREFH  \
	0x54F39980L,0xDA60,0x11CF,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8

#define DDVPTYPE_E_HREFH_VREFL  \
	0x92783220L,0xDA60,0x11CF,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8

#define DDVPTYPE_E_HREFL_VREFH  \
	0xA07A02E0L,0xDA60,0x11CF,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8

#define DDVPTYPE_E_HREFL_VREFL  \
	0xE09C77E0L,0xDA60,0x11CF,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8

#define DDVPTYPE_CCIR656  \
	0xFCA326A0L,0xDA60,0x11CF,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8

GUID            g_HREFL_VREFLGuid = {DDVPTYPE_E_HREFL_VREFL};
GUID            g_CCIR656Guid = {DDVPTYPE_CCIR656};
GUID			g_VMIGuid = {DDVPTYPE_E_HREFL_VREFH};
GUID            g_HREFH_VREFLGuid = {DDVPTYPE_E_HREFH_VREFL};
GUID            g_HREFH_VREFHGuid = {DDVPTYPE_E_HREFH_VREFH};

//
// Pin name GUIDs - hopefully some day these will be added to ksmedia.h
//
#define STATIC_PINNAME_DVD_VIDEOIN \
   0x33AD5F43, 0xF1BC, 0x11D1, 0x94, 0xA5, 0x00, 0x00, 0xF8, 0x05, 0x34, 0x84

#define STATIC_PINNAME_DVD_VPEOUT \
   0x33AD5F44, 0xF1BC, 0x11D1, 0x94, 0xA5, 0x00, 0x00, 0xF8, 0x05, 0x34, 0x84

#define STATIC_PINNAME_DVD_AUDIOIN \
   0x33AD5F45, 0xF1BC, 0x11D1, 0x94, 0xA5, 0x00, 0x00, 0xF8, 0x05, 0x34, 0x84

#define STATIC_PINNAME_DVD_CCOUT \
   0x33AD5F46, 0xF1BC, 0x11D1, 0x94, 0xA5, 0x00, 0x00, 0xF8, 0x05, 0x34, 0x84

#define STATIC_PINNAME_DVD_SUBPICIN \
   0x33AD5F47, 0xF1BC, 0x11D1, 0x94, 0xA5, 0x00, 0x00, 0xF8, 0x05, 0x34, 0x84

#define STATIC_PINNAME_DVD_NTSCOUT \
   0x33AD5F48, 0xF1BC, 0x11D1, 0x94, 0xA5, 0x00, 0x00, 0xF8, 0x05, 0x34, 0x84

GUID g_PINNAME_DVD_VIDEOIN = {STATIC_PINNAME_DVD_VIDEOIN};
GUID g_PINNAME_DVD_VPEOUT  = {STATIC_PINNAME_DVD_VPEOUT};
GUID g_PINNAME_DVD_CCOUT = {STATIC_PINNAME_DVD_CCOUT};
GUID g_PINNAME_DVD_AUDIOIN = {STATIC_PINNAME_DVD_AUDIOIN};
GUID g_PINNAME_DVD_SUBPICIN = {STATIC_PINNAME_DVD_SUBPICIN};
GUID g_PINNAME_DVD_NTSCOUT = {STATIC_PINNAME_DVD_NTSCOUT};


// list of stream types for initialization

typedef enum tagStreamType 
{
    strmVideo = 0,
    strmAc3,
#ifdef NTSC
    strmNTSCVideo,
#endif
    strmSubpicture,
#ifdef VPE
    strmYUVVideo,
#endif

#ifdef CCOUT
	strmCCOut,
#endif
	NUMBER_OF_STREAMS
}STREAMTYPES;

// define the data formats used by the pins in this minidriver

// MPEG2 video format definition
KSDATAFORMAT    hwfmtiMpeg2Vid = {
    sizeof(KSDATAFORMAT),// + sizeof(MPEGVIDEOINFO2),

    /* NOTE: MPEG2 video streams must support the MPEGVIDEOINFO2 format
     * block. This defines aspect ratios, and other stream properties */

    0,
	0,
	0,
    STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
    STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO,
    STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO
};


KSDATAFORMAT    hwfmtiMpeg2VidPES = {
    sizeof(KSDATAFORMAT),// + sizeof(KS_MPEGVIDEOINFO2),

    /* NOTE: MPEG2 video streams must support the MPEGVIDEOINFO2 format
     * block. This defines aspect ratios, and other stream properties */

    0,
	0,
	0,
    STATIC_KSDATAFORMAT_TYPE_MPEG2_PES,
    STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO,
    STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO
};


//Define the supported AC3 Audio format
KSDATAFORMAT Mpeg2ksdataformat = {
   sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX),
   0,
   1,
   0,
   STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
   STATIC_KSDATAFORMAT_SUBTYPE_AC3_AUDIO,
   STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
};

WAVEFORMATEX Mpeg2waveformatex = {
   0,   // WAVE_FORMAT_UNKNOWN
   6,   // channels
   48000,  // sampling rate
   0,  // byte rate
   768, // align
   0,   // resolution
   0    // extra
};

//Define the supported LPCM audio format.
KSDATAFORMAT LPCMksdataformat = {
   sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX),
   0,
   1,
   0,
   STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
   STATIC_KSDATAFORMAT_SUBTYPE_LPCM_AUDIO,
   STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
};

WAVEFORMATEX LPCMwaveformatex = {
/*
The navigator currently does not look at this, all it cares about is that
we provide a valid format block for Mpeg2.  So the correctness of these
values has not been verified.
*/

   WAVE_FORMAT_PCM,
   2,	// channels
   48000,  // sampling rate
   192000,  // byte rate
   4,	// alignment
   16,	// bit resolution
   0	// extra
};


KSDATAFORMAT Mpeg2PESksdataformat = {
   sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX),
   0,
   1,
   0,
   STATIC_KSDATAFORMAT_TYPE_MPEG2_PES,
   STATIC_KSDATAFORMAT_SUBTYPE_AC3_AUDIO,	//Even though spec says DOLBY_AC3, MS confirmed that this is same
   STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
};


/* The KSDATAFORMAT and WAVEFORMATEX structures above are copied in
   here at run time.  See the comment just before the four calls to
   RtlCopyMemory in AdapterStreamInfo() below.
*/
BYTE hwfmtiMpeg2Aud[sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX)];
BYTE hwfmtiLPCMAud[sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX)];

//MPEG PES AC3 can share the same WaveFormatTex structure as DVD AC3
BYTE hwfmtiMpeg2AudPES[sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX)];


// define the NTSC output format
KSDATAFORMAT    hwfmtiNTSCOut
= {
    sizeof(KSDATAFORMAT),
    0,
	0,
	0,
    STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK,
    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_SUBTYPE_VPVideo,
    STATIC_KSDATAFORMAT_SPECIFIER_NONE
};


// 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_SUBTYPE_SUBPICTURE,
    STATIC_GUID_NULL
};

// define the arrays of supported formats pointers

PKSDATAFORMAT   Mpeg2VidInfo[] = {
    &hwfmtiMpeg2Vid,            // pointer to the MPEG 2 video format block
	&hwfmtiMpeg2VidPES			// pointer to the MPEG 2 PES video format block
};

PKSDATAFORMAT Mpeg2AudInfo[] = {
	(PKSDATAFORMAT) hwfmtiMpeg2Aud, // pointer to the Mpeg2 format
	(PKSDATAFORMAT) hwfmtiLPCMAud,   // pointer to the LPCM format
	(PKSDATAFORMAT) hwfmtiMpeg2AudPES	// pointer to the PES format
};


PKSDATAFORMAT   SubPicInfo[] = {
    &hwfmtiSubPic               // pointer to the subpicture 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
        (PFNKSHANDLER)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_COPY_MACROVISION,// DVD Copy protection for Macrovision
        (PFNKSHANDLER)FALSE,      // get property on challenge key requests the
								 // decoder to provide it's challenge key
        sizeof(KSPROPERTY),
		sizeof(KS_COPY_MACROVISION), // minimum size of data requested
        (PFNKSHANDLER) TRUE,     // set palette is supported
        NULL,
        0,
        NULL,
        NULL,
        0
    },

#ifdef DVD_REGION
	{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
    },
#endif
	
	{KSPROPERTY_DVDCOPY_TITLE_KEY,// DVD authentication DVD title key property
        (PFNKSHANDLER)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
        (PFNKSHANDLER)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
    },

	//NEW
	{KSPROPERTY_DVDCOPY_SET_COPY_STATE, // DVD authentication DVD disc key property
        (PFNKSHANDLER)TRUE,              
        sizeof(KSPROPERTY),
		sizeof(KS_DVDCOPY_SET_COPY_STATE),// 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)TRUE,
	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
	}
};

//////////////////////////////
//PROPERTIES FOR RATE CHANGES

static const KSPROPERTY_ITEM RateChangePropItm[]={

	{
		KS_AM_RATE_SimpleRateChange,	//property id
		(PFNKSHANDLER) TRUE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (KS_AM_SimpleRateChange),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},

	{
		KS_AM_RATE_ExactRateChange,
		(PFNKSHANDLER) FALSE,
		sizeof (KSPROPERTY),
		sizeof (KS_AM_ExactRateChange),
		(PFNKSHANDLER) FALSE,
		NULL,
		0,
		NULL,
		NULL,
		0
	},

	{
		KS_AM_RATE_MaxFullDataRate,
		(PFNKSHANDLER) TRUE,
		sizeof (KSPROPERTY),
		sizeof (KS_AM_MaxFullDataRate),
		(PFNKSHANDLER) FALSE,
		NULL,
		0,
		NULL,
		NULL,
		0
	},

	{
		KS_AM_RATE_Step,
		(PFNKSHANDLER) FALSE,
		sizeof (KSPROPERTY),
		sizeof (KS_AM_Step),
		(PFNKSHANDLER) TRUE,	//This was set to true but the handle did not implement
		NULL,
		0,
		NULL,
		NULL,
		0
	}
};


//////////////////////////////
//PROPERTIES FOR Luxsonor Audio

static const KSPROPERTY_ITEM LuxAudioPropItm[]={

	{
		LUXSONOR_AM_PROPERTY_AUD_VOLUME,	//property id
		(PFNKSHANDLER) TRUE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxAudVolume),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_AUD_MUTE,	//property id
		(PFNKSHANDLER) FALSE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxMuteAudVolume),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_AUD_OUTPUTCHANNEL,	//property id
		(PFNKSHANDLER) FALSE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxSetAudChannel),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_AUD_KARAOKE,	//property id
		(PFNKSHANDLER) FALSE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxSetAudKaraokeMode),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	}
};


//////////////////////////////
//PROPERTIES FOR Luxsonor Video

static const KSPROPERTY_ITEM LuxVideoPropItm[]={

	{
		LUXSONOR_AM_PROPERTY_VID_GAMMA,	//property id
		(PFNKSHANDLER) TRUE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxVidGamma),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_VID_ZOOM,	//property id
		(PFNKSHANDLER) FALSE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxSetVidZoom),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_VID_CHROMA,	//property id
		(PFNKSHANDLER) TRUE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxVidChroma),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_VID_EPROM,	//property id
		(PFNKSHANDLER) FALSE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxSetVidEprom),	//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_VID_EPROM_SPDIF,	//property id
		(PFNKSHANDLER) TRUE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxGetVidEpromSPDIF),	//min data length
		(PFNKSHANDLER) FALSE,			//set handler
		NULL,
		0,
		NULL,
		NULL,
		0
	},
	{
		LUXSONOR_AM_PROPERTY_VID_FULLSCR,	//property id
		(PFNKSHANDLER) FALSE,			//get handler
		sizeof (KSPROPERTY),			//min input length
		sizeof (LuxSetVidFullScr),		//min data length
		(PFNKSHANDLER) TRUE,			//set handler
		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
	},
	//New for Rate changes
	{
		&KSPROPSETID_TSRateChange,
		SIZEOF_ARRAY(RateChangePropItm),
		(PKSPROPERTY_ITEM) RateChangePropItm
	},
	{
		&LUXSONOR_AM_KSPROPSETID_Video,
		SIZEOF_ARRAY(LuxVideoPropItm),
		(PKSPROPERTY_ITEM) LuxVideoPropItm
	}

};

// 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
	},

	//New for Rate changes
	{
		&KSPROPSETID_TSRateChange,
		SIZEOF_ARRAY(RateChangePropItm),
		(PKSPROPERTY_ITEM) RateChangePropItm
	}
};

// 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
	},

	//New for Rate changes
	{
		&KSPROPSETID_TSRateChange,
		SIZEOF_ARRAY(RateChangePropItm),
		(PKSPROPERTY_ITEM) RateChangePropItm
	},

	{
		&LUXSONOR_AM_KSPROPSETID_Audio,
		SIZEOF_ARRAY(LuxAudioPropItm),
		(PKSPROPERTY_ITEM) LuxAudioPropItm
	}

};

// 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
};

// 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,
	}
};

#ifdef CCOUT
#ifdef VPE

static const KSTOPOLOGY_CONNECTION Connections[] = {
/*  FromNode   FromPin           ToNode   ToPin          */
   {(ULONG)(-1),        strmVideo,        (ULONG)(-1),      strmCCOut},
   {(ULONG)(-1),        strmVideo,        (ULONG)(-1),      strmYUVVideo},
   {(ULONG)(-1),        strmSubpicture,   (ULONG)(-1),      strmYUVVideo}
};

#endif
#endif

#ifdef ORIG
static const KSTOPOLOGY Topology = {
    1,
    (GUID *) & KSCATEGORY_DATADECOMPRESSOR,
    0,
    NULL,
    0,
    NULL
};
#else
//This was suggested by Serge
static const KSTOPOLOGY Topology = {
    1,
    (GUID *) & KSCATEGORY_DATADECOMPRESSOR,
    0,
    NULL,
    SIZEOF_ARRAY(Connections),
    Connections
};
#endif

KSPIN_MEDIUM VPMedium = {
	STATIC_KSMEDIUMSETID_VPBus,
	0,
	0
};


//GLOBALS

BOOL            bInitialized = FALSE;
PSP_STRM_EX		pSPstrmex=NULL;
ULONG			VidRate;
PHW_DEVICE_EXTENSION pDevEx;
PHW_STREAM_OBJECT pVideoStream;
HANDLE          hClk;
HANDLE          hMaster;
ULONG			cCCRec=0, cCCDeq=0, cCCCB=0 ,cCCQ=0;

extern KS_AMVPDATAINFO VPFmt;
extern BOOLEAN fProgrammed;
extern BOOLEAN fStarted;
extern DWORD luxbase;

extern BOOL	m_alwaysF;
extern BOOL	v_m_VideoSrc_NTSC;	// Video Src

BOOL	m_resume = FALSE;

VOID STREAMAPI  StreamReceiveAudioPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb);
VOID            HwProcessDataIntersection(PHW_STREAM_REQUEST_BLOCK pSrb);
void            AudioPacketStub(PHW_STREAM_OBJECT pstrm);
void			LuxDSPDispatchCallBack(PHW_DEVICE_EXTENSION pdevext);
void			GetPCI_ID(IN PHW_STREAM_REQUEST_BLOCK pSrb);

#ifdef WINDOWS2000
void			CloseSubStream(IN PHW_STREAM_REQUEST_BLOCK pSrb);
#endif

extern void InitAudioRate(PHW_DEVICE_EXTENSION phwdev);
extern void ProcessAudioFormat( PKSDATAFORMAT pfmt, PHW_DEVICE_EXTENSION pHwDevExt );

///////////////////////////////////////////////////////////////////////////////////

/*
** 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);

	/*
	Used to Receive Data packets from YUVstreams
	*/

	#ifdef DBG
		DbgPrint("luxdvd : StreamReceiveFakeDataPacket\n");
	#endif

    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.
    #ifdef DBG
		DbgPrint("luxdvd : DriverEntry\n");
	#endif

    RtlZeroMemory(&HwInitData, sizeof(HW_INITIALIZATION_DATA));

    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);   
    HwInitData.BusMasterDMA = FALSE;
    HwInitData.Dma24BitAddresses = FALSE;
    HwInitData.BufferAlignment = 3;
    HwInitData.TurnOffSynchronization = FALSE;
    HwInitData.DmaBufferSize = 0;//DMA_BUFFER_SIZE;

	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;

    // need to find this packet, pull it off our queues, and cancel it
    // check the video queues to see if the packet is there

	#ifdef DBG
		//DbgPrint("luxdvd : AdapterCancelPacket\n");
	#endif

    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

		#ifdef DBG
			DbgPrint("luxdvd : AdapterCancelPacket - Video\n");
		#endif
        
		pdevex->VideoDeviceExt.pCurrentSRB = NULL;
		
		LUXVideoStop();
		LUXVideoAfterSeek();
    }

    // check the audio queues for the packet
    if (pdevex->AudioDeviceExt.pCurrentSRB == pSrb) 
	{
		#ifdef DBG
			DbgPrint("luxdvd : AdapterCancelPacket - Audio\n");
		#endif

        pdevex->AudioDeviceExt.pCurrentSRB = NULL;

		LUXAudioSetVolume(255);
		LUXAudioStop();
		LUXAudioAfterSeek();
    }

	
    if (pdevex->pCurSrb == pSrb) 
	{
        pdevex->pCurSrb = NULL;
    }
	
	if(pSrb->StreamObject->StreamNumber == strmCCOut)
	{
		#ifdef DBG													 
			DbgPrint("luxdvd : AdapterCancelPacket for CC\n");
		#endif

		CCDequeue();	//remove pack from CC queue

		pSrb->Status = STATUS_CANCELLED;
		pSrb->ActualBytesTransferred = 0;
		StreamClassStreamNotification(StreamRequestComplete,
						pSrb->StreamObject,
						pSrb);
		return;
	}

    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
	
    if (pdevex->VideoDeviceExt.DeviceState == KSSTATE_PAUSE ||
        pdevex->AudioDeviceExt.DeviceState == KSSTATE_PAUSE) 
	{
        // reset the timeout counter, and continue
        pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
		#ifdef DBG
			DbgPrint("luxdvd : AdapterTimeoutPacket - in PAUSE mode, just reset timeoutcounter\n");
		#endif 
        return;
    }

	#ifdef DBG
		DbgPrint("luxdvd : AdapterTimeoutPacket - clean out all device queues\n");
	#endif 

    // 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
    pSrb->StreamObject->ReceiveControlPacket = (PVOID) StreamReceiveCtrlPacket;

    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:
		{
		int i=0;

			#ifdef DBG
				DbgPrint("luxdvd : AdapterOpenStream - strmVideo\n");
			#endif

			LUXInit(0);

			// 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->pfnGetState = (PFN_WRITE_DATA) miniPortGetState;
			strm->pfnGetProp = (PFN_WRITE_DATA) miniPortGetProperty;
            strm->pfnSetProp = (PFN_WRITE_DATA) miniPortSetProperty;
			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;
						
			pdevex->vid_speed = 1000;

	        // set up the initial video format, using the DATAFORMAT specifier
		    // passed in as part of this open command
	        ProcessVideoFormat(pSrb->CommandData.OpenFormat, pdevex);

			//initialise the video rate change params
			InitVideoRate(pdevex);

			EnableIT();

			//initilaise timediscontinutiy count
			pdevex->TimeDisCount = 0;

			//initilaise vid line reached iqr count
			pdevex->dwIntCount = 0;
			pdevex->wIntCause = 0;
			pdevex->bVFlush = FALSE;
			break;
		}

		case strmAc3:
		{
			#ifdef DBG
				DbgPrint("luxdvd : AdapterOpenStream - strmAc3\n");
			#endif

			pdevex->AudioType = AUDIO_AC3;
			LUXAudioInit(pdevex->AudioType);	//ac3 by default
			
	        // 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->pfnGetState = (PFN_WRITE_DATA) miniPortAudioGetState;
			strm->pfnGetProp = (PFN_WRITE_DATA) miniPortAudioGetProperty;
			strm->pfnSetProp = (PFN_WRITE_DATA) miniPortAudioSetProperty;
			strm->pfnQueryAccept = (PFN_WRITE_DATA) AudioQueryAccept;
			pSrb->StreamObject->HwEventRoutine = (PHW_EVENT_ROUTINE) AudioEvent;
	        
			// set up some more nasty Global references
	        pdevex->pstroAud = pSrb->StreamObject;
		
			#ifdef DBG
				DbgPrint("luxdvd : AdapterOpenStream - strmAc3 calling ProcessAudioFormat\n");
			#endif
	        ProcessAudioFormat(pSrb->CommandData.OpenFormat, pdevex);
		
			// ininitalise our clock information
			fStarted = fProgrammed = FALSE;

			pdevex->bAudioFF = FALSE;
			pdevex->bAFlush = FALSE;
	        
			//initailise the rate chnage variables
			InitAudioRate(pdevex);

			EnableIT();
	        break;
		}

		case strmSubpicture:
		{
			#ifdef DBG
				DbgPrint("luxdvd : AdapterOpenStream - strmSubpicture\n");
			#endif

			LS_SP_Init();
			
	        // this is the subpicture stream
	        // set up the control functions for AdapterReceiveCtrlPacket
	        strm->pfnSetState = (PFN_WRITE_DATA) SPSetState;
			strm->pfnGetState = (PFN_WRITE_DATA) SPGetState;
		    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;
	        
			//initialise rate change
			InitSPRate(strm->spstrmex.phwdevex);

			//initialise ShowSP flag to FALSE
			pdevex->ShowSP = 0;

			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;
		}

#ifdef NTSC	
		case strmNTSCVideo:
		{
			#ifdef DBG
				DbgPrint("luxdvd : AdapterOpenStream - strmNTSCVideo\n");
			#endif
	        // 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;
		}
#endif

#ifdef VPE
		case strmYUVVideo:
		{	// this is the Video Port YUV Data stream.  This pin only supports get and set properties
			#ifdef DBG
				DbgPrint("luxdvd : AdapterOpenStream - strmYUVVideo\n");
			#endif
	        
	        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;
		}
#endif

#ifdef CCOUT
	    case strmCCOut:	// this is the close caption stream
		{
			#ifdef DBG
				DbgPrint("luxdvd : AdapterOpenStream - strmCCOut\n");
			#endif
		    
			pSrb->StreamObject->ReceiveControlPacket = (PVOID) CCReceiveCtrlPacket;
	        // set up the receive data packet entry point
			pSrb->StreamObject->ReceiveDataPacket = (PVOID) CCReceiveDataPacket;

			pdevex->pstroCC = pSrb->StreamObject;

			//init some var
			cCCRec=0, cCCDeq=0, cCCCB=0 ,cCCQ=0;
	        break;
		}
#endif

		default:
		{
			#ifdef DBG
				DbgPrint("luxdvd ERROR : AdapterOpenStream - invalid stream type !!!\n");
			#endif
			// 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))) 
	{
		#ifdef DBG
			DbgPrint("luxdvd : OpenSubPicAlloc EEROR - ExAllocatePool failed !!!\n");
		#endif
        // 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);
}

///////////////////////////////////////////////////////////////////////////////////////////
#ifdef WINDOWS2000

void CloseSubStream(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PSTREAMEX       strm = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
PHW_DEVICE_EXTENSION pdevext = ((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);

	if (strm->spstrmex.pdecctl.pData) 
	{
	#ifdef DBG
		DbgPrint("strm->spstrmex.pdecctl.pData is %x\n",strm->spstrmex.pdecctl.pData);
	#endif
		ExFreePool(strm->spstrmex.pdecctl.pData);
	}
	if (strm->spstrmex.pdecctl.pTopWork) 
	{
	#ifdef DBG
		DbgPrint("strm->spstrmex.pdecctl.pTopWork is %x\n",strm->spstrmex.pdecctl.pTopWork);
	#endif
		//ExFreePool(strm->spstrmex.pdecctl.pTopWork);
	}

	#ifdef DBG
		DbgPrint("luxdvd : AdapterCloseStream - strmSubpicture\n");
	#endif

	strm->spstrmex.pdecctl.cDecod = 0;
	strm->spstrmex.pdecctl.pData = 0;
	strm->spstrmex.pdecctl.pTopWork = 0;
    pSPstrmex = 0;

	StreamClassCallAtNewPriority(pSrb->StreamObject,
                                 pdevext,
                                 LowToHigh,
                                 (PHW_PRIORITY_ROUTINE) AdapterCB,
                                 pSrb);
}

#endif
///////////////////////////////////////////////////////////////////////////////////////////

void GetPCI_ID(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevext = ((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);
WORD wDeviceID=0;

	#ifdef DBG
		DbgPrint("luxdvd : GetPCI_ID\n");
	#endif

	StreamClassReadWriteConfig((PVOID)pdevext,
								TRUE,
								(PVOID)(&wDeviceID),
								0x2,
								sizeof(WORD));

	#ifdef DBG
		DbgPrint("luxdvd : GetPCI_ID - Device ID is 0x%x\n",wDeviceID);
	#endif

	if(wDeviceID == 0x20)
	{
		#ifdef DBG
			DbgPrint("luxdvd : Underlying Hardware is LS24x !!!!\n");
		#endif
	}
	else
	{
		#ifdef DBG
			DbgPrint("luxdvd : Underlying Hardware is LS220x !!!!\n");
		#endif
	}

	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:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_OPEN_STREAM - AdapterOpenStream\n");
			#endif
			// this command requests the minidriver to prepare structures
			// and initialize a stream instance
	        AdapterOpenStream(pSrb);
			return;

		case SRB_GET_STREAM_INFO:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_GET_STREAM_INFO - AdapterStreamInfo\n");
			#endif
			AdapterStreamInfo(pSrb);
			break;


		case SRB_INITIALIZE_DEVICE:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_INITIALIZE_DEVICE - HwInitialize\n");
			#endif
			HwInitialize(pSrb);

			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_INITIALIZE_DEVICE - perform Low priority callback\n");
			#endif

			//Do LowP callback so that we can read into PCI Config to determine which LS2xx chip
			StreamClassCallAtNewPriority(pSrb->StreamObject,
                                     pSrb->HwDeviceExtension,
                                     Low,
                                     (PHW_PRIORITY_ROUTINE) GetPCI_ID,
                                     pSrb);
	        return;

		case SRB_CLOSE_STREAM:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_CLOSE_STREAM - AdapterCloseStream\n");
			#endif

#ifdef WINDOWS2000

		    if ( pSrb->StreamObject->StreamNumber == strmSubpicture )
			{
				StreamClassCallAtNewPriority(pSrb->StreamObject,
		                                 pSrb->HwDeviceExtension,
			                             Low,
				                         (PHW_PRIORITY_ROUTINE) CloseSubStream,
					                     pSrb);
				return;
			}
			else
#endif

				AdapterCloseStream(pSrb);
	        pSrb->Status = STATUS_SUCCESS;
	        break;

		case SRB_CHANGE_POWER_STATE:

	        pSrb->Status = STATUS_SUCCESS;

			if (pSrb->CommandData.DeviceState == PowerDeviceD0) // Running
			{
				m_resume = TRUE;
				LUXInit(0);
				EnableIT();
			}
			else												// Sleeping
			{
				m_resume = FALSE;
			    DisableIT();
			}
	        break;

		case SRB_PAGING_OUT_DRIVER:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_PAGING_OUT_DRIVER\n");
			#endif

	        // 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:

			#ifdef DBG
				//DbgPrint("luxdvd : AdapterReceivePacket - SRB_GET_DATA_INTERSECTION - HwProcessDataIntersection\n");
			#endif
			HwProcessDataIntersection(pSrb);
			break;

		case SRB_UNINITIALIZE_DEVICE:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_UNINITIALIZE_DEVICE - HwUnInitialize\n");
			#endif
	        HwUnInitialize(pSrb->HwDeviceExtension);
			DisableIT();
		    pSrb->Status = STATUS_SUCCESS;
	        break;

		case SRB_OPEN_DEVICE_INSTANCE:
			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_OPEN_DEVICE_INSTANCE\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
	        break;

		case SRB_CLOSE_DEVICE_INSTANCE:
			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_CLOSE_DEVICE_INSTANCE\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
	        break;

		case SRB_GET_DEVICE_PROPERTY:
			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_GET_DEVICE_PROPERTY\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
	        break;

		case SRB_SET_DEVICE_PROPERTY:
			#ifdef DBG
				DbgPrint("luxdvd : AdapterReceivePacket - SRB_SET_DEVICE_PROPERTY\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
	        break;

		default:

			#ifdef DBG
				DbgPrint("luxdvd ERROR : AdapterReceivePacket received invalid SRB !!!\n");
			#endif
			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
	#ifdef DBG
		DbgPrint("luxdvd : AdapterStreamInfo - MPEG2 Video\n");
	#endif

    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 = 2;	//number of formats supported
	pstrinfo->StreamFormatsArray = Mpeg2VidInfo;

	pstrinfo->Category = &g_PINNAME_DVD_VIDEOIN;
    pstrinfo->Name = &g_PINNAME_DVD_VIDEOIN;

	//number of property SETS that are supported (each set may have more than one property supported within it
	pstrinfo->NumStreamPropArrayEntries = 4;
    pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) mpegVidPropSet;
    pstrinfo++;

	// set up the stream info structures for the MPEG2 audio
	#ifdef DBG
		DbgPrint("luxdvd : AdapterStreamInfo - MPEG2 Audio\n");
	#endif

    pstrinfo->NumberOfPossibleInstances = 1;
    pstrinfo->DataFlow = KSPIN_DATAFLOW_IN;
    pstrinfo->DataAccessible = TRUE;
	
	pstrinfo->NumberOfFormatArrayEntries = 3;
	
	#ifdef ORIG
		pstrinfo->StreamFormatsArray = AC3AudioInfo;
	#else
		/*
		Initialize the audio formats now.  For each format (there are currently 2),
		take the array of sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) bytes
		allocated for it and paste the KSDATAFORMAT and WAVEFORMATEX structs
		into it.  Cannot just declare a struct that contains the two because
		due to alignment its size would exceed the total of the components,
		and apparently KS assumes that the size of the format block (in this
		case WAVEFORMATEX) is the size of the format minus sizeof(KSDATAFORMAT).
		*/
		RtlCopyMemory (hwfmtiLPCMAud, &LPCMksdataformat, sizeof (KSDATAFORMAT));
		RtlCopyMemory (hwfmtiLPCMAud + sizeof(KSDATAFORMAT), &LPCMwaveformatex, sizeof(WAVEFORMATEX));
		RtlCopyMemory (hwfmtiMpeg2Aud, &Mpeg2ksdataformat, sizeof (KSDATAFORMAT));
		RtlCopyMemory (hwfmtiMpeg2Aud + sizeof(KSDATAFORMAT), &Mpeg2waveformatex, sizeof(WAVEFORMATEX));

		RtlCopyMemory (hwfmtiMpeg2AudPES, &Mpeg2PESksdataformat, sizeof (KSDATAFORMAT));
		RtlCopyMemory (hwfmtiMpeg2AudPES + sizeof(KSDATAFORMAT), &Mpeg2waveformatex, sizeof(WAVEFORMATEX));
			
		pstrinfo->StreamFormatsArray = Mpeg2AudInfo;
	#endif

	pstrinfo->Category = &g_PINNAME_DVD_AUDIOIN;
    pstrinfo->Name = &g_PINNAME_DVD_AUDIOIN;

	pstrinfo->NumStreamPropArrayEntries = 4;
    pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) audPropSet;
	pstrinfo->StreamEventsArray = ClockEventSet;
	pstrinfo->NumStreamEventArrayEntries = SIZEOF_ARRAY(ClockEventSet);
    pstrinfo++;

#ifdef NTSC
	// set up the stream info structures for the MPEG2 NTSC stream
	#ifdef DBG
		DbgPrint("luxdvd : AdapterStreamInfo - MPEG2 NTSC\n");
	#endif

    pstrinfo->NumberOfPossibleInstances = 1;
    pstrinfo->DataFlow = KSPIN_DATAFLOW_OUT;
    pstrinfo->DataAccessible = FALSE;
    pstrinfo->NumberOfFormatArrayEntries = 1;
    pstrinfo->StreamFormatsArray = NtscInfo;

	pstrinfo->Category = &g_PINNAME_DVD_NTSCOUT;
    pstrinfo->Name = &g_PINNAME_DVD_NTSCOUT;
    
	pstrinfo->NumStreamPropArrayEntries = 0;
    pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) NTSCPropSet;
    pstrinfo++;
#endif

	// set up the stream info structures for the MPEG2 subpicture
	#ifdef DBG
		DbgPrint("luxdvd : AdapterStreamInfo - MPEG2 SubPicture\n");
	#endif
    
    pstrinfo->NumberOfPossibleInstances = 1;
    pstrinfo->DataFlow = KSPIN_DATAFLOW_IN;
    pstrinfo->DataAccessible = TRUE;
    pstrinfo->NumberOfFormatArrayEntries = 1;
    pstrinfo->StreamFormatsArray = SubPicInfo;

	pstrinfo->Category = &g_PINNAME_DVD_SUBPICIN;
    pstrinfo->Name = &g_PINNAME_DVD_SUBPICIN;

    pstrinfo->NumStreamPropArrayEntries = 3;
    pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) SPPropSet;

#ifdef VPE
    pstrinfo++;

	// set up the stream info structures for the Video Port
	#ifdef DBG
		DbgPrint("luxdvd : AdapterStreamInfo - VideoPort\n");
	#endif

    pstrinfo->NumberOfPossibleInstances = 1;
    pstrinfo->DataFlow = KSPIN_DATAFLOW_OUT;
    pstrinfo->DataAccessible = FALSE;
    pstrinfo->NumberOfFormatArrayEntries = 1;
    pstrinfo->StreamFormatsArray = VPInfo;

	pstrinfo->Category = &g_PINNAME_DVD_VPEOUT;
    pstrinfo->Name = &g_PINNAME_DVD_VPEOUT;

    pstrinfo->NumStreamPropArrayEntries = 1;
    pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) VideoPortPropSet;
	pstrinfo->MediumsCount = 1;
	pstrinfo->Mediums = &VPMedium;
	pstrinfo->StreamEventsArray = VPEventSet;
	pstrinfo->NumStreamEventArrayEntries = SIZEOF_ARRAY(VPEventSet);
#endif

#ifdef CCOUT
    pstrinfo++;


	// set up the stream info structures for the Close Caption stream
	#ifdef DBG
		DbgPrint("luxdvd : AdapterStreamInfo - Closed Caption\n");
	#endif

    pstrinfo->NumberOfPossibleInstances = 1;
    pstrinfo->DataFlow = KSPIN_DATAFLOW_OUT;
    pstrinfo->DataAccessible = TRUE;
    pstrinfo->NumberOfFormatArrayEntries = 1;
    pstrinfo->StreamFormatsArray = CCInfo;

	pstrinfo->Category = &g_PINNAME_DVD_CCOUT;
    pstrinfo->Name = &g_PINNAME_DVD_CCOUT;

    pstrinfo->NumStreamPropArrayEntries = 1;
    pstrinfo->StreamPropertiesArray = (PKSPROPERTY_SET) CCPropSet;
#endif

    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);
	    
    switch (pSrb->Command) // determine the type of packet.
	{
		case SRB_WRITE_DATA:

	        // This is a write data function.  Call the appropriate handler
		    // if it exists, otherwise fall through
			
			if( (pdevext->AudioDeviceExt.DeviceState == KSSTATE_STOP) ||
				(pdevext->VideoDeviceExt.DeviceState == KSSTATE_STOP) )
			{
				#ifdef DBG
					DbgPrint("luxdvd : StreamReceiveDataPacket - Vid/Aud Strm already Stopped, do not process more packs\n");
				#endif

				pSrb->Status = STATUS_SUCCESS;
				StreamClassStreamNotification(ReadyForNextStreamDataRequest,pSrb->StreamObject);
				StreamClassStreamNotification(StreamRequestComplete,pSrb->StreamObject,pSrb);
				return;
			}

	        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
			#ifdef DBG
				DbgPrint("luxdvd : StreamReceiveDataPacket - invalid cmd !!!\n");
	        #endif

			if(pSrb->Command == SRB_READ_DATA)
			{
				#ifdef DBG
					DbgPrint("luxdvd : StreamReceiveDataPacket - SRB_READ_DATA unsupported !!!\n");
				#endif
			}
				
	        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:
*/
extern void	resetSub(void);

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_STATE:

			// change the stream state (i.e.  play or pause)
			if (((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)->pfnGetState) 
			{
				((PSTREAMEX) pSrb->StreamObject->HwStreamExtension)->pfnGetState(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
			#ifdef DBG
				DbgPrint("luxdvd  : StreamReceiveCtrlPacket - SRB_SET_STREAM_RATE\n");
			#endif
            VidRate = 1000;     /* set the rate from the packet here */
		    break;
		/* end video rate stuff */


		case SRB_PROPOSE_STREAM_RATE:
			#ifdef DBG
				DbgPrint("luxdvd  : StreamReceiveCtrlPacket - SRB_PROPOSE_STREAM_RATE\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;

		case SRB_UNKNOWN_STREAM_COMMAND:
			#ifdef DBG
				DbgPrint("luxdvd  : StreamReceiveCtrlPacket - SRB_UNKNOWN_STREAM_COMMAND\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;

		case SRB_BEGIN_FLUSH:
			#ifdef DBG
				//DbgPrint("luxdvd  : StreamReceiveCtrlPacket - SRB_BEGIN_FLUSH\n");
			#endif
		
			if(pSrb->StreamObject->StreamNumber == strmVideo)
			{
				#ifdef DBG
					DbgPrint("luxdvd : SRB_BEGIN_FLUSH for Video\n");
				#endif

				pdevext->bVFlush = TRUE;

				LUXVideoStop();
				LUXAudioStop();
				LUXVideoAfterSeek();
				LUXAudioAfterSeek();

				resetSub();
			}
			else if(pSrb->StreamObject->StreamNumber == strmAc3)
			{
				#ifdef DBG
					DbgPrint("luxdvd : SRB_BEGIN_FLUSH for Audio\n");
				#endif

				pdevext->bAFlush = TRUE;
			}
		
			break;

		case SRB_END_FLUSH:
			#ifdef DBG
				//DbgPrint("luxdvd  : StreamReceiveCtrlPacket - SRB_END_FLUSH\n");
			#endif
		
			if(pSrb->StreamObject->StreamNumber == strmVideo)
			{
				#ifdef DBG
					DbgPrint("luxdvd : SRB_END_FLUSH for Video\n");
				#endif
				
				LUXVideoPlay(1000);
				LUXAudioPlay(1000);

				pdevext->bVFlush = FALSE;
			}
			else if(pSrb->StreamObject->StreamNumber == strmAc3)
			{
				#ifdef DBG
					DbgPrint("luxdvd : SRB_END_FLUSH for Audio\n");
				#endif

				pdevext->bAFlush = FALSE;
			}
			break;

		default:

			#ifdef DBG
				DbgPrint("luxdvd ERROR : StreamReceiveCtrlPacket received invalid SRB !!!!\n");
			#endif
	        // 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)
{
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
    //
	if(!pSrb)
    {
		#ifdef DBG
			DbgPrint("luxdvd ERROR : AdapterCloseStream - invalid SRB !!!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

    pSrb->Status = STATUS_SUCCESS;

    switch (pSrb->StreamObject->StreamNumber) 
	{
		case strmVideo:
			
			#ifdef DBG
				DbgPrint("luxdvd : AdapterCloseStream - strmVideo\n");
			#endif

			LUXVideoCleanScreen();

			#ifdef LS240
				LUXVideoZVEnableTriState();
			#endif

			pdevex->pstroVid = NULL;
			break;

		case strmAc3:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterCloseStream - strmAc3\n");
			#endif
			pdevex->pstroAud = NULL;

			#ifdef LS240
				LUXAudioPCMEnableTriState();
			#endif

			break;

		case strmSubpicture:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterCloseStream - strmSubpicture\n");
			#endif

	        // 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;

#ifdef VPE
		case strmYUVVideo:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterCloseStream - strmYUVVideo\n");
			#endif
			pdevex->pstroYUV = NULL;
			break;
#endif

#ifdef CCOUT
		case strmCCOut:

			#ifdef DBG
				DbgPrint("luxdvd : AdapterCloseStream - strmCCOut\n");
			#endif
			CleanCCQueue();
			pdevex->pstroCC = NULL;
			break;
#endif

    }

}

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;

	#ifdef DBG
		DbgPrint("luxdvd : HwInitialize\n");
	#endif

	if(!pSrb)
    {
		#ifdef DBG
			DbgPrint("luxdvd ERROR : HwInitialize - invalid SRB !!!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return FALSE;
	}
	 	
	RtlZeroMemory(pHwDevExt, sizeof (PHW_DEVICE_EXTENSION));
    // this board requires at least one memory access range
    if (ConfigInfo->NumberOfAccessRanges < 1) 
	{
		#ifdef DBG
			DbgPrint("luxdvd ERROR : HwInitialize - illegal config info !!!\n");
		#endif 
        pSrb->Status = STATUS_NO_SUCH_DEVICE;
        return (FALSE);
    }
    // the first access range according to this boards inf will be the
    // main PIO address base
    pHwDevExt->ioBaseLocal = (PUSHORT) (ConfigInfo->AccessRanges[0].RangeStart.LowPart);
    // pick up the irq level
    pHwDevExt->Irq = (USHORT) (ConfigInfo->BusInterruptLevel);

	#ifdef DBG
		DbgPrint("luxdvd : # access ranges = 0x%lx\n",ConfigInfo->NumberOfAccessRanges);
		DbgPrint("luxdvd : memory addr length = 0x%lx\n",ConfigInfo->AccessRanges[0].RangeLength);
		DbgPrint("luxdvd : memory addr = 0x%lx\n",pHwDevExt->ioBaseLocal);
		DbgPrint("luxdvd : IRQ = 0x%x\n",pHwDevExt->Irq);
		DbgPrint("luxdvd : ConfigInfo->BusInterruptLevel=0x%lx, ConfigInfo->BusInterruptVector=0x%lx\n",ConfigInfo->BusInterruptLevel,ConfigInfo->BusInterruptVector);
	#endif

    // 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;

	#ifdef DBG
		DbgPrint("luxdvd : HwInitialize - LUXInit()\n");
	#endif

	LUXInit((ULONG)(pHwDevExt->ioBaseLocal));
	
	#ifdef LS240
		LUXVideoZVEnableTriState();
		LUXAudioPCMEnableTriState();
	#endif

	#ifdef MAPPER
		#ifdef DBG
			DbgPrint("luxdvd : HwInitialise - calling LuxGetPhysAddr()\n");
		#endif
		LuxGetPhysAddr(pHwDevExt);
	#endif


	pSrb->Status = STATUS_SUCCESS;
	pDevEx = pHwDevExt;
		
    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)
{
	#ifdef DBG
		DbgPrint("luxdvd : HwUnInitialize\n");
	#endif

	//turn off clock to vga
	LUXVideoSetVPM(0,0);
	DisableIT();
    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)
{
DWORD dwreg14,dwreg20;
PHW_DEVICE_EXTENSION pdevext = (PHW_DEVICE_EXTENSION) pDeviceExtension;
DWORD dwaddr;

	if (!bInitialized)
        return FALSE;

	dwreg20 = DVReadReg(0x20);	//read interrupt status reg
	if(!dwreg20)
		return FALSE;

	dwreg14 = DVReadReg(0x14);	//read interrupt status reg

	if(!(dwreg14&0x104))
		return FALSE;	//let someone else process this irq

	DVWriteREG(0x20, (dwreg20 & 0xfffffefb));//prevent nested int

	if( (dwreg14 & 0x4)  )
	{
		UserDataEvents(pdevext);
	} 
	else if( (dwreg14 & 0x100)  )	//if Vid line reached 
	{
		if( pdevext->dwIntCount++ >= 40 )
		{
			pdevext->dwIntCount=0;
			pdevext->wIntCause = 0x100;

			//schedule a callback at Dispatch IRQL
			StreamClassCallAtNewPriority(NULL,
						pdevext,
						Dispatch,
						LuxDSPDispatchCallBack,
						pdevext);
		}
		
	}

	DVWriteREG(0x18,(DVReadReg(0x18) | 0x104));	//clear 
	DVWriteREG(0x20, (dwreg20 | 0x104));	//re-enable vid line reached interrupt

	if ( m_alwaysF )
		return FALSE;
	else
		return TRUE;			//we processed this irq
}

///////////////////////////////////////////////////////////////////////////////////////////

void LuxDSPDispatchCallBack(PHW_DEVICE_EXTENSION pdevext)
{

	switch(pdevext->wIntCause)
	{
	case 0x100:
		ClockEvents(pdevext);
		break;
	}

}

///////////////////////////////////////////////////////////////////////////////////////////

/*
** DisableIT ()
**
**    disable board interrupts
**
** Arguments:
**
** Returns:
**
** Side Effects:
*/

VOID DisableIT(VOID)
{
	#ifdef DBG
		//DbgPrint("luxdvd : DisableIT\n");
	#endif

	DVWriteREG(0x20,0x0);	//vid line reached interrupt
}

///////////////////////////////////////////////////////////////////////////////////////////

/*
** EnableIT ()
**
**   enable board interrupts
**
** Arguments:
**
** Returns:
**
** Side Effects:
*/

VOID EnableIT(VOID)
{
	#ifdef DBG
		//DbgPrint("luxdvd : EnableIT\n");
	#endif

	#ifdef LINE21
		DVWriteREG(0x20,0x104);	//vid line reached interrupt and dsp irq
	#else
		DVWriteREG(0x20,0x100);	//vid line reached interrupt and dsp irq
	#endif
}

///////////////////////////////////////////////////////////////////////////////////////////

/*
** HostDisableIT ()
**
**   null routine at the moment
**
** Arguments:
**
** Returns:
**
** Side Effects:
*/

VOID HostDisableIT(VOID)
{
}

///////////////////////////////////////////////////////////////////////////////////////////

/*
** HostEnableIT ()
**
**  equally null routine
**
** Arguments:
**
** Returns:
**
** Side Effects:
*/

VOID HostEnableIT(VOID)
{
}

///////////////////////////////////////////////////////////////////////////////////////////

#ifdef NTSC
/*
** 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)
    {
		#ifdef DBG
			DbgPrint("luxdvd ERROR : NTSCSetProp invalid SRB !!!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

    if (pSrb->CommandData.PropertyInfo->PropertySetID) 
	{
		#ifdef DBG
			DbgPrint("luxdvd ERROR : NTSCSetProp received invalid property !!!");
		#endif
        // invalid property
	    pSrb->Status = STATUS_NOT_IMPLEMENTED;
        return;
    }

	switch(pSrb->CommandData.PropertyInfo->Property->Id)
	{
		case KSPROPERTY_COPY_MACROVISION:

			#ifdef DBG
				DbgPrint("luxdvd : NTSCSetProp - KSPROPERTY_COPY_MACROVISION\n");
			#endif 
			// pick up the macrovision level, and set the level accordingly
			//
			// SetMacroVisionLevel(
			//			pSrb->CommandData.PropertyInfo->PropertyInfo);

			pSrb->Status = STATUS_SUCCESS;
			break;

		default:

			#ifdef DBG
				DbgPrint("luxdvd ERROR : NTSCSetProp - received unknown ID !!!\n");
			#endif 
			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)
    {
		#ifdef DBG
			DbgPrint("luxdvd ERROR : NTSCGetProp invalid SRB !!!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

	#ifdef DBG
		DbgPrint("luxdvd : NTSCGetProp\n");
	#endif

    if (pSrb->CommandData.PropertyInfo->PropertySetID) 
	{
		#ifdef DBG
			DbgPrint("luxdvd ERROR : NTSCSetProp received invalid property !!!");
		#endif
        // invalid property
        pSrb->Status = STATUS_NOT_IMPLEMENTED;
        return;
    }

	pSrb->Status = STATUS_NOT_IMPLEMENTED;
}

#endif //NTSC
///////////////////////////////////////////////////////////////////////////////////////////

/*
** 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;

	if(!pSrb)
    {
		#ifdef DBG
			DbgPrint("luxdvd ERROR : CCGetProp invalid SRB !!!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

	pSrb->Status = STATUS_SUCCESS;//STATUS_NOT_IMPLEMENTED;

    if (pSrb->CommandData.PropertyInfo->PropertySetID) 
	{
		#ifdef DBG
			DbgPrint("luxdvd ERROR : CCGetProp returning NO MATCH !!!\n");
		#endif
        // invalid property
		pSrb->Status = STATUS_NO_MATCH;
        return;
    }


	switch(pSrb->CommandData.PropertyInfo->Property->Id)
	{
		case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
		{
			//This read-only property is used to retrieve any allocator framing requirements
			#ifdef DBG
				DbgPrint("luxdvd : CCGetProp - KSPROPERTY_CONNECTION_ALLOCATORFRAMING\n");
			#endif

			pfrm->OptionsFlags = 0;
			pfrm->PoolType = NonPagedPool;
			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:

			#ifdef DBG
				DbgPrint("luxdvd : CCGetProp - KSPROPERTY_CONNECTION_STATE\n");
			#endif

			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;
			}
			pSrb->Status = STATUS_SUCCESS;
			break;

		default:

			TRAP
			#ifdef DBG
				DbgPrint("luxdvd : CCGetProp Error - invalid cmd !!!\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////

/*
** 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;
ULONG index;
#ifdef LS240
	int index_offset=1;	//We have an extra 16bit Video Port which is enum first, so everything shifts down one
#else
	int index_offset=0;
#endif

	if(!pSrb)
    {
		#ifdef DBG
			DbgPrint("luxdvd ERROR : VPESetProp invalid SRB !!!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

	if( pSrb->CommandData.PropertyInfo->PropertySetID ) 
	{
		TRAP;
		pSrb->Status = STATUS_NO_MATCH;
		return;
	}
	
	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:

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_SETCONNECTINFO\n");
			#endif
				
			index = *((ULONG *)(pSrb->CommandData.PropertyInfo->PropertyInfo));

		#ifdef LS240
			if(index == 0)	//HREFH_VREFL 16bit Video Port
			{
				#ifdef DBG
					DbgPrint("luxdvd : KSPROPERTY_VPCONFIG_SETCONNECTINFO index is 0 = HREFH_VREFL 16bit VideoPort\n");
				#endif
				pdevex->VideoPort = HH_VL_16_VGA;
				LUXVideoSetVPM(1,HH_VL_16_VGA);
				break;
			}
		#endif

			if(index == (ULONG)(0 + index_offset))	//HREFL_VREFL
			{
				#ifdef DBG
					DbgPrint("luxdvd : KSPROPERTY_VPCONFIG_SETCONNECTINFO index  = S3 (HREFL_VREFL)\n");
				#endif
				pdevex->VideoPort = S3_VGA;	// S3 LPB
				LUXVideoSetVPM(1,S3_VGA);
			}
			else if( index == (ULONG)(1 + index_offset))	//HREFH_VREFH
			{
				#ifdef DBG
					DbgPrint("luxdvd : KSPROPERTY_VPCONFIG_SETCONNECTINFO index =  HREFH_VREFH)\n");
				#endif
				pdevex->VideoPort = HH_VH_VGA;
				LUXVideoSetVPM(1,HH_VH_VGA);
			}
			else if(index == (ULONG)(2 + index_offset))	//HREFL_VREFH
			{
				#ifdef DBG	  
					DbgPrint("luxdvd : KSPROPERTY_VPCONFIG_SETCONNECTINFO index = VMI (HREFL_VREFH)\n");
				#endif
				pdevex->VideoPort = VMI_VGA;	//VMI Video Port
				LUXVideoSetVPM(1,VMI_VGA);
			}
			else if(index == (ULONG)(3 + index_offset))	//HREFH_VREFL
			{
				#ifdef DBG
					DbgPrint("luxdvd : KSPROPERTY_VPCONFIG_SETCONNECTINFO index = HREFH_VREFL)\n");
				#endif
				pdevex->VideoPort = HH_VL_VGA;
				LUXVideoSetVPM(1,HH_VL_VGA);
			}
			else if(index == (ULONG)(4 + index_offset))	//We enum CCIR656 first so this will be first index
			{	
				#ifdef DBG
					DbgPrint("luxdvd : KSPROPERTY_VPCONFIG_SETCONNECTINFO index = ATI/NVIDIA/CIRRUS\n");
				#endif
				pdevex->VideoPort = CCIR656_VGA;
				LUXVideoSetVPM(1,CCIR656_VGA);
			}
			break;

		case KSPROPERTY_VPCONFIG_DDRAWHANDLE:

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_DDRAWHANDLE\n");
			#endif
			pdevex->ddrawHandle = (*(PULONG)pSrb->CommandData.PropertyInfo->PropertyInfo);
			break;
		

		case KSPROPERTY_VPCONFIG_VIDEOPORTID:

			pdevex->VidPortID = (*(PULONG)pSrb->CommandData.PropertyInfo->PropertyInfo);
			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_VIDEOPORTID is 0x%lx\n",(DWORD)(pdevex->VidPortID));
			#endif
			break;

		case KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE:

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE\n");
			#endif
			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
			index = *((ULONG *)(pSrb->CommandData.PropertyInfo->PropertyInfo));

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_SETVIDEOFORMAT with index = %d\n",index);
			#endif
			break;

	
		case KSPROPERTY_VPCONFIG_INFORMVPINPUT:

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_INFORMVPINPUT\n");
			#endif
			// 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:

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_INVERTPOLARITY\n");
			#endif
			// 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:

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - KSPROPERTY_VPCONFIG_SCALEFACTOR\n");
			#endif
			// 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.

			pDim =(PKS_AMVPSIZE)(pSrb->CommandData.PropertyInfo->PropertyInfo);

			if (pDim->dwWidth != VPFmt.amvpDimInfo.dwFieldWidth - 63)
			{
				#ifdef DBG
					DbgPrint("KSPROPERTY_VPCONFIG_SCALEFACTOR : pDim->dwWidth(0x%lx) != VPFmt.amvpDimInfo.dwFieldWidth-63(0x%lx)\n",
						pDim->dwWidth,VPFmt.amvpDimInfo.dwFieldWidth - 63);
				#endif
			}
			else
			{
			}
			break;

		default:

			#ifdef DBG
				DbgPrint("luxdvd : VPESetProp - unrecognized command !!!\n");
			#endif
			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)
{
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
DWORD dwInputBufferSize;
DWORD dwOutputBufferSize;

#ifdef LS240
	DWORD dwNumConnectInfo = 6;	//5 + one 16bit Vport connection type
#else
	DWORD dwNumConnectInfo = 5;	
#endif

DWORD dwNumVideoFormat = 1;
DWORD dwFieldWidth = 720;
DWORD dwFieldHeight = 240;

ULONG lc;
// the pointers to which the input buffer will be cast to
LPDDVIDEOPORTCONNECT pConnectInfo;
LPDDPIXELFORMAT pVideoFormat;
PKSVPMAXPIXELRATE pMaxPixelRate;
PKS_AMVPDATAINFO pVpdata;
PKSMULTIPLE_ITEM  pmulitem = &(((PKSMULTIPLE_DATA_PROP)pSrb->CommandData.PropertyInfo->Property)->MultipleItem);
PKS_AMVPSIZE pdim = &(((PKSVPSIZE_PROP)pSrb->CommandData.PropertyInfo->Property)->Size);

	if(!pSrb)
    {
		#ifdef DBG
			DbgPrint("luxdvd ERROR : VPEGetProp invalid SRB !!!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

	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:

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_NUMCONNECTINFO - return %d\n",dwNumConnectInfo);
			#endif
			pSrb->ActualBytesTransferred = sizeof(DWORD);	// specify the number of bytes written
			*(PULONG) pSrb->CommandData.PropertyInfo->PropertyInfo = dwNumConnectInfo;
			break;

		case KSPROPERTY_VPCONFIG_NUMVIDEOFORMAT:

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_NUMVIDEOFORMAT - return %d\n",dwNumVideoFormat);
			#endif
			pSrb->ActualBytesTransferred = sizeof(DWORD);	// specify the number of bytes written
			*(PULONG) pSrb->CommandData.PropertyInfo->PropertyInfo = dwNumVideoFormat;
			break;
		
		case KSPROPERTY_VPCONFIG_GETCONNECTINFO:	//Retrieves all possible video port configurations

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_GETCONNECTINFO\n");
				DbgPrint("luxdvd : pmulitem->Count = %d\n",pmulitem->Count);
			#endif
			// check that the size of the output buffer is correct
			if (pmulitem->Count > dwNumConnectInfo ||
				pmulitem->Size != sizeof (DDVIDEOPORTCONNECT) ||
				dwOutputBufferSize < (pmulitem->Count * sizeof (DDVIDEOPORTCONNECT)))
			{
				#ifdef DBG
					DbgPrint("luxdvd ERROR: VPEGetProp KSPROPERTY_VPCONFIG_GETCONNECTINFO error !!!\n");
					DEBUG_BREAKPOINT();
				#endif
				// 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);

			pConnectInfo = (LPDDVIDEOPORTCONNECT)(pSrb->CommandData.PropertyInfo->PropertyInfo);

		#ifdef LS240
			//HREFH_VREFL 16bit Video Port
			pConnectInfo->dwSize = sizeof (DDVIDEOPORTCONNECT);
			pConnectInfo->dwPortWidth = 16;	//!!!!! ZV-PORT !!!!!!
			pConnectInfo->guidTypeID = g_HREFH_VREFLGuid;
			pConnectInfo->dwFlags = DDVPCONNECT_INTERLACED|DDVPCONNECT_HALFLINE;
			pConnectInfo->dwReserved1 = 0;			
			pConnectInfo++;
		#endif
			//The rest are 8bit Video Port connections

			// S3 LPB HREFL_VREFL
			pConnectInfo->dwSize = sizeof (DDVIDEOPORTCONNECT);
			pConnectInfo->dwPortWidth = 8;
			pConnectInfo->guidTypeID = g_HREFL_VREFLGuid;
			pConnectInfo->dwFlags = DDVPCONNECT_INTERLACED|DDVPCONNECT_HALFLINE|DDVPCONNECT_VACT;
			pConnectInfo->dwReserved1 = 0;			
			pConnectInfo++;

			//HREFH_VREFH
			pConnectInfo->dwSize = sizeof (DDVIDEOPORTCONNECT);
			pConnectInfo->dwPortWidth = 8;
			pConnectInfo->guidTypeID = g_HREFH_VREFHGuid;
			pConnectInfo->dwFlags = DDVPCONNECT_INTERLACED|DDVPCONNECT_HALFLINE|DDVPCONNECT_VACT;
			pConnectInfo->dwReserved1 = 0;			
			pConnectInfo++;

			// VMI HREFL_VREFH
			pConnectInfo->dwSize = sizeof (DDVIDEOPORTCONNECT);
			pConnectInfo->dwPortWidth = 8;
			pConnectInfo->guidTypeID = g_VMIGuid;
			pConnectInfo->dwFlags = DDVPCONNECT_INTERLACED|DDVPCONNECT_HALFLINE|DDVPCONNECT_VACT;
			pConnectInfo->dwReserved1 = 0;			
			pConnectInfo++;

			//HREFH_VREFL
			pConnectInfo->dwSize = sizeof (DDVIDEOPORTCONNECT);
			pConnectInfo->dwPortWidth = 8;
			pConnectInfo->guidTypeID = g_HREFH_VREFLGuid;
			pConnectInfo->dwFlags = DDVPCONNECT_INTERLACED|DDVPCONNECT_HALFLINE|DDVPCONNECT_VACT;
			pConnectInfo->dwReserved1 = 0;			
			pConnectInfo++;
						
									
			// ATI or NVIDIA or Cirrus(they share same connection type)
			pConnectInfo->dwSize = sizeof (DDVIDEOPORTCONNECT);
			pConnectInfo->dwPortWidth = 8;
			pConnectInfo->guidTypeID = g_CCIR656Guid;
			pConnectInfo->dwFlags = DDVPCONNECT_INTERLACED|DDVPCONNECT_HALFLINE;
			pConnectInfo->dwReserved1 = 0;
			break;

		case KSPROPERTY_VPCONFIG_VPDATAINFO:	//Determines the initial state of the video port configuration

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_VPDATAINFO\n");
			#endif
			pSrb->ActualBytesTransferred = sizeof(KS_AMVPDATAINFO);
			pVpdata = (PKS_AMVPDATAINFO)pSrb->CommandData.PropertyInfo->PropertyInfo;
			
			*pVpdata = VPFmt;	// set up the current region				
			pVpdata->dwSize = sizeof (KS_AMVPDATAINFO);
			pVpdata->dwMicrosecondsPerField	= 16666;
			pVpdata->dwNumLinesInVREF		= 1;

			if(pHwDevExt->VideoPort == HH_VL_16_VGA ) //HREFH_VREFL 16bit Vport
			{		
			
				#ifdef DBG
					DbgPrint("luxdvd : Get VPCONFIG_VPDATAINFO for HREFH_VREFL 16bit Vport\n");
				#endif
				
				pVpdata->bEnableDoubleClock		= FALSE;
				pVpdata->bEnableVACT			= FALSE;
				pVpdata->bDataIsInterlaced		= TRUE;
				pVpdata->lHalfLinesOdd  		= 0;
				pVpdata->lHalfLinesEven  		= 1;
				pVpdata->bFieldPolarityInverted	= FALSE;
								
				pVpdata->amvpDimInfo.dwFieldWidth	= 720;
				
				if ( v_m_VideoSrc_NTSC )
					pVpdata->amvpDimInfo.dwFieldHeight	= 240;
				else
					pVpdata->amvpDimInfo.dwFieldHeight	= 288;
				
				pVpdata->amvpDimInfo.rcValidRegion.left		= 8;
				pVpdata->amvpDimInfo.rcValidRegion.top		= 20;
				pVpdata->amvpDimInfo.rcValidRegion.right	= 712;
			
				if ( v_m_VideoSrc_NTSC )
					pVpdata->amvpDimInfo.rcValidRegion.bottom	= 256;
				else
					pVpdata->amvpDimInfo.rcValidRegion.bottom	= 288;
				
				pVpdata->amvpDimInfo.dwVBIWidth     = 720;
				pVpdata->amvpDimInfo.dwVBIHeight    = (21 + 1 - 1 - 1);
			}
			else if( pHwDevExt->VideoPort == S3_VGA ) //HREFL_VREFL
			{
				#ifdef DBG
					DbgPrint("luxdvd : Get VPCONFIG_VPDATAINFO for HREFL_VREFL\n");
				#endif
				// S3 LPB
				pVpdata->bEnableDoubleClock		= FALSE;
				pVpdata->bEnableVACT			= TRUE;
				pVpdata->bDataIsInterlaced		= TRUE;
				pVpdata->lHalfLinesOdd  		= 1;
				pVpdata->lHalfLinesEven  		= 0;
				pVpdata->bFieldPolarityInverted	= FALSE;

				pVpdata->amvpDimInfo.dwFieldWidth	= 720;
				pVpdata->amvpDimInfo.dwFieldHeight	= 235;

				pVpdata->amvpDimInfo.rcValidRegion.left		= 36;
				pVpdata->amvpDimInfo.rcValidRegion.top		= 21;
				pVpdata->amvpDimInfo.rcValidRegion.right	= 720 + 36;
				pVpdata->amvpDimInfo.rcValidRegion.bottom	= 256;

				pVpdata->amvpDimInfo.dwVBIWidth     = 720;
				pVpdata->amvpDimInfo.dwVBIHeight    = (21 + 1 - 1 - 1);
			}
			else if( pHwDevExt->VideoPort == CCIR656_VGA ) //CCIR656
			{
			
				#ifdef DBG
					DbgPrint("luxdvd : Get VPCONFIG_VPDATAINFO for CCIR656\n");
				#endif
				
				pVpdata->bEnableDoubleClock		= FALSE;
				pVpdata->bEnableVACT			= FALSE;
				pVpdata->bDataIsInterlaced		= TRUE;
				pVpdata->lHalfLinesOdd  		= 0;
				pVpdata->lHalfLinesEven  		= 1;
				pVpdata->bFieldPolarityInverted	= FALSE;
			
				pVpdata->amvpDimInfo.dwFieldWidth	= 720;
	
				if ( v_m_VideoSrc_NTSC )
					pVpdata->amvpDimInfo.dwFieldHeight	= 238;//240;
				else
					pVpdata->amvpDimInfo.dwFieldHeight	= 288;//240;

#ifdef ati_only
				pVpdata->amvpDimInfo.rcValidRegion.left		= 8;
				pVpdata->amvpDimInfo.rcValidRegion.top		= 16;
				pVpdata->amvpDimInfo.rcValidRegion.right	= 712;
				pVpdata->amvpDimInfo.rcValidRegion.bottom	= 238+16;//256;
				if ( v_m_VideoSrc_NTSC )
					pVpdata->amvpDimInfo.rcValidRegion.bottom	= 238+16;//256;
				else
					pVpdata->amvpDimInfo.rcValidRegion.bottom	= 298;
#else
				pVpdata->amvpDimInfo.rcValidRegion.left		= 0;
				pVpdata->amvpDimInfo.rcValidRegion.top		= 16;
				pVpdata->amvpDimInfo.rcValidRegion.right	= 720;

				if ( v_m_VideoSrc_NTSC )
					pVpdata->amvpDimInfo.rcValidRegion.bottom	= 238+16;//256;
				else
					pVpdata->amvpDimInfo.rcValidRegion.bottom	= 288+16;
#endif
				pVpdata->amvpDimInfo.dwVBIWidth     = 720;
				//VBIHeight = 21 + halfline_adjustment - 1 - #lines_in_VREF_period
				pVpdata->amvpDimInfo.dwVBIHeight    = (21 + 1 - 1 - 1);
			
			}
			else if(pHwDevExt->VideoPort == VMI_VGA ) //HREFL_VREFH
			{
				#ifdef DBG
					DbgPrint("luxdvd : Get VPCONFIG_VPDATAINFO for VMI\n");
				#endif
				
				pVpdata->bEnableDoubleClock		= FALSE;
				pVpdata->bEnableVACT			= TRUE;
				pVpdata->bDataIsInterlaced		= TRUE;
				pVpdata->lHalfLinesOdd  		= 1;
				pVpdata->lHalfLinesEven  		= 0;
				pVpdata->bFieldPolarityInverted	= FALSE;
				
				pVpdata->amvpDimInfo.dwFieldWidth	= 720;
				pVpdata->amvpDimInfo.dwFieldHeight	= 240;
				
				pVpdata->amvpDimInfo.rcValidRegion.left		= 0;
				pVpdata->amvpDimInfo.rcValidRegion.top		= 0;
				pVpdata->amvpDimInfo.rcValidRegion.right	= 720;
				pVpdata->amvpDimInfo.rcValidRegion.bottom	= 240;
				
				pVpdata->amvpDimInfo.dwVBIWidth     = 720;
				pVpdata->amvpDimInfo.dwVBIHeight    = (21 + 1 - 1 - 1);
			}
			else if(pHwDevExt->VideoPort == HH_VL_VGA ) //HREFH_VREFL
			{
				#ifdef DBG
					DbgPrint("luxdvd : Get VPCONFIG_VPDATAINFO for HREFH_VREFL\n");
				#endif
				
				pVpdata->bEnableDoubleClock		= FALSE;
				pVpdata->bEnableVACT			= TRUE;
				pVpdata->bDataIsInterlaced		= TRUE;
				pVpdata->lHalfLinesOdd  		= 1;
				pVpdata->lHalfLinesEven  		= 0;
				pVpdata->bFieldPolarityInverted	= FALSE;
				
				pVpdata->amvpDimInfo.dwFieldWidth	= 720;
				pVpdata->amvpDimInfo.dwFieldHeight	= 240;
				
				pVpdata->amvpDimInfo.rcValidRegion.left		= 0;
				pVpdata->amvpDimInfo.rcValidRegion.top		= 0;
				pVpdata->amvpDimInfo.rcValidRegion.right	= 720;
				pVpdata->amvpDimInfo.rcValidRegion.bottom	= 240;
				
				pVpdata->amvpDimInfo.dwVBIWidth     = 720;
				pVpdata->amvpDimInfo.dwVBIHeight    = (21 + 1 - 1 - 1);
			}
			else if(pHwDevExt->VideoPort == HH_VH_VGA ) //HREFH_VREFH
			{
				#ifdef DBG
					DbgPrint("luxdvd : Get VPCONFIG_VPDATAINFO for HREFH_VREFH\n");
				#endif
				
				pVpdata->bEnableDoubleClock		= FALSE;
				pVpdata->bEnableVACT			= TRUE;
				pVpdata->bDataIsInterlaced		= TRUE;
				pVpdata->lHalfLinesOdd  		= 1;
				pVpdata->lHalfLinesEven  		= 0;
				pVpdata->bFieldPolarityInverted	= FALSE;
				
				pVpdata->amvpDimInfo.dwFieldWidth	= 720;
				pVpdata->amvpDimInfo.dwFieldHeight	= 240;
				
				pVpdata->amvpDimInfo.rcValidRegion.left		= 11;
				pVpdata->amvpDimInfo.rcValidRegion.top		= 19;
				pVpdata->amvpDimInfo.rcValidRegion.right	= 720 + 11;
				pVpdata->amvpDimInfo.rcValidRegion.bottom	= 257;
				
				pVpdata->amvpDimInfo.dwVBIWidth     = 720;
				pVpdata->amvpDimInfo.dwVBIHeight    = (21 + 1 - 1 - 1);
			}
			break ;
							
		case KSPROPERTY_VPCONFIG_MAXPIXELRATE:

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_MAXPIXELRATE\n");
			#endif

			// NOTE:
			// this property is special.  And has another different
			// input property!
			if (dwInputBufferSize < sizeof (KSVPSIZE_PROP))
			{
				TRAP
				pSrb->Status = STATUS_INVALID_BUFFER_SIZE;
				#ifdef DBG
					DbgPrint("luxdvd ERROR : VPEGetProp - KSPROPERTY_VPCONFIG_MAXPIXELRATE !!!!!\n");
				#endif
				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
			
			if ( v_m_VideoSrc_NTSC )
			{
				pMaxPixelRate->Size.dwWidth  	= 720;
				pMaxPixelRate->Size.dwHeight 	= 240;
				pMaxPixelRate->MaxPixelsPerSecond	= 720*240*2*30;	//30fps
			}
			else
			{
				pMaxPixelRate->Size.dwWidth  	= 720;
				pMaxPixelRate->Size.dwHeight 	= 288;
				pMaxPixelRate->MaxPixelsPerSecond	= 720*288*2*30;	//30fps
			}
			break;
							
		case KSPROPERTY_VPCONFIG_INFORMVPINPUT:

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_INFORMVPINPUT\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break ;

		case KSPROPERTY_VPCONFIG_GETVIDEOFORMAT:

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_GETVIDEOFORMAT\n");
				DbgPrint("luxdvd : pmulitem->Count = %d\n",pmulitem->Count);
			#endif
			// check that the size of the output buffer is correct
			if (pmulitem->Count > dwNumConnectInfo ||
					pmulitem->Size != sizeof (DDPIXELFORMAT) ||
					dwOutputBufferSize < (pmulitem->Count * sizeof (DDPIXELFORMAT)))
			{
				#ifdef DBG
					DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_GETVIDEOFORMAT error !!!\n");
					DEBUG_BREAKPOINT();
				#endif
				// 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);

			pVideoFormat = (LPDDPIXELFORMAT)(pSrb->CommandData.PropertyInfo->PropertyInfo);

			if( pHwDevExt->VideoPort == S3_VGA ) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : Get Video Format for S3 LPB (HREFL_VREFL) - FourCC YUY2\n");
				#endif
				// S3 LPB HREFL_VREFL
				pVideoFormat->dwSize= sizeof (DDPIXELFORMAT);
				pVideoFormat->dwFlags = DDPF_FOURCC;
				pVideoFormat->dwFourCC = MKFOURCC( 'Y', 'U', 'Y', '2' );
				pVideoFormat->dwYUVBitCount = 16;
			}
			else if( pHwDevExt->VideoPort == CCIR656_VGA ) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : Get Video Format for CCIR656 - FourCC UYVY\n");
				#endif
				//CCIR656
				pVideoFormat->dwSize= sizeof (DDPIXELFORMAT);
				pVideoFormat->dwFlags = DDPF_FOURCC;
				pVideoFormat->dwYUVBitCount = 16;
				pVideoFormat->dwFourCC = MKFOURCC( 'U', 'Y', 'V', 'Y' );
				/*
				// Not needed?
				pVideoFormat->dwYBitMask = (DWORD)0xFF00FF00;
				pVideoFormat->dwUBitMask = (DWORD)0x000000FF;
				pVideoFormat->dwVBitMask = (DWORD)0x00FF0000;
				*/
			}
			else //if( pHwDevExt->VideoPort == VMI_VGA ) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : Get Video Format for HREF VREF combo - FourCC YUY2\n");
				#endif
				
				pVideoFormat->dwSize= sizeof (DDPIXELFORMAT);
				pVideoFormat->dwFlags = DDPF_FOURCC;
				pVideoFormat->dwYUVBitCount = 16;
				pVideoFormat->dwFourCC = MKFOURCC( 'Y', 'U', 'Y', '2' );
			}

			break;

		case KSPROPERTY_VPCONFIG_DECIMATIONCAPABILITY:

			#ifdef DBG
				DbgPrint("luxdvd : VPEGetProp - KSPROPERTY_VPCONFIG_DECIMATIONCAPABILITY, return TRUE\n");
			#endif
			// 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:
*/

//Here we copy the valid format block corresponding to the
//propsed format into the supplied buffer

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;
	DataRange = IntersectInfo->DataRange;

    switch (IntersectInfo->StreamNumber) 
	{

		case strmVideo:

			if (IsEqualGUID2(&(DataRange->MajorFormat), &(hwfmtiMpeg2Vid.MajorFormat))) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : HwProcessDataIntersection - DVD MPEG Video\n");
				#endif 
				pFormat = &hwfmtiMpeg2Vid;
				formatSize = sizeof hwfmtiMpeg2Vid;
            }
            else if (IsEqualGUID2(&(DataRange->MajorFormat), &(hwfmtiMpeg2VidPES.MajorFormat))) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : HwProcessDataIntersection - MPEG2 PES Video\n");
				#endif 
				pFormat = &hwfmtiMpeg2VidPES;
				formatSize = sizeof hwfmtiMpeg2VidPES;
            }
            else 
			{
				#ifdef DBG
					DbgPrint("luxdvd : HwProcessDataIntersection - strmVideo - invalid format\n");
				#endif 
				pFormat = NULL;
				formatSize = 0;
            }
		
			break;

	#ifdef NTSC
		case strmNTSCVideo:

			pFormat = &hwfmtiNTSCOut;
			formatSize = sizeof hwfmtiNTSCOut;
			break;
	#endif

		case strmSubpicture:
			
			pFormat = &hwfmtiSubPic;
			formatSize = sizeof hwfmtiSubPic;
			break;

		case strmAc3:

			//try to distinguish PES Audio from the MajorFormat
			if (IsEqualGUID2(&(DataRange->MajorFormat), &(Mpeg2PESksdataformat.MajorFormat))) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : HwProcessDataIntersection - strmAc3 - MPEG2 PES Audio AC3\n");
				#endif 
				pFormat = (PKSDATAFORMAT) hwfmtiMpeg2AudPES;
				formatSize = sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX);
				break;
            }
			
			//Can distinguish DVD AC3 and LPCM from SubFormats
            if (IsEqualGUID2(&(DataRange->SubFormat), &(Mpeg2ksdataformat.SubFormat))) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : HwProcessDataIntersection - strmAc3 - AC3\n");
				#endif 
				pFormat = (PKSDATAFORMAT) hwfmtiMpeg2Aud;
				formatSize = sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX);
            }
            else if (IsEqualGUID2(&(DataRange->SubFormat), &(LPCMksdataformat.SubFormat))) 
			{
				#ifdef DBG
					DbgPrint("luxdvd : HwProcessDataIntersection - strmAc3 - LPCM\n");
				#endif 
				pFormat = (PKSDATAFORMAT) hwfmtiLPCMAud;
				formatSize = sizeof (KSDATAFORMAT) + sizeof (WAVEFORMATEX);
            }
		    else 
			{
				#ifdef DBG
					DbgPrint("luxdvd : HwProcessDataIntersection - strmAc3 - invalid format\n");
				#endif 
				pFormat = NULL;
				formatSize = 0;
            }
            break;

#ifdef VPE
		case strmYUVVideo:

			#ifdef DBG
				DbgPrint("luxdvd : HwProcessDataIntersection - strmYUVVideo\n");
			#endif 
			pFormat = &hwfmtiVPOut;
			formatSize = (ULONG)sizeof(hwfmtiVPOut);
			break;
#endif


#ifdef CCOUT	
		case strmCCOut:

			#ifdef DBG
				DbgPrint("luxdvd : HwProcessDataIntersection - strmCCOut\n");
			#endif 
			pFormat = &hwfmtiCCOut;
			formatSize = sizeof hwfmtiCCOut;
			break;
#endif	

	default:

		pSrb->Status = STATUS_NOT_IMPLEMENTED;
		return;
    }                           // 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))) 
		{
			#ifdef DBG
				//DbgPrint("luxdvd ERROR : HwProcessDataIntersection - GUIDs do not match - STATUS_NO_MATCH !!!\n");
			#endif
            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) 
				{
					#ifdef DBG
						//DbgPrint("luxdvd ERROR : HwProcessDataIntersection - buffersize passed in is too small to contain dataformat - STATUS_BUFFER_TOO_SMALL !!!\n");
					#endif	
                    Status = STATUS_BUFFER_TOO_SMALL;
                } 
				else 
				{
                    RtlCopyMemory(IntersectInfo->DataFormatBuffer,pFormat,formatSize);
                    pSrb->ActualBytesTransferred = formatSize;
					#ifdef DBG
						//DbgPrint("luxdvd : HwProcessDataIntersection - STATUS_SUCCESS\n");
					#endif
					Status = STATUS_SUCCESS;
                }

            } 
			else 
			{   // if sizeof ULONG specified
                // caller wants just the size of the buffer.  Get that.
                *(PULONG) IntersectInfo->DataFormatBuffer = formatSize;
                pSrb->ActualBytesTransferred = sizeof(ULONG);
				#ifdef DBG
					//DbgPrint("luxdvd : HwProcessDataIntersection - STATUS_SUCCESS\n");
				#endif
				Status = STATUS_SUCCESS;
            }
        }                       // if guids are equal

    } 
	else 
	{                    // if pFormat
		#ifdef DBG
			DbgPrint("luxdvd ERROR : HwProcessDataIntersection - unrecognised format !!!\n");
		#endif
        Status = STATUS_NOT_SUPPORTED;
    }                           // if pFormat

    pSrb->Status = Status;
}

///////////////////////////////////////////////////////////////////////////////////////////

/*
** CCReceiveDataPacket ()
**
**    Receive the data packets to send to the close-caption decoder
**
** Arguments:}
**
**    
**
** Returns:
**
** Side Effects:
*/

VOID STREAMAPI CCReceiveDataPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pdevex = ((PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension);

    //
    // determine the type of packet.
    //

	if(pSrb==NULL)
	{
		#ifdef DBG
			DbgPrint("luxdvd : CCReceiveDataPacket - invalid pSrb !!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

    switch (pSrb->Command) 
	{
		case SRB_READ_DATA:

			//StreamClass driver passes down empty SRBs
			//Upon StartCode, we copy the Userdata into these empty SRBs
			//and send them back up to the DShow filters

			cCCRec++;
			CCEnqueue(pSrb);
				
			//NEW
			pSrb->Status = STATUS_PENDING;
			pSrb->TimeoutCounter = 0;	//prevent the apcket from ever timing out
			StreamClassStreamNotification(ReadyForNextStreamDataRequest,pSrb->StreamObject);
			return;
			
        
		case SRB_WRITE_DATA:
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;


		default:	// invalid / unsupported command. Fail it as such
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveDataPacket - invalid cmd !!!\n");
			#endif 
            pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;
    }

	StreamClassStreamNotification(ReadyForNextStreamDataRequest,
                                      pSrb->StreamObject);

	StreamClassStreamNotification(StreamRequestComplete,
                                      pSrb->StreamObject,
                                      pSrb);

}

///////////////////////////////////////////////////////////////////////////////////////////

VOID STREAMAPI CCReceiveCtrlPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;

	if(pSrb==NULL)
	{
		#ifdef DBG
			DbgPrint("luxdvd : CCReceiveCtrlPacket - invalid pSrb !!!\n");
			DEBUG_BREAKPOINT();
		#endif
		return;
	}

	switch( pSrb->Command ) 
	{
		case SRB_SET_STREAM_STATE:
		{
			switch( pSrb->CommandData.StreamState ) 
			{
				case KSSTATE_STOP:
				{
					#ifdef DBG
						DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_SET_STREAM_STATE  KSSTATE_STOP\n");
					#endif

					//re-init all cc vars
					cCCRec=0, cCCDeq=0, cCCCB=0 ,cCCQ=0;
					break;
				}

				case KSSTATE_PAUSE:
					#ifdef DBG
						DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_SET_STREAM_STATE  KSSTATE_PAUSE\n");
					#endif
					break;

				case KSSTATE_RUN:
					#ifdef DBG
						DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_SET_STREAM_STATE  KSSTATE_RUN\n");
					#endif
					break;

				case KSSTATE_ACQUIRE:
					#ifdef DBG
						DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_SET_STREAM_STATE  KSSTATE_ACQUIRE\n");
					#endif
					break;
				
			}
			((PSTREAMEX)(pHwDevExt->pstroCC->HwStreamExtension))->state = pSrb->CommandData.StreamState;
			pSrb->Status = STATUS_SUCCESS;
			break;
		}

		case SRB_GET_STREAM_STATE:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_GET_STREAM_STATE\n");
			#endif
					
			pSrb->CommandData.StreamState = ((PSTREAMEX)(pHwDevExt->pstroCC->HwStreamExtension))->state;
			
			pSrb->Status = STATUS_SUCCESS;
			break;
		}

		case SRB_GET_STREAM_PROPERTY:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_GET_STREAM_PROPERTY\n");
			#endif
			CCGetProp(pSrb);
			break;
		}

		case SRB_SET_STREAM_PROPERTY:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_SET_STREAM_PROPERTY\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;
		}

		case SRB_OPEN_MASTER_CLOCK:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_OPEN_MASTER_CLOCK\n");
			#endif
			hMaster = pSrb->CommandData.MasterClockHandle;
			pSrb->Status = STATUS_SUCCESS;
			break;
		}

		case SRB_CLOSE_MASTER_CLOCK:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_CLOSE_MASTER_CLOCK\n");
			#endif
			hMaster = pSrb->CommandData.MasterClockHandle;
			pSrb->Status = STATUS_SUCCESS;
			break;
		}

		case SRB_INDICATE_MASTER_CLOCK:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_INDICATE_MASTER_CLOCK\n");
			#endif
			hClk = pSrb->CommandData.MasterClockHandle;
			pSrb->Status = STATUS_SUCCESS;
			break;
		}

		case SRB_UNKNOWN_STREAM_COMMAND:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_UNKNOWN_STREAM_COMMAND\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;
		}

		case SRB_SET_STREAM_RATE:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_SET_STREAM_RATE\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;
		}

		case SRB_PROPOSE_DATA_FORMAT:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCReceiveCtrlPacket - SRB_PROPOSE_DATA_FORMAT\n");
			#endif
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;
		}

		default:
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
			break;
	}

	StreamClassStreamNotification( ReadyForNextStreamControlRequest,
									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;

	#ifdef DBG
		DbgPrint("luxdvd : CCSetState\n");
	#endif

	switch( ((PSTREAMEX)pdevex->pstroCC->HwStreamExtension)->state )
	{
		case KSSTATE_STOP:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCSetState - KSPROPERTY_CONNECTION_STATE - KSSTATE_STOP\n");
			#endif
			break;
		}

		case KSSTATE_RUN:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCSetState - KSPROPERTY_CONNECTION_STATE - KSSTATE_RUN\n");
			#endif
			break;
		}

		case KSSTATE_PAUSE:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCSetState - KSPROPERTY_CONNECTION_STATE - KSSTATE_PAUSE\n");
			#endif
			break;
		}

		case KSSTATE_ACQUIRE:
		{
			#ifdef DBG
				DbgPrint("luxdvd : CCSetState - KSPROPERTY_CONNECTION_STATE - KSSTATE_ACQUIRE\n");
			#endif
			break;
		}

		default:
			break;
	}
	//APPARENTLY THIS IS ALL THAT NEEDS TO BE DONE
	pSrb->Status = STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////////////////

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++);

	if(pSrbTmp==NULL)
		return;

	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);
	}
}

///////////////////////////////////////////////////////////////////////////////////////////

#ifdef MAPPER

void LuxGetPhysAddr(PHW_DEVICE_EXTENSION pHwDevExt)
{
	#ifdef DBG
		DbgPrint("luxdvd : LuxGetPhysAddr\n");
	#endif

	//gets the Physical Address equivalent of the Linear Addr from StreamClass
	phys_addr = MmGetPhysicalAddress((PVOID)luxbase);

	#ifdef DBG
		DbgPrint("luxdvd : phys_addr.LowPart = 0x%lx\n",phys_addr.LowPart);
		DbgPrint("luxdvd : phys_addr.HighPart = 0x%lx\n",phys_addr.HighPart);
	#endif
}

///////////////////////////////////////////////////////////////////////////////////////////

NTSTATUS DllExport _stdcall OpenDriver()
{
	#ifdef DBG
		DbgPrint("luxdvd : OpenDriver\n");
	#endif

	return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////////////////

NTSTATUS DllExport _stdcall LUXGetBase(OUT ULONG *pLinBase )
{
	#ifdef DBG
		DbgPrint("luxdvd : LUXGetBase - returning 0x%lx\n",(ULONG)phys_addr.LowPart);
	#endif

	*pLinBase = (ULONG)phys_addr.LowPart;

	return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////////////////

NTSTATUS DllExport _stdcall CloseDriver()
{
	#ifdef DBG
		DbgPrint("luxdvd : CloseDriver\n");
	#endif

	return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////////////////

#endif
