📄 init.c
字号:
//++
// File Name:
// init.c
//
// Contents:
// Driver initialization code
//--
//
// Driver-specific header files...
//
#include "version.h"
#include "ave2k.h"
#include "ave2kif.h"
#include "ave2kregs.h"
#include "AudioCtrl.h"
#include "DSP.h"
#include "Saa7111.h"
#include "ave2kutil.h"
#include "iic.h"
#include "channel2.h"
#include "debi.h"
VOID
Ave2kDpcForOSD(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
VOID
Ave2kDpcForAudioReport(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
//Global variables shared by all devices
//DISPLAY_PARAMETER DisplayParameter;
ULONG VGAAddress;
KSPIN_LOCK IsrSpinLock;
KIRQL IsrSynchronizeIrql;
#if _WIN32_WINNT==0x0400
#define WIN_NT 1
#else
#define WIN_2K 1
#endif
#if _WIN32_WINNT==0x0500
USHORT BoardVersion;
long NtDeviceNumber=0;
#endif
//
// Forward declarations of local functions
//
static BOOLEAN InitializeData(PDEVICE_EXTENSION pDE);
void InitializeHardware(PDEVICE_EXTENSION pDE);
#if _WIN32_WINNT==0x0400
static NTSTATUS
Ave2kCreateDevice (
IN PDRIVER_OBJECT DriverObject,
PDEVICE_BLOCK DeviceBlock,
IN ULONG NtDeviceNumber
);
#else
void GetDeviceInfo(PDEVICE_OBJECT DeviceObject);//used to get the specified deive information;
PCHAR PnPMinorFunctionString (UCHAR MinorFunction);
//used to realease hardware resource,it is different from Ave2kPReleaseHardware,
//the later is used in nt device driver
VOID Ave2kPnPReleaseHardware(IN PDEVICE_EXTENSION pDevExt);
ULONG HexCharToInt(char *buf);
#endif
static BOOLEAN
Ave2kInitDevice(
IN PVOID SynchContext
);
//
// If the compiler can handle it, make the DriverEntry
// routine discardable, so that it doesn't waste space
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text( init, DriverEntry )
#if _WIN32_WINNT==0x0400
#pragma alloc_text( init, Ave2kCreateDevice )
#endif
#endif // ALLOC_PRAGMA
//++
// Function:
// DriverEntry
//
// Description:
// This function initializes the driver, locates
// and claims hardware resources, and creates
// various NT objects needed to process I/O
// requests.
//
// Arguments:
// Pointer to the Driver object
// Registry path string for driver service key
//
// Return Value:
// NTSTATUS signaling success or failure
//--
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
#if _WIN32_WINNT==0x0400
PDEVICE_CONFIG ConfigList;
ULONG NtDeviceNumber;
ULONG i;
//Allocate space for configuration
ConfigList = ExAllocatePool(PagedPool,sizeof(*ConfigList));
RtlZeroMemory(ConfigList, sizeof(*ConfigList));
//KdPrint(("Config List=%d", sizeof(*ConfigList)));
//KdPrint(("Device Config=%d", sizeof(DEVICE_CONFIG)));
//KdPrint(("Decive Block=%d", sizeof(DEVICE_BLOCK)));
//
// Load up the Config list...
//
status = Ave2kGetHardwareInfo(
DriverObject,
RegistryPath,
ConfigList );
if( !NT_SUCCESS( status ))
{
ExFreePool(ConfigList);
return status;
}
//Initialize variables used by IoConnectInterrupt
KeInitializeSpinLock(&IsrSpinLock);
//Get max. value of all found device
IsrSynchronizeIrql =0;
for(i=0;i<ConfigList->Count;i++){
if(ConfigList->Device[i].Dirql > IsrSynchronizeIrql)
IsrSynchronizeIrql = ConfigList->Device[i].Dirql;
}
//
// Allocate the hardware...
//
status = Ave2kReportHardwareUsage(
DriverObject,
ConfigList );
if( !NT_SUCCESS( status ))
{
ExFreePool(ConfigList);
return status;
}
#else
HANDLE hDevice;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING deviceName;
WCHAR deviceNameBuffer[ AVE2K_MAX_NAME_LENGTH ];
DebugPrintInit("AVE2K ");
DebugPrintMsg("In the DriverEntry!");
//Initialize variables used by IoConnectInterrupt
KeInitializeSpinLock(&IsrSpinLock);
deviceName.Buffer = deviceNameBuffer;
deviceName.MaximumLength = AVE2K_MAX_NAME_LENGTH;
deviceName.Length = 0;
RtlAppendUnicodeToString(
&deviceName,
L"\\DosDevices\\AVE2Kp1");
InitializeObjectAttributes(
&ObjectAttributes,
&deviceName,
0,
NULL,
NULL);
if(ZwCreateFile(
&hDevice,
GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
0,
NULL,
0
)==STATUS_SUCCESS){
ZwClose(hDevice);
}
else{
//if not exist reset other card's counter
ULONG nTotalOther=0;
RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
L"ave2kp\\",
L"TotalCard",
REG_DWORD,
&nTotalOther,
4);
#if TD_WIN98
RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
L"ave5kex\\Enum",
L"Count",
REG_DWORD,
&nTotalOther,
4);
#endif
}
Ave2kGetVGAHardwareInfo();
#endif
//
// Export other driver entry points...
//
DriverObject->DriverStartIo = Ave2kStartIo;
DriverObject->DriverUnload = Ave2kDriverUnload;
DriverObject->MajorFunction[ IRP_MJ_CREATE ] =
Ave2kDispatchOpenClose;
DriverObject->MajorFunction[ IRP_MJ_CLOSE ] =
Ave2kDispatchOpenClose;
DriverObject->MajorFunction[ IRP_MJ_WRITE ] =
Ave2kDispatchWrite;
DriverObject->MajorFunction[ IRP_MJ_READ ] =
Ave2kDispatchRead;
DriverObject->MajorFunction[ IRP_MJ_CLEANUP ] =
Ave2kDispatchCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
Ave2kDispatchDeviceIoControl;
#if _WIN32_WINNT==0x0400
//
// Initialize a Device object for each piece
// of hardware we've found
//
NtDeviceNumber = 0;
for( i = 0;
i < ConfigList->Count;
i++ )
{
status = Ave2kCreateDevice(
DriverObject,
&(ConfigList->Device[i]),
NtDeviceNumber );
if( !NT_SUCCESS( status )) break;
NtDeviceNumber++;
}
if( !NT_SUCCESS( status ))
{
Ave2kReleaseHardware( DriverObject );
}
//Deallocate device configuration data
ExFreePool( ConfigList );
return status;
#else
DriverObject->MajorFunction[IRP_MJ_PNP] = Ave2kDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = Ave2kDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Ave2kDispatchSystemControl;
DriverObject->DriverExtension->AddDevice = Ave2kAddDevice;
return STATUS_SUCCESS;
#endif
}
#if _WIN32_WINNT==0x0400
//++
// Function:
// Ave2kCreateDevice
//
// Description:
// This function creates and initializes a
// single Device object, using a set of hardware
// descriptions from the Config block.
//
// Arguments:
// Pointer to the Driver object
// Pointer to config data about the device
// Number to associate with NT Device object
//
// Return Value:
// NTSTATUS signaling success or failure
//--
static NTSTATUS
Ave2kCreateDevice (
IN PDRIVER_OBJECT DriverObject,
PDEVICE_BLOCK DeviceBlock,
IN ULONG NtDeviceNumber
)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
UNICODE_STRING deviceName;
WCHAR deviceNameBuffer[ AVE2K_MAX_NAME_LENGTH ];
UNICODE_STRING linkName;
WCHAR linkNameBuffer[ AVE2K_MAX_NAME_LENGTH ];
UNICODE_STRING number;
WCHAR numberBuffer[10];
number.Buffer = numberBuffer;
number.MaximumLength = 10;
//
// Form the base NT device name...
//
deviceName.Buffer = deviceNameBuffer;
deviceName.MaximumLength = AVE2K_MAX_NAME_LENGTH;
deviceName.Length = 0;
RtlAppendUnicodeToString(
&deviceName,
AVE2K_NT_DEVICE_NAME );
//
// Convert the device number into a string and
// attach it to the end of the device name.
//
number.Length = 0;
RtlIntegerToUnicodeString(
NtDeviceNumber,
10,
&number );
RtlAppendUnicodeStringToString(
&deviceName,
&number );
//If NtDeviceNumber is 1, now deviceName is "\\Device\\Ave2k1"
// Create a Device object for this device...
//
status = IoCreateDevice(
DriverObject,
sizeof( DEVICE_EXTENSION ),
&deviceName,
FILE_DEVICE_UNKNOWN,
0,
TRUE, //exclusive
&pDevObj );
if( !NT_SUCCESS( status ))
{
return status;
}
#ifdef USING_DIRECT_IO
pDevObj->Flags |= DO_DIRECT_IO;
#else
pDevObj->Flags |= DO_BUFFERED_IO;
#endif
//
// Initialize the Device Extension
//
pDevExt = pDevObj->DeviceExtension;
pDevExt->DeviceObject = pDevObj;
pDevExt->NtDeviceNumber = NtDeviceNumber;
//
// Copy things from Device Block
//
pDevExt->PortBase = (UCHAR *)DeviceBlock->PortBase;
pDevExt->PortSpan = DeviceBlock->PortSpan;
pDevExt->BusNumber = DeviceBlock->BusNumber;
pDevExt->SlotNumber = DeviceBlock->SlotNumber;
pDevExt->BoardVersion = DeviceBlock->BoardVersion;
InitializeHardware(pDevExt);
//
// Form the Win32 symbolic link name.
//
linkName.Buffer = linkNameBuffer;
linkName.MaximumLength = AVE2K_MAX_NAME_LENGTH;
linkName.Length = 0;
RtlAppendUnicodeToString(
&linkName,
AVE2K_WIN32_DEVICE_NAME );
//
// Reset the number string and do another
// conversion. Win32 device numbers are
// one greater than the NT equivalent.
//
number.Length = 0;
RtlIntegerToUnicodeString(
NtDeviceNumber + 1,
10,
&number );
RtlAppendUnicodeStringToString(
&linkName,
&number );
//
// Create a symbolic link so our device is
// visible to Win32...
//
status = IoCreateSymbolicLink(
&linkName,
&deviceName );
//
// See if the symbolic link was created...
//
if( !NT_SUCCESS( status ))
{
IoDeleteDevice( pDevObj );
return status;
}
//Init device data
if(InitializeData(pDevExt)==FALSE)
return STATUS_UNSUCCESSFUL;
//
// Make sure device interrupts are OFF
//
Ave2kDisableInterrupts( pDevExt );
//
// Connect to an Interrupt object...
//
status =
IoConnectInterrupt(
&pDevExt->pInterrupt,
Ave2kIsr,
pDevExt,
&IsrSpinLock,//NULL,
DeviceBlock->SystemVector,
DeviceBlock->Dirql,
IsrSynchronizeIrql,//DeviceBlock->Dirql,
DeviceBlock->InterruptMode,
TRUE, //ShareVector,
DeviceBlock->Affinity,
FALSE );
if( !NT_SUCCESS( status ))
{
IoDeleteSymbolicLink( &linkName );
IoDeleteDevice( pDevObj );
return status;
}
//
// Initialize the hardware and enable interrupts
//
//KeSynchronizeExecution(
// pDevExt->pInterrupt,
// Ave2kInitDevice,
// pDevExt ); deleted 02/08/22.
//Actually the function don't enable any interrupt, and here interrupt shoud be disabled by
//preceding Ave2kDisableInterrupts.
return status;
}
#endif
//
// Make sure device interrupts are OFF
//
BOOLEAN Ave2kDisableInterrupts(PDEVICE_EXTENSION pDevExt )
{
//clear all interrupt enable bits
pDevExt->IERValue =0L;
Ave2kWriteRegister(pDevExt,IER,pDevExt->IERValue);
return TRUE;
}
//Set Value of IER of SAA7146
BOOLEAN Ave2kSetInterrupts(PDEVICE_EXTENSION pDevExt)
{
Ave2kWriteRegister(pDevExt,IER,pDevExt->IERValue);
return TRUE;
}
//++
// Function:
// Ave2kStartIo
//
// Description:
// This function is responsible for doing any
// function-code specific pre-processing and
// then starting the actual data transfer.
//
// Arguments:
// Pointer to the Device object
// Pointer to the IRP for this request
//
// Return Value:
// (None)
//--
VOID
Ave2kStartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KIRQL OldIrql;
PDEVICE_EXTENSION pDE=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpStack;// =
//IoGetCurrentIrpStackLocation( Irp );
//if(IrpStack->MajorFunction != IRP_MJ_READ)
// return;
// Before starting the operation, see if the
// Cancel routine has run between the time
// the IRP was removed from the Device Queue
// and now. Start by grabbing the Cancel spin
// lock.
//
IoAcquireCancelSpinLock( &OldIrql );
//
// Check the state of the Cancel flag. If
// it's set, release the spin lock and return
// immediately. The IRP has already been
// processed by the Cancel routine.
//
if( Irp->Cancel )
{
IoReleaseCancelSpinLock( OldIrql );
return;
}
//
// If the Cancel flag is clear, remove the
// IRP from the cancelable state and start
// processing it.
//
else
{
IoSetCancelRoutine( Irp, NULL);//Ave2kCancelIrp );
IoReleaseCancelSpinLock( OldIrql );
}
/* KeAcquireSpinLock(&pDE->ReadLock, &OldIrql);
IrpStack = IoGetCurrentIrpStackLocation( Irp );
ASSERT(IrpStack!=NULL);
#ifdef USING_DIRECT_IO
pDE->ReadIrpDataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
#else
pDE->ReadIrpDataBuffer = pIrp->AssociatedIrp.SystemBuffer; //Using buffered I/O
#endif
if(KeSynchronizeExecution(
pDE->pInterrupt,
SyncAudioRead,
DeviceObject->DeviceExtension))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = IrpStack->Parameters.Read.Length //sizeof(AUDIOSTREAMSECTOR);
IoStartNextPacket(DeviceObject,TRUE);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
pDE->ReadIrpDataBuffer=NULL;
}
KeReleaseSpinLock(&pDE->ReadLock, OldIrql);
ErrorRecover(pDE, 0);*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -