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

📄 at2041_inf.c.bak

📁 这个是Linux下的关于2042的程序
💻 BAK
字号:
/* *  Copyright(C) 2004, Pentamicro Inc. All Right Reserved.            *                                       *  Filename    :  at2041_inf.c *  Description :  Linux device driver of AT2041 *                      *  Project     :  MPEG-4 4-channel SDVR *                              *  Date        :  Apr., 20. 2004. *  Company     :  Advanced Technology R&D Center *                 Pentamicro Inc. *    *  Linux version      :   */             /** ************************************************************************* **  ** includes ** ************************************************************************* **/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <linux/ioctl.h>#include <linux/major.h>#include <linux/delay.h>#include <asm/errno.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/delay.h>#include "at2041_inf.h"unsigned short *      mux_buf[MAX_BUF_NUM];unsigned short *      demux_buf[MAX_BUF_NUM];unsigned short *      tx_buf[MAX_TXBUF_NUM];unsigned short *      size_buf[MAX_BUF_NUM];unsigned int          demux_size_buf[MAX_BUF_NUM];volatile unsigned short        enc_txmsg_size = 4;volatile static unsigned short mux_ring_cnt = 0;volatile static unsigned short mux_rd_cnt = 0;volatile static unsigned short mux_wr_cnt = 0; volatile static unsigned short mux_full = 0;volatile static unsigned short demux_ring_cnt = 0;volatile static unsigned short demux_rd_cnt = 0;volatile static unsigned short demux_wr_cnt = 0; volatile static unsigned short txfifo_rd_cnt = 0;volatile static unsigned short txfifo_wr_cnt = 0;volatile static unsigned short txfifo_ring_cnt = 0;static struct semaphore muxfifo_read_sem;static struct semaphore demuxfifo_write_sem;unsigned short * pt;unsigned int ii;/** ************************************************************************* **  ** forward declarations ** ************************************************************************* **/void at2041_ioctl_init() {	int count;	unsigned short status;	unsigned short temp;		printk("\t!!! AT2041 driver initialized... ");		/* check tx fifo empty */// test for swparkprintk("[at2041_inf]at2041_ioctl_init start\n");	count = 0;	do {		status = *((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR));		count ++;		udelay(10);	}while ((status & 0x100) && (count < 1000));// test for swparkprintk("[at2041_inf]check status register\n");	if (count == 1000) {		printk("ERROR !!!\n");	} else {		// test for swparkprintk("[at2041_inf]success check status register\n");		/* data read from Tx_FIFO of the AT2041 */		temp = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));		if (temp != 0x8003) {			printk("\n!!! the AT2041 Ready Error !!!\n");		}				/* TxACK command */		*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;				printk("Complete !!!\n");	}}int at2041_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	unsigned short rx_fifo;	unsigned short cmd_reg, status_reg;// test for swparkprintk("[at2041_inf]start at2041_ioctl : cmd= %d\n", cmd);		switch(cmd) {		case READ_Tx_FIFO :			put_user(*tx_buf[txfifo_rd_cnt], (unsigned short *) arg);						/* txfifo ring buffer control */			if (!txfifo_ring_cnt && txfifo_rd_cnt <= txfifo_wr_cnt) {				txfifo_rd_cnt ++;				if (txfifo_rd_cnt == MAX_BUF_NUM) {					txfifo_ring_cnt --;					txfifo_rd_cnt = 0;				}			} else if (txfifo_ring_cnt) {				txfifo_rd_cnt ++;			}			break; 		case WRITE_Rx_FIFO :			get_user(rx_fifo, (unsigned short *)arg);			*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = rx_fifo;			break;			case WRITE_COMMAND_REG :			get_user(cmd_reg, (unsigned short *)arg);			*((unsigned short *)((unsigned int)pt + AT2041_COMMAND_REG_ADDR)) = cmd_reg;			break;	// swpark//		case WRITE_CONTROL_REG ://			get_user(ctrl_reg, (unsigned short *)arg);//			*((unsigned short *)((unsigned int)pt + 0x00002800)) = ctrl_reg;//			break;	         		case READ_STATUS_REG :			status_reg = *((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR));			put_user(status_reg, (unsigned short *) arg);			break;  		case AT2041_INIT :			at2041_ioctl_init();			break;					default :			break; 	}	return 0;}static ssize_t muxfifo_read(struct file *file, char *buffer,size_t length,loff_t * offset) {	/* copy mux_buf to user space */	/* real transfer size is size_buf[mux_rd_cnt] * 256bit.	 * third parameter of copy_to_user() is the 'byte' number to transfer	 * so, it's calculated size_buf[mux_rd_cnt] * 32	 */	unsigned int size;		down(&muxfifo_read_sem);		size = (*size_buf[mux_rd_cnt] << 5) + (enc_txmsg_size << 1);	copy_to_user(buffer, mux_buf[mux_rd_cnt], size);				/* multiplex ring buffer control */	if (!mux_ring_cnt && mux_rd_cnt <= mux_wr_cnt) {		mux_rd_cnt ++;		if (mux_rd_cnt == MAX_BUF_NUM) {			mux_ring_cnt --;			mux_rd_cnt = 0;		}	} else if (mux_ring_cnt) {		mux_rd_cnt ++;		if (mux_rd_cnt == MAX_BUF_NUM) {			mux_ring_cnt --;						mux_rd_cnt = 0;		}			}	if (mux_full) {		/* acknowledge for data ready message */		*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8803;					mux_full = 0;	}				return 0;}static ssize_t demuxfifo_write(struct file *file,const char *buffer, size_t length, loff_t * offset){	down(&demuxfifo_write_sem);	copy_from_user(demux_buf[demux_wr_cnt], buffer, length);		demux_size_buf[demux_wr_cnt] = length;			/* de-multiplex ring buffer control */	if (!demux_ring_cnt) {		demux_wr_cnt ++;		if (demux_wr_cnt == MAX_BUF_NUM) {			demux_ring_cnt ++;			demux_wr_cnt = 0;		}	} else if (demux_ring_cnt && demux_wr_cnt < demux_rd_cnt) {		demux_wr_cnt ++;	}		return 0;}static int at2041_open(struct inode* inode, struct file* filp){	printk("the AT2041 Open!!!\n");	MOD_INC_USE_COUNT;	return 0;}static int at2041_release(struct inode* inode, struct file* filp){	printk("the AT2041 Release!!!\n"); 	MOD_DEC_USE_COUNT;	return 0;}/* the AT2041 file operations */#if 0static struct file_operations at2041_fops = {	read:   	muxfifo_read,	write:  	demuxfifo_write,	ioctl:		at2041_ioctl,	open:		at2041_open,	release: 	at2041_release,};#elsestruct file_operations device_fops = {	NULL,	read:		muxfifo_read,	write:	demuxfifo_write,	NULL,	ioctl:		at2041_ioctl,	NULL,	open:		at2041_open,	NULL,	release:	at2041_release};#endifstatic void at2041_interrupt_handle(int irq, void *dev_id, struct pt_regs * regs){	unsigned short tx_data;	unsigned short temp;	unsigned int data_size = 0;			/* data read from Tx_FIFO of the AT2041 */	tx_data = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));	/* check whether first tx message is 'data ready message' 	 * or 'data request message'	 */	if (tx_data == 0x8803) {		/* if first tx message is 'data ready message', 		 * read three tx message sequentially.		 * the contents of second tx_message are 'data type', 'channel ID',		 * 'skip', 'loss' and 'output buffer full', etc.		 */		/* check tx fifo empty */		if ( !(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100) ) {			/* read the second parameter of Tx_FIFO */			mux_buf[mux_wr_cnt][0] = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));		} else {			printk("[saa7146] It can't read tx0 register\n");						/* TxACK command */			*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;			}					if ( !(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100) ) {			/* read the third parameter of Tx_FIFO */			/* the contents of the third tx_message are 'output data size' */					mux_buf[mux_wr_cnt][1] = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));		} else {			printk("[saa7146] It can't read tx1 register\n");						/* TxACK command */			*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;		}				if ( !(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100) ) {			/* read the fourth parameter of Tx_FIFO */			/* the contents of the fourth tx_message are 'reserved' */					mux_buf[mux_wr_cnt][2] = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));		} else {			printk("[saa7146] It can't read tx2 register\n");		}								/* calculate data size to transfer */		*size_buf[mux_wr_cnt] = mux_buf[mux_wr_cnt][1];		data_size = ((*size_buf[mux_wr_cnt] & 0xffff) << 4) + enc_txmsg_size;					/* data read from multiplex FIFO of the AT2041 */		/* write multiplex data from the AT2041 to d/d's buffer */		for (ii = enc_txmsg_size; ii < data_size; ii ++) {			mux_buf[mux_wr_cnt][ii] = *((unsigned short *)((unsigned int)pt + AT2041_MUX_FIFO_ADDR));		}		up(&muxfifo_read_sem);							/* multiplex ring buffer control */		if (!mux_ring_cnt) {			mux_wr_cnt ++;							if (mux_wr_cnt == MAX_BUF_NUM) {				mux_ring_cnt ++;								mux_wr_cnt = 0;			}		} else if (mux_ring_cnt && mux_wr_cnt < mux_rd_cnt) {			mux_wr_cnt ++;						} else {			printk("!!![MUX][%02d][%02d][%02d]\n", mux_wr_cnt, mux_rd_cnt, mux_ring_cnt);		}		/* TxACK command */		*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;			if (mux_ring_cnt && mux_wr_cnt == mux_rd_cnt) {			mux_full = 1;			printk("!!!!!!!! MUX FULL !!!!!!!!!\n");		} else {			/* acknowledge for data ready message */			*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8803;								}	}	else if (tx_data == 0x9003) {  /* data write to de-multiplex FIFO of the AT2041 */		if (!demux_ring_cnt && (demux_wr_cnt == demux_rd_cnt)) {			/* check tx fifo empty */			if (!(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100)) {				/* txfifo ring buffer control */				temp = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));			} else {				printk("[saa7146] It can't read tx0 register\n");							/* TxACK command */				*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;			}							/* TxACK command */			*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;						/* acknowledge for data request message */			*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x9003;						return;		}		/* check tx fifo empty */		if (!(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100)) {			/* txfifo ring buffer control */			temp = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));		} else {			printk("[saa7146] It can't read tx0 register\n");						*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;		}					/* write de-multiplex data from d/d's buffer to the AT2041 */		for (ii = 0; ii < (demux_size_buf[demux_rd_cnt] + 256) / 2; ii ++) {			*((unsigned short *)((unsigned int)pt + AT2041_DEMUX_FIFO_ADDR)) = demux_buf[demux_rd_cnt][ii];		}		/* de-multiplex ring buffer control */		if (!demux_ring_cnt && demux_rd_cnt <= demux_wr_cnt) {			demux_rd_cnt ++;			if (demux_rd_cnt == MAX_BUF_NUM) {				demux_ring_cnt --;				demux_rd_cnt = 0;			}		} else if (demux_ring_cnt) {			demux_rd_cnt ++;			if (demux_rd_cnt == MAX_BUF_NUM) {				demux_ring_cnt --;				demux_rd_cnt = 0;			}						}				up(&demuxfifo_write_sem);		/* TxACK command */		*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;				/* acknowledge for data request message */		*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x9003;				}	else {		/* TxACK command */		*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003;		}}int at2041_init_module(void){	int ret, kk;		pt = (unsigned short *)ioremap(AT2041BASE, AT2041REMAP_SIZE);	printk("init_at2041 %p\n",pt);	ret = register_chrdev(AT2041_MAJOR, "at2041", &at2041_fops);	init_MUTEX_LOCKED(&muxfifo_read_sem);	sema_init(&demuxfifo_write_sem, MAX_BUF_NUM);			if (ret < 0) {		printk("at2041: at2041 register failed\n");		return ret;	}		/* mux_buf & demux_buf allocation */	for (kk = 0; kk < MAX_BUF_NUM; kk ++){		if (!(mux_buf[kk] = (unsigned short *) kmalloc(MAX_BUF_SIZE + (enc_txmsg_size << 1), GFP_KERNEL))) {			printk("AT2041 : mux_buf kmalloc failed...\n");			return -ENOMEM;		}		if (!(demux_buf[kk] = (unsigned short *) kmalloc(MAX_BUF_SIZE, GFP_KERNEL))) {			printk("AT2041 : demux_buf kmalloc failed...\n");			return -ENOMEM;		}		if (!(size_buf[kk] = (unsigned short *) vmalloc(sizeof(unsigned short)))) {			printk("AT2041 : size_buf kmalloc failed...\n");			return -ENOMEM;		}	}	printk("the AT2041 driver initialized...\n");		/* AT2041_IRQ = 27, Fast interrupt, No interrupt sharing */	if(request_irq(AT2041_IRQ, at2041_interrupt_handle, SA_INTERRUPT, "at2041", NULL)) {		printk(KERN_ERR "at2041 : cannot register IRQ %d\n", AT2041_IRQ);		return -EIO;	}	return 0;}void at2041_cleanup_module(void){	volatile int ret;		free_irq(AT2041_IRQ, NULL);	ret = unregister_chrdev(AT2041_MAJOR, "at2041");	if (ret < 0) {		printk("at2041: at2041 unregister failed\n");		return;	}	for (ii = 0; ii < MAX_BUF_NUM; ii ++) {		kfree(mux_buf[ii]);		kfree(demux_buf[ii]);		vfree(size_buf[ii]);	}	iounmap((void *)pt);	ret = unregister_chrdev(AT2041_MAJOR, "at2041");	if (ret < 0) {		printk("at2041: at2041 unregister failed\n");		return;	}	printk("at2041: at2041 unloaded\n");	return;}module_init(at2041_init_module);module_exit(at2041_cleanup_module);

⌨️ 快捷键说明

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