mirror of https://github.com/lianthony/NT4.0
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.
780 lines
31 KiB
780 lines
31 KiB
/*++
|
|
*******************************************************************************
|
|
* Copyright (c) 1995 IBM Corporation
|
|
*
|
|
* Module Name:
|
|
*
|
|
* Abstract:
|
|
*
|
|
* Author:
|
|
*
|
|
* Environment:
|
|
*
|
|
* Comments:
|
|
*
|
|
* Rev History:
|
|
*
|
|
*******************************************************************************
|
|
--*/
|
|
|
|
#include "common.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT, cs423xReadRegistryConfig)
|
|
#pragma alloc_text(INIT, cs423xConfigSystem)
|
|
#pragma alloc_text(INIT, cs423xInitializePort)
|
|
#pragma alloc_text(INIT, cs423xInitializeInterrupt)
|
|
#pragma alloc_text(INIT, cs423xInitializeDma)
|
|
#endif /* ALLOC_PRAGMA */
|
|
|
|
/*
|
|
*********************************************************************
|
|
** hardware specific declarations/definitions
|
|
*********************************************************************
|
|
*/
|
|
|
|
ULONG _cs4231_valid_ports[] = VALID_CS4231_IO_PORTS;
|
|
ULONG _cs4232_valid_ports[] = VALID_CS4232_IO_PORTS;
|
|
ULONG _cs4236_valid_ports[] = VALID_CS4236_IO_PORTS;
|
|
ULONG _cs423x_valid_ports[] = VALID_CS423x_IO_PORTS;
|
|
|
|
ULONG _cs4231_valid_irqs[] = VALID_CS4231_INTERRUPTS;
|
|
ULONG _cs4232_valid_irqs[] = VALID_CS4232_INTERRUPTS;
|
|
ULONG _cs4236_valid_irqs[] = VALID_CS4236_INTERRUPTS;
|
|
ULONG _cs423x_valid_irqs[] = VALID_CS423x_INTERRUPTS;
|
|
|
|
ULONG _cs4231_valid_dma[] = VALID_CS4231_DMA_CHANNELS;
|
|
ULONG _cs4232_valid_dma[] = VALID_CS4232_DMA_CHANNELS;
|
|
ULONG _cs4236_valid_dma[] = VALID_CS4236_DMA_CHANNELS;
|
|
ULONG _cs423x_valid_dma[] = VALID_CS423x_DMA_CHANNELS;
|
|
|
|
/*++
|
|
********************************************************************************
|
|
* Read Configuration Function
|
|
* system constants (SOUND_REG...) are defined in X:\nt\private\inc\soundcfg.h
|
|
********************************************************************************
|
|
--*/
|
|
NTSTATUS cs423xReadRegistryConfig(IN PWSTR ValueName, IN ULONG ValueType,
|
|
IN PVOID ValueData, IN ULONG ValueLength,
|
|
IN PVOID Context, IN PVOID EntryContext)
|
|
{
|
|
PSOUND_CONFIG_DATA ConfigData;
|
|
int len;
|
|
ULONG ul;
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xReadRegistryConfig(enter)\n"));
|
|
|
|
ConfigData = Context;
|
|
|
|
switch (ValueType) {
|
|
case REG_SZ:
|
|
if (_wcsicmp((PWSTR)ValueName, CS423X_REG_HWTYPE) == 0) {
|
|
len = ValueLength + sizeof(UNICODE_NULL);
|
|
if (ConfigData->HwType = (PWSTR)ExAllocatePool(NonPagedPool, len)) {
|
|
RtlCopyMemory(ConfigData->HwType, ValueData, ValueLength);
|
|
ConfigData->HwType[ValueLength/sizeof(WCHAR)+1] = UNICODE_NULL;
|
|
_dbgprint((_PRT_STAT, "Chip Type: %ls\n", ConfigData->HwType));
|
|
}
|
|
else {
|
|
_dbgprint((_PRT_ERRO, "STATUS_INSUFFICIENT_RESOURCES)\n"));
|
|
}
|
|
}
|
|
else {
|
|
_dbgprint((_PRT_STAT, "Undefined value name for type REG_SZ: %ls\n",
|
|
ValueData));
|
|
}
|
|
break;
|
|
case REG_DWORD:
|
|
/* Internal Device Info */
|
|
if (_wcsicmp(ValueName, CS423X_REG_HWPORTADDRESS) == 0) {
|
|
ConfigData->HwPort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read HW PortAddr: 0x%08x\n", ConfigData->HwPort));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_DMABUFFERSIZE) == 0) {
|
|
ConfigData->DmaBufferSize = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read Buffer size : %x\n", ConfigData->DmaBufferSize));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_SINGLEMODEDMA) == 0) {
|
|
ConfigData->SingleModeDMA = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT,
|
|
"Read SingleMode DMA: %x\n", ConfigData->SingleModeDMA));
|
|
}
|
|
|
|
/* Logical Device 0 */
|
|
else if (_wcsicmp(ValueName, CS423X_REG_WSSENABLE) == 0) {
|
|
ul = *(PULONG)ValueData;
|
|
ConfigData->WssEnable = (BOOLEAN)ul;
|
|
_dbgprint((_PRT_STAT, "Read WssEnable: %x\n", ConfigData->WssEnable));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_WSSPORT) == 0) {
|
|
ConfigData->WssPort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read WssPort: 0x%08x\n", ConfigData->WssPort));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_SYNPORT) == 0) {
|
|
ConfigData->SynPort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read SynPort: 0x%08x\n", ConfigData->SynPort));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_SBPORT) == 0) {
|
|
ConfigData->SBPort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read SBPort: 0x%08x\n", ConfigData->SBPort));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_WSSIRQ) == 0) {
|
|
ConfigData->WssIrq = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read WssIrq: 0x%08x\n", ConfigData->WssIrq));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_DMA_PLAY_CHAN) == 0) {
|
|
ConfigData->DmaPlayChannel = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT,
|
|
"Read DMA Chan Out: 0x%08x\n", ConfigData->DmaPlayChannel));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_DMA_CAPT_CHAN) == 0) {
|
|
ConfigData->DmaCaptureChannel = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT,
|
|
"Read DMA Chan In: 0x%08x\n", ConfigData->DmaCaptureChannel));
|
|
}
|
|
|
|
/* Logical Device 1 */
|
|
else if (_wcsicmp(ValueName, CS423X_REG_GAMEENABLE) == 0) {
|
|
ul = *(PULONG)ValueData;
|
|
ConfigData->GameEnable = (BOOLEAN)ul;
|
|
_dbgprint((_PRT_STAT, "Read GameEnable: %x\n", ConfigData->GameEnable));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_GAMEPORT) == 0) {
|
|
ConfigData->GamePort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read GamePort: %x\n", ConfigData->GamePort));
|
|
}
|
|
|
|
/* Logical Device 2 */
|
|
else if (_wcsicmp(ValueName, CS423X_REG_CTRLENABLE) == 0) {
|
|
ul = *(PULONG)ValueData;
|
|
ConfigData->CtrlEnable = (BOOLEAN)ul;
|
|
_dbgprint((_PRT_STAT, "Read CtrlEnable: %x\n", ConfigData->CtrlEnable));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_CTRLPORT) == 0) {
|
|
ConfigData->CtrlPort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read CtrlPort: %x\n", ConfigData->CtrlPort));
|
|
}
|
|
|
|
/* Logical Device 3 */
|
|
else if (_wcsicmp(ValueName, CS423X_REG_MPUENABLE) == 0) {
|
|
ul = *(PULONG)ValueData;
|
|
ConfigData->MpuEnable = (BOOLEAN)ul;
|
|
_dbgprint((_PRT_STAT, "Read MpuEnable: %x\n", ConfigData->MpuEnable));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_MPUPORT) == 0) {
|
|
ConfigData->MpuPort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read MpuPort: %x\n", ConfigData->MpuPort));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_MPUIRQ) == 0) {
|
|
ConfigData->MpuIrq = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read MpuIrq: %x\n", ConfigData->MpuIrq));
|
|
}
|
|
|
|
/* Logical Device 4 */
|
|
else if (_wcsicmp(ValueName, CS423X_REG_CDROMENABLE) == 0) {
|
|
ul = *(PULONG)ValueData;
|
|
ConfigData->CDRomEnable = (BOOLEAN)ul;
|
|
_dbgprint((_PRT_STAT, "Read CDRomEnable: %x\n", ConfigData->CDRomEnable));
|
|
}
|
|
else if (_wcsicmp(ValueName, CS423X_REG_CDROMPORT) == 0) {
|
|
ConfigData->CDRomPort = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Read CDRom Port: %x\n", ConfigData->CDRomPort));
|
|
}
|
|
|
|
/* Input Signal Definitions */
|
|
else if (_wcsicmp(ValueName, KPC423X_REG_AUX1INPUT) == 0) {
|
|
ConfigData->Aux1InputSignal = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Aux1InputSignal: %x\n", ConfigData->Aux1InputSignal));
|
|
}
|
|
else if (_wcsicmp(ValueName, KPC423X_REG_AUX2INPUT) == 0) {
|
|
ConfigData->Aux2InputSignal = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "Aux2InputSignal: %x\n", ConfigData->Aux2InputSignal));
|
|
}
|
|
else if (_wcsicmp(ValueName, KPC423X_REG_LINEINPUT) == 0) {
|
|
ConfigData->LineInputSignal = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "LineInputSignal: %x\n", ConfigData->LineInputSignal));
|
|
}
|
|
else if (_wcsicmp(ValueName, KPC423X_REG_MICINPUT) == 0) {
|
|
ConfigData->MicInputSignal = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "MicInputSignal: %x\n", ConfigData->MicInputSignal));
|
|
}
|
|
else if (_wcsicmp(ValueName, KPC423X_REG_MONOINPUT) == 0) {
|
|
ConfigData->MonoInputSignal = *(PULONG)ValueData;
|
|
_dbgprint((_PRT_STAT, "MonoInputSignal: %x\n", ConfigData->MonoInputSignal));
|
|
}
|
|
|
|
/* bad news - unexpected variable */
|
|
else {
|
|
_dbgprint((_PRT_STAT, "Undefined value name for type REG_DWORD\n"));
|
|
}
|
|
break;
|
|
case REG_BINARY:
|
|
if (_wcsicmp(ValueName, CS423X_REG_MIXERSETTINGS) == 0) {
|
|
if (ValueLength == (sizeof(MIXER_REGISTRY_DATA))) {
|
|
RtlCopyMemory(ConfigData->MixerSettings, ValueData, ValueLength);
|
|
ConfigData->MixerSettingsFound = TRUE;
|
|
_dbgprint((_PRT_STAT, "Read Mixer Settings: SUCCESS\n"));
|
|
}
|
|
else {
|
|
_dbgprint((_PRT_STAT, "Read Mixer Settings: FAILURE\n"));
|
|
_dbgprint((_PRT_STAT, "ValueLength: %d sizeof: %d\n", ValueLength,
|
|
(sizeof(MIXER_CONTROL_DATA_ITEM) * NumberOfMixerControls)));
|
|
ConfigData->MixerSettingsFound = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
_dbgprint((_PRT_STAT, "Undefined value name for type REG_BINARY\n"));
|
|
}
|
|
break;
|
|
default:
|
|
_dbgprint((_PRT_STAT, "Undefined data type\n"));
|
|
break;
|
|
}
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xReadRegistryConfig(exit:STATUS_SUCCESS)\n"));
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
#ifdef CS423X_DEBUG_ON
|
|
#define _DBSWITCH _PRT_WARN
|
|
VOID cs423xDbgDisplayConfig(SOUND_CONFIG_DATA *pcd)
|
|
{
|
|
_dbgprint((_DBSWITCH, "======= - Config Data - =======\n"));
|
|
|
|
if (pcd->HwType)
|
|
_dbgprint((_DBSWITCH, " HW Type: %ls\n", pcd->HwType));
|
|
else
|
|
_dbgprint((_DBSWITCH, " HW Type: <NULL>\n"));
|
|
_dbgprint((_DBSWITCH, " HwPort: 0x%08x\n", pcd->HwPort));
|
|
_dbgprint((_DBSWITCH, " DmaBufferSize: 0x%08x\n", pcd->DmaBufferSize));
|
|
_dbgprint((_DBSWITCH, " SingleModeDMA: 0x%08x\n", pcd->SingleModeDMA));
|
|
|
|
_dbgprint((_DBSWITCH, " WssEnable: 0x%08x\n", pcd->WssEnable));
|
|
_dbgprint((_DBSWITCH, " WssPort: 0x%08x\n", pcd->WssPort));
|
|
_dbgprint((_DBSWITCH, " SynPort: 0x%08x\n", pcd->SynPort));
|
|
_dbgprint((_DBSWITCH, " SBPort: 0x%08x\n", pcd->SBPort));
|
|
_dbgprint((_DBSWITCH, " WssIrq: 0x%08x\n", pcd->WssIrq));
|
|
_dbgprint((_DBSWITCH, " DmaPlayChannel: 0x%08x\n", pcd->DmaPlayChannel));
|
|
_dbgprint((_DBSWITCH, " DmaCaptureChannel: 0x%08x\n", pcd->DmaCaptureChannel));
|
|
|
|
_dbgprint((_DBSWITCH, " GameEnable: 0x%08x\n", pcd->GameEnable));
|
|
_dbgprint((_DBSWITCH, " GamePort: 0x%08x\n", pcd->GamePort));
|
|
|
|
_dbgprint((_DBSWITCH, " CtrlEnable: 0x%08x\n", pcd->CtrlEnable));
|
|
_dbgprint((_DBSWITCH, " CtrlPort: 0x%08x\n", pcd->CtrlPort));
|
|
|
|
_dbgprint((_DBSWITCH, " MpuEnable: 0x%08x\n", pcd->MpuEnable));
|
|
_dbgprint((_DBSWITCH, " MpuPort: 0x%08x\n", pcd->MpuPort));
|
|
_dbgprint((_DBSWITCH, " MpuIrq: 0x%08x\n", pcd->MpuIrq));
|
|
|
|
_dbgprint((_DBSWITCH, " CDRomEnable: 0x%08x\n", pcd->CDRomEnable));
|
|
_dbgprint((_DBSWITCH, " CDRomPort: 0x%08x\n", pcd->CDRomPort));
|
|
|
|
_dbgprint((_DBSWITCH, " MixerSettingsFound: 0x%08x\n", pcd->MixerSettingsFound));
|
|
|
|
_dbgprint((_DBSWITCH, " Aux1InputSignal: 0x%08x\n", pcd->Aux1InputSignal));
|
|
_dbgprint((_DBSWITCH, " Aux2InputSignal: 0x%08x\n", pcd->Aux2InputSignal));
|
|
_dbgprint((_DBSWITCH, " LineInputSignal: 0x%08x\n", pcd->LineInputSignal));
|
|
_dbgprint((_DBSWITCH, " MicInputSignal: 0x%08x\n", pcd->MicInputSignal));
|
|
_dbgprint((_DBSWITCH, " MonoInputSignal: 0x%08x\n", pcd->MonoInputSignal));
|
|
|
|
_dbgprint((_DBSWITCH, "======= - Config Data - =======\n"));
|
|
|
|
return;
|
|
}
|
|
#endif /* CS423X_DEBUG_ON */
|
|
|
|
/*
|
|
*********************************************************************
|
|
**
|
|
*********************************************************************
|
|
*/
|
|
NTSTATUS cs423xInitializePort(PGLOBAL_DEVICE_INFO pGDI)
|
|
{
|
|
NTSTATUS status;
|
|
PULONG vpp;
|
|
BOOLEAN valid;
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xInitializePort(entry)\n"));
|
|
_dbgprint((_PRT_DBUG, "pGDI->WssPort: 0x%08x\n", pGDI->WssPort));
|
|
_dbgprint((_PRT_DBUG, "pGDI->Hw.WssPortbase: 0x%08x\n", pGDI->Hw.WssPortbase));
|
|
_dbgprint((_PRT_DBUG, "pGDI->Hw.Type: 0x%08x\n", pGDI->Hw.Type));
|
|
|
|
/* validate type and prepare to validate specified port */
|
|
switch (pGDI->Hw.Type) {
|
|
case hwtype_cs4231:
|
|
vpp = _cs4231_valid_ports;
|
|
break;
|
|
case hwtype_cs4232:
|
|
vpp = _cs4232_valid_ports;
|
|
break;
|
|
case hwtype_cs4236:
|
|
vpp = _cs4236_valid_ports;
|
|
break;
|
|
case hwtype_cs4231x:
|
|
case hwtype_cs4232x:
|
|
case hwtype_cs4236x:
|
|
vpp = _cs423x_valid_ports;
|
|
break;
|
|
default:
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializePort(exit:STATUS_DEVICE_CONFIGURATION_ERROR_1)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
break;
|
|
}
|
|
|
|
/* chip type is valid - now cycle through list of valid ports */
|
|
valid = FALSE;
|
|
while ((!valid) && (*vpp != HW_END_OF_LIST)) {
|
|
if (pGDI->WssPort == *vpp) {
|
|
valid = TRUE;
|
|
break;
|
|
}
|
|
vpp++;
|
|
}
|
|
|
|
if (!valid) {
|
|
/* specified port is NOT valid for current audio chip */
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializePort(exit:STATUS_DEVICE_CONFIGURATION_ERROR_2)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
/* specified port IS valid for native audio chip */
|
|
_dbgprint((_PRT_STAT, "found port: [*vpp:0x%08x]\n", *vpp));
|
|
|
|
/* check if port is valid for current system - i.e., conflicting port? */
|
|
/* use WaveInDevice - any device would work */
|
|
status = SoundReportResourceUsage(pGDI->DeviceObject[WaveInDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
NULL,
|
|
&pGDI->WssPort,
|
|
NUMBER_OF_SOUND_PORTS);
|
|
|
|
/* check if report usage was successful - i.e., if port conflict exists */
|
|
if (!NT_SUCCESS(status)) {
|
|
/* port is NOT valid for current system - apparent port conflict */
|
|
_dbgprint((_PRT_ERRO, "after SoundReportResourceUsage[status=0x%08x]\n", status));
|
|
return(status);
|
|
}
|
|
|
|
/* map the port address and acquire the full 32 bit address */
|
|
pGDI->Hw.WssPortbase = SoundMapPortAddress(pGDI->BusType, pGDI->BusNumber,
|
|
pGDI->WssPort, NUMBER_OF_SOUND_PORTS,
|
|
&pGDI->MemType);
|
|
|
|
|
|
/* check if the mapping operation was successful */
|
|
if (!pGDI->Hw.WssPortbase) {
|
|
_dbgprint((_PRT_ERRO,
|
|
"after SoundMapPortAddress: STATUS_DEVICE_CONFIGURATION_ERROR_3)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xInitializePort(exit:STATUS_SUCCESS])\n"));
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
/*
|
|
*********************************************************************
|
|
**
|
|
*********************************************************************
|
|
*/
|
|
NTSTATUS cs423xInitializeInterrupt(PGLOBAL_DEVICE_INFO pGDI)
|
|
{
|
|
NTSTATUS status;
|
|
PULONG vip;
|
|
BOOLEAN valid;
|
|
PKSERVICE_ROUTINE isrvfunc;
|
|
|
|
_dbgprint((_PRT_DBUG, "enter cs423xInitializeInterrupt(pGDI: 0x%08x)\n", pGDI));
|
|
_dbgprint((_PRT_DBUG, "pGDI->WssIrq: 0x%08x\n", pGDI->WssIrq));
|
|
|
|
/* initialize local variables */
|
|
isrvfunc = (PKSERVICE_ROUTINE)NULL;
|
|
vip = (ULONG)NULL;
|
|
|
|
/* validate type and prepare to validate specified interrupt */
|
|
switch (pGDI->Hw.Type) {
|
|
case hwtype_cs4231:
|
|
vip = _cs4231_valid_irqs;
|
|
isrvfunc = cs423xISR;
|
|
break;
|
|
case hwtype_cs4232:
|
|
vip = _cs4232_valid_irqs;
|
|
isrvfunc = cs423xISR;
|
|
break;
|
|
case hwtype_cs4236:
|
|
vip = _cs4236_valid_irqs;
|
|
isrvfunc = cs423xISR;
|
|
break;
|
|
case hwtype_cs4231x:
|
|
case hwtype_cs4232x:
|
|
case hwtype_cs4236x:
|
|
vip = _cs423x_valid_irqs;
|
|
isrvfunc = cs423xISR;
|
|
break;
|
|
default:
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializeInterrupt(exit:STATUS_DEVICE_CONFIGURATION_ERROR_1)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
break;
|
|
}
|
|
|
|
/* keep this until all device ISRs have been defined */
|
|
if (!vip || !isrvfunc) {
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializeInterrupt(exit:STATUS_DEVICE_CONFIGURATION_ERROR_2)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
/* chip type is valid - now cycle through list of valid IRQS */
|
|
valid = FALSE;
|
|
while ((!valid) && (*vip != HW_END_OF_LIST)) {
|
|
if (pGDI->WssIrq == *vip) {
|
|
valid = TRUE;
|
|
break;
|
|
}
|
|
vip++;
|
|
}
|
|
|
|
if (!valid) {
|
|
/* specified irq is NOT valid for current audio chip */
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializeInterrupt(exit:STATUS_DEVICE_CONFIGURATION_ERROR_3)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
/* specified port IS valid for native audio chip */
|
|
_dbgprint((_PRT_STAT, "found IRQ: [*vip:0x%08x]\n", *vip));
|
|
|
|
/* check if port is valid for current system - i.e., conflicting IRQ? */
|
|
/* use WaveInDevice - any device would work */
|
|
status = SoundReportResourceUsage(pGDI->DeviceObject[WaveInDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
&pGDI->WssIrq,
|
|
Latched,
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
0);
|
|
|
|
/* check if report usage was successful - i.e., if interrupt conflict exists */
|
|
if (!NT_SUCCESS(status)) {
|
|
/* interrupt is NOT valid for current system - apparent IRQ conflict */
|
|
_dbgprint((_PRT_ERRO, "after SoundReportResourceUsage[status=0x%08x]\n", status));
|
|
return(status);
|
|
}
|
|
|
|
/* register interrupt with NT */
|
|
status = SoundConnectInterrupt(pGDI->WssIrq,
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
cs423xISR,
|
|
(PVOID)pGDI,
|
|
Latched,
|
|
FALSE,
|
|
&pGDI->WaveInInfo.Interrupt);
|
|
|
|
/* make sure both playback and capture waveInfo structures */
|
|
/* contain reference to the same interrupt reference */
|
|
pGDI->WaveOutInfo.Interrupt = pGDI->WaveInInfo.Interrupt;
|
|
|
|
/* check if the connection operation was successful */
|
|
if (!NT_SUCCESS(status)) {
|
|
_dbgprint((_PRT_ERRO,
|
|
"after SoundConnectInterrupt: STATUS_DEVICE_CONFIGURATION_ERROR_3)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xInitializeInterrupt(exit:STATUS_SUCCESS])\n"));
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
/*
|
|
*********************************************************************
|
|
**
|
|
*********************************************************************
|
|
*/
|
|
NTSTATUS cs423xInitializeDma(PGLOBAL_DEVICE_INFO pGDI)
|
|
{
|
|
NTSTATUS status;
|
|
PULONG ivdp;
|
|
PULONG ovdp;
|
|
BOOLEAN valid;
|
|
DEVICE_DESCRIPTION DvcDesc;
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xInitializeDma(entry)\n"));
|
|
_dbgprint((_PRT_DBUG, "pGDI->DmaCaptureChannel: 0x%08x\n", pGDI->DmaCaptureChannel));
|
|
_dbgprint((_PRT_DBUG, "pGDI->DmaPlayChannel: 0x%08x\n", pGDI->DmaPlayChannel));
|
|
|
|
/* validate type and prepare to validate specified interrupt */
|
|
switch (pGDI->Hw.Type) {
|
|
case hwtype_cs4231:
|
|
ovdp = ivdp = _cs4231_valid_dma;
|
|
break;
|
|
case hwtype_cs4232:
|
|
ovdp = ivdp = _cs4232_valid_dma;
|
|
break;
|
|
case hwtype_cs4236:
|
|
ovdp = ivdp = _cs4236_valid_dma;
|
|
break;
|
|
case hwtype_cs4231x:
|
|
case hwtype_cs4232x:
|
|
case hwtype_cs4236x:
|
|
ovdp = ivdp = _cs423x_valid_dma;
|
|
break;
|
|
default:
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializeDma(exit:STATUS_DEVICE_CONFIGURATION_ERROR_1)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
*********************************************************************
|
|
** we know that DmaCaptureChannel != DmaPlayChannel - see DriverEntry()
|
|
** now check to see if both are valid
|
|
*********************************************************************
|
|
*/
|
|
|
|
/* chip type is valid - now cycle through list of valid DMA channels - Input */
|
|
valid = FALSE;
|
|
while ((!valid) && (*ivdp != HW_END_OF_LIST)) {
|
|
if (pGDI->DmaCaptureChannel == *ivdp) {
|
|
valid = TRUE;
|
|
break;
|
|
}
|
|
ivdp++;
|
|
}
|
|
|
|
if (!valid) {
|
|
/* specified Input DMA is NOT valid for current audio chip */
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializeDma(exit:STATUS_DEVICE_CONFIGURATION_ERROR_2)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
/* input DMA channel is valid for device */
|
|
_dbgprint((_PRT_STAT, "found Input DMA: [*ivdp:0x%08x]\n", *ivdp));
|
|
|
|
/* cycle through list of valid Output DMA channels */
|
|
valid = FALSE;
|
|
while ((!valid) && (*ovdp != HW_END_OF_LIST)) {
|
|
if (pGDI->DmaPlayChannel == *ovdp) {
|
|
valid = TRUE;
|
|
break;
|
|
}
|
|
ovdp++;
|
|
}
|
|
|
|
if (!valid) {
|
|
/* specified Output DMA is NOT valid for current audio chip */
|
|
_dbgprint((_PRT_ERRO,
|
|
"cs423xInitializeDma(exit:STATUS_DEVICE_CONFIGURATION_ERROR_3)\n"));
|
|
return(STATUS_DEVICE_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
/* output DMA channel is valid for device */
|
|
_dbgprint((_PRT_STAT, "found Output DMA: [*ovdp:0x%08x]\n", *ovdp));
|
|
|
|
/*
|
|
*********************************************************************
|
|
** we now know that both DMA channels are valid
|
|
** see if they conflict with other system resources
|
|
*********************************************************************
|
|
*/
|
|
|
|
/* check if Input DMA is valid for current system - i.e., conflicting DMA? */
|
|
/* use WaveInDevice - any device would work */
|
|
status = SoundReportResourceUsage(pGDI->DeviceObject[WaveInDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
&pGDI->DmaCaptureChannel,
|
|
NULL,
|
|
0);
|
|
|
|
/* check if report usage was successful - i.e., if DMA conflict exists */
|
|
if (!NT_SUCCESS(status)) {
|
|
/* DMA is NOT valid for current system - apparent DMA conflict */
|
|
_dbgprint((_PRT_ERRO, "after SoundReportResourceUsage[status=0x%08x]\n", status));
|
|
return(status);
|
|
}
|
|
|
|
_dbgprint((_PRT_STAT, "Input SoundReportResourceUsage: SUCCESS\n"));
|
|
|
|
/* check if Output DMA is valid for current system - i.e., conflicting DMA? */
|
|
/* use WaveOutDevice since WaveIntDevice has been used */
|
|
status = SoundReportResourceUsage(pGDI->DeviceObject[WaveOutDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
&pGDI->DmaPlayChannel,
|
|
NULL,
|
|
0);
|
|
|
|
/* check if report usage was successful - i.e., if DMA conflict exists */
|
|
if (!NT_SUCCESS(status)) {
|
|
/* DMA is NOT valid for current system - apparent DMA conflict */
|
|
_dbgprint((_PRT_ERRO, "after SoundReportResourceUsage[status=0x%08x]\n", status));
|
|
return(status);
|
|
}
|
|
|
|
_dbgprint((_PRT_STAT, "Output SoundReportResourceUsage: SUCCESS\n"));
|
|
|
|
/*
|
|
*********************************************************************
|
|
** both DMA channels are valid and are available for our use
|
|
** now try to allocate the common buffers
|
|
*********************************************************************
|
|
*/
|
|
|
|
/* first try input channel */
|
|
RtlZeroMemory(&DvcDesc, sizeof(DEVICE_DESCRIPTION));
|
|
DvcDesc.Version = DEVICE_DESCRIPTION_VERSION;
|
|
DvcDesc.AutoInitialize = TRUE;
|
|
if (pGDI->SingleModeDMA)
|
|
DvcDesc.DemandMode = FALSE;
|
|
else
|
|
DvcDesc.DemandMode = TRUE;
|
|
DvcDesc.ScatterGather = FALSE;
|
|
DvcDesc.DmaChannel = pGDI->DmaCaptureChannel;
|
|
DvcDesc.InterfaceType = pGDI->BusType;
|
|
DvcDesc.DmaWidth = Width8Bits;
|
|
DvcDesc.DmaSpeed = Compatible;
|
|
DvcDesc.MaximumLength = pGDI->DmaBufferSize;
|
|
DvcDesc.BusNumber = pGDI->BusNumber;
|
|
|
|
/* allocate buffer and save reference to the DMA Adapter */
|
|
status = SoundGetCommonBuffer(&DvcDesc, &pGDI->WaveInInfo.DMABuf);
|
|
pGDI->InAdapter = pGDI->WaveInInfo.DMABuf.AdapterObject[0];
|
|
|
|
/* check if common buffer allocation was successful */
|
|
if (!NT_SUCCESS(status)) {
|
|
/* failure */
|
|
_dbgprint((_PRT_ERRO, "after SoundGetCommonBuffer In [status=0x%08x]\n", status));
|
|
return(status);
|
|
}
|
|
|
|
_dbgprint((_PRT_STAT, "Input SoundGetCommonBuffer: SUCCESS\n"));
|
|
|
|
/* now try output channel */
|
|
RtlZeroMemory(&DvcDesc, sizeof(DEVICE_DESCRIPTION));
|
|
DvcDesc.Version = DEVICE_DESCRIPTION_VERSION;
|
|
DvcDesc.AutoInitialize = TRUE;
|
|
if (pGDI->SingleModeDMA)
|
|
DvcDesc.DemandMode = FALSE;
|
|
else
|
|
DvcDesc.DemandMode = TRUE;
|
|
DvcDesc.ScatterGather = FALSE;
|
|
DvcDesc.DmaChannel = pGDI->DmaPlayChannel;
|
|
DvcDesc.InterfaceType = pGDI->BusType;
|
|
DvcDesc.DmaWidth = Width8Bits;
|
|
DvcDesc.DmaSpeed = Compatible;
|
|
DvcDesc.MaximumLength = pGDI->DmaBufferSize;
|
|
DvcDesc.BusNumber = pGDI->BusNumber;
|
|
|
|
/* allocate buffer and save reference to the DMA Adapter */
|
|
status = SoundGetCommonBuffer(&DvcDesc, &pGDI->WaveOutInfo.DMABuf);
|
|
pGDI->OutAdapter = pGDI->WaveOutInfo.DMABuf.AdapterObject[0];
|
|
|
|
/* check if common buffer allocation was successful */
|
|
if (!NT_SUCCESS(status)) {
|
|
/* failure */
|
|
_dbgprint((_PRT_ERRO, "after SoundGetCommonBuffer Out [status=0x%08x]\n", status));
|
|
return(status);
|
|
}
|
|
|
|
_dbgprint((_PRT_STAT, "Output SoundGetCommonBuffer: SUCCESS\n"));
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xInitializeDma(exit:STATUS_SUCCESS])\n"));
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
/*
|
|
*********************************************************************
|
|
**
|
|
*********************************************************************
|
|
*/
|
|
NTSTATUS cs423xConfigSystem(PGLOBAL_DEVICE_INFO pGDI)
|
|
{
|
|
NTSTATUS status;
|
|
_dbgprint((_PRT_DBUG, "cs423xConfigSystem(entry)\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
/* claim WSS port address */
|
|
if (!NT_SUCCESS(status = cs423xInitializePort(pGDI))) {
|
|
_dbgprint((_PRT_ERRO, "port init FAILURE(exit:[status:0x%08x])\n", status));
|
|
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_BADPORT);
|
|
return(status);
|
|
}
|
|
|
|
/* claim interrupt resources */
|
|
if (!NT_SUCCESS(status = cs423xInitializeInterrupt(pGDI))) {
|
|
_dbgprint((_PRT_ERRO, "interrupt init FAILURE(exit:[status:0x%08x])\n", status));
|
|
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_BADINT);
|
|
return(status);
|
|
}
|
|
|
|
/* claim DMA resources */
|
|
if (!NT_SUCCESS(status = cs423xInitializeDma(pGDI))) {
|
|
_dbgprint((_PRT_ERRO, "interrupt DMA FAILURE(exit:[status:0x%08x])\n", status));
|
|
SoundSetErrorCode(pGDI->RegPathName, SOUND_CONFIG_BADDMA);
|
|
return(status);
|
|
}
|
|
|
|
/* report complete WaveInDevice resource usage */
|
|
status = SoundReportResourceUsage(pGDI->DeviceObject[WaveInDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
&pGDI->WssIrq,
|
|
Latched,
|
|
FALSE,
|
|
&pGDI->DmaCaptureChannel,
|
|
&pGDI->WssPort,
|
|
NUMBER_OF_SOUND_PORTS);
|
|
|
|
/* check if report usage was successful - input */
|
|
if (!NT_SUCCESS(status)) {
|
|
_dbgprint((_PRT_ERRO, "WaveInDevice SoundReportResourceUsage[status=0x%08x]\n",
|
|
status));
|
|
return(status);
|
|
}
|
|
|
|
_dbgprint((_PRT_STAT, "WaveInDevice SoundReportResourceUsage: SUCCESS\n"));
|
|
|
|
/* report complete WaveOutDevice resource usage */
|
|
status = SoundReportResourceUsage(pGDI->DeviceObject[WaveOutDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
&pGDI->DmaPlayChannel,
|
|
NULL,
|
|
0);
|
|
|
|
/* check if report usage was successful - output */
|
|
if (!NT_SUCCESS(status)) {
|
|
_dbgprint((_PRT_ERRO, "WaveOutDevice SoundReportResourceUsage[status=0x%08x]\n",
|
|
status));
|
|
return(status);
|
|
}
|
|
|
|
_dbgprint((_PRT_STAT, "WaveOutDevice SoundReportResourceUsage: SUCCESS\n"));
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xConfigSystem(exit:[status:0x%08x])\n", status));
|
|
return(status);
|
|
}
|