Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

690 lines
25 KiB

/*++
*******************************************************************************
* Copyright (c) 1995 IBM Corporation
*
* Module Name: init.c
*
* Abstract: DriverEntry() and internal initialization functions
*
* Author: Jim Bozek [IBM]
*
* Environment:
*
* Comments:
*
* Rev History: Creation 09.13.95
*
*******************************************************************************
--*/
#include "common.h"
char _cs423xVersdate_[] = __DATE__;
char _cs423xVerstime_[] = __TIME__;
ULONG _cs423xVersion_ = IBM_CS423X_DRIVER_VERSION;
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDObj, IN PUNICODE_STRING RegistryPathName);
VOID cs423xDbgDisplayConfig(PSOUND_CONFIG_DATA);
VOID kpcMixerFixer(PSOUND_CONFIG_DATA pscd);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, cs423xCreateGdi)
#pragma alloc_text(PAGE, cs423xUnload)
#pragma alloc_text(PAGE, cs423xShutdown)
#pragma alloc_text(PAGE, cs423xCleanup)
#endif /* ALLOC_PRAGMA */
/*++
*********************************************************************************
* device init structure
*********************************************************************************
--*/
CONST SOUND_DEVICE_INIT DeviceInit[NumberOfDevices] =
{
{
NULL, NULL,
0,
FILE_DEVICE_WAVE_IN,
WAVE_IN,
"LDWi",
L"\\Device\\cs423xWaveIn",
SoundWaveDeferred,
cs423xDriverExclude,
SoundWaveDispatch,
waveInGetCaps,
SoundNoVolume,
DO_DIRECT_IO
},
{
NULL, NULL,
0,
FILE_DEVICE_WAVE_OUT,
WAVE_OUT,
"LDWo",
L"\\Device\\cs423xWaveOut",
SoundWaveDeferred,
cs423xDriverExclude,
SoundWaveDispatch,
waveOutGetCaps,
SoundNoVolume,
DO_DIRECT_IO
},
{
NULL, NULL,
0,
FILE_DEVICE_SOUND,
MIXER_DEVICE,
"LDMx",
L"\\Device\\cs423xMixer",
NULL,
cs423xDriverExclude,
SoundMixerDispatch,
cs423xMixerGetConfig,
SoundNoVolume,
DO_BUFFERED_IO
},
{
REG_VALUENAME_LEFTLINEIN, REG_VALUENAME_RIGHTLINEIN,
DEF_AUX_VOLUME,
FILE_DEVICE_SOUND,
AUX_DEVICE,
"LDLi",
L"\\Device\\cs423xAux",
NULL,
cs423xDriverExclude,
SoundAuxDispatch,
auxGetCaps,
SoundNoVolume,
DO_BUFFERED_IO
}
};
/*++
*********************************************************************************
* Driver Entry Function
*********************************************************************************
--*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDObj, IN PUNICODE_STRING RegistryPathName)
{
PGLOBAL_DEVICE_INFO pGDI;
NTSTATUS status;
RTL_QUERY_REGISTRY_TABLE table[2];
SOUND_CONFIG_DATA ConfigData;
/*
*********************************************************************
** print initial status and debug information
*********************************************************************
*/
_dbgprint((_PRT_DBUG, "\n"));
_dbgprint((_PRT_DBUG, "DriverEntry(enter)\n"));
#ifdef CS423X_DEBUG_ON
{
char mbuf0[256];
extern UCHAR _debug_map;
_dbgprint((_PRT_WARN, "\n"));
_dbgprint((_PRT_WARN, "======= - Internal Data - =======\n"));
_dbgprint((_PRT_WARN, "- %ls -\n", RegistryPathName->Buffer));
sprintf(mbuf0, "Driver Build Date: %s\n", _cs423xVersdate_);
_dbgprint((_PRT_WARN, mbuf0));
sprintf(mbuf0, "Driver Build Time: %s\n", _cs423xVerstime_);
_dbgprint((_PRT_WARN, mbuf0));
sprintf(mbuf0, "Driver Build Vers: 0x%04x\n", _cs423xVersion_);
_dbgprint((_PRT_WARN, mbuf0));
sprintf(mbuf0, "cs423x!_debug_map: 0x%02x\n", _debug_map);
_dbgprint((_PRT_WARN, mbuf0));
_dbgprint((_PRT_WARN, "======= - Internal Data - =======\n"));
_dbgprint((_PRT_WARN, "\n"));
_dbgbreak(_BRK_STAT);
}
#endif /* CS423X_DEBUG_ON */
#if DBG
DriverName = DRIVER_NAME;
#endif /* DBG */
/*
*********************************************************************
** define driver object major functions
*********************************************************************
*/
pDObj->DriverUnload = cs423xUnload;
pDObj->MajorFunction[IRP_MJ_CREATE] = SoundDispatch;
pDObj->MajorFunction[IRP_MJ_CLOSE] = SoundDispatch;
pDObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SoundDispatch;
pDObj->MajorFunction[IRP_MJ_READ] = SoundDispatch;
pDObj->MajorFunction[IRP_MJ_WRITE] = SoundDispatch;
pDObj->MajorFunction[IRP_MJ_CLEANUP] = SoundDispatch;
pDObj->MajorFunction[IRP_MJ_SHUTDOWN] = cs423xShutdown;
#ifdef POWER_MANAGEMENT
pDObj->MajorFunction[IRP_MJ_SET_POWER] = SoundSetPower;
pDObj->MajorFunction[IRP_MJ_QUERY_POWER] = SoundQueryPower;
#endif /* POWER_MANAGEMENT */
/*
*********************************************************************
** initialize the global (instance) data structure
*********************************************************************
*/
if (!(pGDI = cs423xCreateGdi(pDObj, RegistryPathName))) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:STATUS_INSUFFICIENT_RESOURCES_1)\n"));
return(STATUS_INSUFFICIENT_RESOURCES);
}
_dbgprint((_PRT_STAT, "pGDI: 0x%08x\n", pGDI));
/*
*********************************************************************
* Configure device from registry
*********************************************************************
*/
/* initialize the configuration information to default values */
ConfigData.HwType = (PWSTR)NULL;
ConfigData.HwPort = CS423X_DEF_CHIP_ADDRESS;
ConfigData.DmaCaptureChannel = CS423X_DEF_DMA_CAPT_CHAN;
ConfigData.DmaPlayChannel = CS423X_DEF_DMA_PLAY_CHAN;
ConfigData.DmaBufferSize = CS423X_DEF_DMA_BUFFERSIZE;
ConfigData.SingleModeDMA = CS423X_DEF_SMODEDMA;
ConfigData.WssEnable = CS423X_DEF_WSSENABLE;
ConfigData.WssPort = CS423X_DEF_WSSPORT;
ConfigData.WssIrq = CS423X_DEF_WSSIRQ;
ConfigData.SynPort = CS423X_DEF_SYNPORT;
ConfigData.SBPort = CS423X_DEF_SBPORT;
ConfigData.GameEnable = CS423X_DEF_GAMEENABLE;
ConfigData.GamePort = CS423X_DEF_GAMEPORT;
ConfigData.CtrlEnable = CS423X_DEF_CTRLENABLE;
ConfigData.CtrlPort = CS423X_DEF_CTRLPORT;
ConfigData.MpuEnable = CS423X_DEF_MPUENABLE;
ConfigData.MpuPort = CS423X_DEF_MPUPORT;
ConfigData.MpuIrq = CS423X_DEF_MPUIRQ;
ConfigData.CDRomEnable = CS423X_DEF_CDROMENABLE;
ConfigData.CDRomPort = CS423X_DEF_CDROMPORT;
ConfigData.Aux1InputSignal = SignalNull;
ConfigData.Aux2InputSignal = SignalNull;
ConfigData.LineInputSignal = SignalNull;
ConfigData.MicInputSignal = SignalNull;
ConfigData.MonoInputSignal = SignalNull;
ConfigData.MixerSettings = (PVOID)ExAllocatePool(NonPagedPool,
(sizeof(MIXER_REGISTRY_DATA)));
if (ConfigData.MixerSettings == NULL) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:STATUS_INSUFFICIENT_RESOURCES_2)\n"));
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_RESOURCE);
cs423xCleanup(pGDI);
return(STATUS_INSUFFICIENT_RESOURCES);
}
ConfigData.MixerSettingsFound = FALSE;
/*
*********************************************************************
* initialize the driver from the registry -
* the method used here is different from the method used in other
* audio drivers (e.g., SoundBlaster) because we do not support multiple
* instances of a HW device
* so, instead of using the Soundlib function SoundEnumSubkeys()
* we call RtlQueryRegistryValues() once with an absolute registry path
*********************************************************************
*/
/* initialize the query table in preparation for registry query */
RtlZeroMemory(table, sizeof(table));
table[0].QueryRoutine = cs423xReadRegistryConfig;
/* fetch the configuration information values from the registry into ConfigData */
if (NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, pGDI->RegPathName,
table, &ConfigData, NULL))) {
_dbgprint((_PRT_STAT, "DriverEntry: fetched registry values\n"));
}
else {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:STATUS_OBJECT_NAME_NOT_FOUND)\n"));
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_RESOURCE);
cs423xCleanup(pGDI);
return(STATUS_OBJECT_NAME_NOT_FOUND);
}
#ifdef CS423X_DEBUG_ON
cs423xDbgDisplayConfig(&ConfigData);
#endif /* CS423X_DEBUG_ON */
pGDI->Hw.Type = cs423xConvertHwtype(ConfigData.HwType);
if ((pGDI->Hw.Type = cs423xConvertHwtype(ConfigData.HwType)) == hwtype_null) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:STATUS_RESOURCE_DATA_NOT_FOUND)\n"));
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_RESOURCE);
cs423xCleanup(pGDI);
return(STATUS_RESOURCE_DATA_NOT_FOUND);
}
if (pGDI->Hw.Type == hwtype_undefined) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:STATUS_RESOURCE_DATA_NOT_FOUND)\n"));
ExFreePool(ConfigData.HwType);
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_NOCARD);
cs423xCleanup(pGDI);
return(STATUS_NO_SUCH_DEVICE);
}
/* free the NonPagedPool memory we allocated in cs423xReadRegistryConfig() */
ExFreePool(ConfigData.HwType);
/* reconnect default mixer line and control names from registry */
kpcMixerFixer(&ConfigData);
/* set the GLOBAL DEVICE INFO to the configuration values obtained from registry */
pGDI->DmaCaptureChannel = ConfigData.DmaCaptureChannel;
pGDI->DmaPlayChannel = ConfigData.DmaPlayChannel;
pGDI->DmaBufferSize = ConfigData.DmaBufferSize;
pGDI->SingleModeDMA = (BOOLEAN)ConfigData.SingleModeDMA;
pGDI->HwPort = ConfigData.HwPort;
pGDI->MemType = GDI_MEMTYPE_DEF;
pGDI->WssEnable = ConfigData.WssEnable;
pGDI->WssPort = ConfigData.WssPort;
pGDI->WssIrq = ConfigData.WssIrq;
pGDI->SynPort = ConfigData.SynPort;
pGDI->SBPort = ConfigData.SBPort;
pGDI->GameEnable = ConfigData.GameEnable;
pGDI->GamePort = ConfigData.GamePort;
pGDI->CtrlEnable = ConfigData.CtrlEnable;
pGDI->CtrlPort = ConfigData.CtrlPort;
pGDI->MpuEnable = ConfigData.MpuEnable;
pGDI->MpuPort = ConfigData.MpuPort;
pGDI->MpuIrq = ConfigData.MpuIrq;
pGDI->CDRomEnable = ConfigData.CDRomEnable;
pGDI->CDRomPort = ConfigData.CDRomPort;
if (ConfigData.MixerSettingsFound) {
RtlCopyMemory(&pGDI->MixerSettings, ConfigData.MixerSettings,
sizeof(MIXER_REGISTRY_DATA));
}
ExFreePool(ConfigData.MixerSettings);
if (pGDI->DmaCaptureChannel == pGDI->DmaPlayChannel) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:STATUS_INVALID_DEVICE_REQUEST)\n"));
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_BADDMA);
cs423xCleanup(pGDI);
return(STATUS_INVALID_DEVICE_REQUEST);
}
/*
*********************************************************************
** create each device
*********************************************************************
*/
/* create the WaveInDevice */
status = SoundCreateDevice(&DeviceInit[WaveInDevice], (UCHAR)0, pGDI->pDrvObj, pGDI,
&pGDI->WaveInInfo, &pGDI->Hw, WaveInDevice, &pGDI->DeviceObject[WaveInDevice]);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "creation FAILURE: %ls [0x%08x]\n",
DeviceInit[WaveInDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
/* save the device name where the non-kernel part can pick it up */
status = SoundSaveDeviceName(pGDI->RegPathName,
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveInDevice]->DeviceExtension);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "save name FAILURE: %ls [0x%08x]\n",
DeviceInit[WaveInDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
pGDI->DeviceInUse[WaveInDevice] = FALSE;
/* create the WaveOutDevice */
status = SoundCreateDevice(&DeviceInit[WaveOutDevice], (UCHAR)0, pGDI->pDrvObj, pGDI,
&pGDI->WaveOutInfo, &pGDI->Hw, WaveOutDevice, &pGDI->DeviceObject[WaveOutDevice]);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "creation FAILURE: %ls [0x%08x]\n",
DeviceInit[WaveOutDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
/* save the device name where the non-kernel part can pick it up */
status = SoundSaveDeviceName(pGDI->RegPathName,
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveOutDevice]->DeviceExtension);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "save name FAILURE: %ls [0x%08x]\n",
DeviceInit[WaveOutDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
pGDI->DeviceInUse[WaveOutDevice] = FALSE;
/* create the MixerDevice */
status = SoundCreateDevice(&DeviceInit[MixerDevice], (UCHAR)0, pGDI->pDrvObj, pGDI,
&pGDI->MixerInfo, &pGDI->Hw, MixerDevice, &pGDI->DeviceObject[MixerDevice]);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "creation FAILURE: %ls [0x%08x]\n",
DeviceInit[MixerDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
/* save the device name where the non-kernel part can pick it up */
status = SoundSaveDeviceName(pGDI->RegPathName,
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[MixerDevice]->DeviceExtension);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "save name FAILURE: %ls [0x%08x]\n",
DeviceInit[MixerDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
pGDI->DeviceInUse[MixerDevice] = FALSE;
/* create the AuxDevice */
status = SoundCreateDevice(&DeviceInit[AuxDevice], (UCHAR)0, pGDI->pDrvObj, pGDI,
NULL, &pGDI->Hw, AuxDevice, &pGDI->DeviceObject[AuxDevice]);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "creation FAILURE: %ls [0x%08x]\n",
DeviceInit[AuxDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
/* save the device name where the non-kernel part can pick it up */
status = SoundSaveDeviceName(pGDI->RegPathName,
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[AuxDevice]->DeviceExtension);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "save name FAILURE: %ls [0x%08x]\n",
DeviceInit[AuxDevice].PrototypeName, status));
_dbgprint((_PRT_ERRO, "DriverEntry(exit)\n"));
cs423xCleanup(pGDI);
return(status);
}
pGDI->DeviceInUse[AuxDevice] = FALSE;
/* register the WaveIn device to be called at shutdown time */
status = IoRegisterShutdownNotification(pGDI->DeviceObject[WaveInDevice]);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:IoRegisterShutdownNotification[0x%08x]]\n",
status));
cs423xCleanup(pGDI);
return(status);
}
/*
*********************************************************************
** initialize the hardware
*********************************************************************
*/
status = cs423xConfigSystem(pGDI);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:cs423xConfigSystem:[0x%08x]]\n", status));
cs423xCleanup(pGDI);
return(status);
}
_dbgprint((_PRT_STAT, "after cs423xConfigSystem: SUCCESS\n"));
status = cs423xConfigureHardware(pGDI);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:cs423xConfigureHardware:[0x%08x]]\n",
status));
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_BADCARD);
cs423xCleanup(pGDI);
return(status);
}
_dbgprint((_PRT_STAT, "after cs423xConfigureHardware: SUCCESS\n"));
/*
*********************************************************************
** Initialize the mixer device
*********************************************************************
*/
status = cs423xMixerInit(
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[MixerDevice]->DeviceExtension,
&pGDI->MixerSettings, ConfigData.MixerSettingsFound);
if (!NT_SUCCESS(status)) {
_dbgprint((_PRT_ERRO, "DriverEntry(exit:mixer initialization)\n"));
cs423xCleanup(pGDI);
return(status);
}
_dbgprint((_PRT_DBUG, "DriverEntry(exit:STATUS_SUCCESS)\n"));
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_OK);
return(STATUS_SUCCESS);
}
/*++
*********************************************************************************
* Chip GLOBAL DEVICE instance creation
*
* The global data structure represents an instance of one audio chip connected to the
* mother board on an IBM Personal Power System.
*
*********************************************************************************
--*/
PGLOBAL_DEVICE_INFO cs423xCreateGdi(PDRIVER_OBJECT pDObj, PUNICODE_STRING RegPathName)
{
PGLOBAL_DEVICE_INFO pGDI;
RTL_QUERY_REGISTRY_TABLE table[2];
SOUND_CONFIG_DATA ConfigData;
int len;
_dbgprint((_PRT_DBUG, "cs423xCreateGdi(enter)\n"));
/*
*********************************************************************
** allocate memory for GLOBAL data structure and name buffer
*********************************************************************
*/
/* allocate GLOBAL_DEVICE_INFO structure for this instance of chip */
pGDI = (PGLOBAL_DEVICE_INFO)ExAllocatePool(NonPagedPool, sizeof(GLOBAL_DEVICE_INFO));
if (pGDI == NULL) {
_dbgprint((_PRT_ERRO, "cs423xCreateGdi(exit:STATUS_INSUFFICIENT_RESOURCES_1)\n"));
return(pGDI);
}
/* clear the memory to zeroes */
RtlZeroMemory(pGDI, sizeof(GLOBAL_DEVICE_INFO));
/* allocate non-paged memory for registry path name */
len = RegPathName->Length + sizeof(CS423X_REGPATHSEP) + sizeof(PARMS_SUBKEY) +
sizeof(CS423X_REGPATHSEP) + sizeof(CS423X_REGDVC0PATH) + sizeof(UNICODE_NULL);
if ((pGDI->RegPathName = (PWSTR)ExAllocatePool(NonPagedPool, len)) == NULL) {
ExFreePool(pGDI);
_dbgprint((_PRT_ERRO, "cs423xCreateGdi(exit:STATUS_INSUFFICIENT_RESOURCES_2)\n"));
return((PGLOBAL_DEVICE_INFO)NULL);
}
/* clear the memory to zeroes */
RtlZeroMemory(pGDI->RegPathName, len);
/*
*********************************************************************
** initialize GLOBAL_DEVICE_INFO
*********************************************************************
*/
/* initialize registry path string */
RtlCopyMemory(pGDI->RegPathName, RegPathName->Buffer, RegPathName->Length);
pGDI->RegPathName[RegPathName->Length / sizeof(WCHAR) + 1] = UNICODE_NULL;
wcscat(pGDI->RegPathName, CS423X_REGPATHSEP);
wcscat(pGDI->RegPathName, PARMS_SUBKEY);
wcscat(pGDI->RegPathName, CS423X_REGPATHSEP);
wcscat(pGDI->RegPathName, CS423X_REGDVC0PATH);
_dbgprint((_PRT_DBUG, "pGDI->RegPathName: %ls\n", pGDI->RegPathName));
/* initialize GDI elements */
pGDI->Key = GDI_KEY;
pGDI->BogusInterrupts = 0;
pGDI->InterruptCount = 0;
pGDI->pDrvObj = pDObj;
KeInitializeMutex(&pGDI->DriverMutex, DISPATCH_LEVEL);
/* initialize Hardware Context elements */
pGDI->Hw.Key = HARDWARE_KEY;
KeInitializeMutex(&pGDI->Hw.HwMutex, DISPATCH_LEVEL);
/* initialize the playback and record WAVE_INFO structures */
SoundInitializeWaveInfo(&pGDI->WaveOutInfo, SoundAutoInitDMA, cs423xQueryFormat,
&pGDI->Hw);
SoundInitializeWaveInfo(&pGDI->WaveInInfo, SoundAutoInitDMA, cs423xQueryFormat,
&pGDI->Hw);
/*
*********************************************************************
* Find Bus Number - used in HalTranslateBusAddress()
*********************************************************************
*/
if (NT_SUCCESS(SoundGetBusNumber(Isa, &pGDI->BusNumber))) {
pGDI->BusType = Isa;
_dbgprint((_PRT_STAT, "Isa [pGDI->Busnumber: 0x%08x]\n", pGDI->BusNumber));
}
else {
if (NT_SUCCESS(SoundGetBusNumber(Eisa, &pGDI->BusNumber))) {
pGDI->BusType = Eisa;
_dbgprint((_PRT_STAT, "Eisa [pGDI->Busnumber: 0x%08x]\n", pGDI->BusNumber));
}
else {
ExFreePool(pGDI);
_dbgprint((_PRT_ERRO,
"cs423xCreateGdi(exit:STATUS_DEVICE_DOES_NOT_EXIST)\n"));
return((PGLOBAL_DEVICE_INFO)NULL);
}
}
_dbgprint((_PRT_DBUG, "cs423xCreateGdi(exit:[pGDI=0x%08x])\n", pGDI));
return(pGDI);
}
/*++
********************************************************************************
* Unload Function
********************************************************************************
--*/
VOID cs423xUnload(IN OUT PDRIVER_OBJECT pDObj)
{
PLOCAL_DEVICE_INFO pLDI;
PGLOBAL_DEVICE_INFO pGDI;
_dbgprint((_PRT_DBUG, "enter cs423xUnload(pDObj: 0x%08x)\n", pDObj));
/* get the global device info pointer */
pLDI = pDObj->DeviceObject->DeviceExtension;
pGDI = pLDI->pGlobalInfo;
/* unregister the WaveIn device for shutdown */
IoUnregisterShutdownNotification(pGDI->DeviceObject[WaveInDevice]);
/* save the mixer setting in the registry */
cs423xSaveMixerSettings(pGDI);
/* delete the instance of the GLOBAL DEVICE INFO structure */
cs423xCleanup(pGDI);
_dbgprint((_PRT_DBUG, "exit cs423xUnload()\n"));
return;
}
/*++
*********************************************************************************
* Shutdown Function
*********************************************************************************
--*/
NTSTATUS cs423xShutdown(IN PDEVICE_OBJECT pDObj, IN PIRP pIrp)
{
NTSTATUS status;
PLOCAL_DEVICE_INFO pLDI;
PGLOBAL_DEVICE_INFO pGDI;
_dbgprint((_PRT_DBUG, "cs423xShutdown(enter)\n"));
/* get the global device info pointer */
pLDI = pDObj->DeviceExtension;
pGDI = pLDI->pGlobalInfo;
/* save the mixer setting in the registry */
if (pGDI->DeviceObject[MixerDevice])
cs423xSaveMixerSettings(pGDI);
status = STATUS_SUCCESS;
_dbgprint((_PRT_DBUG, "cs423xShutdown(exit:[status:0x%08x])\n", status));
return(status);
}
/*++
********************************************************************************
* Cleanup Function
********************************************************************************
--*/
VOID cs423xCleanup(IN PGLOBAL_DEVICE_INFO pGDI)
{
PDRIVER_OBJECT pDObj;
HANDLE hKey;
_dbgprint((_PRT_DBUG, "cs423xCleanup(enter)\n"));
if (!pGDI)
return;
/* disconnect the interrupt */
if (pGDI->WaveInInfo.Interrupt)
IoDisconnectInterrupt(pGDI->WaveInInfo.Interrupt);
/* unmap the memory at the IO port address */
if (pGDI->Hw.WssPortbase && (pGDI->MemType == 0))
MmUnmapIoSpace(pGDI->Hw.WssPortbase, NUMBER_OF_SOUND_PORTS);
SoundFreeCommonBuffer(&pGDI->WaveInInfo.DMABuf);
SoundFreeCommonBuffer(&pGDI->WaveOutInfo.DMABuf);
/*
*********************************************************************
** free all devices for this driver
*********************************************************************
*/
SoundFreeDevice(pGDI->DeviceObject[WaveInDevice]);
SoundFreeDevice(pGDI->DeviceObject[WaveOutDevice]);
SoundFreeDevice(pGDI->DeviceObject[MixerDevice]);
SoundFreeDevice(pGDI->DeviceObject[AuxDevice]);
/* delete the devices node in the registry and deallocate the name buffer */
if (pGDI->RegPathName) {
_dbgprint((_PRT_STAT, "deleting pGDI->RegPathName+Devices: %ls\n", pGDI->RegPathName));
if (NT_SUCCESS(SoundOpenDevicesKey(pGDI->RegPathName, &hKey))) {
ZwDeleteKey(hKey);
ZwClose(hKey);
}
ExFreePool(pGDI->RegPathName);
}
/* free the GLOBAL DEVICE INFO structure */
ExFreePool(pGDI);
_dbgprint((_PRT_DBUG, "cs423xCleanup(exit:VOID)\n"));
return;
}