亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? sscape.c

?? linux 內(nèi)核源代碼
?? C
?? 第 1 頁 / 共 3 頁
字號:
/* *   Low-level ALSA driver for the ENSONIQ SoundScape PnP *   Copyright (c) by Chris Rankin * *   This driver was written in part using information obtained from *   the OSS/Free SoundScape driver, written by Hannu Savolainen. * * *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */#include <sound/driver.h>#include <linux/init.h>#include <linux/err.h>#include <linux/isa.h>#include <linux/delay.h>#include <linux/pnp.h>#include <linux/spinlock.h>#include <linux/moduleparam.h>#include <asm/dma.h>#include <sound/core.h>#include <sound/hwdep.h>#include <sound/cs4231.h>#include <sound/mpu401.h>#include <sound/initval.h>#include <sound/sscape_ioctl.h>MODULE_AUTHOR("Chris Rankin");MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver");MODULE_LICENSE("GPL");static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX;static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR;static long port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;static long wss_port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;static int dma2[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;module_param_array(index, int, NULL, 0444);MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");module_param_array(id, charp, NULL, 0444);MODULE_PARM_DESC(id, "Description for SoundScape card");module_param_array(port, long, NULL, 0444);MODULE_PARM_DESC(port, "Port # for SoundScape driver.");module_param_array(wss_port, long, NULL, 0444);MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver.");module_param_array(irq, int, NULL, 0444);MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver.");module_param_array(mpu_irq, int, NULL, 0444);MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");module_param_array(dma, int, NULL, 0444);MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");module_param_array(dma2, int, NULL, 0444);MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver.");#ifdef CONFIG_PNPstatic int isa_registered;static int pnp_registered;static struct pnp_card_device_id sscape_pnpids[] = {	{ .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */	{ .id = "ENS4081", .devs = { { "ENS1011" } } },	/* VIVO90 */	{ .id = "" }	/* end */};MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);#endif#define MPU401_IO(i)     ((i) + 0)#define MIDI_DATA_IO(i)  ((i) + 0)#define MIDI_CTRL_IO(i)  ((i) + 1)#define HOST_CTRL_IO(i)  ((i) + 2)#define HOST_DATA_IO(i)  ((i) + 3)#define ODIE_ADDR_IO(i)  ((i) + 4)#define ODIE_DATA_IO(i)  ((i) + 5)#define CODEC_IO(i)      ((i) + 8)#define IC_ODIE  1#define IC_OPUS  2#define RX_READY 0x01#define TX_READY 0x02#define CMD_ACK           0x80#define CMD_SET_MIDI_VOL  0x84#define CMD_GET_MIDI_VOL  0x85#define CMD_XXX_MIDI_VOL  0x86#define CMD_SET_EXTMIDI   0x8a#define CMD_GET_EXTMIDI   0x8b#define CMD_SET_MT32      0x8c#define CMD_GET_MT32      0x8denum GA_REG {	GA_INTSTAT_REG = 0,	GA_INTENA_REG,	GA_DMAA_REG,	GA_DMAB_REG,	GA_INTCFG_REG,	GA_DMACFG_REG,	GA_CDCFG_REG,	GA_SMCFGA_REG,	GA_SMCFGB_REG,	GA_HMCTL_REG};#define DMA_8BIT  0x80#define AD1845_FREQ_SEL_MSB    0x16#define AD1845_FREQ_SEL_LSB    0x17enum card_type {	SSCAPE,	SSCAPE_PNP,	SSCAPE_VIVO,};struct soundscape {	spinlock_t lock;	unsigned io_base;	unsigned wss_base;	int codec_type;	int ic_type;	enum card_type type;	struct resource *io_res;	struct resource *wss_res;	struct snd_cs4231 *chip;	struct snd_mpu401 *mpu;	struct snd_hwdep *hw;	/*	 * The MIDI device won't work until we've loaded	 * its firmware via a hardware-dependent device IOCTL	 */	spinlock_t fwlock;	int hw_in_use;	unsigned long midi_usage;	unsigned char midi_vol;};#define INVALID_IRQ  ((unsigned)-1)static inline struct soundscape *get_card_soundscape(struct snd_card *c){	return (struct soundscape *) (c->private_data);}static inline struct soundscape *get_mpu401_soundscape(struct snd_mpu401 * mpu){	return (struct soundscape *) (mpu->private_data);}static inline struct soundscape *get_hwdep_soundscape(struct snd_hwdep * hw){	return (struct soundscape *) (hw->private_data);}/* * Allocates some kernel memory that we can use for DMA. * I think this means that the memory has to map to * contiguous pages of physical memory. */static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned long size){	if (buf) {		if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),						 size, buf) < 0) {			snd_printk(KERN_ERR "sscape: Failed to allocate %lu bytes for DMA\n", size);			return NULL;		}	}	return buf;}/* * Release the DMA-able kernel memory ... */static void free_dmabuf(struct snd_dma_buffer *buf){	if (buf && buf->area)		snd_dma_free_pages(buf);}/* * This function writes to the SoundScape's control registers, * but doesn't do any locking. It's up to the caller to do that. * This is why this function is "unsafe" ... */static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsigned char val){	outb(reg, ODIE_ADDR_IO(io_base));	outb(val, ODIE_DATA_IO(io_base));}/* * Write to the SoundScape's control registers, and do the * necessary locking ... */static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char val){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	sscape_write_unsafe(s->io_base, reg, val);	spin_unlock_irqrestore(&s->lock, flags);}/* * Read from the SoundScape's control registers, but leave any * locking to the caller. This is why the function is "unsafe" ... */static inline unsigned char sscape_read_unsafe(unsigned io_base, enum GA_REG reg){	outb(reg, ODIE_ADDR_IO(io_base));	return inb(ODIE_DATA_IO(io_base));}/* * Puts the SoundScape into "host" mode, as compared to "MIDI" mode */static inline void set_host_mode_unsafe(unsigned io_base){	outb(0x0, HOST_CTRL_IO(io_base));}/* * Puts the SoundScape into "MIDI" mode, as compared to "host" mode */static inline void set_midi_mode_unsafe(unsigned io_base){	outb(0x3, HOST_CTRL_IO(io_base));}/* * Read the SoundScape's host-mode control register, but leave * any locking issues to the caller ... */static inline int host_read_unsafe(unsigned io_base){	int data = -1;	if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) {		data = inb(HOST_DATA_IO(io_base));	}	return data;}/* * Read the SoundScape's host-mode control register, performing * a limited amount of busy-waiting if the register isn't ready. * Also leaves all locking-issues to the caller ... */static int host_read_ctrl_unsafe(unsigned io_base, unsigned timeout){	int data;	while (((data = host_read_unsafe(io_base)) < 0) && (timeout != 0)) {		udelay(100);		--timeout;	} /* while */	return data;}/* * Write to the SoundScape's host-mode control registers, but * leave any locking issues to the caller ... */static inline int host_write_unsafe(unsigned io_base, unsigned char data){	if ((inb(HOST_CTRL_IO(io_base)) & TX_READY) != 0) {		outb(data, HOST_DATA_IO(io_base));		return 1;	}	return 0;}/* * Write to the SoundScape's host-mode control registers, performing * a limited amount of busy-waiting if the register isn't ready. * Also leaves all locking-issues to the caller ... */static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,                                  unsigned timeout){	int err;	while (!(err = host_write_unsafe(io_base, data)) && (timeout != 0)) {		udelay(100);		--timeout;	} /* while */	return err;}/* * Check that the MIDI subsystem is operational. If it isn't, * then we will hang the computer if we try to use it ... * * NOTE: This check is based upon observation, not documentation. */static inline int verify_mpu401(const struct snd_mpu401 * mpu){	return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80);}/* * This is apparently the standard way to initailise an MPU-401 */static inline void initialise_mpu401(const struct snd_mpu401 * mpu){	outb(0, MIDI_DATA_IO(mpu->port));}/* * Tell the SoundScape to activate the AD1845 chip (I think). * The AD1845 detection fails if we *don't* do this, so I * think that this is a good idea ... */static inline void activate_ad1845_unsafe(unsigned io_base){	sscape_write_unsafe(io_base, GA_HMCTL_REG, (sscape_read_unsafe(io_base, GA_HMCTL_REG) & 0xcf) | 0x10);	sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);}/* * Do the necessary ALSA-level cleanup to deallocate our driver ... */static void soundscape_free(struct snd_card *c){	struct soundscape *sscape = get_card_soundscape(c);	release_and_free_resource(sscape->io_res);	release_and_free_resource(sscape->wss_res);	free_dma(sscape->chip->dma1);}/* * Tell the SoundScape to begin a DMA tranfer using the given channel. * All locking issues are left to the caller. */static inline void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg){	sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) | 0x01);	sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) & 0xfe);}/* * Wait for a DMA transfer to complete. This is a "limited busy-wait", * and all locking issues are left to the caller. */static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned timeout){	while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) {		udelay(100);		--timeout;	} /* while */	return (sscape_read_unsafe(io_base, reg) & 0x01);}/* * Wait for the On-Board Processor to return its start-up * acknowledgement sequence. This wait is too long for * us to perform "busy-waiting", and so we must sleep. * This in turn means that we must not be holding any * spinlocks when we call this function. */static int obp_startup_ack(struct soundscape *s, unsigned timeout){	while (timeout != 0) {		unsigned long flags;		unsigned char x;		schedule_timeout_uninterruptible(1);		spin_lock_irqsave(&s->lock, flags);		x = inb(HOST_DATA_IO(s->io_base));		spin_unlock_irqrestore(&s->lock, flags);		if ((x & 0xfe) == 0xfe)			return 1;		--timeout;	} /* while */	return 0;}/* * Wait for the host to return its start-up acknowledgement * sequence. This wait is too long for us to perform * "busy-waiting", and so we must sleep. This in turn means * that we must not be holding any spinlocks when we call * this function. */static int host_startup_ack(struct soundscape *s, unsigned timeout){	while (timeout != 0) {		unsigned long flags;		unsigned char x;		schedule_timeout_uninterruptible(1);		spin_lock_irqsave(&s->lock, flags);		x = inb(HOST_DATA_IO(s->io_base));		spin_unlock_irqrestore(&s->lock, flags);		if (x == 0xfe)			return 1;		--timeout;	} /* while */	return 0;}/* * Upload a byte-stream into the SoundScape using DMA channel A. */static int upload_dma_data(struct soundscape *s,                           const unsigned char __user *data,                           size_t size){	unsigned long flags;	struct snd_dma_buffer dma;	int ret;	if (!get_dmabuf(&dma, PAGE_ALIGN(size)))		return -ENOMEM;	spin_lock_irqsave(&s->lock, flags);	/*	 * Reset the board ...	 */	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f);	/*	 * Enable the DMA channels and configure them ...	 */	sscape_write_unsafe(s->io_base, GA_DMACFG_REG, 0x50);	sscape_write_unsafe(s->io_base, GA_DMAA_REG, (s->chip->dma1 << 4) | DMA_8BIT);	sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);	/*	 * Take the board out of reset ...	 */	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80);	/*	 * Upload the user's data (firmware?) to the SoundScape	 * board through the DMA channel ...	 */	while (size != 0) {		unsigned long len;		/*		 * Apparently, copying to/from userspace can sleep.		 * We are therefore forbidden from holding any		 * spinlocks while we copy ...		 */		spin_unlock_irqrestore(&s->lock, flags);		/*		 * Remember that the data that we want to DMA		 * comes from USERSPACE. We have already verified		 * the userspace pointer ...		 */		len = min(size, dma.bytes);		len -= __copy_from_user(dma.area, data, len);		data += len;		size -= len;		/*		 * Grab that spinlock again, now that we've		 * finished copying!		 */		spin_lock_irqsave(&s->lock, flags);		snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);		sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);		if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {			/*			 * Don't forget to release this spinlock we're holding ...			 */			spin_unlock_irqrestore(&s->lock, flags);			snd_printk(KERN_ERR "sscape: DMA upload has timed out\n");			ret = -EAGAIN;			goto _release_dma;		}	} /* while */

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲精品第一国产综合野| 老司机精品视频在线| 不卡电影一区二区三区| 中文字幕欧美激情一区| 欧美日韩成人综合在线一区二区| 国产伦精品一区二区三区免费迷 | 久久综合九色综合97婷婷| 成人一区在线看| 久久99精品久久只有精品| 亚洲欧洲中文日韩久久av乱码| 日韩欧美电影一二三| 91福利国产成人精品照片| 国产自产2019最新不卡| 污片在线观看一区二区| 亚洲精品伦理在线| 国产亚洲欧美中文| 久久久国产午夜精品| 日韩欧美国产精品| 久久精品72免费观看| 亚洲成人在线免费| 亚洲成a人在线观看| 亚洲综合色网站| 成人亚洲一区二区一| 国产精品国产三级国产aⅴ中文 | 欧美日韩大陆一区二区| 91在线看国产| 国产成人免费xxxxxxxx| 亚洲尤物在线视频观看| 国产精品日日摸夜夜摸av| 久久日韩粉嫩一区二区三区| 精品国产免费人成在线观看| 日韩精品一区国产麻豆| 日韩欧美视频一区| 精品国产91乱码一区二区三区 | 蜜臀av亚洲一区中文字幕| 91麻豆swag| 精品一区二区三区av| 天天av天天翘天天综合网| 国产精品二区一区二区aⅴ污介绍| 欧美日韩一区三区| 欧美日韩精品一区二区天天拍小说| 99久久久久久99| 一本色道久久综合亚洲91| 不卡一区二区中文字幕| 在线一区二区三区| 在线精品视频免费观看| 五月婷婷综合网| 美女免费视频一区二区| 黄色精品一二区| 国产综合色产在线精品| 国产成人超碰人人澡人人澡| 成人一区二区三区视频| 一本一本久久a久久精品综合麻豆 一本一道波多野结衣一区二区 | 日韩精品中文字幕一区| 欧美视频精品在线| 欧美色视频在线| 日韩精品在线网站| 久久精品免费在线观看| 国产精品短视频| 亚洲精品美腿丝袜| 偷拍日韩校园综合在线| 国产在线精品免费av| 粉嫩嫩av羞羞动漫久久久| 国产一区二区三区免费播放| 99久久精品免费看国产| 成人精品国产一区二区4080| 欧美日韩一级二级三级| 久久综合给合久久狠狠狠97色69| 国产精品久久久久久久午夜片 | 成人午夜激情片| 亚洲愉拍自拍另类高清精品| 亚洲一区二区在线观看视频| 91农村精品一区二区在线| 欧美日韩中文另类| 久久久亚洲精品一区二区三区 | 欧美三级三级三级| wwwwxxxxx欧美| 亚洲品质自拍视频| 国产美女娇喘av呻吟久久| 欧美日韩三级一区二区| 欧美精品色一区二区三区| 国产精品丝袜在线| 日本不卡在线视频| 91色porny蝌蚪| 久久久午夜精品| 日韩一区精品视频| 国产成人精品午夜视频免费| 欧美日本国产视频| 一区二区三区在线观看欧美| 国产成人免费视频| 337p日本欧洲亚洲大胆精品| 视频一区欧美精品| 色综合色综合色综合| 国产欧美日韩精品一区| 狠狠色狠狠色综合| 欧美一级久久久久久久大片| 亚洲最新视频在线观看| 91原创在线视频| 久久夜色精品国产欧美乱极品| 亚洲福利国产精品| 色狠狠一区二区三区香蕉| 欧美经典一区二区| 国产精品 欧美精品| 日韩欧美一级二级三级| 午夜精品久久久久久不卡8050| 不卡区在线中文字幕| 国产欧美日韩中文久久| 国产精品1区2区| 久久噜噜亚洲综合| 国产黄人亚洲片| 中文字幕国产一区二区| www.日韩精品| 中文字幕在线播放不卡一区| 成人av影视在线观看| 日韩三级在线免费观看| 日本少妇一区二区| 日韩三级在线观看| 天天色天天爱天天射综合| 欧美日韩久久一区| 亚洲成人一二三| 日韩一区二区视频| 蜜桃av一区二区| 久久夜色精品一区| 国产91丝袜在线播放0| 国产精品电影一区二区| 在线视频你懂得一区二区三区| 亚洲一线二线三线视频| 4438x亚洲最大成人网| 青青草国产成人av片免费| 91精品国产综合久久精品| 久久99国内精品| 国产欧美日本一区视频| 91麻豆产精品久久久久久| 一区二区三区加勒比av| 制服.丝袜.亚洲.中文.综合| 精品中文字幕一区二区小辣椒| 久久免费国产精品| 国产成人久久精品77777最新版本 国产成人鲁色资源国产91色综 | 欧美日韩成人综合| 韩国av一区二区三区在线观看| 欧美日韩国产经典色站一区二区三区 | 国产精品欧美综合在线| 日本高清无吗v一区| 蜜桃一区二区三区在线| 国产精品亲子乱子伦xxxx裸| 在线观看免费视频综合| 精品一区二区免费在线观看| 中文字幕一区二区三区不卡 | 久久精品国产澳门| 日本一区二区三区视频视频| 欧美日韩国产另类不卡| 粉嫩一区二区三区在线看| 久久久久久久久久久电影| 在线欧美日韩精品| 国产精品自在在线| 亚洲国产精品尤物yw在线观看| 久久新电视剧免费观看| 色爱区综合激月婷婷| 97久久超碰精品国产| 国产成人啪免费观看软件| 国产久卡久卡久卡久卡视频精品| 日韩电影在线免费看| 亚洲小说欧美激情另类| 一区二区三区**美女毛片| 中文字幕亚洲综合久久菠萝蜜| 久久久久久麻豆| 精品免费99久久| 精品免费一区二区三区| 精品国产麻豆免费人成网站| 欧美一二三在线| 欧美大片日本大片免费观看| 欧美一卡二卡在线观看| 欧美成人精精品一区二区频| 日韩欧美在线影院| 日韩精品一区二区三区在线观看 | 奇米四色…亚洲| 香蕉乱码成人久久天堂爱免费| 亚洲日本在线a| 亚洲曰韩产成在线| 午夜成人在线视频| 免费在线观看一区| 久久精品国内一区二区三区| 精品一区二区三区免费播放| 国产伦理精品不卡| a亚洲天堂av| 欧洲精品视频在线观看| 欧美日韩电影在线| 精品国产伦一区二区三区观看体验 | 日韩高清在线一区| 麻豆91免费观看| 国产美女一区二区三区| 成人一区二区三区| 欧美性大战久久| 精品国产亚洲一区二区三区在线观看| 91精品久久久久久蜜臀| 久久久久国产精品厨房| 亚洲欧美日韩成人高清在线一区| 亚洲精品中文在线| 麻豆精品精品国产自在97香蕉| 国产精品中文字幕一区二区三区|