summaryrefslogtreecommitdiff
path: root/attic/drv/oss_allegro/kernel.inc
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
committerIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
commit1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch)
tree4495d23e7b54ab5700e3839081e797c1eafe0db9 /attic/drv/oss_allegro/kernel.inc
downloadoss4-1058def8e7827e56ce4a70afb4aeacb5dc44148f.tar.gz
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'attic/drv/oss_allegro/kernel.inc')
-rw-r--r--attic/drv/oss_allegro/kernel.inc6225
1 files changed, 6225 insertions, 0 deletions
diff --git a/attic/drv/oss_allegro/kernel.inc b/attic/drv/oss_allegro/kernel.inc
new file mode 100644
index 0000000..5f7c8b5
--- /dev/null
+++ b/attic/drv/oss_allegro/kernel.inc
@@ -0,0 +1,6225 @@
+/******************************************************************************
+ * *
+ * (C) 1997-1999 ESS Technology, Inc. *
+ * *
+ * This source code, its compiled object code, and its associated data sets *
+ * are copyright (C) 1997-1999 ESS Technology, Inc. *
+ * *
+ ******************************************************************************/
+
+/*---------------------------------------------------------------------------
+ * Copyright (C) 1997-1999, ESS Technology, Inc.
+ *---------------------------------------------------------------------------
+ * FILENAME: kernel.c V2.10 08/19/99
+ *---------------------------------------------------------------------------
+ * DESCRIPTION: Maestro 3/Allegro1 host kernel
+ *---------------------------------------------------------------------------
+ * AUTHOR: Henry Tang/Hong Kim/Alger Yeung/Don Kim
+ *---------------------------------------------------------------------------
+ * HISTORY:
+ * 09/03/97 HT Created.
+ * 04/23/99 AY Use C call for lowest level access (in and out)
+ * 04/23/99 AY Remove delay since M3/Allegro1 has no delay bug
+ * 04/23/99 AY Cleanup dead code
+ * 05/08/99 AY SPDIF support SCMS
+ * 05/21/99 AY Add SwitchClient API to add/remove client from/to task list
+ * 05/24/99 AY Enable Cpythru (dwclient=0) to be loaded even though
+ * its code memory is not available at certain location
+ * 06/02/99 AY Enable PassThru support for adc1 -> mixer & adc2->mixer
+ * 07/29/99 AY Adding 4-speaker support
+ * 08/18/99 AY Adding SPDIF IN support
+ * 08/18/99 AY Remove PIO and SoundBlaster support
+ * 08/18/99 AY Reduce Cpythru to 2 instances instead of 4
+ * 09/22/99 HK Add M3I Features
+ *---------------------------------------------------------------------------
+ */
+
+#define NON_INTEL 1 /* avoid Intel x86 inline assembly instruction */
+/*#define ALLEGRO_DEBUG 1 // KERNEL debug flag */
+/*#define K_DBG 1 // KERNEL debug flag */
+
+#ifdef NT_MODEL
+#define HEAPZEROINIT 0
+#ifdef DON
+#include "../port.h"
+#include "kernel.h"
+#endif
+#endif
+
+#ifdef NON_INTEL
+/*#error ******** No Intel x86 assembly instructions ************* */
+#endif
+
+PCLIENT_BIN kBinStructAddress (PHWI phwi, DWORD dwClient, DWORD dwSearchKey);
+
+/* */
+/* Client info */
+/* */
+
+HWI ghwi = {
+
+ 0,
+ 0,
+ 0,
+ 0,
+
+ 0,
+
+ 0, 0,
+
+ 0,
+
+ /* client table */
+
+ {
+ {
+ gasCpyThruVectCode,
+ 0,
+ MAX_INSTANCE_CPYTHRU,
+ KDATA_INSTANCE0_CPYTHRU,
+ 0,
+ 0,
+ 0}
+ ,
+
+ {
+ gasModemVectCode,
+ 0,
+ MAX_INSTANCE_MODEM,
+ KDATA_INSTANCE0_MODEM,
+ 0,
+ 0,
+ 0}
+ ,
+
+ {
+ gasPos3DVectCode,
+ 0,
+ MAX_INSTANCE_POS3D,
+ KDATA_INSTANCE0_POS3D,
+ 0,
+ 0,
+ 0}
+ ,
+
+ {
+ gasSpkVirtVectCode,
+ 0,
+ MAX_INSTANCE_SPKVIRT,
+ KDATA_INSTANCE0_SPKVIRT,
+ 0,
+ 0,
+ 0}
+ ,
+
+ {
+ gasSpkVirtVectCode_CRL,
+ 0,
+ MAX_INSTANCE_SPKVIRT,
+ KDATA_INSTANCE0_SPKVIRT,
+ 0,
+ 0,
+ 0}
+ ,
+
+ {
+ gasSRCVectCode,
+ 0,
+ MAX_INSTANCE_SRC,
+ KDATA_INSTANCE0_SRC,
+ 0,
+ 0,
+ 0}
+ ,
+
+ {
+ gasMINISRCVectCode,
+ 0,
+ MAX_INSTANCE_MINISRC,
+ KDATA_INSTANCE0_MINISRC,
+ 0,
+ 0,
+ 0}
+ ,
+
+ {
+ gasSPDIFVectCode,
+ 0,
+ MAX_INSTANCE_SPDIF,
+ KDATA_INSTANCE0_SPDIF,
+ 0,
+ 0,
+ 0}
+
+ }
+ ,
+#if 0
+#if (F_FREE || (F_END != -1))
+#error Assumption about storage flags failed.
+#endif
+#endif
+ /* task resource list */
+
+ {
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* Copy Through resource list */
+
+ {
+ F_FREE, F_FREE, /* AY reduce to 2 for SPDIF IN */
+
+ (WORD) F_END}
+ ,
+
+ /* Modem resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* Positional 3D resource list */
+
+ {
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* Speaker Virtualization resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* Sample Rate Conversion resource list */
+
+ {
+ F_FREE, F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* MINI Sample Rate Conversion resource list */
+
+ {
+ F_FREE, F_FREE,
+ F_FREE, F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* SPDIF resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* DMA resource list */
+
+ {
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* ADC1 resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* ADC2 resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* CD resource list */
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* MIC resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* I2S resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* CHI resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+
+ /* SPDIF IN resource list */
+
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* MIXER resource list */
+ {
+ F_FREE, F_FREE,
+ F_FREE, F_FREE,
+ F_FREE, F_FREE,
+ F_FREE, F_FREE,
+ F_FREE, F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /*AY */
+ /* FMIXER resource list */
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* RMIXER resource list */
+ {
+ F_FREE,
+
+ (WORD) F_END}
+ ,
+
+ /* DSP code memory map */
+
+ 0, 0, 0, 0,
+
+ 0, 0, 0, 0,
+
+ {
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ (BYTE) F_END}
+ ,
+
+ /* DSP data memory map */
+
+ {
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ (BYTE) F_END}
+ ,
+
+ /* DSP vector list */
+
+ {
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE}
+
+};
+
+/* */
+/* Memory map images */
+/* */
+#if 0
+#if (NUM_UNITS_KERNEL_CODE != 16)
+#error Assumption about kernel code size failed.
+#endif
+#endif
+
+BYTE gabRevBCodeMemoryMapImage[] = {
+ F_USED, F_USED, F_USED, F_USED, /* 0000 - 03FF */
+ F_USED, F_USED, F_USED, F_USED,
+ F_USED, F_USED, F_USED, F_USED,
+ F_USED, F_USED, F_USED, F_USED,
+
+ F_FREE, F_FREE, F_FREE, F_FREE, /* 0400 - 07FF */
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE, /* 0800 - 0BFF */
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ (BYTE) F_END
+};
+
+#if 0
+#if (NUM_UNITS_KERNEL_DATA != 2)
+#error Assumption about kernel data size failed.
+#endif
+#endif
+
+#if 0
+#if (KDATA_BASE_ADDR != 0x1000)
+#error Assumption about kernel data memory location failed.
+#endif
+#endif
+
+BYTE gabRevBDataMemoryMapImage[] = {
+ F_USED, F_USED, F_FREE, F_FREE, /* 1000 - 17FF */
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_FREE, F_FREE, F_FREE, F_FREE, /* 1800 - 1BFF */
+ F_FREE, F_FREE, F_FREE, F_FREE,
+
+ F_USED, F_USED, F_USED, F_USED, /* 1C00 - 1FFF */
+ F_USED, F_USED, F_USED, F_USED,
+
+ F_USED, F_USED, F_USED, F_USED, /* 2000 - 27FF */
+ F_USED, F_USED, F_USED, F_USED,
+ F_USED, F_USED, F_USED, F_USED,
+ F_USED, F_USED, F_USED, F_USED,
+
+ F_USED, F_USED, F_USED, F_USED, /* 2800 - 2BFF */
+ F_USED, F_USED, F_USED, F_USED,
+
+ (BYTE) F_END
+};
+
+
+extern WORD MIXER_TASK_NUMBER;
+
+#ifdef VXD_MODEL
+#pragma VxD_LOCKED_CODE_SEG
+#endif
+
+#if defined( DOS_MODEL ) || defined( NT_MODEL )
+/*-------------------------------------------------------------------------- */
+/* */
+/* PBYTE _HeapAllocate */
+/* */
+/* Description: */
+/* Allocate memory block of specified length. */
+/* */
+/* Parameters: */
+/* DWORD dwLength */
+/* Length in bytes of memory block. */
+/* */
+/* DWORD dwFlags */
+/* Allocation flags. */
+/* */
+/* Return (PBYTE): */
+/* Pointer to allocated memory block. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+PBYTE
+_HeapAllocate (DWORD dwLength, DWORD dwFlags)
+{
+#ifdef DOS_MODEL
+ return (PBYTE) malloc (dwLength);
+#endif
+
+#ifdef NT_MODEL
+ return (PBYTE) KERNEL_MALLOC (dwLength);
+#endif
+
+} /* _HeapAllocate() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD _HeapFree */
+/* */
+/* Description: */
+/* Deallocate previously allocated memory block. */
+/* */
+/* Parameters: */
+/* PVOID pvBlock, */
+/* Pointer to previously allocated memory block. */
+/* */
+/* DWORD dwFlags */
+/* Allocation flags. */
+/* */
+/* Return (DWORD): */
+/* Non-zero if successful, zero otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+DWORD
+_HeapFree (PVOID pvBlock, DWORD dwFlags)
+{
+#ifdef DOS_MODEL
+ free (pvBlock);
+#endif
+
+#ifdef NT_MODEL
+ KERNEL_FREE (pvBlock);
+#endif
+
+ return 1;
+
+} /* _HeapFree() */
+#endif
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDelayNMicroseconds */
+/* */
+/* Description: */
+/* Delay specified number of microseconds. */
+/* */
+/* Parameters: */
+/* DWORD dwCount */
+/* Number of microseconds to delay. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID
+kDelayNMicroseconds (DWORD dwCount)
+{
+ oss_udelay (dwCount);
+} /* kDelayNMicroseconds() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* BYTE kInB */
+/* */
+/* Description: */
+/* Do BYTE I/O read. */
+/* */
+/* Parameters: */
+/* DWORD dwPort */
+/* I/O port address. */
+/* */
+/* Return (BYTE): */
+/* Data read from specified address. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+BYTE
+kInB (allegro_devc * devc, DWORD dwPort)
+{
+ BYTE bData;
+ bData = READ_PORT_UCHAR (devc->osdev, dwPort);
+ return bData;
+} /* kInB() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kOutB */
+/* */
+/* Description: */
+/* Do BYTE I/O write. */
+/* */
+/* Parameters: */
+/* DWORD dwPort */
+/* I/O port address. */
+/* */
+/* BYTE bData */
+/* I/O port data. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+VOID
+kOutB (allegro_devc * devc, DWORD dwPort, BYTE bData)
+{
+ WRITE_PORT_UCHAR (devc->osdev, dwPort, bData);
+} /* kOutB() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* WORD kInW */
+/* */
+/* Description: */
+/* Do WORD I/O read. */
+/* */
+/* Parameters: */
+/* DWORD dwPort */
+/* I/O port address. */
+/* */
+/* Return (WORD): */
+/* Data read from specified address. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+WORD
+kInW (allegro_devc * devc, DWORD dwPort)
+{
+ WORD wData;
+ wData = READ_PORT_USHORT (devc->osdev, dwPort);
+ return wData;
+} /* kInW() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kOutW */
+/* */
+/* Description: */
+/* Do WORD I/O write. */
+/* */
+/* Parameters: */
+/* DWORD dwPort */
+/* I/O port address. */
+/* */
+/* WORD wData */
+/* I/O port data. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+VOID
+kOutW (allegro_devc * devc, DWORD dwPort, WORD wData)
+{
+ WRITE_PORT_USHORT (devc->osdev, dwPort, wData);
+} /* kOutW() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kInsW */
+/* */
+/* Description: */
+/* Do WORD I/O repeat read. */
+/* */
+/* Parameters: */
+/* DWORD dwPort */
+/* I/O port address. */
+/* */
+/* DWORD dwLen */
+/* Number of WORDs to read from specified address. */
+/* */
+/* DWORD dwAddr */
+/* Host memory address to write to. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+VOID
+kInsW (allegro_devc * devc, DWORD dwPort, DWORD dwLen, DWORD dwAddr)
+{
+#ifdef NON_INTEL
+ DWORD i;
+ WORD *wptr;
+#endif
+
+ if (!dwLen)
+ return;
+
+#ifdef DOS_MODEL
+
+#ifdef NON_INTEL
+ wptr = (WORD *) dwAddr;
+ for (i = 0; i < dwLen; ++i)
+ {
+ *wptr++ = inpw (devc, (WORD) dwPort);
+ } /* endfor */
+#else
+ _asm
+ {
+ push di
+ push es
+ cld
+ mov cx, word ptr dwLen
+ mov dx, word ptr dwPort les di, dwAddr rep insw pop es pop di}
+#endif
+
+#endif
+
+#if defined( VXD_MODEL ) || defined( WDM_MODEL ) || defined( NT_MODEL )
+
+#ifdef NON_INTEL
+ wptr = (WORD *) dwAddr;
+ for (i = 0; i < dwLen; ++i)
+ {
+ *wptr++ = inpw (devc->osdev, (WORD) dwPort);
+ } /* endfor */
+#else
+ _asm
+ {
+ push edi
+ cld mov ecx, dwLen mov edx, dwPort mov edi, dwAddr rep insw pop edi}
+#endif
+
+#endif
+
+} /* kInsW() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kOutsW */
+/* */
+/* Description: */
+/* Do WORD I/O repeat write. */
+/* */
+/* Parameters: */
+/* DWORD dwPort */
+/* I/O port address. */
+/* */
+/* DWORD dwLen */
+/* Number of WORDs to write to specified address. */
+/* */
+/* DWORD dwAddr */
+/* Host memory address to read from. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+VOID
+kOutsW (allegro_devc * devc, DWORD dwPort, DWORD dwLen, DWORD dwAddr)
+{
+#ifdef NON_INTEL
+ DWORD i;
+ WORD *wptr;
+#endif
+
+ if (!dwLen)
+ return;
+
+
+#ifdef DOS_MODEL
+#ifdef NON_INTEL
+
+ wptr = (WORD *) dwAddr;
+ for (i = 0; i < dwLen; ++i)
+ {
+ outpw (devc, (WORD) dwPort, *wptr++);
+ } /* endfor */
+
+#else
+/*#pragma message("----Using slow I/O to overcome hardware bug") */
+ _asm
+ {
+ push si
+ push ds
+ cld
+ mov cx, word ptr dwLen mov dx, word ptr dwPort lds si, dwAddr rep outsw;
+ xx:
+ ;
+ in al, 80 h;
+ delay !;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ ;
+ lodsw;
+ get data;
+ out dx, ax;
+ write it;
+ loop xx;
+ get going ... pop ds pop si}
+#endif
+#endif
+
+#if defined( VXD_MODEL ) || defined( WDM_MODEL ) || defined( NT_MODEL )
+#ifdef NON_INTEL
+ wptr = (WORD *) dwAddr;
+ for (i = 0; i < dwLen; ++i)
+ {
+ outpw (devc->osdev, (WORD) dwPort, *wptr++);
+ } /* endfor */
+#else
+ _asm
+ {
+ push esi cld mov ecx, dwLen mov edx, dwPort mov esi, dwAddr rep outsw;
+ xx:;
+ in al, 80 h;
+ delay !;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ in al, 80 h;
+ lodsw;
+ get data;
+ out dx, ax;
+ write it;
+ loop xx;
+ get going ... pop esi}
+#endif
+#endif
+
+} /* kOutsW() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* WORD kDspReadWord */
+/* */
+/* Description: */
+/* Read WORD from DSP memory. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwMemType */
+/* Type of memory to read from. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to read from. */
+/* */
+/* Return (WORD): */
+/* Data read from specified address. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+WORD
+kDspReadWord (allegro_devc * devc, DWORD dwBaseIO, DWORD dwMemType,
+ DWORD dwMemAddr)
+{
+ WORD wData;
+
+ CRITENTER
+ /* 10/04/97, per Henry Tsay, write zeros to bits 15-2 of type register */
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_TYPE, (WORD) dwMemType);
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_INDEX, (WORD) dwMemAddr);
+ wData = kInW (devc, dwBaseIO + DSP_PORT_MEMORY_DATA);
+ CRITLEAVE return wData;
+} /* kDspReadWord() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDspWriteWord */
+/* */
+/* Description: */
+/* Write WORD to DSP memory. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwMemType */
+/* Type of memory to write to. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to write to. */
+/* */
+/* WORD wMemData */
+/* Data to write to specified address. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID kDspWriteWord
+ (allegro_devc * devc, DWORD dwBaseIO, DWORD dwMemType, DWORD dwMemAddr,
+ WORD wMemData)
+{
+
+ CRITENTER
+ /* 10/04/97, per Henry Tsay, write zeros to bits 15-2 of type register */
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_TYPE, (WORD) dwMemType);
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_INDEX, (WORD) dwMemAddr);
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_DATA, wMemData);
+CRITLEAVE} /* kDspWriteWord() */
+
+/*----------------------------------------------------------------------*/
+/* */
+/* VOID kDspReadWords */
+/* */
+/* Description: */
+/* Read WORD block from DSP memory. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwMemType */
+/* Type of memory to read from. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to read from. */
+/* */
+/* DWORD dwMemLen */
+/* Number of WORDs to read from specified address. */
+/* */
+/* PWORD pwHostAddr */
+/* Host memory address to write to. */
+/* */
+/* Return (VOID): */
+/* */
+/*----------------------------------------------------------------------*/
+
+VOID kDspReadWords
+ (allegro_devc * devc, DWORD dwBaseIO,
+ DWORD dwMemType, DWORD dwMemAddr, DWORD dwMemLen, PWORD pwHostAddr)
+{
+
+ CRITENTER
+ /* 10/04/97, per Henry Tsay, write zeros to bits 15-2 of type register */
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_TYPE, (WORD) dwMemType);
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_INDEX, (WORD) dwMemAddr);
+ kInsW (devc, dwBaseIO + DSP_PORT_MEMORY_DATA, dwMemLen, (DWORD) pwHostAddr);
+CRITLEAVE} /* kDspReadWords() */
+
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDspReadLongWords */
+/* */
+/* Description: */
+/* Read WORD block which could be > 0x1000 from DSP memory. */
+/* Since auto-increment mode can cross 4K boundary, 4K block at a time */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwMemType */
+/* Type of memory to read from. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to read from. */
+/* */
+/* DWORD dwMemLen */
+/* Number of WORDs to read from specified address. */
+/* */
+/* PWORD pwHostAddr */
+/* Host memory address to write to. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID kDspReadLongWords
+ (allegro_devc * devc, DWORD dwBaseIO,
+ DWORD dwMemType, DWORD dwMemLongAddr, DWORD dwMemLongLen, PWORD pwHostAddr)
+{
+ DWORD dwMemLen;
+ DWORD dwMemBegin;
+ WORD *pwBuffer;
+
+ /* take care the Data area which could be > 0x1000 in size */
+ dwMemLen = dwMemLongLen;
+ dwMemBegin = dwMemLongAddr;
+ pwBuffer = pwHostAddr;
+
+ while (dwMemLen > 0)
+ {
+ if (dwMemLen >= 0x1000)
+ {
+ kDspReadWords (devc, dwBaseIO, dwMemType, dwMemBegin, 0x1000,
+ pwBuffer);
+
+ dwMemBegin += 0x1000;
+ dwMemLen -= 0x1000;
+ pwBuffer = (pwBuffer + 0x1000);
+
+ }
+ else
+ {
+ kDspReadWords (devc, dwBaseIO, dwMemType, dwMemBegin, dwMemLen,
+ pwBuffer);
+
+ dwMemLen = 0;
+
+ } /* endif */
+ } /* endwhile */
+} /* kDspReadLongWords() */
+
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDspWriteWords */
+/* */
+/* Description: */
+/* Write WORD block to DSP memory. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwMemType */
+/* Type of memory to write to. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to write to. */
+/* */
+/* DWORD dwMemLen */
+/* Number of WORDs to write to specified address. */
+/* */
+/* PWORD pwHostAddr */
+/* Host memory address to read from. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID kDspWriteWords
+ (allegro_devc * devc, DWORD dwBaseIO,
+ DWORD dwMemType, DWORD dwMemAddr, DWORD dwMemLen, PWORD pwHostAddr)
+{
+
+ CRITENTER
+ /* 10/04/97, per Henry Tsay, write zeros to bits 15-2 of type register */
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_TYPE, (WORD) dwMemType);
+ kOutW (devc, dwBaseIO + DSP_PORT_MEMORY_INDEX, (WORD) dwMemAddr);
+ kOutsW (devc, dwBaseIO + DSP_PORT_MEMORY_DATA, dwMemLen,
+ (DWORD) pwHostAddr);
+CRITLEAVE} /* kDspWriteWords() */
+
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDspWriteLongWords */
+/* */
+/* Description: */
+/* Write WORD block which could be > 0x1000 from DSP memory. */
+/* Since auto-increment mode can cross 4K boundary, 4K block at a time */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwMemType */
+/* Type of memory to Write to. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to Write to . */
+/* */
+/* DWORD dwMemLen */
+/* Number of WORDs to write to specified address. */
+/* */
+/* PWORD pwHostAddr */
+/* Host memory address to read from. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID kDspWriteLongWords
+ (allegro_devc * devc, DWORD dwBaseIO,
+ DWORD dwMemType, DWORD dwMemLongAddr, DWORD dwMemLongLen, PWORD pwHostAddr)
+{
+ DWORD dwMemLen;
+ DWORD dwMemBegin;
+ WORD *pwBuffer;
+
+ /* take care the Data area which could be > 0x1000 in size */
+ dwMemLen = dwMemLongLen;
+ dwMemBegin = dwMemLongAddr;
+ pwBuffer = pwHostAddr;
+
+ while (dwMemLen > 0)
+ {
+ if (dwMemLen >= 0x1000)
+ {
+ kDspWriteWords (devc, dwBaseIO, dwMemType, dwMemBegin, 0x1000,
+ pwBuffer);
+
+ dwMemBegin += 0x1000;
+ dwMemLen -= 0x1000;
+ pwBuffer = (pwBuffer + 0x1000);
+
+ }
+ else
+ {
+ kDspWriteWords (devc, dwBaseIO,
+ dwMemType, dwMemBegin, dwMemLen, pwBuffer);
+
+ dwMemLen = 0;
+
+ } /* endif */
+ } /* endwhile */
+} /* kDspWriteLongWords() */
+
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDspWriteZeros */
+/* */
+/* Description: */
+/* Write zeros to DSP memory. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwMemType */
+/* Type of memory to write to. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to write to. */
+/* */
+/* DWORD dwMemLen */
+/* Number of WORDs of zero to write to specified address. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID kDspWriteZeros
+ (allegro_devc * devc, DWORD dwBaseIO, DWORD dwMemType, DWORD dwMemAddr,
+ DWORD dwMemLen)
+{
+ while (dwMemLen--)
+ {
+/*#pragma message("----Using slow I/O to overcome hardware bug") */
+/* kDelayNMicroseconds( 8 ) ; */
+ kDspWriteWord (devc, dwBaseIO, dwMemType, dwMemAddr++, 0);
+ }
+
+} /* kDspWriteZeros() */
+
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kQueryPosition */
+/* */
+/* Description: */
+/* Return a client's current stream position. A position equal to 0 */
+/* indicates the first byte in the buffer is being transferred. A */
+/* position equal to dwHostXXXBufferLen-1 indicates the last byte */
+/* in the buffer is being transferred. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* DWORD dwQueryOutput */
+/* TRUE if querying host client output position, FALSE if querying input */
+/* */
+/* PDWORD pdwPosition */
+/* Pointer to DWORD that will contain the byte position */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kQueryPosition
+ (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst, DWORD dwQueryOutput, PDWORD pdwPosition)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+ WORD wPosition = 0;
+ WORD wRetry = 10;
+ WORD wPositionL = 0;
+ WORD wPositionH = 0;
+ PWORD pwCur;
+
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ if ((dwQueryOutput && pClient_Inst->dwDSPInConnection == KCONNECT_DMA) ||
+ (!dwQueryOutput && pClient_Inst->dwDSPOutConnection == KCONNECT_DMA))
+ {
+ /* */
+ /* if DMA is not active return position 0 */
+ /* */
+
+ pwCur = phwi->awVirtualDMAList;
+
+ while ((*pwCur != F_FREE) && (*pwCur != (WORD) F_END))
+ {
+ if (*pwCur ==
+ (WORD) (pClient_Inst->dwDspDataClientArea >> DP_SHIFT_COUNT))
+ {
+ break;
+ }
+ ++pwCur;
+ }
+
+ if (*pwCur !=
+ (WORD) (pClient_Inst->dwDspDataClientArea >> DP_SHIFT_COUNT))
+ {
+ *pdwPosition = 0;
+ return KRETURN_SUCCESS;
+ }
+
+ /* */
+ /* Get the position */
+ /* */
+
+ while (wRetry--)
+ {
+ /* read high/low word of current position */
+
+ wPositionH = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea +
+ CDATA_HOST_SRC_CURRENTH);
+
+ wPositionL = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea +
+ CDATA_HOST_SRC_CURRENTL);
+
+ /* if the high word hasn't changed, we've got a meaningful */
+ /* current position value */
+
+ wPosition = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea +
+ CDATA_HOST_SRC_CURRENTH);
+
+ if (wPosition == wPositionH)
+ break;
+ }
+
+ /* fail if we couldn't get a meaningful position */
+
+ if (wPosition != wPositionH)
+ return KRETURN_ERROR_GENERIC;
+
+ *pdwPosition = MAKELONG (wPositionL, wPositionH) -
+ (dwQueryOutput ?
+ pClient_Inst->dwHostSrcBufferAddr :
+ pClient_Inst->dwHostDstBufferAddr);
+ }
+ else if (!dwQueryOutput && pClient_Inst->dwDSPOutConnection == KCONNECT_PIO)
+ {
+ /* */
+ /* Get the position */
+ /* */
+
+ *pdwPosition = pClient_Inst->dwHostDstCurrent -
+ pClient_Inst->dwHostDstBufferAddr;
+ }
+ else
+ {
+ return KRETURN_ERROR_GENERIC;
+ }
+
+ return KRETURN_SUCCESS;
+
+} /* kQueryPosition() */
+
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* BYTE kDspHalt */
+/* */
+/* Description: */
+/* Halt the DSP. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* Return (BYTE): */
+/* Contents of reset port. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+BYTE
+kDspHalt (allegro_devc * devc, DWORD dwBaseIO)
+{
+ BYTE bData;
+ bData = kInB (devc, dwBaseIO + DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK;
+ /* Fix for HP Typhoon Hibernation Problem RJJ 6/17/00 */
+ kDelayNMicroseconds (10);
+ kOutB (devc, dwBaseIO + DSP_PORT_CONTROL_REG_B,
+ (BYTE) (bData & ~REGB_ENABLE_RESET));
+
+ return bData;
+
+} /* kDspHalt() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDspReset */
+/* */
+/* Description: */
+/* Reset the DSP and let it run. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* BYTE bData */
+/* Contents of reset port. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID
+kDspReset (allegro_devc * devc, DWORD dwBaseIO, BYTE bData)
+{
+ kOutB (devc, dwBaseIO + DSP_PORT_CONTROL_REG_B,
+ (BYTE) (bData | REGB_ENABLE_RESET));
+
+} /* kDspReset() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kDisableFMMap */
+/* */
+/* Description: */
+/* Enable/disable FM address mapping. */
+/* */
+/* Parameters: */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwDisable */
+/* TRUE if disabling FM mapping, FALSE otherwise */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID
+kDisableFMMap (allegro_devc * devc, DWORD dwBaseIO, DWORD dwDisable)
+{
+ BYTE bData;
+
+ bData =
+ kInB (devc, dwBaseIO + DSP_PORT_CONTROL_REG_C) & ~REGC_DISABLE_FM_MAPPING;
+ bData |= (dwDisable ? REGC_DISABLE_FM_MAPPING : 0);
+ kOutB (devc, dwBaseIO + DSP_PORT_CONTROL_REG_C, (BYTE) bData);
+
+} /* kDisableFMMap() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kRestartStreams */
+/* */
+/* Description: */
+/* Restart all previously active streams. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID
+kRestartStreams (allegro_devc * devc, PHWI phwi)
+{
+ /* */
+ /* reset DMA state machine in case it was active during the suspend */
+ /* */
+ /* If DMA was active, the worst thing that could happen is that we */
+ /* will re-transfer the 16 words that were being transfered during */
+ /* the suspend. The 16 words are not duplicated in the stream, they */
+ /* simply overwrite the exact copy that was previously transfered. */
+ /* */
+
+ if (phwi->awVirtualDMAList[0])
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_DMA_ACTIVE, FALSE);
+ }
+
+
+} /* kRestartStreams() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kStateExists */
+/* */
+/* Description: */
+/* Checks if the specified DSP data memory location is TRUE or FALSE. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to check. */
+/* */
+/* DWORD dwState */
+/* Specified state to check for (TRUE or FALSE) */
+/* */
+/* Return (DWORD): */
+/* TRUE if specified state exists, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+#define RESET_IF_TIMEOUT
+
+DWORD
+kStateExists (allegro_devc * devc, PHWI phwi, DWORD dwMemAddr, DWORD dwState)
+{
+#ifdef RESET_IF_TIMEOUT
+ DWORD dwResetLoops = 50;
+#endif
+ DWORD dwLoops;
+ WORD wData;
+ BYTE bData;
+
+ for (dwLoops = 0;; ++dwLoops)
+ {
+ wData =
+ kDspReadWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA, dwMemAddr);
+
+ if ((dwState && wData) || (!dwState && !wData))
+ return TRUE;
+
+ kDelayNMicroseconds (1);
+
+ if (dwLoops == DSP_TIMEOUT)
+ {
+#ifdef RESET_IF_TIMEOUT
+
+ /* */
+ /* For some as yet unknown reason, if HSP/DSP modem runs */
+ /* concurrently with other DSP clients for a long time, */
+ /* the DSP stops executing. Under such conditions a reset */
+ /* will resume DSP execution and the clients appear to run */
+ /* fine again. Hence we do a reset if we detect the DSP */
+ /* kernel is no longer running. */
+ /* */
+
+ if (--dwResetLoops)
+ {
+ dwLoops = 0;
+ continue;
+ }
+
+ bData = kDspHalt (devc, phwi->dwBaseIO);
+
+ kRestartStreams (devc, phwi);
+
+ kDspReset (devc, phwi->dwBaseIO, bData);
+
+ /* */
+ /* Update our DSP reset counter. This is purely for */
+ /* diagnostic purposes. */
+ /* */
+
+ if (phwi->wDspResetCount + 1)
+ ++phwi->wDspResetCount;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_DSP_RESET_COUNT, phwi->wDspResetCount);
+#endif
+
+ return FALSE;
+ }
+ }
+
+} /* kStateExists() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* PBYTE kAllocDspMemory */
+/* */
+/* Description: */
+/* Find and allocate available DSP memory. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwClient */
+/* Client ID */
+/* */
+/* PBYTE pbMemoryMap */
+/* Pointer to memory map. */
+/* */
+/* DWORD dwNumWanted */
+/* Number of contiguous memory units requested. */
+/* */
+/* Return (PBYTE): */
+/* Pointer to starting memory map unit if successful, NULL otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+PBYTE kAllocDspMemory
+ (PHWI phwi, DWORD dwClient, PBYTE pbMemoryMap, DWORD dwNumWanted)
+{
+ PBYTE pbMemFound = NULL;
+ PBYTE pbMemFound2 = NULL;
+ DWORD dwNumFound = (DWORD) - 1; /* maximum 0xFFFF */
+ PBYTE pbMemTmp;
+ DWORD dwNumTmp;
+ PBYTE pbMemType;
+
+
+ if (!dwNumWanted)
+ return NULL;
+
+ pbMemType = pbMemoryMap; /*AY990524 Data & Code type */
+
+ /* */
+ /* Search for available memory. We want to find the smallest */
+ /* chunk of memory that can satisfy the request. This will minimize */
+ /* memory fragmentation. */
+ /* */
+
+ for (; *pbMemoryMap != (BYTE) F_END; ++pbMemoryMap)
+ {
+ if (*pbMemoryMap == F_USED)
+ continue;
+
+ pbMemTmp = pbMemoryMap;
+ dwNumTmp = 1;
+
+ while (*++pbMemoryMap == F_FREE)
+ ++dwNumTmp;
+
+ if ((dwNumTmp >= dwNumWanted) && (dwNumTmp < dwNumFound))
+ {
+ pbMemFound = pbMemTmp;
+ dwNumFound = dwNumTmp;
+ /*AY+ */
+ /* */
+ /* memory found, check whether it matches with client Code address */
+ /* */
+ if (pbMemType == (phwi->abCodeMemoryMap)) /* code memory */
+ {
+ DWORD dwCodeArea;
+ /*LINTED*/
+ dwCodeArea = ((pbMemFound - phwi->abCodeMemoryMap) *
+ phwi->dwCodeMemoryUnitLength) +
+ phwi->dwCodeMemoryBegin;
+
+ if (!kBinStructAddress (phwi, dwClient, dwCodeArea))
+ {
+ /* no code binary found */
+ pbMemoryMap = pbMemTmp; /* continue with next search */
+ ++pbMemoryMap;
+ dwCodeArea = NULL;
+ pbMemFound = NULL;
+ dwNumFound = (DWORD) - 1;
+
+ }
+ else
+ {
+
+ /* */
+ /* At least we found something availble, so remember just in case. */
+ /* */
+
+ pbMemFound2 = pbMemFound;
+
+ }
+
+ }
+ /*AY- */
+ }
+ --pbMemoryMap;
+ }
+
+ /* */
+ /* If memory found, allocate it. Only allocate as many units that are */
+ /* necessary to satisfy the request. If the smallest memory is not */
+ /* found, then check whether other memory is available or not because */
+ /* just failing is the last thing that kernel would want to do. */
+ /* */
+
+ if (pbMemFound)
+ {
+
+ pbMemTmp = pbMemFound;
+ dwNumTmp = dwNumWanted;
+
+ while (dwNumTmp--)
+ *pbMemTmp++ = F_USED;
+
+ }
+ else
+ {
+ if (pbMemFound2)
+ {
+
+ pbMemTmp = pbMemFound2;
+ dwNumTmp = dwNumWanted;
+ pbMemFound = pbMemFound2;
+
+ while (dwNumTmp--)
+ *pbMemTmp++ = F_USED;
+
+ }
+
+ }
+
+ return pbMemFound;
+
+} /* kAllocDspMemory() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kDeallocDspMemory */
+/* */
+/* Description: */
+/* Deallocate DSP memory. */
+/* */
+/* Parameters: */
+/* PBYTE pbMemFree */
+/* Pointer to starting memory map unit to free. */
+/* */
+/* DWORD dwNumFree */
+/* Number of contiguous memory units to free. */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD
+kDeallocDspMemory (PBYTE pbMemFree, DWORD dwNumFree)
+{
+
+ while (dwNumFree--)
+ *pbMemFree++ = F_FREE;
+
+ return TRUE;
+
+} /* kDeallocDspMemory() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kConnectDirectMixer */
+/* */
+/* Description: */
+/* Connect/Disconnect the specified directly mixed input and output. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwDSPInConnection */
+/* KCONNECT_XXX indicating input connection */
+/* */
+/* DWORD dwDSPOutConnection */
+/* KCONNECT_XXX indicating output connection */
+/* */
+/* DWORD dwConnect */
+/* TRUE if connecting, FALSE otherwise */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD kConnectDirectMixer
+ (allegro_devc * devc, PHWI phwi,
+ DWORD dwDSPInConnection, DWORD dwDSPOutConnection, DWORD dwConnect)
+{
+ WORD wAddress = 0;
+ WORD wData;
+
+ /* */
+ /* Get input setting */
+ /* */
+
+ if (dwDSPInConnection == KCONNECT_ADC1)
+ wData = DIRECTMIXER_ADC1;
+ else if (dwDSPInConnection == KCONNECT_ADC2)
+ wData = DIRECTMIXER_ADC2;
+ else
+ wData = 0;
+
+ /* */
+ /* Get output setting */
+ /* */
+
+ if ((dwDSPOutConnection == KCONNECT_SPDIF) && dwConnect)
+ {
+ /* set the DSP SPDIF request flag */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_SPDIF_REQUEST, TRUE);
+ wAddress = KDATA_SPDIF_XFER;
+ }
+
+ /* */
+ /* Write setting */
+ /* */
+
+ if (dwConnect)
+ {
+ wData |=
+ kDspReadWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA, wAddress);
+ }
+ else
+ {
+ wData ^=
+ kDspReadWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA, wAddress);
+ }
+
+ kDspWriteWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA, wAddress,
+ wData);
+
+#if 0
+#if (NUMBER_OF_CONNECTIONS != 0x10)
+#error Assumption about number of connections failed.
+#endif
+#endif
+
+ return TRUE;
+
+} /* kConnectDirectMixer() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kAddListEntry */
+/* */
+/* Description: */
+/* Add entry to host and DSP resource lists. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PWORD pwHostListBegin */
+/* Start address of host resource list. */
+/* */
+/* WORD wDSPListBegin */
+/* Start address of DSP resource list. */
+/* */
+/* WORD wEntryValue */
+/* Value of entry to add. Must not equal F_FREE or F_END! */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD kAddListEntry
+ (allegro_devc * devc, PHWI phwi, PWORD pwHostListBegin, WORD wDSPListBegin,
+ WORD wEntryValue)
+{
+ PWORD pwCur = pwHostListBegin;
+
+ /* */
+ /* Search for an unused list entry */
+ /* */
+
+ while (*pwCur != (WORD) F_END)
+ {
+ if (*pwCur == F_FREE)
+ {
+ /* */
+ /* Write wEntryValue to both the host list and the DSP list */
+ /* */
+
+ *pwCur = wEntryValue;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ wDSPListBegin + (pwCur - pwHostListBegin),
+ wEntryValue);
+ return TRUE;
+ }
+ ++pwCur;
+ }
+
+ return FALSE;
+
+} /* kAddListEntry() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kRemoveListEntry */
+/* */
+/* Description: */
+/* Remove entry from host and DSP resource lists. Then compact */
+/* the lists if necessary. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PWORD pwHostListBegin */
+/* Start address of host resource list. */
+/* */
+/* WORD wDSPListBegin */
+/* Start address of DSP resource list. */
+/* */
+/* WORD wEntryValue */
+/* Value of entry to remove. Must not equal F_FREE or F_END! */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD kRemoveListEntry
+ (allegro_devc * devc, PHWI phwi, PWORD pwHostListBegin, WORD wDSPListBegin,
+ WORD wEntryValue)
+{
+ PWORD pwCur = pwHostListBegin;
+ PWORD pwRemove = NULL;
+
+ /* */
+ /* Search for the entry containing wEntryValue and for the */
+ /* last data entry */
+ /* */
+
+ while ((*pwCur != F_FREE) && (*pwCur != (WORD) F_END))
+ {
+ if (*pwCur == wEntryValue)
+ {
+ pwRemove = pwCur;
+ }
+ ++pwCur;
+ }
+
+ /* Point to last data entry */
+
+ if (pwCur != pwHostListBegin)
+ {
+ --pwCur;
+ }
+
+ /* */
+ /* Fail if an entry containing wEntryValue could not be found */
+ /* */
+
+ if (!pwRemove)
+ return FALSE;
+
+ /* */
+ /* OK, we've found our entry to remove and we've got the location */
+ /* of the last data entry. When we remove the entry, the void */
+ /* that is created is filled by moving the last data entry into */
+ /* the void. The last data entry is then deleted. We have to fill */
+ /* up the void because list entries are defined to be packed together */
+ /* (i.e. no gaps between entries). */
+ /* */
+
+ /* */
+ /* If the entry to remove is NOT the same as the last data entry, we */
+ /* first overwrite the entry to be removed with the value of the last */
+ /* data entry. Then we delete the last data entry. */
+ /* */
+ /* If the entry to remove is the same as the last data entry, we */
+ /* simply delete the last data entry. */
+ /* */
+
+ if (pwRemove != pwCur)
+ {
+ *pwRemove = *pwCur;
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ wDSPListBegin + (pwRemove - pwHostListBegin), *pwCur);
+ }
+
+ /* */
+ /* Delete the last data entry */
+ /* */
+
+ *pwCur = NULL;
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ wDSPListBegin + (pwCur - pwHostListBegin), 0);
+
+ return TRUE;
+
+} /* kRemoveListEntry() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* PWORD kInstanceListAddress */
+/* */
+/* Description: */
+/* Return pointer to requested client instance list. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwClient */
+/* Client ID */
+/* */
+/* Return (PWORD): */
+/* Pointer to client instance list. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+PWORD
+kInstanceListAddress (PHWI phwi, DWORD dwClient)
+{
+ switch (dwClient)
+ {
+ case CLIENT_CPYTHRU:
+ return phwi->awInstanceCpyThruList;
+
+ case CLIENT_MODEM:
+ return phwi->awInstanceModemList;
+
+ case CLIENT_POS3D:
+ return phwi->awInstancePos3DList;
+
+ case CLIENT_SPKVIRT:
+ case CLIENT_SPKVIRT_CRL:
+ return phwi->awInstanceSpkVirtList;
+
+ case CLIENT_SRC:
+ return phwi->awInstanceSRCList;
+
+ case CLIENT_MINISRC:
+ return phwi->awInstanceMINISRCList;
+
+ case CLIENT_SPDIF:
+ return phwi->awInstanceSPDIFList;
+
+
+ /* we should never end up here! */
+ default:
+ return NULL;
+ }
+#if 0
+#if (NUMBER_OF_CLIENTS != 8)
+#error Assumption about number of clients failed.
+#endif
+#endif
+} /* kInstanceListAddress() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* PWORD kHostXferListAddress */
+/* */
+/* Description: */
+/* Return pointer to requested host transfer list. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwDSPConnection */
+/* KCONNECT_XXX indicating connection */
+/* */
+/* Return (PWORD): */
+/* Pointer to host transfer list. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+PWORD
+kHostXferListAddress (PHWI phwi, DWORD dwDSPConnection)
+{
+ switch (dwDSPConnection)
+ {
+ case KCONNECT_NONE:
+ return NULL;
+
+ case KCONNECT_DMA:
+ return phwi->awVirtualDMAList;
+
+ case KCONNECT_ADC1:
+ return phwi->awVirtualADC1List;
+
+ case KCONNECT_ADC2:
+ return phwi->awVirtualADC2List;
+
+ case KCONNECT_CD:
+ return phwi->awVirtualCDList;
+
+ case KCONNECT_MIC:
+ return phwi->awVirtualMICList;
+
+ case KCONNECT_I2S:
+ return phwi->awVirtualI2SList;
+
+ case KCONNECT_CHI:
+ return phwi->awVirtualCHIList;
+
+ case KCONNECT_SPDIFIN:
+ return phwi->awVirtualSPDIFINList;
+
+ case KCONNECT_MIXER:
+ return phwi->awVirtualMIXERList;
+
+ /*AY */
+ case KCONNECT_FMIXER:
+ return phwi->awVirtualFMIXERList;
+
+ case KCONNECT_RMIXER:
+ return phwi->awVirtualRMIXERList;
+
+ case KCONNECT_SAME:
+ return NULL;
+
+ /* we should never end up here! */
+ default:
+ return NULL;
+ }
+#if 0
+#if (NUMBER_OF_CONNECTIONS != 0x10)
+#error Assumption about number of connections failed.
+#endif
+#endif
+} /* kHostXferListAddress() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* WORD kDSPXferListAddress */
+/* */
+/* Description: */
+/* Return pointer to requested DSP transfer list. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwDSPConnection */
+/* KCONNECT_XXX indicating connection */
+/* */
+/* Return (WORD): */
+/* Pointer to DSP transfer list. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+WORD
+kDSPXferListAddress (PHWI phwi, DWORD dwDSPConnection)
+{
+ switch (dwDSPConnection)
+ {
+ case KCONNECT_NONE:
+ return NULL;
+
+ case KCONNECT_DMA:
+ return KDATA_DMA_XFER0;
+
+ case KCONNECT_ADC1:
+ return KDATA_ADC1_XFER0;
+
+ case KCONNECT_ADC2:
+ return KDATA_ADC2_XFER0;
+
+ case KCONNECT_CD:
+ return KDATA_CD_XFER0;
+
+ case KCONNECT_MIC:
+ return KDATA_MIC_XFER0;
+
+ case KCONNECT_I2S:
+ return KDATA_I2S_XFER0;
+
+ case KCONNECT_CHI:
+ return KDATA_CHI_XFER0;
+
+ case KCONNECT_SPDIF:
+ return KDATA_SPDIF_XFER;
+
+ case KCONNECT_SPDIFIN:
+ return KDATA_SPDIFIN_XFER0;
+
+ case KCONNECT_MIXER:
+ return KDATA_MIXER_XFER0;
+
+ /*AY */
+ case KCONNECT_FMIXER:
+ return KDATA_FMIXER_XFER0;
+
+ case KCONNECT_RMIXER:
+ return KDATA_RMIXER_XFER0;
+
+ case KCONNECT_SAME:
+ return NULL;
+
+ /* we should never end up here! */
+ default:
+ return NULL;
+ }
+#if 0
+#if (NUMBER_OF_CONNECTIONS != 0x10)
+#error Assumption about number of connections failed.
+#endif
+#endif
+} /* kDSPXferListAddress() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kConnectInputOutput */
+/* */
+/* Description: */
+/* Connect the specified input and output. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwDSPInConnection */
+/* KCONNECT_XXX indicating input connection */
+/* */
+/* DWORD dwDSPOutConnection */
+/* KCONNECT_XXX indicating output connection */
+/* */
+/* DWORD dwDspDataArea */
+/* Address of DSP data area containing connection header */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD kConnectInputOutput
+ (allegro_devc * devc, PHWI phwi,
+ DWORD dwDSPInConnection, DWORD dwDSPOutConnection, DWORD dwDspDataArea)
+{
+ /* */
+ /* connect the input */
+ /* */
+
+ if ((dwDSPInConnection != KCONNECT_NONE) &&
+ (dwDSPInConnection != KCONNECT_SAME) &&
+ (dwDSPInConnection < NUMBER_OF_CONNECTIONS))
+ {
+ if (!kAddListEntry (devc, phwi,
+ kHostXferListAddress (phwi, dwDSPInConnection),
+ kDSPXferListAddress (phwi, dwDSPInConnection),
+ (WORD) (dwDspDataArea >> DP_SHIFT_COUNT)))
+ return FALSE;
+
+ if (dwDSPInConnection == KCONNECT_ADC1)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_ADC1_REQUEST, TRUE);
+
+
+ if (dwDSPInConnection == KCONNECT_ADC2)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_ADC2_REQUEST, TRUE);
+
+
+ if (dwDSPInConnection == KCONNECT_CD)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_CD_REQUEST, TRUE);
+
+ if (dwDSPInConnection == KCONNECT_MIC)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_MIC_REQUEST, TRUE);
+
+ if (dwDSPInConnection == KCONNECT_I2S)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_I2S_INT_METER, 0);
+
+ if (dwDSPInConnection == KCONNECT_SPDIFIN)
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_SPDIFIN_INT_METER, 0);
+
+ }
+
+ }
+ else
+ {
+ /* */
+ /* input buffer is connected to other instance's output buffer */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ (WORD) (dwDspDataArea) + CDATA_IN_BUF_CONNECT,
+ (WORD) dwDSPInConnection);
+ }
+
+
+ /* */
+ /* connect the output */
+ /* */
+
+ if ((dwDSPOutConnection != KCONNECT_NONE) &&
+ (dwDSPOutConnection != KCONNECT_SAME) &&
+ (dwDSPOutConnection < NUMBER_OF_CONNECTIONS))
+ {
+ if (!kAddListEntry (devc, phwi,
+ kHostXferListAddress (phwi, dwDSPOutConnection),
+ kDSPXferListAddress (phwi, dwDSPOutConnection),
+ (WORD) (dwDspDataArea >> DP_SHIFT_COUNT)))
+ return FALSE;
+
+ /* */
+ /* if mixer, tell the dsp the total number of mixing list */
+ /* */
+
+ if (dwDSPOutConnection == KCONNECT_MIXER)
+ {
+
+ MIXER_TASK_NUMBER++;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_MIXER_TASK_NUMBER, MIXER_TASK_NUMBER);
+ }
+ }
+ else
+ {
+ /* */
+ /* output buffer is connected to other instance's input buffer */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ (WORD) (dwDspDataArea) + CDATA_OUT_BUF_CONNECT,
+ (WORD) dwDSPOutConnection);
+ }
+
+ return TRUE;
+
+} /* kConnectInputOutput() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kDisconnectInputOutput */
+/* */
+/* Description: */
+/* Disconnect the specified input and output. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwDSPInConnection */
+/* KCONNECT_XXX indicating input connection */
+/* */
+/* DWORD dwDSPOutConnection */
+/* KCONNECT_XXX indicating output connection */
+/* */
+/* DWORD dwDspDataArea */
+/* Address of DSP data area containing connection header */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD kDisconnectInputOutput
+ (allegro_devc * devc, PHWI phwi,
+ DWORD dwDSPInConnection, DWORD dwDSPOutConnection, DWORD dwDspDataArea)
+{
+ WORD wdata;
+
+ /* */
+ /* disconnect the input */
+ /* */
+
+ if ((dwDSPInConnection != KCONNECT_NONE) &&
+ (dwDSPInConnection != KCONNECT_SAME))
+ {
+
+ kRemoveListEntry (devc, phwi,
+ kHostXferListAddress (phwi, dwDSPInConnection),
+ kDSPXferListAddress (phwi, dwDSPInConnection),
+ (WORD) (dwDspDataArea >> DP_SHIFT_COUNT));
+
+ if (dwDSPInConnection == KCONNECT_ADC1)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_ADC1_REQUEST, FALSE);
+
+ if (dwDSPInConnection == KCONNECT_ADC2)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_ADC2_REQUEST, FALSE);
+
+ if (dwDSPInConnection == KCONNECT_CD)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_CD_REQUEST, FALSE);
+
+ if (dwDSPInConnection == KCONNECT_MIC)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_MIC_REQUEST, FALSE);
+
+ if (dwDSPInConnection == KCONNECT_I2S)
+ {
+ wdata = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_I2S_ACTIVE);
+
+ wdata &= ~0x1;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_I2S_ACTIVE, wdata);
+ }
+
+ if (dwDSPInConnection == KCONNECT_SPDIFIN)
+ {
+ wdata = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_I2S_ACTIVE);
+
+ wdata &= ~0x2;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_I2S_ACTIVE, wdata);
+ }
+
+ }
+
+ /* */
+ /* disconnect the output */
+ /* */
+
+ if ((dwDSPOutConnection != KCONNECT_NONE) &&
+ (dwDSPOutConnection != KCONNECT_SAME))
+ {
+ kRemoveListEntry (devc, phwi,
+ kHostXferListAddress (phwi, dwDSPOutConnection),
+ kDSPXferListAddress (phwi, dwDSPOutConnection),
+ (WORD) (dwDspDataArea >> DP_SHIFT_COUNT));
+ }
+
+ /* */
+ /* if mixer, tell the dsp the total number of mixing list */
+ /* */
+
+ if (dwDSPOutConnection == KCONNECT_MIXER)
+ {
+
+ MIXER_TASK_NUMBER--;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_MIXER_TASK_NUMBER, MIXER_TASK_NUMBER);
+ }
+
+ /* */
+ /* handle special cases */
+ /* */
+
+ if ((dwDSPInConnection == KCONNECT_DMA) ||
+ (dwDSPOutConnection == KCONNECT_DMA))
+ {
+ /* do DMA synchronization */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_DMA_SWITCH, FALSE);
+ }
+
+ return TRUE;
+
+} /* kDisconnectInputOutput() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* PCLIENT_BIN kBinStructAddress */
+/* */
+/* Description: */
+/* Return pointer to requested binary image structure. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwClient */
+/* Client ID */
+/* */
+/* DWORD dwSearchKey */
+/* Search key */
+/* */
+/* Return (PCLIENT_BIN): */
+/* Pointer to structure if successful, NULL otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+PCLIENT_BIN
+kBinStructAddress (PHWI phwi, DWORD dwClient, DWORD dwSearchKey)
+{
+ PCLIENT_BIN pClient_Bin;
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return NULL;
+
+ pClient_Bin = phwi->asClientTable[dwClient].pClient_Bin;
+
+ /* */
+ /* If search key is NULL, then just return address of first struct */
+ /* */
+
+ if (!dwSearchKey)
+ return pClient_Bin;
+
+ /* */
+ /* Search key is code load address */
+ /* */
+
+ while (pClient_Bin->dwCodeAddress)
+ {
+ if (pClient_Bin->dwCodeAddress == dwSearchKey)
+ {
+ return pClient_Bin;
+ }
+
+ ++pClient_Bin;
+ }
+
+ return NULL;
+
+} /* kBinStructAddress() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kAllocDspVectors */
+/* */
+/* Description: */
+/* Allocate DSP vectors required by client. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwClient */
+/* Client ID */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD
+kAllocDspVectors (allegro_devc * devc, PHWI phwi, DWORD dwClient)
+{
+ PCLIENT_BIN pClient_Bin;
+ DWORD dwAllocate;
+ DWORD dwIndex;
+
+ /* */
+ /* Check if client needs to allocate DSP vectors */
+ /* */
+
+ if (!(pClient_Bin = kBinStructAddress (phwi, dwClient,
+ phwi->asClientTable[dwClient].
+ dwDspCodeClientArea)))
+ return FALSE;
+
+ dwAllocate = FALSE;
+
+ for (dwIndex = KCODE_VECTORS_UNIT_LENGTH; /* vector 0 reserved */
+ dwIndex < KCODE_VECTORS_LENGTH; dwIndex += KCODE_VECTORS_UNIT_LENGTH)
+ {
+ if (pClient_Bin->pwBinVect[dwIndex + 0] ||
+ pClient_Bin->pwBinVect[dwIndex + 1])
+ {
+ dwAllocate = TRUE;
+
+ /* fail if the vector is already allocated */
+
+ if ((phwi->awVectorList[dwIndex + 0] != F_FREE) ||
+ (phwi->awVectorList[dwIndex + 1] != F_FREE))
+ return FALSE;
+ }
+ }
+
+ if (!dwAllocate)
+ return TRUE;
+
+ /* */
+ /* Make sure DSP kernel is ready to be halted */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, FALSE))
+ return FALSE;
+
+ /* */
+ /* halt the DSP kernel and wait for an acknowledgement */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, TRUE);
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, TRUE))
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ return FALSE;
+ }
+
+ /* */
+ /* DSP kernel has halted, do vector allocation */
+ /* */
+ /* Note: We halt the DSP in order to safely modify vectors */
+ /* */
+
+ for (dwIndex = KCODE_VECTORS_UNIT_LENGTH; /* vector 0 reserved */
+ dwIndex < KCODE_VECTORS_LENGTH; dwIndex += KCODE_VECTORS_UNIT_LENGTH)
+ {
+ if (pClient_Bin->pwBinVect[dwIndex + 0] ||
+ pClient_Bin->pwBinVect[dwIndex + 1])
+ {
+ /* save current DSP vector */
+
+ phwi->awVectorList[dwIndex + 0] =
+ kDspReadWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_CODE,
+ dwIndex + 0);
+
+ phwi->awVectorList[dwIndex + 1] =
+ kDspReadWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_CODE,
+ dwIndex + 1);
+
+ /* write new DSP vector */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ dwIndex + 0, pClient_Bin->pwBinVect[dwIndex + 0]);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ dwIndex + 1, pClient_Bin->pwBinVect[dwIndex + 1]);
+ }
+ }
+
+ /* */
+ /* all done, reset halt request flag to resume DSP kernel execution */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ return TRUE;
+
+} /* kAllocDspVectors() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kDeallocDspVectors */
+/* */
+/* Description: */
+/* Deallocate DSP vectors previously required by client. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwClient */
+/* Client ID */
+/* */
+/* Return (DWORD): */
+/* TRUE if successful, FALSE otherwise */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD
+kDeallocDspVectors (allegro_devc * devc, PHWI phwi, DWORD dwClient)
+{
+ PCLIENT_BIN pClient_Bin;
+ DWORD dwDeallocate;
+ DWORD dwIndex;
+
+ /* */
+ /* Check if client needs to deallocate DSP vectors */
+ /* */
+
+ if (!(pClient_Bin = kBinStructAddress (phwi, dwClient,
+ phwi->asClientTable[dwClient].
+ dwDspCodeClientArea)))
+ return FALSE;
+
+ dwDeallocate = FALSE;
+
+ for (dwIndex = KCODE_VECTORS_UNIT_LENGTH; /* vector 0 reserved */
+ dwIndex < KCODE_VECTORS_LENGTH; dwIndex += KCODE_VECTORS_UNIT_LENGTH)
+ {
+ if (pClient_Bin->pwBinVect[dwIndex + 0] ||
+ pClient_Bin->pwBinVect[dwIndex + 1])
+ {
+ dwDeallocate = TRUE;
+
+ /* fail if the vector was not allocated */
+
+ if ((phwi->awVectorList[dwIndex + 0] == F_FREE) &&
+ (phwi->awVectorList[dwIndex + 1] == F_FREE))
+ return FALSE;
+ }
+ }
+
+ if (!dwDeallocate)
+ return TRUE;
+
+ /* */
+ /* Make sure DSP kernel is ready to be halted */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, FALSE))
+ return FALSE;
+
+ /* */
+ /* halt the DSP kernel and wait for an acknowledgement */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, TRUE);
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, TRUE))
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ return FALSE;
+ }
+
+ /* */
+ /* DSP kernel has halted, do vector deallocation */
+ /* */
+ /* Note: We halt the DSP in order to safely modify vectors */
+ /* */
+
+ for (dwIndex = KCODE_VECTORS_UNIT_LENGTH; /* vector 0 reserved */
+ dwIndex < KCODE_VECTORS_LENGTH; dwIndex += KCODE_VECTORS_UNIT_LENGTH)
+ {
+ if (pClient_Bin->pwBinVect[dwIndex + 0] ||
+ pClient_Bin->pwBinVect[dwIndex + 1])
+ {
+ /* restore original DSP vector */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ dwIndex + 0, phwi->awVectorList[dwIndex + 0]);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ dwIndex + 1, phwi->awVectorList[dwIndex + 1]);
+
+ /* reset vector list */
+
+ phwi->awVectorList[dwIndex + 0] = F_FREE;
+ phwi->awVectorList[dwIndex + 1] = F_FREE;
+ }
+ }
+
+ /* */
+ /* all done, reset halt request flag to resume DSP kernel execution */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ return TRUE;
+
+} /* kDeallocDspVectors() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kLoadKernel */
+/* */
+/* Description: */
+/* Load the kernel into DSP memory. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwFlags */
+/* Hardware instance flags. */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+/*ARGSUSED*/
+VOID
+kLoadKernel (allegro_devc * devc, PHWI phwi, DWORD dwBaseIO, DWORD dwFlags)
+{
+ BYTE bData;
+
+ bData = kDspHalt (devc, dwBaseIO);
+
+ kDisableFMMap (devc, dwBaseIO, TRUE);
+
+ /* clear DSP kernel data memory */
+
+ kDspWriteZeros (devc, dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_BASE_ADDR,
+ NUM_UNITS_KERNEL_DATA * phwi->dwDataMemoryUnitLength);
+
+ /* clear DSP kernel mixer data memory */
+
+ kDspWriteZeros (devc, dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_BASE_ADDR2,
+ NUM_UNITS_KERNEL_DATA * phwi->dwDataMemoryUnitLength);
+
+
+ /* initialize current DMA pointer */
+
+ kDspWriteWord (devc, dwBaseIO, MEMTYPE_INTERNAL_DATA, KDATA_CURRENT_DMA, KDATA_DMA_XFER0); /* khs 121198 */
+
+ /* initialize SPDIF frame status pointer and array */
+
+ kDspWriteWord (devc, dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_SPDIF_CURRENT_FRAME, KDATA_SPDIF_FRAME0);
+
+ kDspWriteWord (devc, dwBaseIO, MEMTYPE_INTERNAL_DATA, KDATA_SPDIF_FRAME0,
+ /* 0x0204 ) ; */
+ 0x0100); /*AY990508 CD data and copy prohibited for SCMS */
+
+ kDspWriteWord (devc, dwBaseIO, MEMTYPE_INTERNAL_DATA, KDATA_SPDIF_FRAME1, 0x0200); /*48K only */
+
+ /* download kernel to DSP memory */
+ {
+ kDspWriteWords (devc, dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->dwCodeMemoryBegin,
+ (gsKernelVectCode.dwLengthCode + 1) / 2,
+ gsKernelVectCode.pwBinCode);
+ }
+
+ /* indicate that kernel is loaded */
+ phwi->dwFlags &= ~HWI_FLAG_UNLOADED;
+
+ /* Set Master Volume to Maximum */
+ kSetMasterVolume (devc, phwi, 0x7FFF, 0x7FFF);
+
+ kDspReset (devc, dwBaseIO, bData);
+
+} /* kLoadKernel() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kInitKernel */
+/* */
+/* Description: */
+/* Initialize the host and DSP kernel. */
+/* */
+/* Parameters: */
+/* PHWI *pphwi */
+/* Pointer to Pointer to hardware instance. */
+/* */
+/* DWORD dwDeviceID */
+/* Device ID. */
+/* */
+/* DWORD dwRevisionID */
+/* Revision ID. */
+/* should always be 0x10 for M3/Allegro1 */
+/* */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* DWORD dwFlags */
+/* Hardware instance flags. */
+/* should always be 0 since there is no difference for HSP */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kInitKernel
+ (allegro_devc * devc, PHWI * pphwi,
+ DWORD dwDeviceID, DWORD dwRevisionID, DWORD dwBaseIO, DWORD dwFlags)
+{
+
+ PHWI phwi;
+ BYTE *pbSrc;
+ BYTE *pbDst;
+ WORD i;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kInitKernel DID=%X RID=%X IO=%X Flag=%X\n",
+ dwDeviceID, dwRevisionID, dwBaseIO, dwFlags);
+#endif
+ /* */
+ /* Allocate hardware instance buffer, initialize it, and pass */
+ /* the buffer address back to the caller */
+ /* */
+
+ if (!(phwi = (PHWI) _HeapAllocate (sizeof (HWI), HEAPZEROINIT)))
+ return KRETURN_ERROR_GENERIC;
+
+ *phwi = ghwi;
+ *pphwi = phwi;
+
+ /* */
+ /* Initialize the hardware instance */
+ /* */
+
+ phwi->dwDeviceID = dwDeviceID;
+ phwi->dwRevisionID = dwRevisionID;
+ phwi->dwBaseIO = dwBaseIO;
+ phwi->dwFlags = dwFlags; /* should be 0x0 */
+
+
+ /* */
+ /* Check and report bad sectors in DSP Memory */
+ /* */
+/*aaa */
+ /*if (phwi -> dwFlags & HWI_FLAG_MEM_CHECK) { */
+ kDSPMemCheck (devc, phwi);
+ /* return KRETURN_ERROR_GENERIC ; */
+ /* } */
+
+ /* init memory map bounds */
+
+ {
+ phwi->dwCodeMemoryBegin = REV_B_CODE_MEMORY_BEGIN;
+ phwi->dwCodeMemoryEnd = REV_B_CODE_MEMORY_END;
+ phwi->dwCodeMemoryUnitLength = REV_B_CODE_MEMORY_UNIT_LENGTH;
+ phwi->dwCodeMemoryLength = REV_B_CODE_MEMORY_LENGTH;
+
+ phwi->dwDataMemoryBegin = REV_B_DATA_MEMORY_BEGIN;
+ phwi->dwDataMemoryEnd = REV_B_DATA_MEMORY_END;
+ phwi->dwDataMemoryUnitLength = REV_B_DATA_MEMORY_UNIT_LENGTH;
+ phwi->dwDataMemoryLength = REV_B_DATA_MEMORY_LENGTH;
+
+ /* transfer memory map images */
+
+ pbSrc = gabRevBCodeMemoryMapImage;
+ pbDst = phwi->abCodeMemoryMap;
+
+ while ((*pbDst++ = *pbSrc++) != (BYTE) F_END);
+
+ pbSrc = gabRevBDataMemoryMapImage;
+ pbDst = phwi->abDataMemoryMap;
+
+ while ((*pbDst++ = *pbSrc++) != (BYTE) F_END);
+ }
+
+ /* */
+ /* Initialize the DSP */
+ /* */
+
+ kLoadKernel (devc, phwi, dwBaseIO, dwFlags);
+
+
+
+ /* testing : dump memory map to 0x1800 */
+ pbDst = phwi->abDataMemoryMap;
+
+ *pbDst++ = F_USED;
+ *pbDst++ = F_USED;
+
+ pbDst = phwi->abDataMemoryMap;
+
+ for (i = 0; i < 24; i++)
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ (DWORD) 0x10c0 + i, (WORD) ((*pbDst++) * 0xFFFF));
+ }
+
+ return KRETURN_SUCCESS;
+
+} /* kInitKernel() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kDSPMemCheck */
+/* */
+/* Description: */
+/* Check the DSP Data memory and update a memory map in host kernel. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+/*kkk */
+KRETURN
+kDSPMemCheck (allegro_devc * devc, PHWI phwi)
+{
+ BYTE bData;
+ BYTE bData2;
+
+ WORD wLoop = 0;
+ WORD wFlag = 0;
+ WORD wFlag2 = 1;
+ WORD wFlag3 = 1;
+ WORD i;
+ DWORD addr = 0;
+
+
+ /* */
+ /* begin to check memory */
+ /* */
+
+ /* save the clock speed for restoreing */
+ bData2 = kInB (devc, phwi->dwBaseIO + DSP_PORT_CONTROL_REG_A);
+
+ for (wLoop = 0; wLoop < 20; wLoop++)
+ {
+
+ bData = kDspHalt (devc, phwi->dwBaseIO);
+
+ /* change to 49Mhz for intensive memory test */
+
+ kOutB (devc, phwi->dwBaseIO + DSP_PORT_CONTROL_REG_A, (BYTE) 0x09);
+/* kOutB( phwi -> dwBaseIO + DSP_PORT_CONTROL_REG_C, (BYTE) 0x10 ) ; */
+
+
+ /* clear DSP kernel data memory */
+
+ kDspWriteZeros (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_BASE_ADDR, REV_B_DATA_MEMORY_LENGTH);
+
+ /* load memory check code */
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->dwCodeMemoryBegin,
+ (gsMemChkVectCode.dwLengthCode + 1) / 2,
+ gsMemChkVectCode.pwBinCode);
+
+ /* start DSP */
+
+
+ kDspReset (devc, phwi->dwBaseIO, bData);
+
+ for (i = 0; i < 3; i++)
+ {
+
+ if (i == 0)
+ addr = FLAGADD1;
+ if (i == 1)
+ addr = FLAGADD2;
+ if (i == 2)
+ addr = FLAGADD3;
+
+
+ /* initialize */
+
+ kDspWriteWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr + 9, wFlag);
+
+ kDspWriteWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr + 5, wFlag2);
+
+ kDspWriteWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr + 6, wFlag3);
+
+
+ /* first 1k check */
+
+ /*LINTED*/
+ while (1)
+ {
+
+ wFlag =
+ kDspReadWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr);
+
+ if (wFlag == 0x0001) /* passed */
+ {
+
+ wFlag = 0;
+
+ kDspWriteWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr, wFlag);
+
+ break;
+
+ }
+ else if (wFlag == 0x0002) /* found a bad sector */
+ {
+
+ wFlag =
+ kDspReadWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr + 2);
+
+ /* update memory map */
+ gabRevBDataMemoryMapImage[((wFlag -
+ REV_B_DATA_MEMORY_BEGIN) >> 7)]
+ = F_USED;
+
+ wFlag = 0;
+
+ kDspWriteWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr, wFlag);
+
+ kDspWriteWord (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA,
+ addr + 5, wFlag2);
+ }
+
+ } /* while */
+
+ } /* for(3) */
+
+ } /* for(100) */
+
+
+ /* */
+ /* everything is done, so restore the clock */
+ /* */
+
+ bData = kDspHalt (devc, phwi->dwBaseIO);
+
+ kOutB (devc, phwi->dwBaseIO + DSP_PORT_CONTROL_REG_A, (BYTE) bData2);
+
+ kDspReset (devc, phwi->dwBaseIO, bData);
+
+
+ return KRETURN_SUCCESS;
+
+}
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kTermKernel */
+/* */
+/* Description: */
+/* Terminate the host and DSP kernel. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwBaseIO */
+/* Base I/O address of device. */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kTermKernel (allegro_devc * devc, PHWI phwi, DWORD dwBaseIO)
+{
+ kDspHalt (devc, dwBaseIO);
+
+ _HeapFree (phwi, 0);
+
+ return KRETURN_SUCCESS;
+
+} /* kTermKernel() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSuspendKernel */
+/* */
+/* Description: */
+/* Suspend the kernel and save its state. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kSuspendKernel (allegro_devc * devc, PHWI phwi)
+{
+ /* */
+ /* FM is a special case */
+ /* */
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSuspendKernel %X\n", phwi);
+#endif
+
+ if (phwi->dwFlags & HWI_FLAG_FM_LOADED)
+ {
+ /* */
+ /* Allocate host memory */
+ /* */
+
+ if (!(phwi->pwSuspendBuffer = (PWORD)
+ _HeapAllocate ((phwi->dwCodeMemoryLength +
+ phwi->dwDataMemoryLength) * 2, HEAPZEROINIT)))
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Do memory save */
+ /* */
+
+ kDspReadWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->dwCodeMemoryBegin,
+ phwi->dwCodeMemoryLength, phwi->pwSuspendBuffer);
+
+ kDspReadLongWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ phwi->dwDataMemoryBegin,
+ phwi->dwDataMemoryLength,
+ phwi->pwSuspendBuffer + phwi->dwCodeMemoryLength);
+
+ /* */
+ /* Indicate FM is suspended */
+ /* */
+
+ phwi->dwFlags |= HWI_FLAG_SUSPENDED;
+
+ return KRETURN_SUCCESS;
+ }
+
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Allocate host memory */
+ /* */
+
+ if (!(phwi->pwSuspendBuffer = (PWORD)
+ _HeapAllocate ((phwi->dwCodeMemoryLength +
+ phwi->dwDataMemoryLength) * 2, HEAPZEROINIT)))
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Make sure DSP kernel is ready to be halted */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, FALSE))
+ goto kSuspend_Error;
+
+ /* */
+ /* halt the DSP kernel and wait for an acknowledgement */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, TRUE);
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, TRUE))
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ goto kSuspend_Error;
+ }
+
+ /* */
+ /* DSP kernel has halted, do memory save */
+ /* */
+ /* Note: We halt the DSP in order to place it in a known state */
+ /* */
+
+ kDspReadWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->dwCodeMemoryBegin,
+ phwi->dwCodeMemoryLength, phwi->pwSuspendBuffer);
+
+ kDspReadLongWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ phwi->dwDataMemoryBegin,
+ phwi->dwDataMemoryLength,
+ phwi->pwSuspendBuffer + phwi->dwCodeMemoryLength);
+
+ /* */
+ /* Kernel was successfully suspended, indicate kernel is unloaded */
+ /* */
+
+ phwi->dwFlags |= (HWI_FLAG_SUSPENDED | HWI_FLAG_UNLOADED);
+
+ return KRETURN_SUCCESS;
+
+kSuspend_Error:
+
+ /* */
+ /* Failure, undo all that was done... */
+ /* */
+
+ if (phwi->pwSuspendBuffer)
+ {
+ _HeapFree (phwi->pwSuspendBuffer, 0);
+ }
+
+ return KRETURN_ERROR_GENERIC;
+
+} /* kSuspendKernel() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kResumeKernel */
+/* */
+/* Description: */
+/* Resume the kernel and restore its state. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kResumeKernel (allegro_devc * devc, PHWI phwi)
+{
+ BYTE bData;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kResumeKernel %X\n", phwi);
+#endif
+ /* */
+ /* FM is a special case */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_FM_LOADED)
+ {
+ /* */
+ /* Fail if FM isn't suspended */
+ /* */
+
+ if (!(phwi->dwFlags & HWI_FLAG_SUSPENDED))
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Do memory restore */
+ /* */
+
+ bData = kDspHalt (devc, phwi->dwBaseIO);
+
+ if (!phwi->pwSuspendBuffer)
+ return KRETURN_ERROR_GENERIC;
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->dwCodeMemoryBegin,
+ phwi->dwCodeMemoryLength, phwi->pwSuspendBuffer);
+
+ kDspWriteLongWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ phwi->dwDataMemoryBegin,
+ phwi->dwDataMemoryLength,
+ phwi->pwSuspendBuffer + phwi->dwCodeMemoryLength);
+
+ _HeapFree (phwi->pwSuspendBuffer, 0);
+
+ phwi->pwSuspendBuffer = 0;
+
+ kDspReset (devc, phwi->dwBaseIO, bData);
+
+ /* Indicate FM is no longer suspended */
+
+ phwi->dwFlags &= ~HWI_FLAG_SUSPENDED;
+
+ return KRETURN_SUCCESS;
+ }
+
+ /* */
+ /* Fail if the kernel isn't suspended */
+ /* */
+
+ if (!(phwi->dwFlags & HWI_FLAG_SUSPENDED))
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Do memory restore */
+ /* */
+
+ bData = kDspHalt (devc, phwi->dwBaseIO);
+
+ if (!phwi->pwSuspendBuffer)
+ return KRETURN_ERROR_GENERIC;
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->dwCodeMemoryBegin,
+ phwi->dwCodeMemoryLength, phwi->pwSuspendBuffer);
+
+ kDspWriteLongWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ phwi->dwDataMemoryBegin,
+ phwi->dwDataMemoryLength,
+ phwi->pwSuspendBuffer + phwi->dwCodeMemoryLength);
+
+ _HeapFree (phwi->pwSuspendBuffer, 0);
+
+ phwi->pwSuspendBuffer = 0;
+
+ kRestartStreams (devc, phwi);
+
+ /* */
+ /* all done, reset halt request flag to resume DSP kernel execution */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_ACKNOWLEDGE, FALSE);
+
+ kDspReset (devc, phwi->dwBaseIO, bData);
+
+ /* Indicate kernel is loaded */
+
+ phwi->dwFlags &= ~(HWI_FLAG_SUSPENDED | HWI_FLAG_UNLOADED);
+
+ return KRETURN_SUCCESS;
+
+} /* kResumeKernel() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kOpenInstance */
+/* */
+/* Description: */
+/* Open a client instance. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwClient */
+/* Client ID */
+/* */
+/* DWORD dwFlags */
+/* KOPENCLOSE_XXX flags indicating open to perform */
+/* */
+/* DWORD dwLen */
+/* Length in bytes of data area of CLIENT_INST (zero allowed) */
+/* */
+/* PCLIENT_INST *ppClient_Inst */
+/* Pointer to PCLIENT_INST that will contain the instance pointer */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kOpenInstance
+ (allegro_devc * devc, PHWI phwi,
+ DWORD dwClient, DWORD dwFlags, DWORD dwLen, PCLIENT_INST * ppClient_Inst)
+{
+ PCLIENT_INST pClient_Inst = NULL;
+ PCLIENT_BIN pClient_Bin = NULL;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kOpenInstance %X %X %X %X\n", phwi,
+ dwClient, dwFlags, dwLen);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+#ifndef NT_MODEL
+ /* */
+ /* FM client is a special case */
+ /* */
+ /* The FM client isn't really a client of the DSP kernel. It requires */
+ /* the entire DSP to execute therefore the DSP kernel must be swapped */
+ /* out of the DSP before it can run. When FM is closed the DSP kernel */
+ /* is reloaded into the DSP. */
+ /* */
+
+ if (dwClient == CLIENT_FM)
+ {
+ DWORD dwClientMasks;
+ DWORD dwConnectMasks;
+ BYTE bData;
+
+ /* Fail if the DSP kernel is not idle */
+
+ if (kQueryActivity (devc, phwi, &dwClientMasks, &dwConnectMasks) !=
+ KRETURN_SUCCESS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (dwClientMasks || dwConnectMasks)
+ return KRETURN_ERROR_BUSY;
+
+ /* */
+ /* Allocate host memory */
+ /* */
+
+ if (!(pClient_Inst = (PCLIENT_INST)
+ _HeapAllocate (sizeof (CLIENT_INST) + dwLen, HEAPZEROINIT)))
+ return KRETURN_ERROR_GENERIC;
+
+ pClient_Inst->dwClient = dwClient;
+
+ *ppClient_Inst = pClient_Inst;
+
+ /* download FM client to DSP memory */
+
+ bData = kDspHalt (devc, phwi->dwBaseIO);
+
+ kDisableFMMap (devc, phwi->dwBaseIO, FALSE);
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->dwCodeMemoryBegin,
+ (gsFMVectCode.dwLengthVect + 1) / 2,
+ gsFMVectCode.pwBinVect);
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ gsFMVectCode.dwCodeAddress,
+ (gsFMVectCode.dwLengthCode + 1) / 2,
+ gsFMVectCode.pwBinCode);
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ phwi->dwDataMemoryBegin,
+ (gsFMVectCode.dwLengthData + 1) / 2,
+ gsFMVectCode.pwBinData);
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ gsFMVectCode.dwData2Address,
+ (gsFMVectCode.dwLengthData2 + 1) / 2,
+ gsFMVectCode.pwBinData2);
+
+ kDspReset (devc, phwi->dwBaseIO, bData);
+
+ /* FM client was successfully loaded, indicate kernel is unloaded */
+
+ phwi->dwFlags |= (HWI_FLAG_FM_LOADED | HWI_FLAG_UNLOADED);
+
+ return KRETURN_SUCCESS;
+ }
+#endif
+
+ /* */
+ /* Do open/close synchronization */
+ /* */
+ /* Generally, an open can safely be done except just after a close. */
+ /* The reason a close might cause a problem is that when a client */
+ /* requests a close, the host-side may close but the DSP-side */
+ /* may be executing AT THAT MOMENT. This means the host-side thinks */
+ /* resources that were formally allocated are now free, whereas on */
+ /* the DSP-side they actually are still in use. So if an open is done, */
+ /* and the open happens to be assigned some of these same resources, a */
+ /* resource conflict arises. For example, the executable of the open */
+ /* client might get downloaded over the still executing close client, */
+ /* likely causing a DSP crash. */
+ /* */
+ /* One way to overcome this danger is by making sure a client task */
+ /* switch has occured SINCE THE CLOSE WAS COMPLETED. A task switch */
+ /* covers the following cases: */
+ /* */
+ /* 1) A DSP-side client is executing just as the kernel closes it. */
+ /* A subsequent task switch means this client is no longer running, */
+ /* so the close is complete and the freed resources are available. */
+ /* */
+ /* 2) A DSP-side client is idle when the kernel closes it. A */
+ /* subsequent task switch to this client either means the client */
+ /* doesn't run at all (client closed) or an instance is not */
+ /* processed at all (instance closed). Thus the resources */
+ /* previously used by the client or instance are freed. */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_TASK_SWITCH, TRUE))
+ return KRETURN_ERROR_BUSY;
+
+ /* */
+ /* Make sure client and an available instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (phwi->asClientTable[dwClient].dwReferenceCount >=
+ phwi->asClientTable[dwClient].dwMaxReference)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Allocate host memory */
+ /* */
+
+ if (!(pClient_Inst = (PCLIENT_INST)
+ _HeapAllocate (sizeof (CLIENT_INST) + dwLen, HEAPZEROINIT)))
+ goto kOpen_Error;
+
+ pClient_Inst->dwClient = dwClient;
+ pClient_Inst->dwDspDataNumUnits =
+ NUM_UNITS (dwLen, phwi->dwDataMemoryUnitLength);
+
+ /* */
+ /* Allocate DSP data memory */
+ /* */
+
+ if (dwLen)
+ {
+ if (!(pClient_Inst->pbDspDataMapPtr =
+ kAllocDspMemory (phwi, NULL,
+ phwi->abDataMemoryMap,
+ pClient_Inst->dwDspDataNumUnits)))
+ goto kOpen_Error;
+
+ pClient_Inst->dwDspDataClientArea =
+ /*LINTED*/
+ ((pClient_Inst->pbDspDataMapPtr - phwi->abDataMemoryMap) *
+ phwi->dwDataMemoryUnitLength) + phwi->dwDataMemoryBegin;
+
+ /* clear DSP client data memory */
+
+ kDspWriteZeros (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea,
+ pClient_Inst->dwDspDataNumUnits *
+ phwi->dwDataMemoryUnitLength);
+
+ /* download client data binary */
+
+ if (!(pClient_Bin = kBinStructAddress (phwi, dwClient, NULL)))
+ goto kOpen_Error;
+
+ /* make sure allocation size can hold data binary */
+
+ if (dwLen < pClient_Bin->dwLengthData)
+ goto kOpen_Error;
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea,
+ (pClient_Bin->dwLengthData + 1) / 2,
+ pClient_Bin->pwBinData);
+
+ /* add instance to instance list */
+ if (dwFlags & KOPENCLOSE_SYNCHRONOUS)
+ /*if ( 0 ) */
+ {
+ DWORD dwReturn;
+
+ /* */
+ /* Make sure DSP kernel is ready to be halted */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, FALSE))
+ goto kOpen_Error;
+
+ /* */
+ /* halt the DSP kernel and wait for an acknowledgement */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_HALT_SYNCH_CLIENT, TRUE);
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, TRUE))
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ goto kOpen_Error;
+ }
+
+ /* */
+ /* DSP kernel has halted, do open */
+ /* */
+ /* Note: We halt the DSP in order to synchronize the open */
+ /* with the client */
+ /* */
+
+ dwReturn = kAddListEntry (devc, phwi,
+ kInstanceListAddress (phwi, dwClient),
+ (WORD) phwi->asClientTable[dwClient].
+ dwInstanceListArea,
+ (WORD) (pClient_Inst->
+ dwDspDataClientArea >>
+ DP_SHIFT_COUNT));
+
+ /* */
+ /* all done, reset halt request flag to resume DSP kernel execution */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_HALT_SYNCH_CLIENT, FALSE);
+
+ if (!dwReturn)
+ goto kOpen_Error;
+ }
+ else
+ {
+ if (!kAddListEntry (devc, phwi,
+ kInstanceListAddress (phwi, dwClient),
+ (WORD) phwi->asClientTable[dwClient].
+ dwInstanceListArea,
+ (WORD) (pClient_Inst->
+ dwDspDataClientArea >> DP_SHIFT_COUNT)))
+ goto kOpen_Error;
+
+ }
+
+
+
+ }
+
+/*#pragma message("----Assuming individual client code binaries are equal length!") */
+
+ phwi->asClientTable[dwClient].dwDspCodeNumUnits =
+ NUM_UNITS (phwi->asClientTable[dwClient].pClient_Bin->dwLengthCode,
+ phwi->dwCodeMemoryUnitLength);
+
+ /* */
+ /* Allocate DSP code memory */
+ /* */
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ {
+ if (!(phwi->asClientTable[dwClient].pbDspCodeMapPtr =
+ kAllocDspMemory (phwi, dwClient,
+ phwi->abCodeMemoryMap,
+ phwi->asClientTable[dwClient].
+ dwDspCodeNumUnits)))
+ goto kOpen_Error;
+
+ phwi->asClientTable[dwClient].dwDspCodeClientArea =
+ /*LINTED*/
+ ((phwi->asClientTable[dwClient].pbDspCodeMapPtr -
+ phwi->abCodeMemoryMap) * phwi->dwCodeMemoryUnitLength) +
+ phwi->dwCodeMemoryBegin;
+
+ pClient_Inst->dwDspCodeClientArea =
+ phwi->asClientTable[dwClient].dwDspCodeClientArea;
+
+ /* clear DSP client code memory */
+
+ kDspWriteZeros (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->asClientTable[dwClient].dwDspCodeClientArea,
+ phwi->asClientTable[dwClient].dwDspCodeNumUnits *
+ phwi->dwCodeMemoryUnitLength);
+
+ /* download client code binary */
+
+ if (!(pClient_Bin = kBinStructAddress (phwi, dwClient,
+ phwi->asClientTable[dwClient].
+ dwDspCodeClientArea)))
+ goto kOpen_Error;
+
+ kDspWriteWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_CODE,
+ phwi->asClientTable[dwClient].dwDspCodeClientArea,
+ (pClient_Bin->dwLengthCode + 1) / 2,
+ pClient_Bin->pwBinCode);
+
+ /* allocate DSP vectors */
+
+ if (!kAllocDspVectors (devc, phwi, dwClient))
+ goto kOpen_Error;
+
+ /* add client to task list */
+
+ if (!kAddListEntry (devc, phwi,
+ phwi->awTaskList,
+ KDATA_TASK0,
+ (WORD) phwi->asClientTable[dwClient].
+ dwDspCodeClientArea))
+ goto kOpen_Error;
+ }
+ else
+ {
+ pClient_Inst->dwDspCodeClientArea =
+ phwi->asClientTable[dwClient].dwDspCodeClientArea;
+ }
+
+ /* */
+ /* Everything worked, increment reference counter */
+ /* */
+
+ ++phwi->asClientTable[dwClient].dwReferenceCount;
+
+ *ppClient_Inst = pClient_Inst;
+#ifdef K_DBG
+ _Debug_Printf_Service ("kOpenInstance OK %X\n", pClient_Inst);
+#endif
+
+ return KRETURN_SUCCESS;
+
+kOpen_Error:
+
+ /* */
+ /* Failure, undo all that was done... */
+ /* */
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ {
+ if (phwi->asClientTable[dwClient].pbDspCodeMapPtr)
+ {
+ kDeallocDspVectors (devc, phwi, dwClient);
+
+ kDeallocDspMemory (phwi->asClientTable[dwClient].pbDspCodeMapPtr,
+ phwi->asClientTable[dwClient].dwDspCodeNumUnits);
+ phwi->asClientTable[dwClient].pbDspCodeMapPtr = NULL;
+ }
+ }
+
+ if (pClient_Inst)
+ {
+ if (pClient_Inst->pbDspDataMapPtr)
+ {
+ kRemoveListEntry (devc, phwi,
+ kInstanceListAddress (phwi, dwClient),
+ (WORD) phwi->asClientTable[dwClient].
+ dwInstanceListArea,
+ (WORD) (pClient_Inst->
+ dwDspDataClientArea >> DP_SHIFT_COUNT));
+
+ kDeallocDspMemory (pClient_Inst->pbDspDataMapPtr,
+ pClient_Inst->dwDspDataNumUnits);
+ }
+
+ _HeapFree (pClient_Inst, 0);
+ }
+#ifdef K_DBG
+ _Debug_Printf_Service ("kOpenInstance Failed\n");
+#endif
+
+ return KRETURN_ERROR_GENERIC;
+
+} /* kOpenInstance() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kCloseInstance */
+/* */
+/* Description: */
+/* Close a client instance. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* DWORD dwFlags */
+/* KOPENCLOSE_XXX flags indicating close to perform */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kCloseInstance (allegro_devc * devc, PHWI phwi, PCLIENT_INST pClient_Inst,
+ DWORD dwFlags)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kCloseInstance %X %X %X\n", phwi,
+ pClient_Inst, dwFlags);
+
+
+#endif
+#ifndef NT_MODEL
+ /* */
+ /* FM client is a special case */
+ /* */
+
+ if (dwClient == CLIENT_FM)
+ {
+ /* Fail if the FM client isn't open */
+
+ if (!(phwi->dwFlags & HWI_FLAG_FM_LOADED))
+ return KRETURN_ERROR_GENERIC;
+
+ kLoadKernel (devc, phwi, phwi->dwBaseIO, phwi->dwFlags);
+
+ _HeapFree (pClient_Inst, 0);
+
+ /* Indicate kernel is loaded */
+
+ phwi->dwFlags &= ~(HWI_FLAG_FM_LOADED | HWI_FLAG_UNLOADED);
+
+ return KRETURN_SUCCESS;
+ }
+#endif
+
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Do DMA synchronization */
+ /* */
+ /* (see discussion in kOpenInstance) */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_DMA_SWITCH, TRUE))
+ return KRETURN_ERROR_BUSY;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Deallocate memory */
+ /* */
+
+ if (--phwi->asClientTable[dwClient].dwReferenceCount == 0)
+ {
+ /* remove client from task list */
+
+ kRemoveListEntry (devc, phwi,
+ phwi->awTaskList,
+ KDATA_TASK0,
+ (WORD) phwi->asClientTable[dwClient].
+ dwDspCodeClientArea);
+
+ if (!phwi->asClientTable[dwClient].pbDspCodeMapPtr)
+ return KRETURN_ERROR_GENERIC;
+
+ kDeallocDspVectors (devc, phwi, dwClient);
+
+ kDeallocDspMemory (phwi->asClientTable[dwClient].pbDspCodeMapPtr,
+ phwi->asClientTable[dwClient].dwDspCodeNumUnits);
+ phwi->asClientTable[dwClient].pbDspCodeMapPtr = NULL;
+ }
+
+
+ if (!pClient_Inst)
+ return KRETURN_ERROR_GENERIC;
+
+ if (pClient_Inst->pbDspDataMapPtr)
+ {
+ if (dwFlags & KOPENCLOSE_SYNCHRONOUS)
+ /* if ( 0 ) */
+ {
+ /* */
+ /* Make sure DSP kernel is ready to be halted */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, FALSE))
+ goto kClose_Error;
+
+ /* */
+ /* halt the DSP kernel and wait for an acknowledgement */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_HALT_SYNCH_CLIENT, TRUE);
+
+ kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, TRUE);
+
+ kClose_Error:
+
+ /* */
+ /* DSP kernel has halted, do close */
+ /* */
+ /* Note: We halt the DSP in order to synchronize the close */
+ /* with the client */
+ /* */
+
+ kRemoveListEntry (devc, phwi,
+ kInstanceListAddress (phwi, dwClient),
+ (WORD) phwi->asClientTable[dwClient].
+ dwInstanceListArea,
+ (WORD) (pClient_Inst->
+ dwDspDataClientArea >> DP_SHIFT_COUNT));
+
+ /* */
+ /* all done, reset halt request flag to resume DSP kernel execution */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_HALT_SYNCH_CLIENT, FALSE);
+ }
+ else
+ {
+ kRemoveListEntry (devc, phwi,
+ kInstanceListAddress (phwi, dwClient),
+ (WORD) phwi->asClientTable[dwClient].
+ dwInstanceListArea,
+ (WORD) (pClient_Inst->
+ dwDspDataClientArea >> DP_SHIFT_COUNT));
+
+ }
+
+ kDeallocDspMemory (pClient_Inst->pbDspDataMapPtr,
+ pClient_Inst->dwDspDataNumUnits);
+ }
+
+ _HeapFree (pClient_Inst, 0);
+
+ /* */
+ /* Do open/close synchronization */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_TASK_SWITCH, FALSE);
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kCloseInstance OK\n");
+#endif
+ return KRETURN_SUCCESS;
+
+} /* kCloseInstance() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSwitchClient */
+/* */
+/* Description: */
+/* Remove/Add the client from/to the task list. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* DWORD dwFlags */
+/* KENABLE_CLIENT flags adding client back to task list */
+/* KDISABLE_CLIENT flags removing client from task list */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kSwitchClient (allegro_devc * devc, PHWI phwi, PCLIENT_INST pClient_Inst,
+ DWORD dwFlags)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSwitchClient %X %X %X\n", phwi,
+ pClient_Inst, dwFlags);
+
+
+
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Do DMA synchronization */
+ /* */
+ /* (see discussion in kOpenInstance) */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_DMA_SWITCH, TRUE))
+ return KRETURN_ERROR_BUSY;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (phwi->asClientTable[dwClient].dwReferenceCount != 1)
+ return KRETURN_ERROR_GENERIC;
+
+ if (dwFlags == KDISABLE_CLIENT)
+ {
+ /* remove client from task list */
+
+ kRemoveListEntry (devc, phwi,
+ phwi->awTaskList,
+ KDATA_TASK0,
+ (WORD) phwi->asClientTable[dwClient].
+ dwDspCodeClientArea);
+
+ }
+ else
+ {
+ if (dwFlags == KENABLE_CLIENT)
+ {
+ /* add client to task list */
+
+ if (!kAddListEntry (devc, phwi,
+ phwi->awTaskList,
+ KDATA_TASK0,
+ (WORD) phwi->asClientTable[dwClient].
+ dwDspCodeClientArea))
+ {
+ return KRETURN_ERROR_GENERIC;
+ }
+
+ }
+ else
+ {
+ return KRETURN_ERROR_GENERIC;
+ } /* endif */
+ } /* endif */
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSwitchClient OK\n");
+#endif
+
+ return KRETURN_SUCCESS;
+
+} /* kSwitchClient() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetInstanceReady */
+/* */
+/* Description: */
+/* Set a client instance to the ready state. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kSetInstanceReady (allegro_devc * devc, PHWI phwi, PCLIENT_INST pClient_Inst)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSetInstanceReady %X %x\n", phwi, pClient_Inst);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Set the instance ready flag */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_INSTANCE_READY, TRUE);
+
+ return KRETURN_SUCCESS;
+
+} /* kSetInstanceReady() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetInstanceNotReady */
+/* */
+/* Description: */
+/* Set a client instance to the not ready state. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kSetInstanceNotReady (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSetInstanceNotReady %X %x\n", phwi, pClient_Inst);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Clear the instance ready flag */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_INSTANCE_READY, FALSE);
+
+ return KRETURN_SUCCESS;
+
+} /* kSetInstanceNotReady() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kStartTransfer */
+/* */
+/* Description: */
+/* Start data transfer to/from client instance data memory. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* DWORD dwAutoRepeat */
+/* TRUE if auto-repeat buffer, FALSE if one-shot buffer */
+/* */
+/* DWORD dwHostSrcBufferAddr */
+/* Host source buffer physical address */
+/* */
+/* DWORD dwHostSrcBufferLen */
+/* Host source buffer length in bytes */
+/* */
+/* DWORD dwHostDstBufferAddr */
+/* Host destination buffer linear address */
+/* */
+/* DWORD dwHostDstBufferLen */
+/* Host destination buffer length in bytes */
+/* */
+/* DWORD dwDSPInBufferAddr */
+/* DSP input buffer absolute address */
+/* */
+/* DWORD dwDSPInBufferLen */
+/* DSP input buffer length in bytes */
+/* */
+/* DWORD dwDSPOutBufferAddr */
+/* DSP output buffer absolute address */
+/* */
+/* DWORD dwDSPOutBufferLen */
+/* DSP output buffer length in bytes */
+/* */
+/* DWORD dwDSPInConnection */
+/* KCONNECT_XXX indicating input connection */
+/* */
+/* DWORD dwDSPOutConnection */
+/* KCONNECT_XXX indicating output connection */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kStartTransfer
+ (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst,
+ DWORD dwAutoRepeat,
+ DWORD dwHostSrcBufferAddr,
+ DWORD dwHostSrcBufferLen,
+ DWORD dwHostDstBufferAddr,
+ DWORD dwHostDstBufferLen,
+ DWORD dwDSPInBufferAddr,
+ DWORD dwDSPInBufferLen,
+ DWORD dwDSPOutBufferAddr,
+ DWORD dwDSPOutBufferLen, DWORD dwDSPInConnection, DWORD dwDSPOutConnection)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+ DWORD dwDspDataClientArea = pClient_Inst->dwDspDataClientArea;
+
+#ifdef K_DBG
+ _Debug_Printf_Service
+ ("kStartTransfer %X %X %X %X %X %X %X %X %X %X %X %X %X\n", phwi,
+ pClient_Inst, dwAutoRepeat, dwHostSrcBufferAddr, dwHostSrcBufferLen,
+ dwHostDstBufferAddr, dwHostDstBufferLen, dwDSPInBufferAddr,
+ dwDSPInBufferLen, dwDSPOutBufferAddr, dwDSPOutBufferLen,
+ dwDSPInConnection, dwDSPOutConnection);
+
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+
+ if ((dwDSPInConnection == KCONNECT_DMA) ||
+ (dwDSPOutConnection == KCONNECT_DMA))
+ {
+ /* */
+ /* Do DMA synchronization */
+ /* */
+ /* (see discussion in kOpenInstance) */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_DMA_SWITCH, TRUE))
+ return KRETURN_ERROR_BUSY;
+ }
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Verify input connection parameters */
+ /* */
+
+ if ((dwDSPInConnection != KCONNECT_NONE) &&
+ (dwDSPInConnection != KCONNECT_SAME))
+ {
+ if (!dwDSPInBufferLen)
+ return KRETURN_ERROR_GENERIC;
+
+ /* DSP buffer length must be block multiple */
+
+ if (dwDSPInBufferLen & (DMA_BLOCK_LENGTH - 1))
+ return KRETURN_ERROR_GENERIC;
+
+ if (dwDSPInConnection == KCONNECT_DMA)
+ {
+ /* host buffer must be DWORD aligned */
+
+ if (dwHostSrcBufferAddr & (sizeof (DWORD) - 1))
+ return KRETURN_ERROR_GENERIC;
+
+ if (!dwHostSrcBufferLen)
+ return KRETURN_ERROR_GENERIC;
+ }
+ }
+
+ /* */
+ /* Verify output connection parameters */
+ /* */
+
+ if ((dwDSPOutConnection != KCONNECT_NONE) &&
+ (dwDSPOutConnection != KCONNECT_SAME))
+ {
+ if (!dwDSPOutBufferLen)
+ return KRETURN_ERROR_GENERIC;
+
+ /* DSP buffer length must be block multiple */
+
+ if (dwDSPOutBufferLen & (DMA_BLOCK_LENGTH - 1))
+ return KRETURN_ERROR_GENERIC;
+
+ if ((dwDSPOutConnection == KCONNECT_DMA) ||
+ (dwDSPOutConnection == KCONNECT_PIO))
+ {
+ /* host buffer must be DWORD aligned */
+
+ if (dwHostDstBufferAddr & (sizeof (DWORD) - 1))
+ return KRETURN_ERROR_GENERIC;
+
+ if (!dwHostDstBufferLen)
+ return KRETURN_ERROR_GENERIC;
+ }
+ }
+
+ pClient_Inst->dwHostSrcBufferAddr = dwHostSrcBufferAddr;
+ pClient_Inst->dwHostSrcBufferLen = dwHostSrcBufferLen;
+ pClient_Inst->dwHostDstBufferAddr = dwHostDstBufferAddr;
+ pClient_Inst->dwHostDstBufferLen = dwHostDstBufferLen;
+ pClient_Inst->dwHostDstCurrent = dwHostDstBufferAddr;
+ pClient_Inst->dwDSPOutBufferAddr = dwDSPOutBufferAddr;
+ pClient_Inst->dwDSPOutBufferLen = dwDSPOutBufferLen;
+ pClient_Inst->dwDSPInConnection = dwDSPInConnection;
+ pClient_Inst->dwDSPOutConnection = dwDSPOutConnection;
+
+ /* */
+ /* Write parameters to client instance memory */
+ /* */
+
+ if (dwDSPInConnection == KCONNECT_DMA)
+ {
+ /* host source */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_ADDRL,
+ LOWORD (dwHostSrcBufferAddr));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_ADDRH,
+ HIWORD (dwHostSrcBufferAddr));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_END_PLUS_1L,
+ LOWORD (dwHostSrcBufferAddr + dwHostSrcBufferLen));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_END_PLUS_1H,
+ HIWORD (dwHostSrcBufferAddr + dwHostSrcBufferLen));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_CURRENTL,
+ LOWORD (dwHostSrcBufferAddr));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_CURRENTH,
+ HIWORD (dwHostSrcBufferAddr));
+ }
+
+/*#pragma message("----Stream loopback not supported!") */
+
+ else if (dwDSPOutConnection == KCONNECT_DMA)
+ {
+ /* host destination */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_ADDRL,
+ LOWORD (dwHostDstBufferAddr));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_ADDRH,
+ HIWORD (dwHostDstBufferAddr));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_END_PLUS_1L,
+ LOWORD (dwHostDstBufferAddr + dwHostDstBufferLen));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_END_PLUS_1H,
+ HIWORD (dwHostDstBufferAddr + dwHostDstBufferLen));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_CURRENTL,
+ LOWORD (dwHostDstBufferAddr));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_HOST_SRC_CURRENTH,
+ HIWORD (dwHostDstBufferAddr));
+ }
+
+ /* DSP input */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_IN_BUF_BEGIN,
+ (WORD) dwDSPInBufferAddr);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_IN_BUF_END_PLUS_1,
+ (WORD) (dwDSPInBufferAddr + (dwDSPInBufferLen / 2)));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_IN_BUF_HEAD,
+ (WORD) dwDSPInBufferAddr);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_IN_BUF_TAIL,
+ (WORD) dwDSPInBufferAddr);
+
+ /* DSP output */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_OUT_BUF_BEGIN,
+ (WORD) dwDSPOutBufferAddr);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_OUT_BUF_END_PLUS_1,
+ (WORD) (dwDSPOutBufferAddr + (dwDSPOutBufferLen / 2)));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_OUT_BUF_HEAD,
+ (WORD) dwDSPOutBufferAddr);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_OUT_BUF_TAIL,
+ (WORD) dwDSPOutBufferAddr);
+
+ /* connect the input and output */
+
+ if (dwDSPInConnection == KCONNECT_DMA)
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_DMA_CONTROL,
+ (WORD) (dwAutoRepeat ?
+ (DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR +
+ DMAC_BLOCKF_SELECTOR) : (DMAC_PAGE3_SELECTOR +
+ DMAC_BLOCKF_SELECTOR)));
+ }
+
+/*#pragma message("----Stream loopback not supported!") */
+
+ /* */
+ /* The kernel currently does not support stream loopback. */
+ /* Loopback means data is tranfered via DMA from the host to the */
+ /* DSP, then the data is transfered via DMA from the DSP back to */
+ /* the host. While the data is in DSP memory it is filtered in */
+ /* some way. Thus the DSP acts as a hardware accelerator by */
+ /* off-loading filter processing from the host processor. */
+ /* */
+
+ else if (dwDSPOutConnection == KCONNECT_DMA)
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwDspDataClientArea + CDATA_DMA_CONTROL,
+ (WORD) (dwAutoRepeat ?
+ (DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT +
+ DMAC_PAGE3_SELECTOR +
+ DMAC_BLOCKF_SELECTOR) : (DMACONTROL_DIRECTION +
+ DMAC_PAGE3_SELECTOR +
+ DMAC_BLOCKF_SELECTOR)));
+ }
+
+ if (!kConnectInputOutput (devc, phwi,
+ dwDSPInConnection,
+ dwDSPOutConnection, dwDspDataClientArea))
+ return KRETURN_ERROR_GENERIC;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kStartTransfer OK\n");
+#endif
+ return KRETURN_SUCCESS;
+
+} /* kStartTransfer() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kStopTransfer */
+/* */
+/* Description: */
+/* Stop data transfer to/from client instance data memory. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kStopTransfer (allegro_devc * devc, PHWI phwi, PCLIENT_INST pClient_Inst)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kStopTransfer %X %X\n", phwi, pClient_Inst);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* disconnect the input and output */
+ /* */
+
+ if (!kDisconnectInputOutput (devc, phwi,
+ pClient_Inst->dwDSPInConnection,
+ pClient_Inst->dwDSPOutConnection,
+ pClient_Inst->dwDspDataClientArea))
+ return KRETURN_ERROR_GENERIC;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kStopTransfer OK\n");
+#endif
+ return KRETURN_SUCCESS;
+
+} /* kStopTransfer() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kAlterTransfer */
+/* */
+/* Description: */
+/* Alter a client's DMA transfer. */
+/* */
+/* When altering a client's current stream position, a position */
+/* equal to 0 indicates the first byte in the buffer. A position */
+/* equal to dwHostXXXBufferLen-1 indicates the last byte in the */
+/* buffer. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* DWORD dwFlags */
+/* KALTER_XXX flags indicating alterations to perform */
+/* */
+/* DWORD dwAutoRepeat */
+/* TRUE if auto-repeat buffer, FALSE if one-shot buffer */
+/* */
+/* DWORD dwPosition */
+/* The byte position to set */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kAlterTransfer
+ (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst,
+ DWORD dwFlags, DWORD dwAutoRepeat, DWORD dwPosition)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+ WORD wDmaControl;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kAlterTransfer %X %X %X %X %X\n", phwi,
+ pClient_Inst, dwFlags, dwAutoRepeat, dwPosition);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Make sure DSP kernel is ready to be halted */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, FALSE))
+ return KRETURN_ERROR_BUSY;
+
+ /* */
+ /* halt the DSP kernel and wait for an acknowledgement */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_DMA, TRUE);
+
+ if (!kStateExists (devc, phwi, KDATA_HALT_ACKNOWLEDGE, TRUE))
+ {
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_DMA, FALSE);
+
+ return KRETURN_ERROR_BUSY;
+ }
+
+ /* */
+ /* DSP kernel has halted, do DMA alterations */
+ /* */
+ /* Note: We halt the DSP in order to synchronize the alterations */
+ /* with the DMA state machine */
+ /* */
+
+ if (dwFlags & KALTER_AUTOREPEAT)
+ {
+ wDmaControl = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea +
+ CDATA_DMA_CONTROL);
+
+ wDmaControl &= ~(DMACONTROL_STOPPED | DMACONTROL_AUTOREPEAT);
+
+ if (dwAutoRepeat)
+ wDmaControl |= DMACONTROL_AUTOREPEAT;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea + CDATA_DMA_CONTROL,
+ wDmaControl);
+ }
+
+ if (dwFlags & KALTER_POSITION)
+ {
+ /* */
+ /* Position alterations are only permitted on playback streams... */
+ /* */
+
+ if (pClient_Inst->dwDSPInConnection == KCONNECT_DMA)
+ {
+ dwPosition += pClient_Inst->dwHostSrcBufferAddr;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea +
+ CDATA_HOST_SRC_CURRENTL, LOWORD (dwPosition));
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea +
+ CDATA_HOST_SRC_CURRENTH, HIWORD (dwPosition));
+ }
+ }
+
+ /* */
+ /* all done, reset halt request flag to resume DSP kernel execution */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_HALT_SYNCH_DMA, FALSE);
+
+ return KRETURN_SUCCESS;
+
+} /* kAlterTransfer() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSwitchPINConnection */
+/* */
+/* Description: */
+/* Switch data transfer PIN connection to/from client instance data memory. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* DWORD dwDSPInConnection */
+/* KCONNECT_XXX indicating input connection */
+/* */
+/* DWORD dwDSPOutConnection */
+/* KCONNECT_XXX indicating output connection */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kSwitchPINConnection
+ (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst,
+ DWORD dwDSPInConnection, DWORD dwDSPOutConnection)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+ DWORD dwDspDataClientArea = pClient_Inst->dwDspDataClientArea;
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSwitchPINConnection %X %X %X %X \n",
+ phwi,
+ pClient_Inst, dwDSPInConnection, dwDSPOutConnection);
+
+#endif
+
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure connections are valid... */
+ /* */
+
+ if (dwDSPInConnection >= NUMBER_OF_CONNECTIONS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (dwDSPOutConnection >= NUMBER_OF_CONNECTIONS)
+ return KRETURN_ERROR_GENERIC;
+
+ if ((dwDSPInConnection == KCONNECT_DMA) ||
+ (dwDSPOutConnection == KCONNECT_DMA))
+ {
+ /* */
+ /* Do DMA synchronization */
+ /* */
+ /* DMA engine is not switchable at this moment!!! */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_DMA_SWITCH, TRUE))
+ return KRETURN_ERROR_BUSY;
+ }
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+
+ /* */
+ /* disconnect the input and output first */
+ /* */
+
+ if (!kDisconnectInputOutput (devc, phwi,
+ pClient_Inst->dwDSPInConnection,
+ pClient_Inst->dwDSPOutConnection,
+ pClient_Inst->dwDspDataClientArea))
+ return KRETURN_ERROR_GENERIC;
+
+
+ /* */
+ /* update PIN connection */
+ /* */
+
+ if (dwDSPInConnection != KCONNECT_SAME)
+ pClient_Inst->dwDSPInConnection = dwDSPInConnection;
+
+ if (dwDSPOutConnection != KCONNECT_SAME)
+ pClient_Inst->dwDSPOutConnection = dwDSPOutConnection;
+
+
+ /* */
+ /* Finally, connect updated PIN */
+ /* */
+
+ if (!kConnectInputOutput (devc, phwi,
+ pClient_Inst->dwDSPInConnection,
+ pClient_Inst->dwDSPOutConnection,
+ dwDspDataClientArea))
+ return KRETURN_ERROR_GENERIC;
+
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSwitchPINConnection OK\n");
+#endif
+ return KRETURN_SUCCESS;
+
+} /* kSwitchPINConnection() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kQueryActivity */
+/* */
+/* Description: */
+/* Indicate what clients and/or connections are active */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PDWORD pdwClientMasks */
+/* Pointer to DWORD that will contain MASK_CLIENT_XXX masks */
+/* */
+/* PDWORD pdwConnectMasks */
+/* Pointer to DWORD that will contain MASK_KCONNECT_XXX masks */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kQueryActivity
+ (allegro_devc * devc, PHWI phwi, PDWORD pdwClientMasks,
+ PDWORD pdwConnectMasks)
+{
+ DWORD dwClient;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kQueryActivity %X %X %X\n", phwi,
+ pdwClientMasks, pdwConnectMasks);
+
+
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Check if any client instance is defined */
+ /* */
+
+ *pdwClientMasks = 0;
+
+ for (dwClient = 0; dwClient < NUMBER_OF_CLIENTS; ++dwClient)
+ {
+ if (phwi->asClientTable[dwClient].dwReferenceCount)
+ {
+ *pdwClientMasks |= (1 << dwClient);
+ }
+ }
+
+ /* */
+ /* Check if any connections are defined */
+ /* */
+
+ *pdwConnectMasks = 0;
+
+ if (phwi->awVirtualDMAList[0])
+ *pdwConnectMasks |= MASK_KCONNECT_DMA;
+
+ if (phwi->awVirtualADC1List[0])
+ *pdwConnectMasks |= MASK_KCONNECT_ADC1;
+
+ if (phwi->awVirtualADC2List[0])
+ *pdwConnectMasks |= MASK_KCONNECT_ADC2;
+
+ if (phwi->awVirtualI2SList[0])
+ *pdwConnectMasks |= MASK_KCONNECT_I2S;
+
+ if (phwi->awVirtualCHIList[0])
+ *pdwConnectMasks |= MASK_KCONNECT_CHI;
+
+ if (kDspReadWord
+ (devc, phwi->dwBaseIO, MEMTYPE_INTERNAL_DATA, KDATA_SPDIF_XFER))
+ *pdwConnectMasks |= MASK_KCONNECT_SPDIF;
+
+ if (phwi->awVirtualMIXERList[0])
+ *pdwConnectMasks |= MASK_KCONNECT_MIXER;
+
+#if 0
+#if (NUMBER_OF_CONNECTIONS != 0x10)
+#error Assumption about number of connections failed.
+#endif
+#endif
+
+ return KRETURN_SUCCESS;
+
+} /* kQueryActivity() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetTimer */
+/* */
+/* Description: */
+/* Set the DSP to Host interrupt time interval */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwTimeInterval */
+/* Number of APU interrupts per DSP to Host interrupt */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kSetTimer (allegro_devc * devc, PHWI phwi, DWORD dwTimeInterval)
+{
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSetTimer %X %X\n", phwi, dwTimeInterval);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Check time interval size */
+ /* */
+
+ if (HIWORD (dwTimeInterval))
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Write timer values */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_TIMER_COUNT_RELOAD, (WORD) dwTimeInterval);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_TIMER_COUNT_CURRENT, (WORD) dwTimeInterval);
+
+ return KRETURN_SUCCESS;
+
+} /* kSetTimer() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kOpenPassThru */
+/* */
+/* Description: */
+/* Open a pass through. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PPASSTHRU *ppPassThru */
+/* Pointer to PPASSTHRU that will contain the pass through pointer */
+/* */
+/* DWORD dwDSPInConnection */
+/* KCONNECT_XXX indicating input connection */
+/* */
+/* DWORD dwDSPOutConnection */
+/* KCONNECT_XXX indicating output connection */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kOpenPassThru
+ (allegro_devc * devc, PHWI phwi,
+ PPASSTHRU * ppPassThru, DWORD dwDSPInConnection, DWORD dwDSPOutConnection)
+{
+ PPASSTHRU pPassThru = NULL;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kOpenPassThru %X %X <-> %X\n", phwi,
+ dwDSPInConnection, dwDSPOutConnection);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure connections are valid... */
+ /* */
+
+ if ((dwDSPInConnection == KCONNECT_NONE) ||
+ (dwDSPInConnection == KCONNECT_SAME) ||
+ (dwDSPInConnection >= NUMBER_OF_CONNECTIONS))
+ return KRETURN_ERROR_GENERIC;
+
+ if ((dwDSPOutConnection == KCONNECT_NONE) ||
+ (dwDSPOutConnection == KCONNECT_SAME) ||
+ (dwDSPOutConnection >= NUMBER_OF_CONNECTIONS))
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Do open/close synchronization */
+ /* */
+
+ if (!kStateExists (devc, phwi, KDATA_TASK_SWITCH, TRUE))
+ return KRETURN_ERROR_BUSY;
+
+ /* */
+ /* Allocate host memory */
+ /* */
+
+ if (!(pPassThru = (PPASSTHRU)
+ _HeapAllocate (sizeof (PASSTHRU), HEAPZEROINIT)))
+ return KRETURN_ERROR_GENERIC;
+
+ pPassThru->dwDSPInConnection = dwDSPInConnection;
+ pPassThru->dwDSPOutConnection = dwDSPOutConnection;
+
+ /* */
+ /* Handle directly mixed (i.e. non-buffered) connections */
+ /* */
+
+ if (dwDSPOutConnection == KCONNECT_SPDIF)
+ {
+ kConnectDirectMixer (devc, phwi, dwDSPInConnection, dwDSPOutConnection,
+ TRUE);
+ }
+ else
+ {
+ if (dwDSPOutConnection == KCONNECT_MIXER)
+ {
+ switch (dwDSPInConnection)
+ {
+ case KCONNECT_ADC1:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC1_MIXER_REQUEST, TRUE);
+ break;
+ case KCONNECT_ADC2:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC2_MIXER_REQUEST, TRUE);
+ break;
+
+ case KCONNECT_CD:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_CD_MIXER_REQUEST, TRUE);
+ break;
+
+ case KCONNECT_MIC:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_MIC_MIXER_REQUEST, TRUE);
+ break;
+
+ default:
+ goto kOpen_Error;
+ } /* endswitch */
+ } /* endif */
+
+ }
+
+ /* */
+ /* Everything worked */
+ /* */
+
+ *ppPassThru = pPassThru;
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kOpenPassThru OK %X\n", pPassThru);
+#endif
+ return KRETURN_SUCCESS;
+
+kOpen_Error:
+
+ /* */
+ /* Failure, undo all that was done... */
+ /* */
+
+ if (pPassThru)
+ {
+ _HeapFree (pPassThru, 0);
+ }
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kOpenPassThru Failed\n");
+#endif
+ return KRETURN_ERROR_GENERIC;
+
+} /* kOpenPassThru() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kClosePassThru */
+/* */
+/* Description: */
+/* Close a pass through. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PPASSTHRU pPassThru */
+/* Pointer to pass through */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kClosePassThru (allegro_devc * devc, PHWI phwi, PPASSTHRU pPassThru)
+{
+#ifdef K_DBG
+ _Debug_Printf_Service ("kClosePassThru %X %X\n", phwi, pPassThru);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Deallocate memory */
+ /* */
+
+ if (!pPassThru)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Handle directly mixed (i.e. non-buffered) connections */
+ /* */
+
+ if (pPassThru->dwDSPOutConnection == KCONNECT_SPDIF)
+ {
+ kConnectDirectMixer (devc, phwi,
+ pPassThru->dwDSPInConnection,
+ pPassThru->dwDSPOutConnection, FALSE);
+ }
+ else
+ {
+ if (pPassThru->dwDSPOutConnection == KCONNECT_MIXER)
+ {
+ switch (pPassThru->dwDSPInConnection)
+ {
+ case KCONNECT_ADC1:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC1_MIXER_REQUEST, FALSE);
+ break;
+
+ case KCONNECT_ADC2:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC2_MIXER_REQUEST, FALSE);
+ break;
+
+ case KCONNECT_CD:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_CD_MIXER_REQUEST, FALSE);
+ break;
+
+ case KCONNECT_MIC:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_MIC_MIXER_REQUEST, FALSE);
+ break;
+
+ } /* endswitch */
+
+ } /* endif */
+
+ }
+
+ _HeapFree (pPassThru, 0);
+
+ /* */
+ /* Do open/close synchronization */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_TASK_SWITCH, FALSE);
+
+ return KRETURN_SUCCESS;
+
+} /* kClosePassThru() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetVolume */
+/* */
+/* Description: */
+/* Set a client's current stream left/right Volume. */
+/* Maximum is 0x7FFF and Minimum is 0x0000. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* WORD wLeftVolume */
+/* 16 bit constant for left channel volume */
+/* */
+/* WORD wRightVolume */
+/* 16 bit constant for right channel volume */
+/* */
+/* WORD wBoosterMode */
+/* TRUE activates a broader range of volume setting. */
+/* In this mode, 7FFF represents 18dB gain */
+/* 1000 represents 0dB gain */
+/* 0 represents -Inf gain(mute) */
+/* FALSE supports only an attenuation mode. */
+/* In this mode, 7FFF represents 0dB gain */
+/* 0 represents -Inf gain(mute) */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kSetVolume
+ (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst,
+ WORD wLeftVolume, WORD wRightVolume, WORD wBoosterMode)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+
+#if 0
+ WORD wCurLVol, wCurRVol, wLTemp, wRTemp;
+#endif
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSetVolume %X %X %X %X\n",
+ phwi, pClient_Inst, wLeftVolume, wRightVolume);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+#if 0 /* micro step the volume */
+ wCurLVol = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_LEFT_VOLUME);
+
+ wCurRVol = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_RIGHT_VOLUME);
+
+ /* need to do micro steps to avoid zipper noise */
+ /* max 7 steps */
+ wLTemp = wLeftVolume;
+ wRTemp = wRightVolume;
+
+
+ wCurLVol &= 0xF000;
+ wCurLVol |= (wLeftVolume & 0x0FFF);
+
+ if (wCurLVol < wLeftVolume)
+ {
+ wLeftVolume = wCurLVol;
+ wCurLVol = wLTemp;
+ } /* endif */
+
+ do
+ {
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_LEFT_VOLUME, wCurLVol);
+
+ kDelayNMicroseconds (10);
+ wCurLVol -= 0x800;
+ }
+ while (wCurLVol > wLeftVolume);
+
+ wCurRVol &= 0xF000;
+ wCurRVol |= (wRightVolume & 0x0FFF);
+
+ if (wCurRVol < wRightVolume)
+ {
+ wRightVolume = wCurRVol;
+ wCurRVol = wRTemp;
+ } /* endif */
+
+ do
+ {
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_RIGHT_VOLUME, wCurRVol);
+
+ kDelayNMicroseconds (10);
+ wCurRVol -= 0x800;
+ }
+ while (wCurRVol > wRightVolume);
+
+ wLeftVolume = wLTemp;
+ wRightVolume = wRTemp;
+#endif
+ /* */
+ /* write left/right word of current stream volume */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_LEFT_VOLUME, -wLeftVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_RIGHT_VOLUME, -wRightVolume);
+
+ /* */
+ /* tell the client whether this is broader range */
+ /* of volume setting or not */
+ /* */
+
+ if (wBoosterMode)
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_HEADER_LEN + 23, TRUE);
+ else
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_HEADER_LEN + 23, FALSE);
+
+
+ return KRETURN_SUCCESS;
+
+} /* kSetVolume() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetRearVolume */
+/* */
+/* Description: */
+/* Set a client's current stream rear left/rear right Volume. */
+/* Maximum is 0x7FFF and Minimum is 0x0000. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* WORD wLeftRearVolume */
+/* 16 bit constant for rear left channel volume */
+/* */
+/* WORD wRightRearVolume */
+/* 16 bit constant for rear right channel volume */
+/* */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kSetRearVolume
+ (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst, WORD wLeftRearVolume, WORD wRightRearVolume)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+
+
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSetVolume %X %X %X %X\n",
+ phwi,
+ pClient_Inst, wLeftRearVolume, wRightRearVolume);
+#endif
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* write rear left/rear right word of current stream volume */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_LEFT_SUR_VOL, wLeftRearVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_RIGHT_SUR_VOL, wRightRearVolume);
+
+ return KRETURN_SUCCESS;
+
+} /* kSetRearVolume() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetPassThruVolume */
+/* */
+/* Description: */
+/* Set a passthrough instance volume. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PPASSTHRU *ppPassThru */
+/* Pointer to PPASSTHRU that will contain the pass through pointer */
+/* */
+/* WORD wLeftVolume */
+/* 16 bit constant for left channel volume */
+/* */
+/* WORD wRightVolume */
+/* 16 bit constant for right channel volume */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+KRETURN kSetPassThruVolume
+ (allegro_devc * devc, PHWI phwi, PPASSTHRU pPassThru, WORD wLeftVolume,
+ WORD wRightVolume)
+{
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* pPassThru -> wLeftVolume = wLeftVolume ; */
+ /* pPassThru -> wRightVolume = wRightVolume ; */
+
+ switch (pPassThru->dwDSPInConnection)
+ {
+ case KCONNECT_ADC1:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC1_LEFT_VOLUME, wLeftVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC1_RIGHT_VOLUME, wRightVolume);
+
+ break;
+
+ case KCONNECT_ADC2:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC2_LEFT_VOLUME, wLeftVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC2_RIGHT_VOLUME, wRightVolume);
+
+ break;
+
+ case KCONNECT_CD:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_CD_LEFT_VOLUME, wLeftVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_CD_RIGHT_VOLUME, wRightVolume);
+ break;
+
+ case KCONNECT_MIC:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_MIC_VOLUME, wLeftVolume);
+
+ break;
+
+ default:
+ return KRETURN_ERROR_GENERIC;
+ } /* endswitch */
+
+
+ return KRETURN_SUCCESS;
+
+} /* kSetPassThruVolume */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetPassThruRearVolume */
+/* */
+/* Description: */
+/* Set a passthrough instance's rear volume. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PPASSTHRU *ppPassThru */
+/* Pointer to PPASSTHRU that will contain the pass through pointer */
+/* */
+/* WORD wLeftRearVolume */
+/* 16 bit constant for left rear channel volume */
+/* */
+/* WORD wRightRearVolume */
+/* 16 bit constant for right rear channel volume */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+KRETURN kSetPassThruRearVolume
+ (allegro_devc * devc, PHWI phwi,
+ PPASSTHRU pPassThru, WORD wLeftRearVolume, WORD wRightRearVolume)
+{
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ switch (pPassThru->dwDSPInConnection)
+ {
+ case KCONNECT_ADC1:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC1_LEFT_SUR_VOL, wLeftRearVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC1_RIGHT_SUR_VOL, wRightRearVolume);
+
+ break;
+
+
+ case KCONNECT_ADC2:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC2_LEFT_SUR_VOL, wLeftRearVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_ADC2_RIGHT_SUR_VOL, wRightRearVolume);
+
+ break;
+
+ case KCONNECT_CD:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_CD_LEFT_SUR_VOL, wLeftRearVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_CD_RIGHT_SUR_VOL, wRightRearVolume);
+ break;
+
+ case KCONNECT_MIC:
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_MIC_SUR_VOL, wLeftRearVolume);
+
+ break;
+
+ default:
+ return KRETURN_ERROR_GENERIC;
+ } /* endswitch */
+
+
+ return KRETURN_SUCCESS;
+
+} /* kSetPassThruRearVolume */
+
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetMasterVolume */
+/* */
+/* Description: */
+/* Set master volume. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* WORD wLeftVolume */
+/* 16 bit constant for left channel volume */
+/* */
+/* WORD wRightVolume */
+/* 16 bit constant for right channel volume */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+KRETURN
+kSetMasterVolume (allegro_devc * devc, PHWI phwi, WORD wLeftVolume,
+ WORD wRightVolume)
+{
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_DAC_LEFT_VOLUME, wLeftVolume);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_DAC_RIGHT_VOLUME, wRightVolume);
+
+ return KRETURN_SUCCESS;
+
+} /* kSetMasterVolume */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kSetFrequency */
+/* */
+/* Description: */
+/* Set a client's current stream sampling frequency. */
+/* 48khz is corresponding to 0x7FFF */
+/* 0 hz is corresponding to 0x0000 */
+/* The other frequencies are linear mapping between those two */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* WORD wFrequency */
+/* 16 bit constant for sampling frequency */
+/* */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kSetFrequency (allegro_devc * devc, PHWI phwi, PCLIENT_INST pClient_Inst,
+ WORD wFrequency)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+#ifdef K_DBG
+ _Debug_Printf_Service ("kSetVolume %X %X %X\n", phwi,
+ pClient_Inst, wFrequency);
+#endif
+
+
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* write left/right word of current stream sampling frequency */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_FREQUENCY, wFrequency);
+
+ return KRETURN_SUCCESS;
+
+} /* kSetFrequency */
+
+
+/**************************************************************************** */
+/* The following is unique to M2/M2E only */
+/**************************************************************************** */
+#ifdef PIOREC
+/*-------------------------------------------------------------------------- */
+/* */
+/* DWORD kCopyLinearToCircular */
+/* */
+/* Description: */
+/* Copy data from a linear DSP output buffer to a potentially */
+/* circular host destination buffer. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* DWORD dwMemAddr */
+/* Memory address to read from. */
+/* */
+/* DWORD dwMemLen */
+/* Number of WORDs to read from specified address. */
+/* */
+/* DWORD dwHostAddr */
+/* Host memory address to write to. */
+/* */
+/* DWORD dwHostBase */
+/* Base address of host buffer. */
+/* */
+/* DWORD dwHostLen */
+/* Length in bytes of host buffer. */
+/* */
+/* Return (DWORD): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+DWORD kCopyLinearToCircular
+ (allegro_devc * devc, PHWI phwi,
+ DWORD dwMemAddr,
+ DWORD dwMemLen, DWORD dwHostAddr, DWORD dwHostBase, DWORD dwHostLen)
+{
+ DWORD dwPreWrapLen;
+
+ /* */
+ /* copy DSP buffer data to host buffer */
+ /* */
+
+ if ((dwHostAddr + (dwMemLen * sizeof (WORD))) <= (dwHostBase + dwHostLen))
+ {
+ /* */
+ /* host buffer won't wrap, do straight copy */
+ /* */
+
+ kDspReadWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwMemAddr, dwMemLen, (PWORD) dwHostAddr);
+ }
+ else
+ {
+ dwPreWrapLen = (dwHostBase + dwHostLen - dwHostAddr) / sizeof (WORD);
+
+ /* */
+ /* host buffer will wrap, do pre-wrap copy */
+ /* */
+
+ kDspReadWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwMemAddr, dwPreWrapLen, (PWORD) dwHostAddr);
+
+ /* */
+ /* do post-wrap copy */
+ /* */
+
+ kDspReadWords (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ dwMemAddr + dwPreWrapLen,
+ dwMemLen - dwPreWrapLen, (PWORD) dwHostBase);
+ }
+
+ /* */
+ /* update current host pointer and check for wrap */
+ /* */
+
+ dwHostAddr += (dwMemLen * sizeof (WORD));
+
+ if (dwHostAddr >= (dwHostBase + dwHostLen))
+ {
+ dwHostAddr = dwHostBase + (dwHostAddr - (dwHostBase + dwHostLen));
+ }
+
+ return dwHostAddr;
+
+} /* kCopyLinearToCircular() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kPIOInterruptHandler */
+/* */
+/* Description: */
+/* PIO data available interrupt handler. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID
+kPIOInterruptHandler (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst)
+{
+ DWORD dwHostDstBufferAddr = pClient_Inst->dwHostDstBufferAddr;
+ DWORD dwHostDstBufferLen = pClient_Inst->dwHostDstBufferLen;
+ DWORD dwHostDstCurrent = pClient_Inst->dwHostDstCurrent;
+ DWORD dwDSPOutBufferAddr = pClient_Inst->dwDSPOutBufferAddr;
+ DWORD dwDSPOutBufferLen = pClient_Inst->dwDSPOutBufferLen;
+ DWORD dwOutBufHead;
+ DWORD dwOutBufTail;
+
+ /* */
+ /* return if PIO recording not active */
+ /* */
+
+ if (!phwi->awVirtualPIOList[0])
+ return;
+
+ /* */
+ /* read buffer state from DSP */
+ /* */
+
+ dwOutBufHead = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea +
+ CDATA_OUT_BUF_HEAD);
+
+ dwOutBufTail = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea +
+ CDATA_OUT_BUF_TAIL);
+
+ /* */
+ /* copy DSP buffer data to host buffer */
+ /* */
+
+ if (dwOutBufHead > dwOutBufTail)
+ {
+ /* */
+ /* DSP buffer data doesn't wrap, do straight copy */
+ /* */
+
+ dwHostDstCurrent =
+ kCopyLinearToCircular (devc, phwi,
+ dwOutBufTail,
+ dwOutBufHead - dwOutBufTail,
+ dwHostDstCurrent,
+ dwHostDstBufferAddr, dwHostDstBufferLen);
+ }
+ else
+ {
+ /* */
+ /* DSP buffer data wraps, do pre-wrap copy */
+ /* */
+
+ dwHostDstCurrent =
+ kCopyLinearToCircular (devc, phwi,
+ dwOutBufTail,
+ dwDSPOutBufferAddr + (dwDSPOutBufferLen / 2)
+ - dwOutBufTail,
+ dwHostDstCurrent,
+ dwHostDstBufferAddr, dwHostDstBufferLen);
+
+ /* */
+ /* do post-wrap copy */
+ /* */
+
+ dwHostDstCurrent =
+ kCopyLinearToCircular (devc, phwi,
+ dwDSPOutBufferAddr,
+ dwOutBufHead - dwDSPOutBufferAddr,
+ dwHostDstCurrent,
+ dwHostDstBufferAddr, dwHostDstBufferLen);
+ }
+
+ /* */
+ /* write updated buffer state to DSP */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->dwDspDataClientArea + CDATA_OUT_BUF_TAIL,
+ (WORD) dwOutBufHead);
+
+ pClient_Inst->dwHostDstCurrent = dwHostDstCurrent;
+
+} /* kPIOInterruptHandler() */
+#endif
+
+#ifdef HOSTI2SFREQCALC /* I2S was calculated in the host */
+#ifdef DOS_MODEL
+#pragma message("----kI2SInterruptHandler omitted (causes internal compiler error)")
+#else
+/*-------------------------------------------------------------------------- */
+/* */
+/* VOID kI2SInterruptHandler */
+/* */
+/* Description: */
+/* I2S data flow impeded interrupt handler. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PDWORD pdwI2SRate */
+/* Pointer to DWORD that will contain the I2S sample rate or */
+/* -1 if the sample rate should not be changed */
+/* */
+/* Return (VOID): */
+/* */
+/*-------------------------------------------------------------------------- */
+
+VOID
+kI2SInterruptHandler (allegro_devc * devc, PHWI phwi, PDWORD pdwI2SRate)
+{
+ WORD wI2SSampleCount;
+ WORD wI2STimerCount;
+ WORD wI2SSampleRate;
+
+ /* */
+ /* Get current sample count and timer count */
+ /* */
+
+ wI2SSampleCount = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ KDATA_I2S_SAMPLE_COUNT);
+
+ wI2STimerCount = kInW (devc, phwi->dwBaseIO + DSP_PORT_TIMER_COUNT);
+
+ /* */
+ /* I2S sample rate determination is a two pass operation. */
+ /* On the first pass we zero the activity flag and return -1. */
+ /* On the second pass we check if the activity flag is still */
+ /* zero. If so, we know the I2S data stream has stopped */
+ /* and we return 0 for the sample rate. Otherwise, we use */
+ /* the sample count data and do our best to determine the */
+ /* sample rate. */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_I2S_SECONDPASS)
+ {
+ if (!kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_I2S_ACTIVE))
+ {
+ /* */
+ /* the I2S stream has stopped */
+ /* */
+
+ *pdwI2SRate = 0;
+ }
+ else
+ {
+ /* */
+ /* the I2S stream is moving */
+ /* */
+
+ wI2SSampleCount -= phwi->wI2SSampleCount;
+ wI2STimerCount -= phwi->wI2STimerCount;
+
+ /* */
+ /* determine sample rate */
+ /* */
+ /* The timer rate is 48,000 ticks/second, so */
+ /* */
+ /* samples N samples 48,000 ticks 1 */
+ /* ------- = --------- X ------------ X ------- */
+ /* second 1 1 second M ticks */
+ /* */
+
+ wI2SSampleRate = (wI2SSampleCount * 48000) / wI2STimerCount;
+
+ if (wI2SSampleRate > (48000 + 44100) / 2)
+ *pdwI2SRate = 48000;
+ else if (wI2SSampleRate > (44100 + 32000) / 2)
+ *pdwI2SRate = 44100;
+ else if (wI2SSampleRate > (32000 + 22050) / 2)
+ *pdwI2SRate = 32000;
+ else
+ *pdwI2SRate = 22050;
+ }
+
+ phwi->dwFlags &= ~HWI_FLAG_I2S_SECONDPASS;
+ }
+ else
+ {
+ /* */
+ /* zero the activity flag and advance to the next state */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA, KDATA_I2S_ACTIVE, 0);
+
+ phwi->wI2SSampleCount = wI2SSampleCount;
+ phwi->wI2STimerCount = wI2STimerCount;
+
+ *pdwI2SRate = (DWORD) - 1;
+
+ phwi->dwFlags |= HWI_FLAG_I2S_SECONDPASS;
+ }
+
+} /* kI2SInterruptHandler() */
+#endif
+#endif
+
+#ifdef APUBLOCKCOUNT
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kResetApuBlockCount */
+/* */
+/* Description: */
+/* Reset a client's APU block count field. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN
+kResetApuBlockCount (allegro_devc * devc, PHWI phwi,
+ PCLIENT_INST pClient_Inst)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Reset the block count */
+ /* */
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_APU_BLOCK_COUNTL, 0);
+
+ kDspWriteWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea + CDATA_APU_BLOCK_COUNTH, 0);
+
+ return KRETURN_SUCCESS;
+
+} /* kResetApuBlockCount() */
+
+/*-------------------------------------------------------------------------- */
+/* */
+/* KRETURN kGetApuBlockCount */
+/* */
+/* Description: */
+/* Return a client's current stream position in terms of the number */
+/* of APU blocks transfered. */
+/* */
+/* Parameters: */
+/* PHWI phwi */
+/* Pointer to hardware instance. */
+/* */
+/* PCLIENT_INST pClient_Inst */
+/* Pointer to client instance */
+/* */
+/* PDWORD pdwBlockCount */
+/* Pointer to DWORD that will contain the number of APU blocks */
+/* */
+/* Return (KRETURN): */
+/* KRETURN_SUCCESS if successful, KRETURN_ERROR_XXX otherwise. */
+/* */
+/*-------------------------------------------------------------------------- */
+
+KRETURN kGetApuBlockCount
+ (allegro_devc * devc, PHWI phwi, PCLIENT_INST pClient_Inst,
+ PDWORD pdwBlockCount)
+{
+ DWORD dwClient = pClient_Inst->dwClient;
+ WORD wBlockCount;
+ WORD wRetry = 10;
+ WORD wBlockCountL;
+ WORD wBlockCountH;
+
+ /* */
+ /* Fail if the DSP kernel has been unloaded */
+ /* */
+
+ if (phwi->dwFlags & HWI_FLAG_UNLOADED)
+ return KRETURN_ERROR_UNLOADED;
+
+ /* */
+ /* Make sure client and an instance exist... */
+ /* */
+
+ if (dwClient >= NUMBER_OF_CLIENTS)
+ return KRETURN_ERROR_GENERIC;
+
+ if (!phwi->asClientTable[dwClient].dwReferenceCount)
+ return KRETURN_ERROR_GENERIC;
+
+ /* */
+ /* Get the block count */
+ /* */
+
+ while (wRetry--)
+ {
+ /* read high/low word of current block count */
+
+ wBlockCountH = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea +
+ CDATA_APU_BLOCK_COUNTH);
+
+ wBlockCountL = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea +
+ CDATA_APU_BLOCK_COUNTL);
+
+ /* if the high word hasn't changed, we've got a meaningful */
+ /* block count value */
+
+ wBlockCount = kDspReadWord (devc, phwi->dwBaseIO,
+ MEMTYPE_INTERNAL_DATA,
+ pClient_Inst->
+ dwDspDataClientArea +
+ CDATA_APU_BLOCK_COUNTH);
+
+ if (wBlockCount == wBlockCountH)
+ break;
+ }
+
+ /* fail if we couldn't get a meaningful block count */
+
+ if (wBlockCount != wBlockCountH)
+ return KRETURN_ERROR_GENERIC;
+
+ *pdwBlockCount = MAKELONG (wBlockCountL, wBlockCountH);
+
+ return KRETURN_SUCCESS;
+
+} /* kGetApuBlockCount() */
+
+#endif
+
+/*--------------------------------------------------------------------------- */
+/* End of File: kernel.c */
+/*--------------------------------------------------------------------------- */
+
+/******************************************************************************
+ * *
+ * (C) 1997-1999 ESS Technology, Inc. *
+ * *
+ ******************************************************************************/