📄 dmasound_core.c
字号:
* will be set so long as the shared resources have no owner. */ if (shared_resource_owner == 0) { dmasound.soft = dmasound.mach.default_soft ; dmasound.hard = dmasound.mach.default_hard ; dmasound.dsp = dmasound.mach.default_soft ; shared_resources_initialised = 0 ; } return 0 ;} /* * /dev/sndstat *//* we allow more space for record-enabled because there are extra output lines. the number here must include the amount we are prepared to give to the low-level driver.*/#ifdef HAS_RECORD#define STAT_BUFF_LEN 1024#else#define STAT_BUFF_LEN 768#endif/* this is how much space we will allow the low-level driver to use in the stat buffer. Currently, 2 * (80 character line + <NL>). We do not police this (it is up to the ll driver to be honest).*/#define LOW_LEVEL_STAT_ALLOC 162static struct { int busy; char buf[STAT_BUFF_LEN]; /* state.buf should not overflow! */ int len, ptr;} state;/* publish this function for use by low-level code, if required */char *get_afmt_string(int afmt){ switch(afmt) { case AFMT_MU_LAW: return "mu-law"; break; case AFMT_A_LAW: return "A-law"; break; case AFMT_U8: return "unsigned 8 bit"; break; case AFMT_S8: return "signed 8 bit"; break; case AFMT_S16_BE: return "signed 16 bit BE"; break; case AFMT_U16_BE: return "unsigned 16 bit BE"; break; case AFMT_S16_LE: return "signed 16 bit LE"; break; case AFMT_U16_LE: return "unsigned 16 bit LE"; break; case 0: return "format not set" ; break ; default: break ; } return "ERROR: Unsupported AFMT_XXXX code" ;}static int state_open(struct inode *inode, struct file *file){ char *buffer = state.buf; int len = 0; if (state.busy) return -EBUSY; if (!try_module_get(dmasound.mach.owner)) return -ENODEV; state.ptr = 0; state.busy = 1; len += sprintf(buffer+len, "%sDMA sound driver rev %03d :\n", dmasound.mach.name, (DMASOUND_CORE_REVISION<<4) + ((dmasound.mach.version>>8) & 0x0f)); len += sprintf(buffer+len, "Core driver edition %02d.%02d : %s driver edition %02d.%02d\n", DMASOUND_CORE_REVISION, DMASOUND_CORE_EDITION, dmasound.mach.name2, (dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ; /* call the low-level module to fill in any stat info. that it has if present. Maximum buffer usage is specified. */ if (dmasound.mach.state_info) len += dmasound.mach.state_info(buffer+len, (size_t) LOW_LEVEL_STAT_ALLOC) ; /* make usage of the state buffer as deterministic as poss. exceptional conditions could cause overrun - and this is flagged as a kernel error. */ /* formats and settings */ len += sprintf(buffer+len,"\t\t === Formats & settings ===\n") ; len += sprintf(buffer+len,"Parameter %20s%20s\n","soft","hard") ; len += sprintf(buffer+len,"Format :%20s%20s\n", get_afmt_string(dmasound.soft.format), get_afmt_string(dmasound.hard.format)); len += sprintf(buffer+len,"Samp Rate:%14d s/sec%14d s/sec\n", dmasound.soft.speed, dmasound.hard.speed); len += sprintf(buffer+len,"Channels :%20s%20s\n", dmasound.soft.stereo ? "stereo" : "mono", dmasound.hard.stereo ? "stereo" : "mono" ); /* sound queue status */ len += sprintf(buffer+len,"\t\t === Sound Queue status ===\n"); len += sprintf(buffer+len,"Allocated:%8s%6s\n","Buffers","Size") ; len += sprintf(buffer+len,"%9s:%8d%6d\n", "write", write_sq.numBufs, write_sq.bufSize) ;#ifdef HAS_RECORD if (dmasound.mach.record) len += sprintf(buffer+len,"%9s:%8d%6d\n", "read", read_sq.numBufs, read_sq.bufSize) ;#endif len += sprintf(buffer+len, "Current : MaxFrg FragSiz MaxAct Frnt Rear " "Cnt RrSize A B S L xruns\n") ; len += sprintf(buffer+len,"%9s:%7d%8d%7d%5d%5d%4d%7d%2d%2d%2d%2d%7d\n", "write", write_sq.max_count, write_sq.block_size, write_sq.max_active, write_sq.front, write_sq.rear, write_sq.count, write_sq.rear_size, write_sq.active, write_sq.busy, write_sq.syncing, write_sq.locked, write_sq.xruns) ;#ifdef HAS_RECORD if (dmasound.mach.record) len += sprintf(buffer+len,"%9s:%7d%8d%7d%5d%5d%4d%7d%2d%2d%2d%2d%7d\n", "read", read_sq.max_count, read_sq.block_size, read_sq.max_active, read_sq.front, read_sq.rear, read_sq.count, read_sq.rear_size, read_sq.active, read_sq.busy, read_sq.syncing, read_sq.locked, read_sq.xruns) ;#endif#ifdef DEBUG_DMASOUNDprintk("dmasound: stat buffer used %d bytes\n", len) ;#endif if (len >= STAT_BUFF_LEN) printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n"); state.len = len; return 0;}static int state_release(struct inode *inode, struct file *file){ lock_kernel(); state.busy = 0; module_put(dmasound.mach.owner); unlock_kernel(); return 0;}static ssize_t state_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){ int n = state.len - state.ptr; if (n > count) n = count; if (n <= 0) return 0; if (copy_to_user(buf, &state.buf[state.ptr], n)) return -EFAULT; state.ptr += n; return n;}static struct file_operations state_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = state_read, .open = state_open, .release = state_release,};static int state_init(void){#ifndef MODULE int state_unit;#endif state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); if (state_unit < 0) return state_unit ; state.busy = 0; return 0 ;} /* * Config & Setup * * This function is called by _one_ chipset-specific driver */int dmasound_init(void){ int res ;#ifdef MODULE if (irq_installed) return -EBUSY;#endif /* Set up sound queue, /dev/audio and /dev/dsp. */ /* Set default settings. */ if ((res = sq_init()) < 0) return res ; /* Set up /dev/sndstat. */ if ((res = state_init()) < 0) return res ; /* Set up /dev/mixer. */ mixer_init(); if (!dmasound.mach.irqinit()) { printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); return -ENODEV; }#ifdef MODULE irq_installed = 1;#endif printk(KERN_INFO "%s DMA sound driver rev %03d installed\n", dmasound.mach.name, (DMASOUND_CORE_REVISION<<4) + ((dmasound.mach.version>>8) & 0x0f)); printk(KERN_INFO "Core driver edition %02d.%02d : %s driver edition %02d.%02d\n", DMASOUND_CORE_REVISION, DMASOUND_CORE_EDITION, dmasound.mach.name2, (dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ; printk(KERN_INFO "Write will use %4d fragments of %7d bytes as default\n", numWriteBufs, writeBufSize) ;#ifdef HAS_RECORD if (dmasound.mach.record) printk(KERN_INFO "Read will use %4d fragments of %7d bytes as default\n", numReadBufs, readBufSize) ;#endif return 0;}#ifdef MODULEvoid dmasound_deinit(void){ if (irq_installed) { sound_silence(); dmasound.mach.irqcleanup(); irq_installed = 0; } write_sq_release_buffers(); read_sq_release_buffers(); if (mixer_unit >= 0) unregister_sound_mixer(mixer_unit); if (state_unit >= 0) unregister_sound_special(state_unit); if (sq_unit >= 0) unregister_sound_dsp(sq_unit);}#else /* !MODULE */static int dmasound_setup(char *str){ int ints[6], size; str = get_options(str, ARRAY_SIZE(ints), ints); /* check the bootstrap parameter for "dmasound=" */ /* FIXME: other than in the most naive of cases there is no sense in these * buffers being other than powers of two. This is not checked yet. */ switch (ints[0]) {#ifdef HAS_RECORD case 5: if ((ints[5] < 0) || (ints[5] > MAX_CATCH_RADIUS)) printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); else catchRadius = ints[5]; /* fall through */ case 4: if (ints[4] < MIN_BUFFERS) printk("dmasound_setup: invalid number of read buffers, using default = %d\n", numReadBufs); else numReadBufs = ints[4]; /* fall through */ case 3: if ((size = ints[3]) < 256) /* check for small buffer specs */ size <<= 10 ; if (size < MIN_BUFSIZE || size > MAX_BUFSIZE) printk("dmasound_setup: invalid read buffer size, using default = %d\n", readBufSize); else readBufSize = size; /* fall through */#else case 3: if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); else catchRadius = ints[3]; /* fall through */#endif case 2: if (ints[1] < MIN_BUFFERS) printk("dmasound_setup: invalid number of buffers, using default = %d\n", numWriteBufs); else numWriteBufs = ints[1]; /* fall through */ case 1: if ((size = ints[2]) < 256) /* check for small buffer specs */ size <<= 10 ; if (size < MIN_BUFSIZE || size > MAX_BUFSIZE) printk("dmasound_setup: invalid write buffer size, using default = %d\n", writeBufSize); else writeBufSize = size; case 0: break; default: printk("dmasound_setup: invalid number of arguments\n"); return 0; } return 1;}__setup("dmasound=", dmasound_setup);#endif /* !MODULE */ /* * Conversion tables */#ifdef HAS_8BIT_TABLES/* 8 bit mu-law */char dmasound_ulaw2dma8[] = { -126, -122, -118, -114, -110, -106, -102, -98, -94, -90, -86, -82, -78, -74, -70, -66, -63, -61, -59, -57, -55, -53, -51, -49, -47, -45, -43, -41, -39, -37, -35, -33, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -16, -15, -15, -14, -14, -13, -13, -12, -12, -11, -11, -10, -10, -9, -9, -8, -8, -8, -7, -7, -7, -7, -6, -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, -4, -4, -4, -3, -3, -3, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 125, 121, 117, 113, 109, 105, 101, 97, 93, 89, 85, 81, 77, 73, 69, 65, 62, 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* 8 bit A-law */char dmasound_alaw2dma8[] = { -22, -21, -24, -23, -18, -17, -20, -19, -30, -29, -32, -31, -26, -25, -28, -27, -11, -11, -12, -12, -9, -9, -10, -10, -15, -15, -16, -16, -13, -13, -14, -14, -86, -82, -94, -90, -70, -66, -78, -74, -118, -114, -126, -122, -102, -98, -110, -106, -43, -41, -47, -45, -35, -33, -39, -37, -59, -57, -63, -61, -51, -49, -55, -53, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -6, -6, -6, -6, -5, -5, -5, -5, -8, -8, -8, -8, -7, -7, -7, -7, -3, -3, -3, -3, -3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, 21, 20, 23, 22, 17, 16, 19, 18, 29, 28, 31, 30, 25, 24, 27, 26, 10, 10, 11, 11, 8, 8, 9, 9, 14, 14, 15, 15, 12, 12, 13, 13, 86, 82, 94, 90, 70, 66, 78, 74, 118, 114, 126, 122, 102, 98, 110, 106, 43, 41, 47, 45, 35, 33, 39, 37, 59, 57, 63, 61, 51, 49, 55, 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 4, 4, 4, 4, 7, 7, 7, 7, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3};#endif /* HAS_8BIT_TABLES */ /* * Visible symbols for modules */EXPORT_SYMBOL(dmasound);EXPORT_SYMBOL(dmasound_init);#ifdef MODULEEXPORT_SYMBOL(dmasound_deinit);#endifEXPORT_SYMBOL(dmasound_write_sq);#ifdef HAS_RECORDEXPORT_SYMBOL(dmasound_read_sq);#endifEXPORT_SYMBOL(dmasound_catchRadius);#ifdef HAS_8BIT_TABLESEXPORT_SYMBOL(dmasound_ulaw2dma8);EXPORT_SYMBOL(dmasound_alaw2dma8);#endifEXPORT_SYMBOL(get_afmt_string) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -