summaryrefslogtreecommitdiff
path: root/kernel/drv/oss_cs4281
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drv/oss_cs4281')
-rw-r--r--kernel/drv/oss_cs4281/.devices1
-rw-r--r--kernel/drv/oss_cs4281/.name1
-rw-r--r--kernel/drv/oss_cs4281/cs4281.h1108
-rw-r--r--kernel/drv/oss_cs4281/oss_cs4281.c1061
-rw-r--r--kernel/drv/oss_cs4281/oss_cs4281.man21
5 files changed, 2192 insertions, 0 deletions
diff --git a/kernel/drv/oss_cs4281/.devices b/kernel/drv/oss_cs4281/.devices
new file mode 100644
index 0000000..1c415d7
--- /dev/null
+++ b/kernel/drv/oss_cs4281/.devices
@@ -0,0 +1 @@
+oss_cs4281 pci1013,6005 Crystal CS4281
diff --git a/kernel/drv/oss_cs4281/.name b/kernel/drv/oss_cs4281/.name
new file mode 100644
index 0000000..6464db1
--- /dev/null
+++ b/kernel/drv/oss_cs4281/.name
@@ -0,0 +1 @@
+Crystal CS4281
diff --git a/kernel/drv/oss_cs4281/cs4281.h b/kernel/drv/oss_cs4281/cs4281.h
new file mode 100644
index 0000000..f82568f
--- /dev/null
+++ b/kernel/drv/oss_cs4281/cs4281.h
@@ -0,0 +1,1108 @@
+/*
+ * Purpose: Definitions for the cs4281 driver
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+/***************************************************************************** */
+/* */
+/* HWDEFS.H - Definitions of the registers and data structures used by the */
+/* CS4281 */
+/* */
+/***************************************************************************** */
+
+#ifndef _H_HWDEFS
+#define _H_HWDEFS
+
+/***************************************************************************** */
+/* */
+/* The following define the offsets of the registers accessed via base address */
+/* register zero on the CS4281 part. */
+/* */
+/***************************************************************************** */
+#define BA0_HISR 0x00000000L
+#define BA0_HICR 0x00000008L
+#define BA0_HIMR 0x0000000CL
+#define BA0_IIER 0x00000010L
+#define BA0_HDSR0 0x000000F0L
+#define BA0_HDSR1 0x000000F4L
+#define BA0_HDSR2 0x000000F8L
+#define BA0_HDSR3 0x000000FCL
+#define BA0_DCA0 0x00000110L
+#define BA0_DCC0 0x00000114L
+#define BA0_DBA0 0x00000118L
+#define BA0_DBC0 0x0000011CL
+#define BA0_DCA1 0x00000120L
+#define BA0_DCC1 0x00000124L
+#define BA0_DBA1 0x00000128L
+#define BA0_DBC1 0x0000012CL
+#define BA0_DCA2 0x00000130L
+#define BA0_DCC2 0x00000134L
+#define BA0_DBA2 0x00000138L
+#define BA0_DBC2 0x0000013CL
+#define BA0_DCA3 0x00000140L
+#define BA0_DCC3 0x00000144L
+#define BA0_DBA3 0x00000148L
+#define BA0_DBC3 0x0000014CL
+#define BA0_DMR0 0x00000150L
+#define BA0_DCR0 0x00000154L
+#define BA0_DMR1 0x00000158L
+#define BA0_DCR1 0x0000015CL
+#define BA0_DMR2 0x00000160L
+#define BA0_DCR2 0x00000164L
+#define BA0_DMR3 0x00000168L
+#define BA0_DCR3 0x0000016CL
+#define BA0_DLMR 0x00000170L
+#define BA0_DLSR 0x00000174L
+#define BA0_FCR0 0x00000180L
+#define BA0_FCR1 0x00000184L
+#define BA0_FCR2 0x00000188L
+#define BA0_FCR3 0x0000018CL
+#define BA0_FPDR0 0x00000190L
+#define BA0_FPDR1 0x00000194L
+#define BA0_FPDR2 0x00000198L
+#define BA0_FPDR3 0x0000019CL
+#define BA0_FCHS 0x0000020CL
+#define BA0_FSIC0 0x00000210L
+#define BA0_FSIC1 0x00000214L
+#define BA0_FSIC2 0x00000218L
+#define BA0_FSIC3 0x0000021CL
+#define BA0_PCICFG00 0x00000300L
+#define BA0_PCICFG04 0x00000304L
+#define BA0_PCICFG08 0x00000308L
+#define BA0_PCICFG0C 0x0000030CL
+#define BA0_PCICFG10 0x00000310L
+#define BA0_PCICFG14 0x00000314L
+#define BA0_PCICFG18 0x00000318L
+#define BA0_PCICFG1C 0x0000031CL
+#define BA0_PCICFG20 0x00000320L
+#define BA0_PCICFG24 0x00000324L
+#define BA0_PCICFG28 0x00000328L
+#define BA0_PCICFG2C 0x0000032CL
+#define BA0_PCICFG30 0x00000330L
+#define BA0_PCICFG34 0x00000334L
+#define BA0_PCICFG38 0x00000338L
+#define BA0_PCICFG3C 0x0000033CL
+#define BA0_PCICFG40 0x00000340L
+#define BA0_PMCS 0x00000344L
+#define BA0_CWPR 0x000003E0L
+#define BA0_EPPMC 0x000003E4L
+#define BA0_GPIOR 0x000003E8L
+#define BA0_SPMC 0x000003ECL
+#define BA0_CFLR 0x000003F0L
+#define BA0_IISR 0x000003F4L
+#define BA0_TMS 0x000003F8L
+#define BA0_SSVID 0x000003FCL
+#define BA0_CLKCR1 0x00000400L
+#define BA0_FRR 0x00000410L
+#define BA0_SLT12O 0x0000041CL
+#define BA0_SERMC 0x00000420L
+#define BA0_SERC1 0x00000428L
+#define BA0_SERC2 0x0000042CL
+#define BA0_SLT12M 0x0000045CL
+#define BA0_ACCTL 0x00000460L
+#define BA0_ACSTS 0x00000464L
+#define BA0_ACOSV 0x00000468L
+#define BA0_ACCAD 0x0000046CL
+#define BA0_ACCDA 0x00000470L
+#define BA0_ACISV 0x00000474L
+#define BA0_ACSAD 0x00000478L
+#define BA0_ACSDA 0x0000047CL
+#define BA0_JSPT 0x00000480L
+#define BA0_JSCTL 0x00000484L
+#define BA0_MIDCR 0x00000490L
+#define BA0_MIDCMD 0x00000494L
+#define BA0_MIDSR 0x00000494L
+#define BA0_MIDWP 0x00000498L
+#define BA0_MIDRP 0x0000049CL
+#define BA0_AODSD1 0x000004A8L
+#define BA0_AODSD2 0x000004ACL
+#define BA0_CFGI 0x000004B0L
+#define BA0_SLT12M2 0x000004DCL
+#define BA0_ACSTS2 0x000004E4L
+#define BA0_ACISV2 0x000004F4L
+#define BA0_ACSAD2 0x000004F8L
+#define BA0_ACSDA2 0x000004FCL
+#define BA0_IOTGP 0x00000500L
+#define BA0_IOTSB 0x00000504L
+#define BA0_IOTFM 0x00000508L
+#define BA0_IOTDMA 0x0000050CL
+#define BA0_IOTAC0 0x00000500L
+#define BA0_IOTAC1 0x00000504L
+#define BA0_IOTAC2 0x00000508L
+#define BA0_IOTAC3 0x0000050CL
+#define BA0_IOTPCP 0x0000052CL
+#define BA0_IOTCC 0x00000530L
+#define BA0_IOTCR 0x0000058CL
+#define BA0_PCPRR 0x00000600L
+#define BA0_PCPGR 0x00000604L
+#define BA0_PCPCR 0x00000608L
+#define BA0_PCPCIEN 0x00000608L
+#define BA0_SBMAR 0x00000700L
+#define BA0_SBMDR 0x00000704L
+#define BA0_SBRR 0x00000708L
+#define BA0_SBRDP 0x0000070CL
+#define BA0_SBWDP 0x00000710L
+#define BA0_SBWBS 0x00000710L
+#define BA0_SBRBS 0x00000714L
+#define BA0_FMSR 0x00000730L
+#define BA0_B0AP 0x00000730L
+#define BA0_FMDP 0x00000734L
+#define BA0_B1AP 0x00000738L
+#define BA0_B1DP 0x0000073CL
+#define BA0_SSPM 0x00000740L
+#define BA0_DACSR 0x00000744L
+#define BA0_ADCSR 0x00000748L
+#define BA0_SSCR 0x0000074CL
+#define BA0_FMLVC 0x00000754L
+#define BA0_FMRVC 0x00000758L
+#define BA0_SRCSA 0x0000075CL
+#define BA0_PPLVC 0x00000760L
+#define BA0_PPRVC 0x00000764L
+#define BA0_PASR 0x00000768L
+#define BA0_CASR 0x0000076CL
+
+/***************************************************************************** */
+/* */
+/* The following define the offsets of the AC97 shadow registers, which appear */
+/* as a virtual extension to the base address register zero memory range. */
+/* */
+/***************************************************************************** */
+#define AC97_REG_OFFSET_MASK 0x0000007EL
+#define AC97_CODEC_NUMBER_MASK 0x00003000L
+
+#define BA0_AC97_RESET 0x00001000L
+#define BA0_AC97_MASTER_VOLUME 0x00001002L
+#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L
+#define BA0_AC97_MASTER_VOLUME_MONO 0x00001006L
+#define BA0_AC97_MASTER_TONE 0x00001008L
+#define BA0_AC97_PC_BEEP_VOLUME 0x0000100AL
+#define BA0_AC97_PHONE_VOLUME 0x0000100CL
+#define BA0_AC97_MIC_VOLUME 0x0000100EL
+#define BA0_AC97_LINE_IN_VOLUME 0x00001010L
+#define BA0_AC97_CD_VOLUME 0x00001012L
+#define BA0_AC97_VIDEO_VOLUME 0x00001014L
+#define BA0_AC97_AUX_VOLUME 0x00001016L
+#define BA0_AC97_PCM_OUT_VOLUME 0x00001018L
+#define BA0_AC97_RECORD_SELECT 0x0000101AL
+#define BA0_AC97_RECORD_GAIN 0x0000101CL
+#define BA0_AC97_RECORD_GAIN_MIC 0x0000101EL
+#define BA0_AC97_GENERAL_PURPOSE 0x00001020L
+#define BA0_AC97_3D_CONTROL 0x00001022L
+#define BA0_AC97_MODEM_RATE 0x00001024L
+#define BA0_AC97_POWERDOWN 0x00001026L
+#define BA0_AC97_EXT_AUDIO_ID 0x00001028L
+#define BA0_AC97_EXT_AUDIO_POWER 0x0000102AL
+#define BA0_AC97_PCM_FRONT_DAC_RATE 0x0000102CL
+#define BA0_AC97_PCM_SURR_DAC_RATE 0x0000102EL
+#define BA0_AC97_PCM_LFE_DAC_RATE 0x00001030L
+#define BA0_AC97_PCM_LR_ADC_RATE 0x00001032L
+#define BA0_AC97_MIC_ADC_RATE 0x00001034L
+#define BA0_AC97_6CH_VOL_C_LFE 0x00001036L
+#define BA0_AC97_6CH_VOL_SURROUND 0x00001038L
+#define BA0_AC97_RESERVED_3A 0x0000103AL
+#define BA0_AC97_EXT_MODEM_ID 0x0000103CL
+#define BA0_AC97_EXT_MODEM_POWER 0x0000103EL
+#define BA0_AC97_LINE1_CODEC_RATE 0x00001040L
+#define BA0_AC97_LINE2_CODEC_RATE 0x00001042L
+#define BA0_AC97_HANDSET_CODEC_RATE 0x00001044L
+#define BA0_AC97_LINE1_CODEC_LEVEL 0x00001046L
+#define BA0_AC97_LINE2_CODEC_LEVEL 0x00001048L
+#define BA0_AC97_HANDSET_CODEC_LEVEL 0x0000104AL
+#define BA0_AC97_GPIO_PIN_CONFIG 0x0000104CL
+#define BA0_AC97_GPIO_PIN_TYPE 0x0000104EL
+#define BA0_AC97_GPIO_PIN_STICKY 0x00001050L
+#define BA0_AC97_GPIO_PIN_WAKEUP 0x00001052L
+#define BA0_AC97_GPIO_PIN_STATUS 0x00001054L
+#define BA0_AC97_MISC_MODEM_AFE_STAT 0x00001056L
+#define BA0_AC97_RESERVED_58 0x00001058L
+#define BA0_AC97_CRYSTAL_REV_N_FAB_ID 0x0000105AL
+#define BA0_AC97_TEST_AND_MISC_CTRL 0x0000105CL
+#define BA0_AC97_AC_MODE 0x0000105EL
+#define BA0_AC97_MISC_CRYSTAL_CONTROL 0x00001060L
+#define BA0_AC97_LINE1_HYPRID_CTRL 0x00001062L
+#define BA0_AC97_VENDOR_RESERVED_64 0x00001064L
+#define BA0_AC97_VENDOR_RESERVED_66 0x00001066L
+#define BA0_AC97_SPDIF_CONTROL 0x00001068L
+#define BA0_AC97_VENDOR_RESERVED_6A 0x0000106AL
+#define BA0_AC97_VENDOR_RESERVED_6C 0x0000106CL
+#define BA0_AC97_VENDOR_RESERVED_6E 0x0000106EL
+#define BA0_AC97_VENDOR_RESERVED_70 0x00001070L
+#define BA0_AC97_VENDOR_RESERVED_72 0x00001072L
+#define BA0_AC97_VENDOR_RESERVED_74 0x00001074L
+#define BA0_AC97_CAL_ADDRESS 0x00001076L
+#define BA0_AC97_CAL_DATA 0x00001078L
+#define BA0_AC97_VENDOR_RESERVED_7A 0x0000107AL
+#define BA0_AC97_VENDOR_ID1 0x0000107CL
+#define BA0_AC97_VENDOR_ID2 0x0000107EL
+
+/***************************************************************************** */
+/* */
+/* The following define the offsets of the registers and memories accessed via */
+/* base address register one on the CS4281 part. */
+/* */
+/***************************************************************************** */
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the host interrupt status */
+/* register. */
+/* */
+/***************************************************************************** */
+#define HISR_HVOLMASK 0x00000003L
+#define HISR_VDNI 0x00000001L
+#define HISR_VUPI 0x00000002L
+#define HISR_GP1I 0x00000004L
+#define HISR_GP3I 0x00000008L
+#define HISR_GPSI 0x00000010L
+#define HISR_GPPI 0x00000020L
+#define HISR_DMAI 0x00040000L
+#define HISR_FIFOI 0x00100000L
+#define HISR_HVOL 0x00200000L
+#define HISR_MIDI 0x00400000L
+#define HISR_SBINT 0x00800000L
+#define HISR_INTENA 0x80000000UL
+#define HISR_DMA_MASK 0x00000F00L
+#define HISR_FIFO_MASK 0x0000F000L
+#define HISR_DMA_SHIFT 8L
+#define HISR_FIFO_SHIFT 12L
+#define HISR_FIFO0 0x00001000L
+#define HISR_FIFO1 0x00002000L
+#define HISR_FIFO2 0x00004000L
+#define HISR_FIFO3 0x00008000L
+#define HISR_DMA0 0x00000100L
+#define HISR_DMA1 0x00000200L
+#define HISR_DMA2 0x00000400L
+#define HISR_DMA3 0x00000800L
+#define HISR_RESERVED 0x40000000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the host interrupt control */
+/* register. */
+/* */
+/***************************************************************************** */
+#define HICR_IEV 0x00000001L
+#define HICR_CHGM 0x00000002L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the DMA Mode Register n */
+/* (DMRn) */
+/* */
+/***************************************************************************** */
+#define DMRn_TR_MASK 0x0000000CL
+#define DMRn_TR_SHIFT 2L
+#define DMRn_AUTO 0x00000010L
+#define DMRn_TR_READ 0x00000008L
+#define DMRn_TR_WRITE 0x00000004L
+#define DMRn_TYPE_MASK 0x000000C0L
+#define DMRn_TYPE_SHIFT 6L
+#define DMRn_SIZE8 0x00010000L
+#define DMRn_MONO 0x00020000L
+#define DMRn_BEND 0x00040000L
+#define DMRn_USIGN 0x00080000L
+#define DMRn_SIZE20 0x00100000L
+#define DMRn_SWAPC 0x00400000L
+#define DMRn_CBC 0x01000000L
+#define DMRn_TBC 0x02000000L
+#define DMRn_POLL 0x10000000L
+#define DMRn_DMA 0x20000000L
+#define DMRn_FSEL_MASK 0xC0000000L
+#define DMRn_FSEL_SHIFT 30L
+#define DMRn_FSEL0 0x00000000L
+#define DMRn_FSEL1 0x40000000L
+#define DMRn_FSEL2 0x80000000L
+#define DMRn_FSEL3 0xC0000000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the DMA Command Register n */
+/* (DCRn) */
+/* */
+/***************************************************************************** */
+#define DCRn_HTCIE 0x00020000L
+#define DCRn_TCIE 0x00010000L
+#define DCRn_MSK 0x00000001L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the FIFO Control */
+/* register n.(FCRn) */
+/* */
+/***************************************************************************** */
+#define FCRn_OF_MASK 0x0000007FL
+#define FCRn_OF_SHIFT 0L
+#define FCRn_SZ_MASK 0x00007F00L
+#define FCRn_SZ_SHIFT 8L
+#define FCRn_LS_MASK 0x001F0000L
+#define FCRn_LS_SHIFT 16L
+#define FCRn_RS_MASK 0x1F000000L
+#define FCRn_RS_SHIFT 24L
+#define FCRn_FEN 0x80000000UL
+#define FCRn_PSH 0x20000000L
+#define FCRn_DACZ 0x40000000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the serial port Power Management */
+/* control register.(SPMC) */
+/* */
+/***************************************************************************** */
+#define SPMC_RSTN 0x00000001L
+#define SPMC_ASYN 0x00000002L
+#define SPMC_WUP1 0x00000004L
+#define SPMC_WUP2 0x00000008L
+#define SPMC_ASDI2E 0x00000100L
+#define SPMC_ESSPD 0x00000200L
+#define SPMC_GISPEN 0x00004000L
+#define SPMC_GIPPEN 0x00008000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the Configuration Load register. */
+/* (CFLR) */
+/* */
+/***************************************************************************** */
+#define CFLR_CLOCK_SOURCE_MASK 0x00000003L
+#define CFLR_CLOCK_SOURCE_AC97 0x00000001L
+
+#define CFLR_CB0_MASK 0x000000FFL
+#define CFLR_CB1_MASK 0x0000FF00L
+#define CFLR_CB2_MASK 0x00FF0000L
+#define CFLR_CB3_MASK 0xFF000000L
+#define CFLR_CB0_SHIFT 0L
+#define CFLR_CB1_SHIFT 8L
+#define CFLR_CB2_SHIFT 16L
+#define CFLR_CB3_SHIFT 24L
+
+#define IOTCR_DMA0 0x00000000L
+#define IOTCR_DMA1 0x00000400L
+#define IOTCR_DMA2 0x00000800L
+#define IOTCR_DMA3 0x00000C00L
+#define IOTCR_CCLS 0x00000100L
+#define IOTCR_PCPCI 0x00000200L
+#define IOTCR_DDMA 0x00000300L
+
+#define SBWBS_WBB 0x00000080L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the SRC Slot Assignment Register */
+/* (SRCSA) */
+/* */
+/***************************************************************************** */
+#define SRCSA_PLSS_MASK 0x0000001FL
+#define SRCSA_PLSS_SHIFT 0L
+#define SRCSA_PRSS_MASK 0x00001F00L
+#define SRCSA_PRSS_SHIFT 8L
+#define SRCSA_CLSS_MASK 0x001F0000L
+#define SRCSA_CLSS_SHIFT 16L
+#define SRCSA_CRSS_MASK 0x1F000000L
+#define SRCSA_CRSS_SHIFT 24L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the Sound System Power Management */
+/* register.(SSPM) */
+/* */
+/***************************************************************************** */
+#define SSPM_FPDN 0x00000080L
+#define SSPM_MIXEN 0x00000040L
+#define SSPM_CSRCEN 0x00000020L
+#define SSPM_PSRCEN 0x00000010L
+#define SSPM_JSEN 0x00000008L
+#define SSPM_ACLEN 0x00000004L
+#define SSPM_FMEN 0x00000002L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the Sound System Control */
+/* Register. (SSCR) */
+/* */
+/***************************************************************************** */
+#define SSCR_SB 0x00000004L
+#define SSCR_HVC 0x00000008L
+#define SSCR_LPFIFO 0x00000040L
+#define SSCR_LPSRC 0x00000080L
+#define SSCR_XLPSRC 0x00000100L
+#define SSCR_MVMD 0x00010000L
+#define SSCR_MVAD 0x00020000L
+#define SSCR_MVLD 0x00040000L
+#define SSCR_MVCS 0x00080000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the Clock Control Register 1. */
+/* (CLKCR1) */
+/* */
+/***************************************************************************** */
+#define CLKCR1_DLLSS_MASK 0x0000000CL
+#define CLKCR1_DLLSS_SHIFT 2L
+#define CLKCR1_DLLP 0x00000010L
+#define CLKCR1_SWCE 0x00000020L
+#define CLKCR1_DLLOS 0x00000040L
+#define CLKCR1_CKRA 0x00010000L
+#define CLKCR1_CKRN 0x00020000L
+#define CLKCR1_DLLRDY 0x01000000L
+#define CLKCR1_CLKON 0x02000000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the Sound Blaster Read Buffer */
+/* Status.(SBRBS) */
+/* */
+/***************************************************************************** */
+#define SBRBS_RD_MASK 0x0000007FL
+#define SBRBS_RD_SHIFT 0L
+#define SBRBS_RBF 0x00000080L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the serial port master control */
+/* register.(SERMC) */
+/* */
+/***************************************************************************** */
+#define SERMC_MSPE 0x00000001L
+#define SERMC_PTC_MASK 0x0000000EL
+#define SERMC_PTC_SHIFT 1L
+#define SERMC_PTC_AC97 0x00000002L
+#define SERMC_PLB 0x00000010L
+#define SERMC_PXLB 0x00000020L
+#define SERMC_LOFV 0x00080000L
+#define SERMC_SLB 0x00100000L
+#define SERMC_SXLB 0x00200000L
+#define SERMC_ODSEN1 0x01000000L
+#define SERMC_ODSEN2 0x02000000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the General Purpose I/O Register. */
+/* (GPIOR) */
+/* */
+/***************************************************************************** */
+#define GPIOR_VDNS 0x00000001L
+#define GPIOR_VUPS 0x00000002L
+#define GPIOR_GP1S 0x00000004L
+#define GPIOR_GP3S 0x00000008L
+#define GPIOR_GPSS 0x00000010L
+#define GPIOR_GPPS 0x00000020L
+#define GPIOR_GP1D 0x00000400L
+#define GPIOR_GP3D 0x00000800L
+#define GPIOR_VDNLT 0x00010000L
+#define GPIOR_VDNPO 0x00020000L
+#define GPIOR_VDNST 0x00040000L
+#define GPIOR_VDNW 0x00080000L
+#define GPIOR_VUPLT 0x00100000L
+#define GPIOR_VUPPO 0x00200000L
+#define GPIOR_VUPST 0x00400000L
+#define GPIOR_VUPW 0x00800000L
+#define GPIOR_GP1OE 0x01000000L
+#define GPIOR_GP1PT 0x02000000L
+#define GPIOR_GP1ST 0x04000000L
+#define GPIOR_GP1W 0x08000000L
+#define GPIOR_GP3OE 0x10000000L
+#define GPIOR_GP3PT 0x20000000L
+#define GPIOR_GP3ST 0x40000000L
+#define GPIOR_GP3W 0x80000000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the clock control register 1. */
+/* */
+/***************************************************************************** */
+#define CLKCR1_OSCS 0x00000001L
+#define CLKCR1_OSCP 0x00000002L
+#define CLKCR1_PLLSS_MASK 0x0000000CL
+#define CLKCR1_PLLSS_SERIAL 0x00000000L
+#define CLKCR1_PLLSS_CRYSTAL 0x00000004L
+#define CLKCR1_PLLSS_PCI 0x00000008L
+#define CLKCR1_PLLSS_RESERVED 0x0000000CL
+#define CLKCR1_PLLP 0x00000010L
+#define CLKCR1_SWCE 0x00000020L
+#define CLKCR1_PLLOS 0x00000040L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the feature reporting register. */
+/* */
+/***************************************************************************** */
+#define FRR_FAB_MASK 0x00000003L
+#define FRR_MASK_MASK 0x0000001CL
+#define FRR_ID_MASK 0x00003000L
+#define FRR_FAB_SHIFT 0L
+#define FRR_MASK_SHIFT 2L
+#define FRR_ID_SHIFT 12L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the serial port 1 configuration */
+/* register. */
+/* */
+/***************************************************************************** */
+#define SERC1_VALUE 0x00000003L
+#define SERC1_SO1EN 0x00000001L
+#define SERC1_SO1F_MASK 0x0000000EL
+#define SERC1_SO1F_CS423X 0x00000000L
+#define SERC1_SO1F_AC97 0x00000002L
+#define SERC1_SO1F_DAC 0x00000004L
+#define SERC1_SO1F_SPDIF 0x00000006L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the serial port 2 configuration */
+/* register. */
+/* */
+/***************************************************************************** */
+#define SERC2_VALUE 0x00000003L
+#define SERC2_SI1EN 0x00000001L
+#define SERC2_SI1F_MASK 0x0000000EL
+#define SERC2_SI1F_CS423X 0x00000000L
+#define SERC2_SI1F_AC97 0x00000002L
+#define SERC2_SI1F_ADC 0x00000004L
+#define SERC2_SI1F_SPDIF 0x00000006L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 control register. */
+/* */
+/***************************************************************************** */
+#define ACCTL_ESYN 0x00000002L
+#define ACCTL_VFRM 0x00000004L
+#define ACCTL_DCV 0x00000008L
+#define ACCTL_CRW 0x00000010L
+#define ACCTL_TC 0x00000040L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 status register. */
+/* */
+/***************************************************************************** */
+#define ACSTS_CRDY 0x00000001L
+#define ACSTS_VSTS 0x00000002L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 output slot valid */
+/* register. */
+/* */
+/***************************************************************************** */
+#define ACOSV_SLV3 0x00000001L
+#define ACOSV_SLV4 0x00000002L
+#define ACOSV_SLV5 0x00000004L
+#define ACOSV_SLV6 0x00000008L
+#define ACOSV_SLV7 0x00000010L
+#define ACOSV_SLV8 0x00000020L
+#define ACOSV_SLV9 0x00000040L
+#define ACOSV_SLV10 0x00000080L
+#define ACOSV_SLV11 0x00000100L
+#define ACOSV_SLV12 0x00000200L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 command address */
+/* register. */
+/* */
+/***************************************************************************** */
+#define ACCAD_CI_MASK 0x0000007FL
+#define ACCAD_CI_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 command data register. */
+/* */
+/***************************************************************************** */
+#define ACCDA_CD_MASK 0x0000FFFFL
+#define ACCDA_CD_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 input slot valid */
+/* register. */
+/* */
+/***************************************************************************** */
+#define ACISV_ISV3 0x00000001L
+#define ACISV_ISV4 0x00000002L
+#define ACISV_ISV5 0x00000004L
+#define ACISV_ISV6 0x00000008L
+#define ACISV_ISV7 0x00000010L
+#define ACISV_ISV8 0x00000020L
+#define ACISV_ISV9 0x00000040L
+#define ACISV_ISV10 0x00000080L
+#define ACISV_ISV11 0x00000100L
+#define ACISV_ISV12 0x00000200L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 status address */
+/* register. */
+/* */
+/***************************************************************************** */
+#define ACSAD_SI_MASK 0x0000007FL
+#define ACSAD_SI_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 status data register. */
+/* */
+/***************************************************************************** */
+#define ACSDA_SD_MASK 0x0000FFFFL
+#define ACSDA_SD_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the I/O trap address and control */
+/* registers (all 12). */
+/* */
+/***************************************************************************** */
+#define IOTAC_SA_MASK 0x0000FFFFL
+#define IOTAC_MSK_MASK 0x000F0000L
+#define IOTAC_IODC_MASK 0x06000000L
+#define IOTAC_IODC_16_BIT 0x00000000L
+#define IOTAC_IODC_10_BIT 0x02000000L
+#define IOTAC_IODC_12_BIT 0x04000000L
+#define IOTAC_WSPI 0x08000000L
+#define IOTAC_RSPI 0x10000000L
+#define IOTAC_WSE 0x20000000L
+#define IOTAC_WE 0x40000000L
+#define IOTAC_RE 0x80000000L
+#define IOTAC_SA_SHIFT 0L
+#define IOTAC_MSK_SHIFT 16L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the PC/PCI master enable */
+/* register. */
+/* */
+/***************************************************************************** */
+#define PCPCIEN_EN 0x00000001L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the joystick poll/trigger */
+/* register. */
+/* */
+/***************************************************************************** */
+#define JSPT_CAX 0x00000001L
+#define JSPT_CAY 0x00000002L
+#define JSPT_CBX 0x00000004L
+#define JSPT_CBY 0x00000008L
+#define JSPT_BA1 0x00000010L
+#define JSPT_BA2 0x00000020L
+#define JSPT_BB1 0x00000040L
+#define JSPT_BB2 0x00000080L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the joystick control register. */
+/* */
+/***************************************************************************** */
+#define JSCTL_SP_MASK 0x00000003L
+#define JSCTL_SP_SLOW 0x00000000L
+#define JSCTL_SP_MEDIUM_SLOW 0x00000001L
+#define JSCTL_SP_MEDIUM_FAST 0x00000002L
+#define JSCTL_SP_FAST 0x00000003L
+#define JSCTL_ARE 0x00000004L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the MIDI control register. */
+/* */
+/***************************************************************************** */
+#define MIDCR_TXE 0x00000001L
+#define MIDCR_RXE 0x00000002L
+#define MIDCR_RIE 0x00000004L
+#define MIDCR_TIE 0x00000008L
+#define MIDCR_MLB 0x00000010L
+#define MIDCR_MRST 0x00000020L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the MIDI status register. */
+/* */
+/***************************************************************************** */
+#define MIDSR_TBF 0x00000040L
+#define MIDSR_RBE 0x00000080L
+#define MIDSR_RDA 0x00008000L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the MIDI write port register. */
+/* */
+/***************************************************************************** */
+#define MIDWP_MWD_MASK 0x000000FFL
+#define MIDWP_MWD_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the MIDI read port register. */
+/* */
+/***************************************************************************** */
+#define MIDRP_MRD_MASK 0x000000FFL
+#define MIDRP_MRD_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the configuration interface */
+/* register. */
+/* */
+/***************************************************************************** */
+#define CFGI_CLK 0x00000001L
+#define CFGI_DOUT 0x00000002L
+#define CFGI_DIN_EEN 0x00000004L
+#define CFGI_EELD 0x00000008L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the subsystem ID and vendor ID */
+/* register. */
+/* */
+/***************************************************************************** */
+#define SSVID_VID_MASK 0x0000FFFFL
+#define SSVID_SID_MASK 0xFFFF0000L
+#define SSVID_VID_SHIFT 0L
+#define SSVID_SID_SHIFT 16L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the GPIO pin interface register. */
+/* */
+/***************************************************************************** */
+#define GPIOR_VOLDN 0x00000001L
+#define GPIOR_VOLUP 0x00000002L
+#define GPIOR_SI2D 0x00000004L
+#define GPIOR_SI2OE 0x00000008L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 status register 2. */
+/* */
+/***************************************************************************** */
+#define ACSTS2_CRDY 0x00000001L
+#define ACSTS2_VSTS 0x00000002L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 input slot valid */
+/* register 2. */
+/* */
+/***************************************************************************** */
+#define ACISV2_ISV3 0x00000001L
+#define ACISV2_ISV4 0x00000002L
+#define ACISV2_ISV5 0x00000004L
+#define ACISV2_ISV6 0x00000008L
+#define ACISV2_ISV7 0x00000010L
+#define ACISV2_ISV8 0x00000020L
+#define ACISV2_ISV9 0x00000040L
+#define ACISV2_ISV10 0x00000080L
+#define ACISV2_ISV11 0x00000100L
+#define ACISV2_ISV12 0x00000200L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 status address */
+/* register 2. */
+/* */
+/***************************************************************************** */
+#define ACSAD2_SI_MASK 0x0000007FL
+#define ACSAD2_SI_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the AC97 status data register 2. */
+/* */
+/***************************************************************************** */
+#define ACSDA2_SD_MASK 0x0000FFFFL
+#define ACSDA2_SD_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the I/O trap control register. */
+/* */
+/***************************************************************************** */
+#define IOTCR_ITD 0x00000001L
+#define IOTCR_HRV 0x00000002L
+#define IOTCR_SRV 0x00000004L
+#define IOTCR_DTI 0x00000008L
+#define IOTCR_DFI 0x00000010L
+#define IOTCR_DDP 0x00000020L
+#define IOTCR_JTE 0x00000040L
+#define IOTCR_PPE 0x00000080L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the I/O trap address and control */
+/* registers for Hardware Master Volume. */
+/* */
+/***************************************************************************** */
+#define IOTGP_SA_MASK 0x0000FFFFL
+#define IOTGP_MSK_MASK 0x000F0000L
+#define IOTGP_IODC_MASK 0x06000000L
+#define IOTGP_IODC_16_BIT 0x00000000L
+#define IOTGP_IODC_10_BIT 0x02000000L
+#define IOTGP_IODC_12_BIT 0x04000000L
+#define IOTGP_WSPI 0x08000000L
+#define IOTGP_RSPI 0x10000000L
+#define IOTGP_WSE 0x20000000L
+#define IOTGP_WE 0x40000000L
+#define IOTGP_RE 0x80000000L
+#define IOTGP_SA_SHIFT 0L
+#define IOTGP_MSK_SHIFT 16L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the I/O trap address and control */
+/* registers for Sound Blaster */
+/* */
+/***************************************************************************** */
+#define IOTSB_SA_MASK 0x0000FFFFL
+#define IOTSB_MSK_MASK 0x000F0000L
+#define IOTSB_IODC_MASK 0x06000000L
+#define IOTSB_IODC_16_BIT 0x00000000L
+#define IOTSB_IODC_10_BIT 0x02000000L
+#define IOTSB_IODC_12_BIT 0x04000000L
+#define IOTSB_WSPI 0x08000000L
+#define IOTSB_RSPI 0x10000000L
+#define IOTSB_WSE 0x20000000L
+#define IOTSB_WE 0x40000000L
+#define IOTSB_RE 0x80000000L
+#define IOTSB_SA_SHIFT 0L
+#define IOTSB_MSK_SHIFT 16L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the I/O trap address and control */
+/* registers for FM. */
+/* */
+/***************************************************************************** */
+#define IOTFM_SA_MASK 0x0000FFFFL
+#define IOTFM_MSK_MASK 0x000F0000L
+#define IOTFM_IODC_MASK 0x06000000L
+#define IOTFM_IODC_16_BIT 0x00000000L
+#define IOTFM_IODC_10_BIT 0x02000000L
+#define IOTFM_IODC_12_BIT 0x04000000L
+#define IOTFM_WSPI 0x08000000L
+#define IOTFM_RSPI 0x10000000L
+#define IOTFM_WSE 0x20000000L
+#define IOTFM_WE 0x40000000L
+#define IOTFM_RE 0x80000000L
+#define IOTFM_SA_SHIFT 0L
+#define IOTFM_MSK_SHIFT 16L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the PC/PCI request register. */
+/* */
+/***************************************************************************** */
+#define PCPRR_RDC_MASK 0x00000007L
+#define PCPRR_REQ 0x00008000L
+#define PCPRR_RDC_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the PC/PCI grant register. */
+/* */
+/***************************************************************************** */
+#define PCPGR_GDC_MASK 0x00000007L
+#define PCPGR_VL 0x00008000L
+#define PCPGR_GDC_SHIFT 0L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the PC/PCI Control Register. */
+/* */
+/***************************************************************************** */
+#define PCPCR_EN 0x00000001L
+
+/***************************************************************************** */
+/* */
+/* The following defines are for the flags in the debug index register. */
+/* */
+/***************************************************************************** */
+#define DREG_REGID_MASK 0x0000007FL
+#define DREG_DEBUG 0x00000080L
+#define DREG_RGBK_MASK 0x00000700L
+#define DREG_TRAP 0x00000800L
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_TRAPX 0x00001000L
+#endif
+#endif
+#define DREG_REGID_SHIFT 0L
+#define DREG_RGBK_SHIFT 8L
+#define DREG_RGBK_REGID_MASK 0x0000077FL
+#define DREG_REGID_R0 0x00000010L
+#define DREG_REGID_R1 0x00000011L
+#define DREG_REGID_R2 0x00000012L
+#define DREG_REGID_R3 0x00000013L
+#define DREG_REGID_R4 0x00000014L
+#define DREG_REGID_R5 0x00000015L
+#define DREG_REGID_R6 0x00000016L
+#define DREG_REGID_R7 0x00000017L
+#define DREG_REGID_R8 0x00000018L
+#define DREG_REGID_R9 0x00000019L
+#define DREG_REGID_RA 0x0000001AL
+#define DREG_REGID_RB 0x0000001BL
+#define DREG_REGID_RC 0x0000001CL
+#define DREG_REGID_RD 0x0000001DL
+#define DREG_REGID_RE 0x0000001EL
+#define DREG_REGID_RF 0x0000001FL
+#define DREG_REGID_RA_BUS_LOW 0x00000020L
+#define DREG_REGID_RA_BUS_HIGH 0x00000038L
+#define DREG_REGID_YBUS_LOW 0x00000050L
+#define DREG_REGID_YBUS_HIGH 0x00000058L
+#define DREG_REGID_TRAP_0 0x00000100L
+#define DREG_REGID_TRAP_1 0x00000101L
+#define DREG_REGID_TRAP_2 0x00000102L
+#define DREG_REGID_TRAP_3 0x00000103L
+#define DREG_REGID_TRAP_4 0x00000104L
+#define DREG_REGID_TRAP_5 0x00000105L
+#define DREG_REGID_TRAP_6 0x00000106L
+#define DREG_REGID_TRAP_7 0x00000107L
+#define DREG_REGID_INDIRECT_ADDRESS 0x0000010EL
+#define DREG_REGID_TOP_OF_STACK 0x0000010FL
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_REGID_TRAP_8 0x00000110L
+#define DREG_REGID_TRAP_9 0x00000111L
+#define DREG_REGID_TRAP_10 0x00000112L
+#define DREG_REGID_TRAP_11 0x00000113L
+#define DREG_REGID_TRAP_12 0x00000114L
+#define DREG_REGID_TRAP_13 0x00000115L
+#define DREG_REGID_TRAP_14 0x00000116L
+#define DREG_REGID_TRAP_15 0x00000117L
+#define DREG_REGID_TRAP_16 0x00000118L
+#define DREG_REGID_TRAP_17 0x00000119L
+#define DREG_REGID_TRAP_18 0x0000011AL
+#define DREG_REGID_TRAP_19 0x0000011BL
+#define DREG_REGID_TRAP_20 0x0000011CL
+#define DREG_REGID_TRAP_21 0x0000011DL
+#define DREG_REGID_TRAP_22 0x0000011EL
+#define DREG_REGID_TRAP_23 0x0000011FL
+#endif
+#endif
+#define DREG_REGID_RSA0_LOW 0x00000200L
+#define DREG_REGID_RSA0_HIGH 0x00000201L
+#define DREG_REGID_RSA1_LOW 0x00000202L
+#define DREG_REGID_RSA1_HIGH 0x00000203L
+#define DREG_REGID_RSA2 0x00000204L
+#define DREG_REGID_RSA3 0x00000205L
+#define DREG_REGID_RSI0_LOW 0x00000206L
+#define DREG_REGID_RSI0_HIGH 0x00000207L
+#define DREG_REGID_RSI1 0x00000208L
+#define DREG_REGID_RSI2 0x00000209L
+#define DREG_REGID_SAGUSTATUS 0x0000020AL
+#define DREG_REGID_RSCONFIG01_LOW 0x0000020BL
+#define DREG_REGID_RSCONFIG01_HIGH 0x0000020CL
+#define DREG_REGID_RSCONFIG23_LOW 0x0000020DL
+#define DREG_REGID_RSCONFIG23_HIGH 0x0000020EL
+#define DREG_REGID_RSDMA01E 0x0000020FL
+#define DREG_REGID_RSDMA23E 0x00000210L
+#define DREG_REGID_RSD0_LOW 0x00000211L
+#define DREG_REGID_RSD0_HIGH 0x00000212L
+#define DREG_REGID_RSD1_LOW 0x00000213L
+#define DREG_REGID_RSD1_HIGH 0x00000214L
+#define DREG_REGID_RSD2_LOW 0x00000215L
+#define DREG_REGID_RSD2_HIGH 0x00000216L
+#define DREG_REGID_RSD3_LOW 0x00000217L
+#define DREG_REGID_RSD3_HIGH 0x00000218L
+#define DREG_REGID_SRAR_HIGH 0x0000021AL
+#define DREG_REGID_SRAR_LOW 0x0000021BL
+#define DREG_REGID_DMA_STATE 0x0000021CL
+#define DREG_REGID_CURRENT_DMA_STREAM 0x0000021DL
+#define DREG_REGID_NEXT_DMA_STREAM 0x0000021EL
+#define DREG_REGID_CPU_STATUS 0x00000300L
+#define DREG_REGID_MAC_MODE 0x00000301L
+#define DREG_REGID_STACK_AND_REPEAT 0x00000302L
+#define DREG_REGID_INDEX0 0x00000304L
+#define DREG_REGID_INDEX1 0x00000305L
+#define DREG_REGID_DMA_STATE_0_3 0x00000400L
+#define DREG_REGID_DMA_STATE_4_7 0x00000404L
+#define DREG_REGID_DMA_STATE_8_11 0x00000408L
+#define DREG_REGID_DMA_STATE_12_15 0x0000040CL
+#define DREG_REGID_DMA_STATE_16_19 0x00000410L
+#define DREG_REGID_DMA_STATE_20_23 0x00000414L
+#define DREG_REGID_DMA_STATE_24_27 0x00000418L
+#define DREG_REGID_DMA_STATE_28_31 0x0000041CL
+#define DREG_REGID_DMA_STATE_32_35 0x00000420L
+#define DREG_REGID_DMA_STATE_36_39 0x00000424L
+#define DREG_REGID_DMA_STATE_40_43 0x00000428L
+#define DREG_REGID_DMA_STATE_44_47 0x0000042CL
+#define DREG_REGID_DMA_STATE_48_51 0x00000430L
+#define DREG_REGID_DMA_STATE_52_55 0x00000434L
+#define DREG_REGID_DMA_STATE_56_59 0x00000438L
+#define DREG_REGID_DMA_STATE_60_63 0x0000043CL
+#define DREG_REGID_DMA_STATE_64_67 0x00000440L
+#define DREG_REGID_DMA_STATE_68_71 0x00000444L
+#define DREG_REGID_DMA_STATE_72_75 0x00000448L
+#define DREG_REGID_DMA_STATE_76_79 0x0000044CL
+#define DREG_REGID_DMA_STATE_80_83 0x00000450L
+#define DREG_REGID_DMA_STATE_84_87 0x00000454L
+#define DREG_REGID_DMA_STATE_88_91 0x00000458L
+#define DREG_REGID_DMA_STATE_92_95 0x0000045CL
+#define DREG_REGID_TRAP_SELECT 0x00000500L
+#define DREG_REGID_TRAP_WRITE_0 0x00000500L
+#define DREG_REGID_TRAP_WRITE_1 0x00000501L
+#define DREG_REGID_TRAP_WRITE_2 0x00000502L
+#define DREG_REGID_TRAP_WRITE_3 0x00000503L
+#define DREG_REGID_TRAP_WRITE_4 0x00000504L
+#define DREG_REGID_TRAP_WRITE_5 0x00000505L
+#define DREG_REGID_TRAP_WRITE_6 0x00000506L
+#define DREG_REGID_TRAP_WRITE_7 0x00000507L
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_REGID_TRAP_WRITE_8 0x00000510L
+#define DREG_REGID_TRAP_WRITE_9 0x00000511L
+#define DREG_REGID_TRAP_WRITE_10 0x00000512L
+#define DREG_REGID_TRAP_WRITE_11 0x00000513L
+#define DREG_REGID_TRAP_WRITE_12 0x00000514L
+#define DREG_REGID_TRAP_WRITE_13 0x00000515L
+#define DREG_REGID_TRAP_WRITE_14 0x00000516L
+#define DREG_REGID_TRAP_WRITE_15 0x00000517L
+#define DREG_REGID_TRAP_WRITE_16 0x00000518L
+#define DREG_REGID_TRAP_WRITE_17 0x00000519L
+#define DREG_REGID_TRAP_WRITE_18 0x0000051AL
+#define DREG_REGID_TRAP_WRITE_19 0x0000051BL
+#define DREG_REGID_TRAP_WRITE_20 0x0000051CL
+#define DREG_REGID_TRAP_WRITE_21 0x0000051DL
+#define DREG_REGID_TRAP_WRITE_22 0x0000051EL
+#define DREG_REGID_TRAP_WRITE_23 0x0000051FL
+#endif
+#endif
+#define DREG_REGID_MAC0_ACC0_LOW 0x00000600L
+#define DREG_REGID_MAC0_ACC1_LOW 0x00000601L
+#define DREG_REGID_MAC0_ACC2_LOW 0x00000602L
+#define DREG_REGID_MAC0_ACC3_LOW 0x00000603L
+#define DREG_REGID_MAC1_ACC0_LOW 0x00000604L
+#define DREG_REGID_MAC1_ACC1_LOW 0x00000605L
+#define DREG_REGID_MAC1_ACC2_LOW 0x00000606L
+#define DREG_REGID_MAC1_ACC3_LOW 0x00000607L
+#define DREG_REGID_MAC0_ACC0_MID 0x00000608L
+#define DREG_REGID_MAC0_ACC1_MID 0x00000609L
+#define DREG_REGID_MAC0_ACC2_MID 0x0000060AL
+#define DREG_REGID_MAC0_ACC3_MID 0x0000060BL
+#define DREG_REGID_MAC1_ACC0_MID 0x0000060CL
+#define DREG_REGID_MAC1_ACC1_MID 0x0000060DL
+#define DREG_REGID_MAC1_ACC2_MID 0x0000060EL
+#define DREG_REGID_MAC1_ACC3_MID 0x0000060FL
+#define DREG_REGID_MAC0_ACC0_HIGH 0x00000610L
+#define DREG_REGID_MAC0_ACC1_HIGH 0x00000611L
+#define DREG_REGID_MAC0_ACC2_HIGH 0x00000612L
+#define DREG_REGID_MAC0_ACC3_HIGH 0x00000613L
+#define DREG_REGID_MAC1_ACC0_HIGH 0x00000614L
+#define DREG_REGID_MAC1_ACC1_HIGH 0x00000615L
+#define DREG_REGID_MAC1_ACC2_HIGH 0x00000616L
+#define DREG_REGID_MAC1_ACC3_HIGH 0x00000617L
+#define DREG_REGID_RSHOUT_LOW 0x00000620L
+#define DREG_REGID_RSHOUT_MID 0x00000628L
+#define DREG_REGID_RSHOUT_HIGH 0x00000630L
+
+#endif /* _H_HWDEFS */
diff --git a/kernel/drv/oss_cs4281/oss_cs4281.c b/kernel/drv/oss_cs4281/oss_cs4281.c
new file mode 100644
index 0000000..45ceaa7
--- /dev/null
+++ b/kernel/drv/oss_cs4281/oss_cs4281.c
@@ -0,0 +1,1061 @@
+/*
+ * Purpose: Driver for Crystal PCI audio controller.
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include "oss_cs4281_cfg.h"
+#include "midi_core.h"
+#include "ac97.h"
+#include "oss_pci.h"
+#include "cs4281.h"
+
+#define CRYSTAL_VENDOR_ID 0x1013
+#define CRYSTAL_CS4281_ID 0x6005
+
+#if 1
+#define WRITEB(a,d) devc->bRegister0[a] = d
+#define READB(a) devc->bRegister0[a]
+#define WRITEW(a,d) devc->wRegister0[a>>1] = d
+#define READW(a) devc->wRegister0[a>>1]
+#define READL(a) (devc->dwRegister0[a>>2])
+#define WRITEL(a, d) devc->dwRegister0[a>>2] = d
+#else
+#define WRITEB(a,d) PCI_WRITEB(devc->osdev, d, devc->bRegister0[a])
+#define READB(a) PCI_READB(devc->osdev, devc->bRegister0[a])
+#define WRITEW(a,d) PCI_WRITEW(devc->osdev, d, devc->wRegister0[a>>1])
+#define READW(a) PCI_READW(devc->osdev, devc->wRegister0[a>>1])
+#define READL(a) PCI_READL(devc->osdev, devc->dwRegister0[a>>2])
+#define WRITEL(a, d) PCI_WRITEL(devc->osdev, d, devc->dwRegister0[a>>2])
+#endif
+
+#ifdef OSS_BIG_ENDIAN
+static unsigned int
+be_swap (unsigned int x)
+{
+ return ((x & 0x000000ff) << 24) |
+ ((x & 0x0000ff00) << 8) |
+ ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
+}
+
+#define LSWAP(x) be_swap(x)
+#else
+#define LSWAP(x) x
+#endif
+
+#define MAX_PORTC 2
+
+typedef struct cs4281_portc
+{
+ int speed, bits, channels;
+ int open_mode;
+ int trigger_bits;
+ int audio_enabled;
+ int audiodev;
+}
+cs4281_portc;
+
+typedef struct cs4281_devc
+{
+ oss_device_t *osdev;
+ char *chip_name;
+ oss_native_word bar0addr, bar1addr;
+ unsigned int *bar0virt, *bar1virt;
+ volatile unsigned int *dwRegister0, *dwRegister1;
+ volatile unsigned short *wRegister0, *wRegister1;
+ volatile unsigned char *bRegister0, *bRegister1;
+ int irq;
+ volatile unsigned char intr_mask;
+ oss_mutex_t mutex;
+ oss_mutex_t low_mutex;
+
+ /* MIDI */
+ int midi_opened;
+ int midi_dev;
+ oss_midi_inputbyte_t midi_input_intr;
+
+ /* Mixer parameters */
+ ac97_devc ac97devc;
+ int mixer_dev;
+
+ /* Audio parameters */
+ cs4281_portc portc[MAX_PORTC];
+ int open_mode;
+ int fm_attached, mpu_attached;
+}
+cs4281_devc;
+
+
+
+static int
+ac97_read (void *devc_, int reg)
+{
+ cs4281_devc *devc = devc_;
+ int count;
+ oss_native_word status, value;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ /*
+ * Make sure that there is not data sitting around from a previous
+ * uncompleted access. ACSDA = Status Data Register = 47Ch
+ */
+ status = READL (BA0_ACSDA);
+ /* Get the actual AC97 register from the offset */
+ WRITEL (BA0_ACCAD, reg);
+ WRITEL (BA0_ACCDA, 0);
+ WRITEL (BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN);
+
+ /* Wait for the read to occur. */
+ for (count = 0; count < 500; count++)
+ {
+ /* First, we want to wait for a short time. */
+ oss_udelay (10);
+ /*
+ * Now, check to see if the read has completed.
+ * ACCTL = 460h, DCV should be reset by now and 460h = 17h
+ */
+ status = READL (BA0_ACCTL);
+ if (!(status & ACCTL_DCV))
+ {
+ break;
+ }
+ }
+
+ /* Make sure the read completed. */
+ if (status & ACCTL_DCV)
+ {
+ cmn_err (CE_WARN, "AC97 Read Timedout\n");
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return (-1);
+ }
+
+ /* Wait for the valid status bit to go active. */
+
+ for (count = 0; count < 500; count++)
+ {
+ /*
+ * Read the AC97 status register.
+ * ACSTS = Status Register = 464h
+ */
+ status = READL (BA0_ACSTS);
+ /*
+ * See if we have valid status.
+ * VSTS - Valid Status
+ */
+ if (status & ACSTS_VSTS)
+ break;
+
+ /*
+ * Wait for a short while.
+ */
+ oss_udelay (10);
+ }
+ /* Make sure we got valid status. */
+ if (!(status & ACSTS_VSTS))
+ {
+ cmn_err (CE_WARN, "AC97 Read Timedout\n");
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return (-1);
+ }
+
+ /*
+ * Read the data returned from the AC97 register.
+ * ACSDA = Status Data Register = 474h
+ */
+ value = READL (BA0_ACSDA);
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return (value);
+}
+
+static int
+ac97_write (void *devc_, int reg, int data)
+{
+ cs4281_devc *devc = devc_;
+ int count;
+ oss_native_word status, flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ WRITEL (BA0_ACCAD, reg);
+ WRITEL (BA0_ACCDA, data);
+ WRITEL (BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN);
+ for (count = 0; count < 500; count++)
+ {
+ /* First, we want to wait for a short time. */
+ oss_udelay (10);
+ /* Now, check to see if the write has completed. */
+ /* ACCTL = 460h, DCV should be reset by now and 460h = 07h */
+ status = READL (BA0_ACCTL);
+ if (!(status & ACCTL_DCV))
+ break;
+ }
+
+ /* write didn't completed. */
+ if (status & ACCTL_DCV)
+ {
+ cmn_err (CE_WARN, "AC97 Write timeout\n");
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return (-1);
+ }
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return 0;
+}
+
+
+static int
+cs4281intr (oss_device_t * osdev)
+{
+ cs4281_devc *devc = (cs4281_devc *) osdev->devc;
+ cs4281_portc *portc;
+ oss_native_word status, uart_stat;
+ int i;
+ int serviced = 0;
+
+/* Read the Interrupt Status Register */
+ status = READL (BA0_HISR);
+
+/*
+ * This is the MIDI read interrupt service. First check to see
+ * if the MIDI interrupt flag is set in the HISR register. Next
+ * read the MIDI status register. See if Receive Buffer Empty
+ * is empty (0=FIFO Not empty, 1=FIFO is empty
+ */
+ if ((devc->midi_opened & OPEN_READ) && (status & HISR_MIDI))
+ {
+ serviced = 1;
+ uart_stat = READL (BA0_MIDSR);
+/*
+ * read one byte of MIDI data and hand it off the the sequencer module
+ * to decode this. Keep checking to see if the data is available. Stop
+ * when no more data is there in the FIFO.
+ */
+ while (!(uart_stat & MIDSR_RBE))
+ {
+ unsigned char d;
+ d = READL (BA0_MIDRP);
+
+ if (devc->midi_opened & OPEN_READ && devc->midi_input_intr)
+ devc->midi_input_intr (devc->midi_dev, d);
+ uart_stat = READL (BA0_MIDSR);
+ }
+ }
+/* Audio interrupt handling */
+ if (status & (HISR_INTENA | HISR_DMAI))
+ for (i = 0; i < MAX_PORTC; i++)
+ {
+ portc = &devc->portc[i];
+ if ((status & HISR_DMA0) && (portc->trigger_bits & PCM_ENABLE_OUTPUT))
+ {
+ dmap_t *dmapout = audio_engines[portc->audiodev]->dmap_out;
+ unsigned int currdac;
+ int n;
+
+ serviced = 1;
+ READL (BA0_HDSR0); /* ack the DMA interrupt */
+ currdac = READL (BA0_DCA0) - dmapout->dmabuf_phys;
+ currdac /= dmapout->fragment_size;
+ n = 0;
+ while (dmap_get_qhead (dmapout) != currdac
+ && n++ < dmapout->nfrags)
+ oss_audio_outputintr (portc->audiodev, 1);
+ }
+
+ if ((status & HISR_DMA1) && (portc->trigger_bits & PCM_ENABLE_INPUT))
+ {
+ dmap_t *dmapin = audio_engines[portc->audiodev]->dmap_in;
+ unsigned int curradc;
+ int n;
+
+ serviced = 1;
+ READL (BA0_HDSR1); /* ack the DMA interrupt */
+ curradc = READL (BA0_DCA1) - dmapin->dmabuf_phys;
+ curradc /= dmapin->fragment_size;
+ n = 0;
+ while (dmap_get_qtail (dmapin) != curradc && n++ < dmapin->nfrags)
+ oss_audio_inputintr (portc->audiodev, 0);
+ }
+ WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM);
+ }
+ return serviced;
+}
+
+static int
+cs4281_audio_set_rate (int dev, int arg)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ if (arg == 0)
+ return portc->speed;
+ if (arg > 48000)
+ arg = 48000;
+ if (arg < 6023)
+ arg = 6023;
+ portc->speed = arg;
+ return portc->speed;
+}
+
+static short
+cs4281_audio_set_channels (int dev, short arg)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ if ((arg != 1) && (arg != 2))
+ return portc->channels;
+ portc->channels = arg;
+ return portc->channels;
+}
+
+static unsigned int
+cs4281_audio_set_format (int dev, unsigned int arg)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ if (arg == 0)
+ return portc->bits;
+ if (!(arg & (AFMT_U8 | AFMT_S16_LE)))
+ return portc->bits;
+ portc->bits = arg;
+ return portc->bits;
+}
+
+/*ARGSUSED*/
+static int
+cs4281_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+{
+ return OSS_EINVAL;
+}
+
+static void cs4281_audio_trigger (int dev, int state);
+static void
+cs4281_audio_reset (int dev)
+{
+ cs4281_audio_trigger (dev, 0);
+}
+
+static void
+cs4281_audio_reset_input (int dev)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ cs4281_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT);
+}
+
+static void
+cs4281_audio_reset_output (int dev)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ cs4281_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT);
+}
+
+/*ARGSUSED*/
+static int
+cs4281_audio_open (int dev, int mode, int open_flags)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ cs4281_devc *devc = audio_engines[dev]->devc;
+ oss_native_word flags;
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ if (portc->open_mode)
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return OSS_EBUSY;
+ }
+
+ if (devc->open_mode & mode)
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return OSS_EBUSY;
+ }
+
+ devc->open_mode |= mode;
+ portc->open_mode = mode;
+ portc->audio_enabled &= ~mode;
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return 0;
+}
+
+static void
+cs4281_audio_close (int dev, int mode)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ cs4281_devc *devc = audio_engines[dev]->devc;
+ cs4281_audio_reset (dev);
+ portc->open_mode = 0;
+ devc->open_mode &= ~mode;
+ portc->audio_enabled &= ~mode;
+}
+
+/*ARGSUSED*/
+static void
+cs4281_audio_output_block (int dev, oss_native_word buf, int count,
+ int fragsize, int intrflag)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+
+ portc->audio_enabled |= PCM_ENABLE_OUTPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
+}
+
+/*ARGSUSED*/
+static void
+cs4281_audio_start_input (int dev, oss_native_word buf, int count,
+ int fragsize, int intrflag)
+{
+ cs4281_portc *portc = audio_engines[dev]->portc;
+
+ portc->audio_enabled |= PCM_ENABLE_INPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_INPUT;
+}
+
+static void
+cs4281_audio_trigger (int dev, int state)
+{
+ cs4281_devc *devc = audio_engines[dev]->devc;
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ oss_native_word tmp1;
+ oss_native_word flags;
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ if (portc->open_mode & OPEN_WRITE)
+ {
+ if (state & PCM_ENABLE_OUTPUT)
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
+ !(portc->trigger_bits & PCM_ENABLE_OUTPUT))
+ {
+ /* Clear DMA0 channel Mask bit. Start Playing. */
+ tmp1 = READL (BA0_DCR0) & ~DCRn_MSK; /*enable DMA */
+ WRITEL (BA0_DCR0, tmp1); /* (154h) */
+ WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM); /*enable intr */
+ portc->trigger_bits |= PCM_ENABLE_OUTPUT;
+ }
+ }
+ else
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
+ (portc->trigger_bits & PCM_ENABLE_OUTPUT))
+ {
+ portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
+ tmp1 = READL (BA0_DCR0) & ~DCRn_MSK;
+ WRITEL (BA0_DCR0, tmp1 | DCRn_MSK);
+ }
+ }
+ }
+ if (portc->open_mode & OPEN_READ)
+ {
+ if (state & PCM_ENABLE_INPUT)
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
+ !(portc->trigger_bits & PCM_ENABLE_INPUT))
+ {
+ /* Clear DMA1 channel Mask bit. Start recording. */
+ tmp1 = READL (BA0_DCR1) & ~DCRn_MSK;
+ WRITEL (BA0_DCR1, tmp1); /* (15ch) */
+ WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM); /*Set INTENA=1. */
+ portc->trigger_bits |= PCM_ENABLE_INPUT;
+ }
+ }
+ else
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
+ (portc->trigger_bits & PCM_ENABLE_INPUT))
+ {
+ portc->audio_enabled &= ~PCM_ENABLE_INPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_INPUT;
+ tmp1 = READL (BA0_DCR1) & ~DCRn_MSK;
+ WRITEL (BA0_DCR1, tmp1 | DCRn_MSK);
+ }
+ }
+ }
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+}
+
+static int
+cs4281_rate (oss_native_word rate)
+{
+ int val = 0;
+
+ switch (rate)
+ {
+ case 8000:
+ val = 5;
+ break;
+ case 11025:
+ val = 4;
+ break;
+ case 16000:
+ val = 3;
+ break;
+ case 22050:
+ val = 2;
+ break;
+ case 44100:
+ val = 1;
+ break;
+ case 48000:
+ val = 0;
+ break;
+ default:
+ val = 1536000 / rate;
+ break;
+ }
+ return val;
+}
+
+/*ARGSUSED*/
+static int
+cs4281_audio_prepare_for_input (int dev, int bsize, int bcount)
+{
+ cs4281_devc *devc = audio_engines[dev]->devc;
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ dmap_t *dmap = audio_engines[dev]->dmap_in;
+ int count = dmap->bytes_in_use;
+ oss_native_word recordFormat;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ /* set the record rate */
+ WRITEL (BA0_ADCSR, cs4281_rate (portc->speed)); /* (748h) */
+ /* Start with defaults for the record format */
+ /* reg & modify them for the current case. */
+ recordFormat = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE;
+ if (portc->channels == 1) /* If mono, */
+ recordFormat |= DMRn_MONO; /* Turn on mono bit. */
+ if (portc->bits == 8) /* If 8-bit, */
+ recordFormat |= (DMRn_SIZE8 | DMRn_USIGN); /* turn on 8bit/unsigned. */
+ WRITEL (BA0_DMR1, recordFormat);
+ /* set input gain to 0db */
+ /* ac97_write(devc, BA0_AC97_RECORD_GAIN, 0x0808); */
+ if (portc->channels == 2) /* If stereo, */
+ count /= 2; /* halve DMA count(stereo); */
+ if (portc->bits == 16) /* If 16-bit, */
+ count /= 2;
+ /* Set the physical play buffer address DMA1 Base & Current. */
+ WRITEL (BA0_DBA1, dmap->dmabuf_phys); /* (118h) */
+ /* Set the sample count(-1) in DMA Base Count register 1. */
+ WRITEL (BA0_DBC1, count - 1);
+ portc->audio_enabled &= ~PCM_ENABLE_INPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_INPUT;
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return 0;
+}
+
+/*ARGSUSED*/
+static int
+cs4281_audio_prepare_for_output (int dev, int bsize, int bcount)
+{
+ cs4281_devc *devc = audio_engines[dev]->devc;
+ cs4281_portc *portc = audio_engines[dev]->portc;
+ dmap_t *dmap = audio_engines[dev]->dmap_out;
+ int count = dmap->bytes_in_use;
+ oss_native_word playFormat;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ /* Set the sample rate converter */
+ WRITEL (BA0_DACSR, cs4281_rate (portc->speed));
+ playFormat = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ | (1 << 6);
+ if (portc->channels == 1) /* If stereo, */
+ playFormat |= DMRn_MONO; /* Turn on mono bit. */
+ if (portc->bits == 8) /* If 16-bit, */
+ playFormat |= (DMRn_SIZE8 | DMRn_USIGN); /* turn on 8-bit/unsigned. */
+ WRITEL (BA0_DMR0, playFormat); /* (150h) */
+ if (portc->channels == 2) /* If stereo, */
+ count /= 2; /* halve DMA count(stereo); */
+ if (portc->bits == 16) /* If 16-bit, */
+ count /= 2;
+ /* Set the physical play buffer address DMA0 Base & Current. */
+ WRITEL (BA0_DBA0, dmap->dmabuf_phys & ~0x3); /* (118h) */
+ /* Set the sample count(-1) in DMA Base Count register 0. */
+ WRITEL (BA0_DBC0, count - 1);
+ portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return 0;
+}
+
+static int
+cs4281_get_buffer_pointer (int dev, dmap_t * dmap, int direction)
+{
+ cs4281_devc *devc = audio_engines[dev]->devc;
+ unsigned int ptr = 0;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+
+ if (direction == PCM_ENABLE_OUTPUT)
+ {
+ ptr = READL (BA0_DCA0);
+ }
+ if (direction == PCM_ENABLE_INPUT)
+ {
+ ptr = READL (BA0_DCA1);
+ }
+ ptr -= dmap->dmabuf_phys;
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return ptr;
+}
+
+static audiodrv_t cs4281_audio_driver = {
+ cs4281_audio_open,
+ cs4281_audio_close,
+ cs4281_audio_output_block,
+ cs4281_audio_start_input,
+ cs4281_audio_ioctl,
+ cs4281_audio_prepare_for_input,
+ cs4281_audio_prepare_for_output,
+ cs4281_audio_reset,
+ NULL,
+ NULL,
+ cs4281_audio_reset_input,
+ cs4281_audio_reset_output,
+ cs4281_audio_trigger,
+ cs4281_audio_set_rate,
+ cs4281_audio_set_format,
+ cs4281_audio_set_channels,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* cs4281_alloc_buffer, */
+ NULL, /* cs4281_free_buffer, */
+ NULL,
+ NULL,
+ cs4281_get_buffer_pointer
+};
+
+/***********************MIDI PORT ROUTINES ****************/
+/*ARGSUSED*/
+static int
+cs4281_midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte,
+ oss_midi_inputbuf_t inputbuf,
+ oss_midi_outputintr_t outputintr)
+{
+ cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc;
+ if (devc->midi_opened)
+ {
+ return OSS_EBUSY;
+ }
+
+ devc->midi_input_intr = inputbyte;
+ devc->midi_opened = mode;
+ /* first reset the MIDI port */
+ WRITEL (BA0_MIDCR, 0x10);
+ WRITEL (BA0_MIDCR, 0x00);
+ /* Now check if we're in Read or Write mode */
+ if (mode & OPEN_READ)
+ {
+ /* enable MIDI Input intr and receive enable */
+ WRITEL (BA0_MIDCR, MIDCR_RXE | MIDCR_RIE);
+ }
+
+ if (mode & OPEN_WRITE)
+ {
+ /* enable MIDI transmit enable */
+ WRITEL (BA0_MIDCR, MIDCR_TXE);
+ }
+ return 0;
+}
+
+/*ARGSUSED*/
+static void
+cs4281_midi_close (int dev, int mode)
+{
+ cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc;
+/* Reset the device*/
+ WRITEL (BA0_MIDCR, 0x10);
+ WRITEL (BA0_MIDCR, 0x00);
+ devc->midi_opened = 0;
+}
+
+static int
+cs4281_midi_out (int dev, unsigned char midi_byte)
+{
+ cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc;
+ unsigned char uart_stat = READL (BA0_MIDSR);
+/* Check if Transmit buffer full flag is set - if so return */
+ if ((uart_stat & MIDSR_TBF))
+ return 0;
+/* Now put the MIDI databyte in the write port */
+ WRITEL (BA0_MIDWP, midi_byte);
+ return 1;
+}
+
+/*ARGSUSED*/
+static int
+cs4281_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+{
+ return OSS_EINVAL;
+}
+
+static midi_driver_t cs4281_midi_driver = {
+ cs4281_midi_open,
+ cs4281_midi_close,
+ cs4281_midi_ioctl,
+ cs4281_midi_out
+};
+
+static int
+init_cs4281 (cs4281_devc * devc)
+{
+
+ int my_mixer, i;
+ oss_native_word dwAC97SlotID, tmp1;
+ int first_dev = 0;
+/****************BEGIN HARDWARE INIT*****************/
+ /* Setup CFLR */
+ tmp1 = READL (BA0_CFLR);
+ if (tmp1 != 0x01)
+ {
+ WRITEL (BA0_CFLR, 0x01); /*set up AC97 mode */
+ tmp1 = READL (BA0_CFLR);
+ if (tmp1 != 0x01)
+ {
+ tmp1 = READL (BA0_CWPR);
+ if (tmp1 != 0x4281)
+ WRITEL (BA0_CWPR, 0x4281);
+ tmp1 = READL (BA0_CWPR);
+ if (tmp1 != 0x4281)
+ {
+ cmn_err (CE_WARN, "Resetting AC97 failed\n");
+ return OSS_EIO;
+ }
+ WRITEL (BA0_CFLR, 0x1);
+ tmp1 = READL (BA0_CFLR);
+ if (tmp1 != 0x1)
+ {
+ cmn_err (CE_WARN, "Resetting AC97 still fails\n");
+ return OSS_EIO;
+ }
+ }
+ }
+ /* Setup the FM and Joystick trap address for Legacy emulation */
+ WRITEL (BA0_IOTCR, 0x1);
+ WRITEL (BA0_IOTFM, 0xc0030388);
+ WRITEL (BA0_IOTGP, 0xc0070200);
+ /**************************************** */
+ /* Set up the Sound System Configuration */
+ /**************************************** */
+ /* Set the 'Configuration Write Protect' register */
+ /* to 4281h. Allows vendor-defined configuration */
+ /* space between 0e4h and 0ffh to be written. */
+ WRITEL (BA0_CWPR, 0x4281); /* (3e0h) */
+ if ((tmp1 = READL (BA0_SERC1)) != (SERC1_SO1EN | SERC1_SO1F_AC97))
+ {
+ cmn_err (CE_WARN, "SERC1: AC97 check failed\n");
+ return OSS_EIO;
+ }
+ /* setup power management to full power */
+ WRITEL (BA0_SSPM, 0x7E);
+ /* First, blast the clock control register to zero so that the */
+ /* PLL starts out in a known state, and blast the master serial */
+ /* port control register to zero so that the serial ports also */
+ /* start out in a known state. */
+ WRITEL (BA0_CLKCR1, 0); /* (400h) */
+ WRITEL (BA0_SERMC, 0); /* (420h) */
+ /* (1) Drive the ARST# pin low for a minimum of 1uS (as defined in */
+ /* the AC97 spec) and then drive it high. This is done for non */
+ /* AC97 modes since there might be logic external to the CS461x */
+ /* that uses the ARST# line for a reset. */
+ WRITEL (BA0_ACCTL, 0);
+ oss_udelay (50);
+ WRITEL (BA0_SPMC, 0); /* (3ech) */
+ oss_udelay (50);
+ WRITEL (BA0_SPMC, SPMC_RSTN);
+ oss_udelay (50000);
+ WRITEL (BA0_SERMC, SERMC_PTC_AC97 | SERMC_MSPE | 0x10000);
+ /* (3) Turn on the Sound System Clocks. */
+ WRITEL (BA0_CLKCR1, CLKCR1_DLLP); /* (400h) */
+ /* Wait for the PLL to stabilize. */
+ oss_udelay (50000);
+ /* Turn on clocking of the core (CLKCR1(400h) = 0x00000030) */
+ WRITEL (BA0_CLKCR1, CLKCR1_DLLP | CLKCR1_SWCE);
+ /* (5) Wait for clock stabilization. */
+ for (tmp1 = 0; tmp1 < 100; tmp1++)
+ {
+ if (READL (BA0_CLKCR1) & CLKCR1_DLLRDY)
+ break;
+ oss_udelay (50000);
+ }
+ if (!(READL (BA0_CLKCR1) & CLKCR1_DLLRDY))
+ {
+ cmn_err (CE_WARN, "DLLRDY Clock not ready\n");
+ return OSS_EIO;
+ }
+ /* (6) Enable ASYNC generation. */
+ WRITEL (BA0_ACCTL, ACCTL_ESYN); /* (460h) */
+ /* Now wait 'for a short while' to allow the AC97 */
+ /* part to start generating bit clock. (so we don't */
+ /* Try to start the PLL without an input clock.) */
+ /* (7) Wait for the codec ready signal from the AC97 codec. */
+ for (tmp1 = 0; tmp1 < 100; tmp1++)
+ {
+ /* Delay a mil to let things settle out and */
+ /* to prevent retrying the read too quickly. */
+ if (READL (BA0_ACSTS) & ACSTS_CRDY) /* If ready, (464h) */
+ break; /* exit the 'for' loop. */
+ oss_udelay (50000);
+ }
+ if (!(READL (BA0_ACSTS) & ACSTS_CRDY)) /* If never came ready, */
+ {
+ cmn_err (CE_WARN, "AC97 not ready\n");
+ return OSS_EIO; /* exit initialization. */
+ }
+ /* (8) Assert the 'valid frame' signal so we can */
+ /* begin sending commands to the AC97 codec. */
+ WRITEL (BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN); /* (460h) */
+
+ /* (11) Wait until we've sampled input slots 3 & 4 as valid, meaning */
+ /* that the codec is pumping ADC data across the AC link. */
+ for (tmp1 = 0; tmp1 < 100; tmp1++)
+ {
+ /* Read the input slot valid register; See */
+ /* if input slots 3 and 4 are valid yet. */
+ if ((READL (BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == /* (474h) */
+ (ACISV_ISV3 | ACISV_ISV4))
+ break; /* Exit the 'for' if slots are valid. */
+ oss_udelay (50000);
+ }
+ /* If we never got valid data, exit initialization. */
+ if ((READL (BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) !=
+ (ACISV_ISV3 | ACISV_ISV4))
+ {
+ cmn_err (CE_WARN, "AC97 Slot not valid\n");
+ return OSS_EIO; /* If no valid data, exit initialization. */
+ }
+ /* (12) Start digital data transfer of audio data to the codec. */
+ WRITEL (BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); /* (468h) */
+
+ /* For playback, we map AC97 slot 3 and 4(Left */
+ /* & Right PCM playback) to DMA Channel 0. */
+ /* Set the fifo to be 31 bytes at offset zero. */
+ dwAC97SlotID = 0x01001F00; /* FCR0.RS[4:0]=1(=>slot4, right PCM playback). */
+ /* FCR0.LS[4:0]=0(=>slot3, left PCM playback). */
+ /* FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. */
+ WRITEL (BA0_FCR0, dwAC97SlotID); /* (180h) */
+ WRITEL (BA0_FCR0, dwAC97SlotID | FCRn_FEN); /* Turn on FIFO Enable. */
+ /* For capture, we map AC97 slot 10 and 11(Left */
+ /* and Right PCM Record) to DMA Channel 1. */
+ /* Set the fifo to be 31 bytes at offset 32. */
+ dwAC97SlotID = 0x0B0A1F20; /* FCR1.RS[4:0]=11(=>slot11, right PCM record). */
+ /* FCR1.LS[4:0]=10(=>slot10, left PCM record). */
+ /* FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. */
+ WRITEL (BA0_FCR1, dwAC97SlotID); /* (184h) */
+ WRITEL (BA0_FCR1, dwAC97SlotID | FCRn_FEN); /* Turn on FIFO Enable. */
+ /* Map the Playback SRC to the same AC97 slots(3 & 4-- */
+ /* --Playback left & right)as DMA channel 0. */
+ /* Map the record SRC to the same AC97 slots(10 & 11-- */
+ /* -- Record left & right) as DMA channel 1. */
+ dwAC97SlotID = 0x0b0a0100; /*SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback). */
+ /*SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). */
+ /*SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) */
+ /*SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). */
+ WRITEL (BA0_SRCSA, dwAC97SlotID); /* (75ch) */
+ /* Set 'Half Terminal Count Interrupt Enable' and 'Terminal */
+ /* Count Interrupt Enable' in DMA Control Registers 0 & 1. */
+ /* Set 'MSK' flag to 1 to keep the DMA engines paused. */
+ tmp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK); /* (00030001h) */
+ WRITEL (BA0_DCR0, tmp1); /* (154h) */
+ WRITEL (BA0_DCR1, tmp1); /* (15ch) */
+ /* Set 'Auto-Initialize Control' to 'enabled'; For playback, */
+ /* set 'Transfer Type Control'(TR[1:0]) to 'read transfer', */
+ /* for record, set Transfer Type Control to 'write transfer'. */
+ /* All other bits set to zero; Some will be changed @ transfer start. */
+ tmp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); /* (20000018h) */
+ WRITEL (BA0_DMR0, tmp1); /* (150h) */
+ tmp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); /* (20000014h) */
+ WRITEL (BA0_DMR1, tmp1); /* (158h) */
+ /* Enable DMA interrupts generally, and */
+ /* DMA0 & DMA1 interrupts specifically. */
+ tmp1 = READL (BA0_HIMR) & 0x7fbbfcff;
+ WRITEL (BA0_HIMR, tmp1);
+ /* set up some volume defaults */
+ WRITEL (BA0_PPLVC, 0x0808);
+ WRITEL (BA0_PPRVC, 0x0808);
+ WRITEL (BA0_FMLVC, 0x0);
+ WRITEL (BA0_FMRVC, 0x0);
+/****** END OF HARDWARE INIT *****/
+
+
+ my_mixer =
+ ac97_install (&devc->ac97devc, "CS4281 AC97 Mixer", ac97_read, ac97_write,
+ devc, devc->osdev);
+ if (my_mixer < 0)
+ {
+ return 0;
+ }
+
+ devc->mixer_dev = my_mixer;
+
+ /* ac97_write(devc, 0x26, ac97_read(devc, 0x26) | 0x8000); */
+ for (i = 0; i < MAX_PORTC; i++)
+ {
+ int adev;
+ int caps = 0;
+ cs4281_portc *portc = &devc->portc[i];
+ char tmp_name[100];
+ strcpy (tmp_name, devc->chip_name);
+
+ if (i == 0)
+ {
+ caps = ADEV_AUTOMODE | ADEV_DUPLEX;
+ strcpy (tmp_name, devc->chip_name);
+ }
+ else
+ {
+ caps = ADEV_AUTOMODE | ADEV_DUPLEX | ADEV_SHADOW;
+ strcpy (tmp_name, devc->chip_name);
+ }
+
+ if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
+ devc->osdev,
+ devc->osdev,
+ tmp_name,
+ &cs4281_audio_driver,
+ sizeof (audiodrv_t),
+ caps,
+ AFMT_S16_LE | AFMT_U8, devc, -1)) < 0)
+ {
+ adev = -1;
+ return 0;
+ }
+ else
+ {
+ if (i == 0)
+ first_dev = adev;
+ audio_engines[adev]->portc = portc;
+ audio_engines[adev]->rate_source = first_dev;
+ audio_engines[adev]->mixer_dev = my_mixer;
+ audio_engines[adev]->min_rate = 6023;
+ audio_engines[adev]->max_rate = 48000;
+ audio_engines[adev]->caps |= PCM_CAP_FREERATE;
+ portc->open_mode = 0;
+ portc->audiodev = adev;
+ portc->audio_enabled = 0;
+#ifdef CONFIG_OSS_VMIX
+ if (i == 0)
+ vmix_attach_audiodev(devc->osdev, adev, -1, 0);
+#endif
+ }
+ }
+
+ devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "CS4281", "CS4281 MIDI Port", &cs4281_midi_driver, sizeof (midi_driver_t),
+ 0, devc, devc->osdev);
+ devc->midi_opened = 0;
+ return 1;
+}
+
+int
+oss_cs4281_attach (oss_device_t * osdev)
+{
+ unsigned char pci_irq_line, pci_revision, pci_irq_inta;
+ unsigned short pci_command, vendor, device;
+ unsigned int ioaddr;
+ int err;
+ cs4281_devc *devc;
+
+ DDB (cmn_err (CE_WARN, "Entered CS4281 probe routine\n"));
+
+ pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
+ pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
+
+ if (vendor != CRYSTAL_VENDOR_ID || device != CRYSTAL_CS4281_ID)
+ return 0;
+
+ if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
+ {
+ cmn_err (CE_WARN, "Out of memory\n");
+ return 0;
+ }
+
+ devc->osdev = osdev;
+ osdev->devc = devc;
+
+ oss_pci_byteswap (osdev, 1);
+
+ pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
+ pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
+ pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
+ pci_read_config_byte (osdev, PCI_INTERRUPT_LINE + 1, &pci_irq_inta);
+ pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &ioaddr);
+ devc->bar0addr = ioaddr;
+ pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_1, &ioaddr);
+ devc->bar1addr = ioaddr;
+
+ /* activate the device enable bus master/memory space */
+ pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_write_config_word (osdev, PCI_COMMAND, pci_command);
+
+ if ((devc->bar0addr == 0) || (devc->bar1addr == 0))
+ {
+ cmn_err (CE_WARN, "undefined MEMORY I/O address.\n");
+ return 0;
+ }
+
+ if (pci_irq_line == 0)
+ {
+ cmn_err (CE_WARN, "IRQ not assigned by BIOS.\n");
+ return 0;
+ }
+
+
+ /* Map the shared memory area */
+ devc->bar0virt =
+ (unsigned int *) MAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, 4 * 1024);
+ devc->bar1virt =
+ (unsigned int *) MAP_PCI_MEM (devc->osdev, 1, devc->bar1addr,
+ 1024 * 1024);
+ devc->dwRegister0 = devc->bar0virt;
+ devc->wRegister0 = (unsigned short *) devc->bar0virt;
+ devc->bRegister0 = (unsigned char *) devc->bar0virt;
+ devc->dwRegister1 = devc->bar1virt;
+ devc->wRegister1 = (unsigned short *) devc->bar1virt;
+ devc->bRegister1 = (unsigned char *) devc->bar1virt;
+
+ devc->chip_name = "CS4281";
+ devc->irq = pci_irq_line;
+ devc->open_mode = 0;
+
+ MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
+ MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);
+
+ oss_register_device (osdev, devc->chip_name);
+
+ if ((err = oss_register_interrupts (devc->osdev, 0, cs4281intr, NULL)) < 0)
+ {
+ cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err);
+ return 0;
+ }
+ return init_cs4281 (devc); /*Detected */
+}
+
+
+int
+oss_cs4281_detach (oss_device_t * osdev)
+{
+ cs4281_devc *devc = (cs4281_devc *) osdev->devc;
+
+ if (oss_disable_device (osdev) < 0)
+ return 0;
+
+ WRITEL (BA0_HICR, 0x02); /*enable intena */
+
+ oss_unregister_interrupts (devc->osdev);
+
+ MUTEX_CLEANUP (devc->mutex);
+ MUTEX_CLEANUP (devc->low_mutex);
+
+ UNMAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, devc->bar0virt, 4 * 1024);
+ UNMAP_PCI_MEM (devc->osdev, 1, devc->bar1addr, devc->bar1virt, 1024 * 1024);
+
+ devc->bar0addr = 0;
+ devc->bar1addr = 0;
+
+ oss_unregister_device (devc->osdev);
+ return 1;
+}
diff --git a/kernel/drv/oss_cs4281/oss_cs4281.man b/kernel/drv/oss_cs4281/oss_cs4281.man
new file mode 100644
index 0000000..7e19190
--- /dev/null
+++ b/kernel/drv/oss_cs4281/oss_cs4281.man
@@ -0,0 +1,21 @@
+NAME
+oss_cs4281 - Cirrus Logic CS4281 driver
+
+DESCRIPTION
+Open Sound System driver for Cirrus Logic (Crystal Semicoductor) CS4281 audio
+controller.
+
+CS4281 device characteristics:
+ o 8/16 bit playback/record
+ o mono/stereo playback/recording
+ o 8KHz to 48Khz sample rate.
+
+OPTIONS
+None
+
+FILES
+CONFIGFILEPATH/oss_cs4281.conf Device configuration file
+
+AUTHOR
+4Front Technologies
+