⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sonicvibes.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************//* *      sonicvibes.c  --  S3 Sonic Vibes audio driver. * *      Copyright (C) 1998-2001  Thomas Sailer (t.sailer@alumni.ethz.ch) * *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. * *      This program is distributed in the hope that it will be useful, *      but WITHOUT ANY WARRANTY; without even the implied warranty of *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *      GNU General Public License for more details. * *      You should have received a copy of the GNU General Public License *      along with this program; if not, write to the Free Software *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Special thanks to David C. Niemi * * * Module command line parameters: *   none so far * * *  Supported devices: *  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible *  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible *  /dev/midi   simple MIDI UART interface, no ioctl * *  The card has both an FM and a Wavetable synth, but I have to figure *  out first how to drive them... * *  Revision history *    06.05.1998   0.1   Initial release *    10.05.1998   0.2   Fixed many bugs, esp. ADC rate calculation *                       First stab at a simple midi interface (no bells&whistles) *    13.05.1998   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of *                       set_dac_rate in the FMODE_WRITE case in sv_open *                       Fix hwptr out of bounds (now mpg123 works) *    14.05.1998   0.4   Don't allow excessive interrupt rates *    08.06.1998   0.5   First release using Alan Cox' soundcore instead of miscdevice *    03.08.1998   0.6   Do not include modversions.h *                       Now mixer behaviour can basically be selected between *                       "OSS documented" and "OSS actual" behaviour *    31.08.1998   0.7   Fix realplayer problems - dac.count issues *    10.12.1998   0.8   Fix drain_dac trying to wait on not yet initialized DMA *    16.12.1998   0.9   Fix a few f_file & FMODE_ bugs *    06.01.1999   0.10  remove the silly SA_INTERRUPT flag. *                       hopefully killed the egcs section type conflict *    12.03.1999   0.11  cinfo.blocks should be reset after GETxPTR ioctl. *                       reported by Johan Maes <joma@telindus.be> *    22.03.1999   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK *                       read/write cannot be executed *    05.04.1999   0.13  added code to sv_read and sv_write which should detect *                       lockups of the sound chip and revive it. This is basically *                       an ugly hack, but at least applications using this driver *                       won't hang forever. I don't know why these lockups happen, *                       it might well be the motherboard chipset (an early 486 PCI *                       board with ALI chipset), since every busmastering 100MB *                       ethernet card I've tried (Realtek 8139 and Macronix tulip clone) *                       exhibit similar behaviour (they work for a couple of packets *                       and then lock up and can be revived by ifconfig down/up). *    07.04.1999   0.14  implemented the following ioctl's: SOUND_PCM_READ_RATE,  *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;  *                       Alpha fixes reported by Peter Jones <pjones@redhat.com> *                       Note: dmaio hack might still be wrong on archs other than i386 *    15.06.1999   0.15  Fix bad allocation bug. *                       Thanks to Deti Fliegl <fliegl@in.tum.de> *    28.06.1999   0.16  Add pci_set_master *    03.08.1999   0.17  adapt to Linus' new __setup/__initcall *                       added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr" *    12.08.1999   0.18  module_init/__setup fixes *    24.08.1999   0.19  get rid of the dmaio kludge, replace with allocate_resource *    31.08.1999   0.20  add spin_lock_init *                       use new resource allocation to allocate DDMA IO space *                       replaced current->state = x with set_current_state(x) *    03.09.1999   0.21  change read semantics for MIDI to match *                       OSS more closely; remove possible wakeup race *    28.10.1999   0.22  More waitqueue races fixed *    01.12.1999   0.23  New argument to allocate_resource *    07.12.1999   0.24  More allocate_resource semantics change *    08.01.2000   0.25  Prevent some ioctl's from returning bad count values on underrun/overrun; *                       Tim Janik's BSE (Bedevilled Sound Engine) found this *                       use Martin Mares' pci_assign_resource *    07.02.2000   0.26  Use pci_alloc_consistent and pci_register_driver *    21.11.2000   0.27  Initialize dma buffers in poll, otherwise poll may return a bogus mask *    12.12.2000   0.28  More dma buffer initializations, patch from *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com> *    31.01.2001   0.29  Register/Unregister gameport *                       Fix SETTRIGGER non OSS API conformity *    18.05.2001   0.30  PCI probing and error values cleaned up by Marcus *                       Meissner <mm@caldera.de> * *//*****************************************************************************/      #include <linux/version.h>#include <linux/module.h>#include <linux/string.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/sound.h>#include <linux/slab.h>#include <linux/soundcard.h>#include <linux/pci.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/smp_lock.h>#include <linux/wrapper.h>#include <asm/uaccess.h>#include <asm/hardirq.h>#include <linux/gameport.h>#include "dm.h"/* --------------------------------------------------------------------- */#undef OSS_DOCUMENTED_MIXER_SEMANTICS/* --------------------------------------------------------------------- */#ifndef PCI_VENDOR_ID_S3#define PCI_VENDOR_ID_S3             0x5333#endif#ifndef PCI_DEVICE_ID_S3_SONICVIBES#define PCI_DEVICE_ID_S3_SONICVIBES  0xca00#endif#define SV_MAGIC  ((PCI_VENDOR_ID_S3<<16)|PCI_DEVICE_ID_S3_SONICVIBES)#define SV_EXTENT_SB      0x10#define SV_EXTENT_ENH     0x10#define SV_EXTENT_SYNTH   0x4#define SV_EXTENT_MIDI    0x4#define SV_EXTENT_GAME    0x8#define SV_EXTENT_DMA     0x10/* * we are not a bridge and thus use a resource for DDMA that is used for bridges but * left empty for normal devices */#define RESOURCE_SB       0#define RESOURCE_ENH      1#define RESOURCE_SYNTH    2#define RESOURCE_MIDI     3#define RESOURCE_GAME     4#define RESOURCE_DDMA     7#define SV_MIDI_DATA      0#define SV_MIDI_COMMAND   1#define SV_MIDI_STATUS    1#define SV_DMA_ADDR0      0#define SV_DMA_ADDR1      1#define SV_DMA_ADDR2      2#define SV_DMA_ADDR3      3#define SV_DMA_COUNT0     4#define SV_DMA_COUNT1     5#define SV_DMA_COUNT2     6#define SV_DMA_MODE       0xb#define SV_DMA_RESET      0xd#define SV_DMA_MASK       0xf/* * DONT reset the DMA controllers unless you understand * the reset semantics. Assuming reset semantics as in * the 8237 does not work. */#define DMA_MODE_AUTOINIT 0x10#define DMA_MODE_READ     0x44    /* I/O to memory, no autoinit, increment, single mode */#define DMA_MODE_WRITE    0x48    /* memory to I/O, no autoinit, increment, single mode */#define SV_CODEC_CONTROL  0#define SV_CODEC_INTMASK  1#define SV_CODEC_STATUS   2#define SV_CODEC_IADDR    4#define SV_CODEC_IDATA    5#define SV_CCTRL_RESET      0x80#define SV_CCTRL_INTADRIVE  0x20#define SV_CCTRL_WAVETABLE  0x08#define SV_CCTRL_REVERB     0x04#define SV_CCTRL_ENHANCED   0x01#define SV_CINTMASK_DMAA    0x01#define SV_CINTMASK_DMAC    0x04#define SV_CINTMASK_SPECIAL 0x08#define SV_CINTMASK_UPDOWN  0x40#define SV_CINTMASK_MIDI    0x80#define SV_CSTAT_DMAA       0x01#define SV_CSTAT_DMAC	    0x04#define SV_CSTAT_SPECIAL    0x08#define SV_CSTAT_UPDOWN	    0x40#define SV_CSTAT_MIDI	    0x80#define SV_CIADDR_TRD       0x80#define SV_CIADDR_MCE       0x40/* codec indirect registers */#define SV_CIMIX_ADCINL     0x00#define SV_CIMIX_ADCINR     0x01#define SV_CIMIX_AUX1INL    0x02#define SV_CIMIX_AUX1INR    0x03#define SV_CIMIX_CDINL      0x04#define SV_CIMIX_CDINR      0x05#define SV_CIMIX_LINEINL    0x06#define SV_CIMIX_LINEINR    0x07#define SV_CIMIX_MICIN      0x08#define SV_CIMIX_SYNTHINL   0x0A#define SV_CIMIX_SYNTHINR   0x0B#define SV_CIMIX_AUX2INL    0x0C#define SV_CIMIX_AUX2INR    0x0D#define SV_CIMIX_ANALOGINL  0x0E#define SV_CIMIX_ANALOGINR  0x0F#define SV_CIMIX_PCMINL     0x10#define SV_CIMIX_PCMINR     0x11#define SV_CIGAMECONTROL    0x09#define SV_CIDATAFMT        0x12#define SV_CIENABLE         0x13#define SV_CIUPDOWN         0x14#define SV_CIREVISION       0x15#define SV_CIADCOUTPUT      0x16#define SV_CIDMAABASECOUNT1 0x18#define SV_CIDMAABASECOUNT0 0x19#define SV_CIDMACBASECOUNT1 0x1c#define SV_CIDMACBASECOUNT0 0x1d#define SV_CIPCMSR0         0x1e#define SV_CIPCMSR1         0x1f#define SV_CISYNTHSR0       0x20#define SV_CISYNTHSR1       0x21#define SV_CIADCCLKSOURCE   0x22#define SV_CIADCALTSR       0x23#define SV_CIADCPLLM        0x24#define SV_CIADCPLLN        0x25#define SV_CISYNTHPLLM      0x26#define SV_CISYNTHPLLN      0x27#define SV_CIUARTCONTROL    0x2a#define SV_CIDRIVECONTROL   0x2b#define SV_CISRSSPACE       0x2c#define SV_CISRSCENTER      0x2d#define SV_CIWAVETABLESRC   0x2e#define SV_CIANALOGPWRDOWN  0x30#define SV_CIDIGITALPWRDOWN 0x31#define SV_CIMIX_ADCSRC_CD     0x20#define SV_CIMIX_ADCSRC_DAC    0x40#define SV_CIMIX_ADCSRC_AUX2   0x60#define SV_CIMIX_ADCSRC_LINE   0x80#define SV_CIMIX_ADCSRC_AUX1   0xa0#define SV_CIMIX_ADCSRC_MIC    0xc0#define SV_CIMIX_ADCSRC_MIXOUT 0xe0#define SV_CIMIX_ADCSRC_MASK   0xe0#define SV_CFMT_STEREO     0x01#define SV_CFMT_16BIT      0x02#define SV_CFMT_MASK       0x03#define SV_CFMT_ASHIFT     0   #define SV_CFMT_CSHIFT     4static const unsigned sample_size[] = { 1, 2, 2, 4 };static const unsigned sample_shift[] = { 0, 1, 1, 2 };#define SV_CENABLE_PPE     0x4#define SV_CENABLE_RE      0x2#define SV_CENABLE_PE      0x1/* MIDI buffer sizes */#define MIDIINBUF  256#define MIDIOUTBUF 256#define FMODE_MIDI_SHIFT 2#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)#define FMODE_DMFM 0x10/* --------------------------------------------------------------------- */struct sv_state {	/* magic */	unsigned int magic;	/* list of sonicvibes devices */	struct list_head devs;	/* the corresponding pci_dev structure */	struct pci_dev *dev;	/* soundcore stuff */	int dev_audio;	int dev_mixer;	int dev_midi;	int dev_dmfm;	/* hardware resources */	unsigned long iosb, ioenh, iosynth, iomidi;  /* long for SPARC */	unsigned int iodmaa, iodmac, irq;        /* mixer stuff */        struct {                unsigned int modcnt;#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS		unsigned short vol[13];#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */        } mix;	/* wave stuff */	unsigned int rateadc, ratedac;	unsigned char fmt, enable;	spinlock_t lock;	struct semaphore open_sem;	mode_t open_mode;	wait_queue_head_t open_wait;	struct dmabuf {		void *rawbuf;		dma_addr_t dmaaddr;		unsigned buforder;		unsigned numfrag;		unsigned fragshift;		unsigned hwptr, swptr;		unsigned total_bytes;		int count;		unsigned error; /* over/underrun */		wait_queue_head_t wait;		/* redundant, but makes calculations easier */		unsigned fragsize;		unsigned dmasize;		unsigned fragsamples;		/* OSS stuff */		unsigned mapped:1;		unsigned ready:1;		unsigned endcleared:1;		unsigned enabled:1;		unsigned ossfragshift;		int ossmaxfrags;		unsigned subdivision;	} dma_dac, dma_adc;	/* midi stuff */	struct {		unsigned ird, iwr, icnt;		unsigned ord, owr, ocnt;		wait_queue_head_t iwait;		wait_queue_head_t owait;		struct timer_list timer;		unsigned char ibuf[MIDIINBUF];		unsigned char obuf[MIDIOUTBUF];	} midi;	struct gameport gameport;};/* --------------------------------------------------------------------- */static LIST_HEAD(devs);static unsigned long wavetable_mem = 0;/* --------------------------------------------------------------------- */static inline unsigned ld2(unsigned int x){	unsigned r = 0;		if (x >= 0x10000) {		x >>= 16;		r += 16;	}	if (x >= 0x100) {		x >>= 8;		r += 8;	}	if (x >= 0x10) {		x >>= 4;		r += 4;	}	if (x >= 4) {		x >>= 2;		r += 2;	}	if (x >= 2)		r++;	return r;}/* * hweightN: returns the hamming weight (i.e. the number * of bits set) of a N-bit word */#ifdef hweight32#undef hweight32#endifstatic inline unsigned int hweight32(unsigned int w){        unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);        res = (res & 0x33333333) + ((res >> 2) & 0x33333333);        res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);        res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);        return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);}/* --------------------------------------------------------------------- *//* * Why use byte IO? Nobody knows, but S3 does it also in their Windows driver. */#undef DMABYTEIOstatic void set_dmaa(struct sv_state *s, unsigned int addr, unsigned int count){#ifdef DMABYTEIO	unsigned io = s->iodmaa, u;	count--;	for (u = 4; u > 0; u--, addr >>= 8, io++)		outb(addr & 0xff, io);	for (u = 3; u > 0; u--, count >>= 8, io++)		outb(count & 0xff, io);#else /* DMABYTEIO */	count--;	outl(addr, s->iodmaa + SV_DMA_ADDR0);	outl(count, s->iodmaa + SV_DMA_COUNT0);#endif /* DMABYTEIO */	outb(0x18, s->iodmaa + SV_DMA_MODE);}static void set_dmac(struct sv_state *s, unsigned int addr, unsigned int count){#ifdef DMABYTEIO	unsigned io = s->iodmac, u;	count >>= 1;	count--;	for (u = 4; u > 0; u--, addr >>= 8, io++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -