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

📄 sync_serial.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		avail = end - start;	else 		avail = port->in_buffer_size - (start - end);	return avail;}static inline int sync_data_avail_to_end(struct sync_port *port){	int avail;	unsigned char *start;	unsigned char *end;		start = (unsigned char*)port->readp; /* cast away volatile */	end = (unsigned char*)port->writep;  /* cast away volatile */	/* 0123456789  0123456789	 *  -----           -----	 *  ^rp  ^wp    ^wp ^rp	 */	          	if (end >= start)		avail = end - start;	else 		avail = port->in_buffer + port->in_buffer_size - start;	return avail;}static int sync_serial_open(struct inode *inode, struct file *file){	int dev = MINOR(inode->i_rdev);	sync_port* port;	int mode;		DEBUG(printk("Open sync serial port %d\n", dev));   	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	/* Allow open this device twice (assuming one reader and one writer) */	if (port->busy == 2) 	{		DEBUG(printk("Device is busy.. \n"));		return -EBUSY;	}	port->busy++;	/* Start port if we use it as input */	mode = IO_EXTRACT(R_SYNC_SERIAL1_CTRL, mode, port->ctrl_data_shadow);	if (mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_input) ||	    mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_input) ||	    mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_bidir) ||	    mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_bidir)) {		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, enable);		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, enable);		port->started = 1;		*port->ctrl_data = port->ctrl_data_shadow;		if (!port->use_dma)			*R_IRQ_MASK1_SET = 1 << port->data_avail_bit;		DEBUG(printk("sser%d rec started\n", dev)); 	}			return 0;}static int sync_serial_release(struct inode *inode, struct file *file){	int dev = MINOR(inode->i_rdev);	sync_port* port;	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	if (port->busy)		port->busy--;	if (!port->busy) 		*R_IRQ_MASK1_CLR = ((1 << port->data_avail_bit) |				    (1 << port->transmitter_ready_bit));	return 0;}static unsigned int sync_serial_poll(struct file *file, poll_table *wait){	int dev = MINOR(file->f_dentry->d_inode->i_rdev);	unsigned int mask = 0;	sync_port* port;	DEBUGPOLL( static unsigned int prev_mask = 0; );		port = &ports[dev];	poll_wait(file, &port->out_wait_q, wait);	poll_wait(file, &port->in_wait_q, wait);	/* Some room to write */	if (port->out_count < OUT_BUFFER_SIZE)		mask |=  POLLOUT | POLLWRNORM;	/* At least an inbufchunk of data */	if (sync_data_avail(port) >= port->inbufchunk)		mask |= POLLIN | POLLRDNORM;		DEBUGPOLL(if (mask != prev_mask)	      printk("sync_serial_poll: mask 0x%08X %s %s\n", mask,		     mask&POLLOUT?"POLLOUT":"", mask&POLLIN?"POLLIN":"");	      prev_mask = mask;	      );	return mask;}static int sync_serial_ioctl(struct inode *inode, struct file *file,		  unsigned int cmd, unsigned long arg){	int return_val = 0;	unsigned long flags;		int dev = MINOR(file->f_dentry->d_inode->i_rdev);	sync_port* port;        	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -1;	}        port = &ports[dev];	save_flags(flags);	cli();	/* Disable port while changing config */	if (dev)	{		if (port->use_dma) {			RESET_DMA(4); WAIT_DMA(4);			*R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |				IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);		}		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);	}	else	{		if (port->use_dma) {					RESET_DMA(8); WAIT_DMA(8);			*R_DMA_CH8_CLR_INTR = IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |				IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do);		}		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);	}	*R_GEN_CONFIG_II = gen_config_ii_shadow;	restore_flags(flags);	switch(cmd)	{	case SSP_SPEED:		if (GET_SPEED(arg) == CODEC)		{			if (dev)				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec);			else				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec);						SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, prescaler, GET_FREQ(arg));			SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, frame_rate, GET_FRAME_RATE(arg));			SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, word_rate, GET_WORD_RATE(arg));		}		else		{			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_baud, GET_SPEED(arg));			if (dev)				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, baudrate);			else				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, baudrate);		}		break;	case SSP_MODE:		if (arg > 5)			return -EINVAL;		if (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT)			*R_IRQ_MASK1_CLR = 1 << port->data_avail_bit;		else if (!port->use_dma)			*R_IRQ_MASK1_SET = 1 << port->data_avail_bit;		SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg);		break;	case SSP_FRAME_SYNC:		if (arg & NORMAL_SYNC)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);		else if (arg & EARLY_SYNC)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, early);				if (arg & BIT_SYNC)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, bit);		else if (arg & WORD_SYNC)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);		else if (arg & EXTENDED_SYNC)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, extended);				if (arg & SYNC_ON)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);		else if (arg & SYNC_OFF)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, off);				if (arg & WORD_SIZE_8)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);		else if (arg & WORD_SIZE_12)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size12bit);		else if (arg & WORD_SIZE_16)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size16bit);		else if (arg & WORD_SIZE_24)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size24bit);		else if (arg & WORD_SIZE_32)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size32bit);				if (arg & BIT_ORDER_MSB)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);		else if (arg & BIT_ORDER_LSB)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, lsb);				if (arg & FLOW_CONTROL_ENABLE)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled);		else if (arg & FLOW_CONTROL_DISABLE)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);				if (arg & CLOCK_NOT_GATED)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, normal);		else if (arg & CLOCK_GATED)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, gated);    				break;	case SSP_IPOLARITY:		/* NOTE!! negedge is considered NORMAL */		if (arg & CLOCK_NORMAL)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);		else if (arg & CLOCK_INVERT)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, pos);				if (arg & FRAME_NORMAL)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, normal);		else if (arg & FRAME_INVERT)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);				if (arg & STATUS_NORMAL)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, normal);		else if (arg & STATUS_INVERT)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, inverted);		break;	case SSP_OPOLARITY:		if (arg & CLOCK_NORMAL)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, normal);		else if (arg & CLOCK_INVERT)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);				if (arg & FRAME_NORMAL)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, normal);		else if (arg & FRAME_INVERT)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);				if (arg & STATUS_NORMAL)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, normal);		else if (arg & STATUS_INVERT)			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, inverted);		break;	case SSP_SPI:		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);		if (arg & SPI_SLAVE)		{			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, SLAVE_INPUT);		}		else		{			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, MASTER_OUTPUT);		}		break;	case SSP_INBUFCHUNK:		if (arg > port->in_buffer_size/NUM_IN_DESCR)			return -EINVAL;		port->inbufchunk = arg;		/* Make sure in_buffer_size is a multiple of inbufchunk */		port->in_buffer_size = (port->in_buffer_size/port->inbufchunk) * port->inbufchunk;		DEBUG(printk("inbufchunk %i in_buffer_size: %i\n", port->inbufchunk, port->in_buffer_size));		if (port->use_dma) {			if (port->port_nbr == 0) {				RESET_DMA(9);				WAIT_DMA(9);			} else {				RESET_DMA(5);				WAIT_DMA(5);			}			start_dma_in(port);		}		break;	default:		return_val = -1;	}	/* Make sure we write the config without interruption */	save_flags(flags);	cli();		/* Set config and enable port */	*port->ctrl_data = port->ctrl_data_shadow;	nop(); nop(); nop(); nop();	*R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow;	nop(); nop(); nop(); nop();	if (dev)		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);	else		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);	*R_GEN_CONFIG_II = gen_config_ii_shadow;	restore_flags(flags);		return return_val;}static ssize_t sync_serial_write(struct file * file, const char * buf,                                  size_t count, loff_t *ppos){	int dev = MINOR(file->f_dentry->d_inode->i_rdev);	DECLARE_WAITQUEUE(wait, current);		sync_port *port;	unsigned long flags;	unsigned long c, c1;	unsigned long free_outp;	unsigned long outp;	unsigned long out_buffer;	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	DEBUGWRITE(printk("W d%d c %lu (%d/%d)\n", port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE));	/* Space to end of buffer */	/* 	 * out_buffer <c1>012345<-   c    ->OUT_BUFFER_SIZE	 *            outp^    +out_count	                        ^free_outp	 * out_buffer 45<-     c      ->0123OUT_BUFFER_SIZE	 *             +out_count   outp^	 *              free_outp	 *	 */	/* Read variables that may be updated by interrupts */	save_flags(flags);	cli();			count = count > OUT_BUFFER_SIZE - port->out_count ? OUT_BUFFER_SIZE  - port->out_count : count;	outp = (unsigned long)port->outp;	free_outp = outp + port->out_count;	restore_flags(flags);	out_buffer = (unsigned long)port->out_buffer;		/* Find out where and how much to write */	if (free_outp >= out_buffer + OUT_BUFFER_SIZE)		free_outp -= OUT_BUFFER_SIZE;	if (free_outp >= outp)		c = out_buffer + OUT_BUFFER_SIZE - free_outp;	else		c = outp - free_outp;	if (c > count)		c = count;	//	DEBUGWRITE(printk("w op %08lX fop %08lX c %lu\n", outp, free_outp, c));	if (copy_from_user((void*)free_outp, buf, c))		return -EFAULT;	if (c != count) {		buf += c;		c1 = count - c;		DEBUGWRITE(printk("w2 fi %lu c %lu c1 %lu\n", free_outp-out_buffer, c, c1));		if (copy_from_user((void*)out_buffer, buf, c1))			return -EFAULT;	}	save_flags(flags);	cli();			port->out_count += count;	restore_flags(flags);	/* Make sure transmitter/receiver is running */	if (!port->started)	{		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);

⌨️ 快捷键说明

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