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

412 lines
12 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
dvdinit.c
Abstract:
Device initialization for DVDTS
Environment:
Kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1998 Microsoft Corporation. All Rights Reserved.
Some portions adapted with permission from code Copyright (c) 1997-1998 Toshiba Corporation
Revision History:
5/1/98: created
--*/
#include "strmini.h"
#include "ks.h"
#include "ksmedia.h"
#include "debug.h"
#include "dvdinit.h"
#include "que.h"
#include "dvdcmd.h"
#include "DvdTDCod.h" // header for DvdTDCod.lib routines hiding proprietary HW stuff
BOOLEAN STREAMAPI HwInterrupt( IN PHW_DEVICE_EXTENSION pHwDevExt );
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Initial load entry point into the driver. Initializes the key
entry points to the mini driver. The driver
should then call the StreamClassRegisterAdapter function to register with
the stream class driver.
Arguments:
DriverObject and RegistryPath, corresponding to the Context1 and Context2 arguments
passed from the stream class driver
The arguments point to private plug and play structures
used by the stream class driver to find the resources for this
adapter
Return Value:
The NT_STATUS 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
If a value other than STATUS_SUCCESS is returned, the
minidriver will be unloaded.
--*/
{
HW_INITIALIZATION_DATA HwInitData;
NTSTATUS ntStatus;
DebugPrint( (DebugLevelTrace, "DVDTS:DriverEntry\r\n") );
RtlZeroMemory( &HwInitData, sizeof(HW_INITIALIZATION_DATA) );
HwInitData.HwInitializationDataSize = sizeof(HwInitData);
//
//
// Entry points for the mini Driver. All entry routines will be called
// at High priority. If the driver has a task that requires a large amount
// of time to accomplish (e.g. double buffer copying of large amounts of
// data) The driver should request a callback at lower priority to perform the
// desired function. See the Syncronization comment for issues on re-entrancy
//
//
HwInitData.HwInterrupt = (PHW_INTERRUPT)HwInterrupt; // ISR routine
//
// The HwReceivePacket field describes the entry point for receiving an SRB
// Request from the stream class driver that is a request to the adapter, as
// opposed to the stream based request handlers that are initialised in the
// OpenStream function
//
HwInitData.HwReceivePacket = AdapterReceivePacket;
//
// The HwCancelPacket entry is used to cancel any packet the minidriver may
// currently have outstanding. This could be a stream, or an adapter based
// request. This routine will only be called under extreme circumstances, when
// an upper layer is attempting to recover and packets are considered lost
//
HwInitData.HwCancelPacket = AdapterCancelPacket;
//
// The HwRequestTimeoutHandler entry is used when a packet times out. Again,
// This could be a packet for the device, or a stream based packet. This is
// not necessarily an error, and it is up to the minidriver to determine what
// to do with the packet that has timed out.
//
HwInitData.HwRequestTimeoutHandler = AdapterTimeoutPacket;
//
// Sizes for data structure extensions. See mpinit.h for definitions
//
HwInitData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
HwInitData.PerRequestExtensionSize = sizeof(SRB_EXTENSION);
HwInitData.PerStreamExtensionSize = sizeof(STREAMEX);
HwInitData.FilterInstanceExtensionSize = 0;
//
// The BusMasterDMA field indicates to the system that the memory pointers passed
// in to the mini driver in the data packets may be used for direct Bus Master DMA
// access. If the mini driver uses a translation buffer (to ensure minimum DMA
// size, or correct buffer alignment), this BOOLEAN should be set to FALSE.
//
HwInitData.BusMasterDMA = TRUE;
//
// The Ddma24BitAddresses field indicates a device that uses DMA that only can
// access the lower 24bits of the 32 bit address space. Again, this should only
// be set to true if the minidriver is going to be doing DMA directly to the buffer
// passed in the data packets, and not through a double buffer scenario.
//
HwInitData.Dma24BitAddresses = FALSE;
HwInitData.BufferAlignment = 4;
//
// If the TurnOffSynchronization field is set to FALSE, the mini driver may never
// be re-entered. Under these conditions, if the mini-driver uses a DISPATCH or lower priority
// callback routine, the miniDriver must disable any interrupts that it might
// receive. If an interrupt controlled by the driver is received while code in
// the mini driver is running at DISPATCH or lower priority, the interrupt will
// be LOST. If an interrupt is received while at HIGH priority, it will be queued
// until the code in the driver is finished.
//
// If the TurnOffSynchronization field is set to TRUE, the mini-driver must be
// fully capable of handling multi-processor and single processor re-entrancy
//
HwInitData.TurnOffSynchronization = FALSE;
//
// The DmaBufferSize specifies the size of the single contiguous region of
// physical memory that the driver needs at hardware intialization time. The
// memory will be returned to the driver when the driver makes the
// StreamClassGetDmaBuffer call. It is important to use as little physical
// buffer as possible here, as this will be locked physical memory that is
// unavailable to the sytem, even when the streaming class mini driver is not
// in use
//
HwInitData.DmaBufferSize = DMASIZE;
//
// attempt to register with the streaming class driver. Note, this will
// result in calls to the HW_INITIALIZE routine.
//
ntStatus = (
StreamClassRegisterMinidriver(
(PVOID)DriverObject,
(PVOID)RegistryPath,
&HwInitData )
);
if ( !NT_SUCCESS( ntStatus ) ) {
ASSERT( 0 );
}
return ntStatus;
}
void GetPCIConfigSpace(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;
if( StreamClassReadWriteConfig(
pSrb->HwDeviceExtension,
TRUE, // indicates a READ (FALSE means a WRITE)
(PVOID)&pHwDevExt->PciConfigSpace,
0, // this is the offset into the PCI space,
// change this to whatever you need to read
64 // this is the # of bytes to read. Changer
// it to the correct #.
)) {
//
// process the config info your read here.
//
{
ULONG i, j;
DebugPrint( (DebugLevelTrace, "DVDTS:PCI Config Space\r\n" ) );
for( i=0; i<64; ) {
DebugPrint( (DebugLevelTrace, "DVDTS: " ) );
for( j=0; j<8 && i<64; j++, i++ ) {
DebugPrint( (DebugLevelTrace, "0x%02x ", (UCHAR)*(((PUCHAR)&pHwDevExt->PciConfigSpace) + i) ) );
}
DebugPrint( (DebugLevelTrace, "\r\n" ) );
}
}
//
// note that the PCI_COMMON_CONFIG structure in WDM.H can be used
// for referencing the PCI data.
//
}
//
// now return to high priority to complete initialization
//
StreamClassCallAtNewPriority(
NULL,
pSrb->HwDeviceExtension,
LowToHigh,
(PHW_PRIORITY_ROUTINE) InitializationEntry,
pSrb
);
return;
}
void InitializationEntry(IN PHW_STREAM_REQUEST_BLOCK pSrb)
{
DWORD st, et;
st = GetCurrentTime_ms();
HwInitialize( pSrb );
et = GetCurrentTime_ms();
DebugPrint( (DebugLevelTrace, "DVDTS:init %dms\r\n", et - st ) );
StreamClassDeviceNotification( ReadyForNextDeviceRequest,
pSrb->HwDeviceExtension );
StreamClassDeviceNotification( DeviceRequestComplete,
pSrb->HwDeviceExtension,
pSrb );
}
/*
** HwInitialize()
*/
NTSTATUS HwInitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{
PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
PHW_DEVICE_EXTENSION pHwDevExt =
(PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;
STREAM_PHYSICAL_ADDRESS adr;
ULONG Size;
PUCHAR pDmaBuf;
NTSTATUS Stat;
PUCHAR ioBase;
BOOLEAN bStatus;
PVOID DecoderInfo;
DebugPrint( (DebugLevelTrace, "DVDTS:HwInitialize()\r\n") );
DebugPrint( (DebugLevelTrace, "DVDTS: pHwDevExt = 0x%x\r\n", pHwDevExt ) );
DebugPrint( (DebugLevelTrace, "DVDTS: pSrb->HwDeviceExtension = 0x%x\r\n", pSrb->HwDeviceExtension ) );
DebugPrint( (DebugLevelTrace, "DVDTS: NumberOfAccessRanges = %d\r\n", ConfigInfo->NumberOfAccessRanges ) );
if ( ConfigInfo->NumberOfAccessRanges < 1 ) {
DebugPrint( (DebugLevelTrace, "DVDTS:illegal config info") );
pSrb->Status = STATUS_NO_SUCH_DEVICE;
return( STATUS_NO_SUCH_DEVICE );
}
// Debug Dump ConfigInfo
DebugPrint( (DebugLevelTrace, "DVDTS: Port = 0x%x\r\n", ConfigInfo->AccessRanges[0].RangeStart.LowPart ) );
DebugPrint( (DebugLevelTrace, "DVDTS: Length = 0x%x\r\n", ConfigInfo->AccessRanges[0].RangeLength ) );
DebugPrint( (DebugLevelTrace, "DVDTS: IRQ = 0x%x\r\n", ConfigInfo->BusInterruptLevel ) );
DebugPrint( (DebugLevelTrace, "DVDTS: Vector = 0x%x\r\n", ConfigInfo->BusInterruptVector ) );
DebugPrint( (DebugLevelTrace, "DVDTS: DMA = 0x%x\r\n", ConfigInfo->DmaChannel ) );
// initialize the size of stream descriptor information.
ConfigInfo->StreamDescriptorSize =
STREAMNUM * sizeof(HW_STREAM_INFORMATION) +
sizeof(HW_STREAM_HEADER);
// allocate decoder data area and put 'blind' ptr to it in our device ext
DecoderInfo = decAllocateDecoderInfo( pHwDevExt );
if ( !DecoderInfo ) {
DebugPrint( (DebugLevelTrace, "DVDTS: failed to allocate decoder info buffer") );
pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
return( STATUS_INSUFFICIENT_RESOURCES );
}
// pick up the I/O windows for the card.
pHwDevExt->ioBaseLocal =
(PUCHAR)ConfigInfo->AccessRanges[0].RangeStart.LowPart;
// pick up the Interrupt level
pHwDevExt->Irq =
ConfigInfo->BusInterruptLevel;
// pick up the Revision id
pHwDevExt->RevID =
(ULONG)pHwDevExt->PciConfigSpace.RevisionID;
pDmaBuf = (PUCHAR)StreamClassGetDmaBuffer( pHwDevExt );
pHwDevExt->pDmaBuf = pDmaBuf;
DebugPrint( (DebugLevelTrace, "DVDTS: DMA Buffer Logical Addr = 0x%x\r\n", pDmaBuf ) );
adr = StreamClassGetPhysicalAddress( pHwDevExt, NULL, pDmaBuf, DmaBuffer, &Size) ;
pHwDevExt->addr = adr;
DebugPrint( (DebugLevelTrace, "DVDTS: DMA Buffer Physical Addr = 0x%x\r\n", adr.LowPart ) );
DebugPrint( (DebugLevelTrace, "DVDTS: DMA Buffer Size = %d\r\n", Size ) );
ioBase = pHwDevExt->ioBaseLocal;
// initialize the hardware settings
pHwDevExt->pSrbDMA0 = NULL;
pHwDevExt->pSrbDMA1 = NULL;
pHwDevExt->SendFirst = FALSE;
pHwDevExt->DecodeStart = FALSE;
pHwDevExt->TimeDiscontFlagCount = 0;
pHwDevExt->DataDiscontFlagCount = 0;
pHwDevExt->bKeyDataXfer = FALSE;
pHwDevExt->CppFlagCount = 0;
pHwDevExt->pSrbCpp = NULL;
pHwDevExt->bCppReset = FALSE;
pHwDevExt->XferStartCount = 0;
pHwDevExt->dwSTCInit = 0;
pHwDevExt->bDMAscheduled = FALSE;
pHwDevExt->fCauseOfStop = 0;
pHwDevExt->bDMAstop = FALSE;
pHwDevExt->bVideoQueue = FALSE;
pHwDevExt->bAudioQueue = FALSE;
pHwDevExt->bSubpicQueue = FALSE;
pHwDevExt->VideoMaxFullRate = 1 * 10000;
pHwDevExt->AudioMaxFullRate = 1 * 10000;
pHwDevExt->SubpicMaxFullRate = 1 * 10000;
pHwDevExt->cOpenInputStream = 0;
pHwDevExt->pstroVid = NULL;
pHwDevExt->pstroAud = NULL;
pHwDevExt->pstroSP = NULL;
pHwDevExt->pstroYUV = NULL;
pHwDevExt->pstroCC = NULL;
// Set Stream Mode
if ( !decSetStreamMode( pHwDevExt, pSrb )) //tell dvdtdcod.lib to set stream modes on HW
return FALSE; // will also set error in srb
// Set Display Mode
decSetDisplayMode( pHwDevExt ); // set display mode on HW
// Set Audio Mode
decSetAudioMode( pHwDevExt ); // set audio mode on HW
// NTSC Copy Gaurd
decSetCopyGuard( pHwDevExt ); // set copy protection on HW
DebugPrint( (DebugLevelTrace, "DVDTS:HwInitialize() exit\r\n") );
pSrb->Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}