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

📄 dmasound_atari.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/sound/oss/dmasound/dmasound_atari.c * *  Atari TT and Falcon DMA Sound Driver * *  See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits *  prior to 28/01/2001 * *  28/01/2001 [0.1] Iain Sandoe *		     - added versioning *		     - put in and populated the hardware_afmts field. *             [0.2] - put in SNDCTL_DSP_GETCAPS value. *  01/02/2001 [0.3] - put in default hard/soft settings. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/soundcard.h>#include <linux/mm.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <asm/atariints.h>#include <asm/atari_stram.h>#include "dmasound.h"#define DMASOUND_ATARI_REVISION 0#define DMASOUND_ATARI_EDITION 3extern void atari_microwire_cmd(int cmd);static int is_falcon;static int write_sq_ignore_int;	/* ++TeSche: used for Falcon */static int expand_bal;	/* Balance factor for expanding (not volume!) */static int expand_data;	/* Data for expanding *//*** Translations ************************************************************//* ++TeSche: radically changed for new expanding purposes... * * These two routines now deal with copying/expanding/translating the samples * from user space into our buffer at the right frequency. They take care about * how much data there's actually to read, how much buffer space there is and * to convert samples into the right frequency/encoding. They will only work on * complete samples so it may happen they leave some bytes in the input stream * if the user didn't write a multiple of the current sample size. They both * return the number of bytes they've used from both streams so you may detect * such a situation. Luckily all programs should be able to cope with that. * * I think I've optimized anything as far as one can do in plain C, all * variables should fit in registers and the loops are really short. There's * one loop for every possible situation. Writing a more generalized and thus * parameterized loop would only produce slower code. Feel free to optimize * this in assembler if you like. :) * * I think these routines belong here because they're not yet really hardware * independent, especially the fact that the Falcon can play 16bit samples * only in stereo is hardcoded in both of them! * * ++geert: split in even more functions (one per format) */static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,			  u_char frame[], ssize_t *frameUsed,			  ssize_t frameLeft);static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,			 u_char frame[], ssize_t *frameUsed,			 ssize_t frameLeft);static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,			 u_char frame[], ssize_t *frameUsed,			 ssize_t frameLeft);static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft);static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft);static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft);static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft);static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,			   u_char frame[], ssize_t *frameUsed,			   ssize_t frameLeft);static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,			  u_char frame[], ssize_t *frameUsed,			  ssize_t frameLeft);static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,			  u_char frame[], ssize_t *frameUsed,			  ssize_t frameLeft);static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,			     u_char frame[], ssize_t *frameUsed,			     ssize_t frameLeft);static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,			     u_char frame[], ssize_t *frameUsed,			     ssize_t frameLeft);static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,			     u_char frame[], ssize_t *frameUsed,			     ssize_t frameLeft);static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,			     u_char frame[], ssize_t *frameUsed,			     ssize_t frameLeft);/*** Low level stuff *********************************************************/static void *AtaAlloc(unsigned int size, int flags);static void AtaFree(void *, unsigned int size);static int AtaIrqInit(void);#ifdef MODULEstatic void AtaIrqCleanUp(void);#endif /* MODULE */static int AtaSetBass(int bass);static int AtaSetTreble(int treble);static void TTSilence(void);static void TTInit(void);static int TTSetFormat(int format);static int TTSetVolume(int volume);static int TTSetGain(int gain);static void FalconSilence(void);static void FalconInit(void);static int FalconSetFormat(int format);static int FalconSetVolume(int volume);static void AtaPlayNextFrame(int index);static void AtaPlay(void);static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp);/*** Mid level stuff *********************************************************/static void TTMixerInit(void);static void FalconMixerInit(void);static int AtaMixerIoctl(u_int cmd, u_long arg);static int TTMixerIoctl(u_int cmd, u_long arg);static int FalconMixerIoctl(u_int cmd, u_long arg);static int AtaWriteSqSetup(void);static int AtaSqOpen(mode_t mode);static int TTStateInfo(char *buffer, size_t space);static int FalconStateInfo(char *buffer, size_t space);/*** Translations ************************************************************/static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,			  u_char frame[], ssize_t *frameUsed,			  ssize_t frameLeft){	char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8							  : dmasound_alaw2dma8;	ssize_t count, used;	u_char *p = &frame[*frameUsed];	count = min_t(unsigned long, userCount, frameLeft);	if (dmasound.soft.stereo)		count &= ~1;	used = count;	while (count > 0) {		u_char data;		if (get_user(data, userPtr++))			return -EFAULT;		*p++ = table[data];		count--;	}	*frameUsed += used;	return used;}static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,			 u_char frame[], ssize_t *frameUsed,			 ssize_t frameLeft){	ssize_t count, used;	void *p = &frame[*frameUsed];	count = min_t(unsigned long, userCount, frameLeft);	if (dmasound.soft.stereo)		count &= ~1;	used = count;	if (copy_from_user(p, userPtr, count))		return -EFAULT;	*frameUsed += used;	return used;}static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,			 u_char frame[], ssize_t *frameUsed,			 ssize_t frameLeft){	ssize_t count, used;	if (!dmasound.soft.stereo) {		u_char *p = &frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft);		used = count;		while (count > 0) {			u_char data;			if (get_user(data, userPtr++))				return -EFAULT;			*p++ = data ^ 0x80;			count--;		}	} else {		u_short *p = (u_short *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>1;		used = count*2;		while (count > 0) {			u_short data;			if (get_user(data, ((u_short *)userPtr)++))				return -EFAULT;			*p++ = data ^ 0x8080;			count--;		}	}	*frameUsed += used;	return used;}static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft){	ssize_t count, used;	if (!dmasound.soft.stereo) {		u_short *p = (u_short *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>1;		used = count*2;		while (count > 0) {			u_short data;			if (get_user(data, ((u_short *)userPtr)++))				return -EFAULT;			*p++ = data;			*p++ = data;			count--;		}		*frameUsed += used*2;	} else {		void *p = (u_short *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft) & ~3;		used = count;		if (copy_from_user(p, userPtr, count))			return -EFAULT;		*frameUsed += used;	}	return used;}static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft){	ssize_t count, used;	if (!dmasound.soft.stereo) {		u_short *p = (u_short *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>1;		used = count*2;		while (count > 0) {			u_short data;			if (get_user(data, ((u_short *)userPtr)++))				return -EFAULT;			data ^= 0x8000;			*p++ = data;			*p++ = data;			count--;		}		*frameUsed += used*2;	} else {		u_long *p = (u_long *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>2;		used = count*4;		while (count > 0) {			u_long data;			if (get_user(data, ((u_int *)userPtr)++))				return -EFAULT;			*p++ = data ^ 0x80008000;			count--;		}		*frameUsed += used;	}	return used;}static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft){	ssize_t count, used;	count = frameLeft;	if (!dmasound.soft.stereo) {		u_short *p = (u_short *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>1;		used = count*2;		while (count > 0) {			u_short data;			if (get_user(data, ((u_short *)userPtr)++))				return -EFAULT;			data = le2be16(data);			*p++ = data;			*p++ = data;			count--;		}		*frameUsed += used*2;	} else {		u_long *p = (u_long *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>2;		used = count*4;		while (count > 0) {			u_long data;			if (get_user(data, ((u_int *)userPtr)++))				return -EFAULT;			data = le2be16dbl(data);			*p++ = data;			count--;		}		*frameUsed += used;	}	return used;}static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,			    u_char frame[], ssize_t *frameUsed,			    ssize_t frameLeft){	ssize_t count, used;	count = frameLeft;	if (!dmasound.soft.stereo) {		u_short *p = (u_short *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>1;		used = count*2;		while (count > 0) {			u_short data;			if (get_user(data, ((u_short *)userPtr)++))				return -EFAULT;			data = le2be16(data) ^ 0x8000;			*p++ = data;			*p++ = data;		}		*frameUsed += used*2;	} else {		u_long *p = (u_long *)&frame[*frameUsed];		count = min_t(unsigned long, userCount, frameLeft)>>2;		used = count;		while (count > 0) {			u_long data;			if (get_user(data, ((u_int *)userPtr)++))				return -EFAULT;			data = le2be16dbl(data) ^ 0x80008000;			*p++ = data;			count--;		}		*frameUsed += used;	}	return used;}static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,			   u_char frame[], ssize_t *frameUsed,			   ssize_t frameLeft){	char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8							  : dmasound_alaw2dma8;	/* this should help gcc to stuff everything into registers */	long bal = expand_bal;	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;	ssize_t used, usedf;	used = userCount;	usedf = frameLeft;	if (!dmasound.soft.stereo) {		u_char *p = &frame[*frameUsed];		u_char data = expand_data;		while (frameLeft) {			u_char c;			if (bal < 0) {				if (!userCount)					break;				if (get_user(c, userPtr++))					return -EFAULT;				data = table[c];				userCount--;				bal += hSpeed;			}			*p++ = data;			frameLeft--;			bal -= sSpeed;		}		expand_data = data;	} else {		u_short *p = (u_short *)&frame[*frameUsed];		u_short data = expand_data;		while (frameLeft >= 2) {			u_char c;			if (bal < 0) {				if (userCount < 2)					break;				if (get_user(c, userPtr++))					return -EFAULT;				data = table[c] << 8;				if (get_user(c, userPtr++))					return -EFAULT;				data |= table[c];				userCount -= 2;				bal += hSpeed;			}			*p++ = data;			frameLeft -= 2;			bal -= sSpeed;		}		expand_data = data;	}	expand_bal = bal;	used -= userCount;	*frameUsed += usedf-frameLeft;	return used;}static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,			  u_char frame[], ssize_t *frameUsed,			  ssize_t frameLeft){	/* this should help gcc to stuff everything into registers */	long bal = expand_bal;	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;	ssize_t used, usedf;	used = userCount;	usedf = frameLeft;	if (!dmasound.soft.stereo) {		u_char *p = &frame[*frameUsed];		u_char data = expand_data;		while (frameLeft) {			if (bal < 0) {				if (!userCount)					break;				if (get_user(data, userPtr++))					return -EFAULT;				userCount--;				bal += hSpeed;			}			*p++ = data;			frameLeft--;			bal -= sSpeed;		}		expand_data = data;	} else {		u_short *p = (u_short *)&frame[*frameUsed];		u_short data = expand_data;		while (frameLeft >= 2) {			if (bal < 0) {				if (userCount < 2)					break;				if (get_user(data, ((u_short *)userPtr)++))					return -EFAULT;				userCount -= 2;				bal += hSpeed;			}			*p++ = data;			frameLeft -= 2;			bal -= sSpeed;		}		expand_data = data;	}	expand_bal = bal;	used -= userCount;	*frameUsed += usedf-frameLeft;	return used;}static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,			  u_char frame[], ssize_t *frameUsed,			  ssize_t frameLeft){	/* this should help gcc to stuff everything into registers */	long bal = expand_bal;	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;	ssize_t used, usedf;	used = userCount;	usedf = frameLeft;	if (!dmasound.soft.stereo) {		u_char *p = &frame[*frameUsed];		u_char data = expand_data;		while (frameLeft) {			if (bal < 0) {				if (!userCount)					break;				if (get_user(data, userPtr++))					return -EFAULT;				data ^= 0x80;				userCount--;				bal += hSpeed;			}			*p++ = data;			frameLeft--;			bal -= sSpeed;		}		expand_data = data;	} else {		u_short *p = (u_short *)&frame[*frameUsed];		u_short data = expand_data;		while (frameLeft >= 2) {			if (bal < 0) {				if (userCount < 2)					break;				if (get_user(data, ((u_short *)userPtr)++))					return -EFAULT;				data ^= 0x8080;				userCount -= 2;				bal += hSpeed;			}			*p++ = data;			frameLeft -= 2;

⌨️ 快捷键说明

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