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

📄 sync_serial.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
				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:			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;		default:			return_val = -1;	}	/* Set config and enable port */	*port->ctrl_data = port->ctrl_data_shadow;	*R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow;	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;	return return_val;}static ssize_t sync_serial_manual_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;	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	copy_from_user(port->out_buffer, buf, count);	port->outp = port->out_buffer;	port->out_count = count;	add_wait_queue(&port->out_wait_q, &wait);	set_current_state(TASK_INTERRUPTIBLE);	send_word(port); /* Start sender by sending first word */	*R_IRQ_MASK1_SET = 1 << port->ready_irq_bit; /* transmitter ready IRQ on */	schedule();	set_current_state(TASK_RUNNING);	remove_wait_queue(&port->out_wait_q, &wait);	if (signal_pending(current))	{		return -EINTR;	}	return count;}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;	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	DEBUG(printk("Write dev %d count %d\n", port->port_nbr, count));	count = count > OUT_BUFFER_SIZE ? OUT_BUFFER_SIZE : count;	/* Make sure transmitter/receiver is running */	if (!port->started)	{		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)	{		return sync_serial_manual_write(file, buf, count, ppos); 	}  	copy_from_user(port->out_buffer, buf, count);	add_wait_queue(&port->out_wait_q, &wait);	set_current_state(TASK_INTERRUPTIBLE);	start_dma(port, buf, count);	schedule();	set_current_state(TASK_RUNNING);	remove_wait_queue(&port->out_wait_q, &wait);	if (signal_pending(current))	{		return -EINTR;	}	return count;}static ssize_t sync_serial_read(struct file * file, char * buf, 				size_t count, loff_t *ppos){	int dev = MINOR(file->f_dentry->d_inode->i_rdev);	int avail;	sync_port *port;	char* start; 	char* end;	unsigned long flags;		if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	DEBUG(printk("Read dev %d count %d\n", dev, count));	if (!port->started)	{		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;	/* Calculate number of available bytes */	while (port->readp == port->writep) /* No data */	{		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		interruptible_sleep_on(&port->in_wait_q);		if (signal_pending(current))		{			return -EINTR;		}	}		/* Save pointers to avoid that they are modified by interrupt */	start = port->readp;	end = port->writep;	/* Lazy read, never return wrapped data. */	if (end > start)		avail = end - start;	else 		avail = port->in_buffer + IN_BUFFER_SIZE - start;  	count = count > avail ? avail : count;	copy_to_user(buf, start, count);	/* Disable interrupts while updating readp */	save_flags(flags);	cli();		port->readp += count;	if (port->readp == port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */		port->readp = port->in_buffer;	restore_flags(flags);	DEBUG(printk("%d bytes read\n", count));	return count;}static void send_word(sync_port* port){	switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))	{		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):			port->out_count--;			*port->data_out = *port->outp++;			break;		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):			{				int data = (*port->outp++) << 8;				data |= *port->outp++;				port->out_count-=2;  				*port->data_out = data;			}			break;		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):			port->out_count-=2;			*port->data_out = *(unsigned short *)port->outp;			port->outp+=2;			break;		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):			port->out_count-=3;			*port->data_out = *(unsigned int *)port->outp;			port->outp+=3;			break;		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):			port->out_count-=4;			*port->data_out = *(unsigned int *)port->outp;			port->outp+=4;			break;	}}static void start_dma(struct sync_port* port, const char* data, int count){	port->out_descr.hw_len = 0;	port->out_descr.next = 0;	port->out_descr.ctrl = d_eol | d_eop | d_wait;	port->out_descr.sw_len = count;	port->out_descr.buf = virt_to_phys(port->out_buffer);	port->out_descr.status = 0;	*port->output_dma_first = virt_to_phys(&port->out_descr);	*port->output_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);}static void start_dma_in(sync_port* port){	if (port->writep > port->in_buffer + IN_BUFFER_SIZE)	{		panic("Offset too large in sync serial driver\n");		return;	}	port->in_descr1.hw_len = 0;	port->in_descr1.ctrl = d_int;	port->in_descr1.status = 0;	port->in_descr1.next = virt_to_phys(&port->in_descr2);	port->in_descr2.hw_len = 0;	port->in_descr2.next = virt_to_phys(&port->in_descr1);	port->in_descr2.ctrl = d_int;	port->in_descr2.status = 0;	/* Find out which descriptor to start */	if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2)	{		/* Start descriptor 2 */		port->in_descr1.sw_len = IN_BUFFER_SIZE/2; /* All data available in 1 */		port->in_descr1.buf = virt_to_phys(port->in_buffer);		port->in_descr2.sw_len = port->in_buffer + IN_BUFFER_SIZE - port->writep;		port->in_descr2.buf = virt_to_phys(port->writep);		*port->input_dma_first = virt_to_phys(&port->in_descr2);	}	else	{		/* Start descriptor 1 */		port->in_descr1.sw_len = port->in_buffer + IN_BUFFER_SIZE/2 - port->writep;		port->in_descr1.buf = virt_to_phys(port->writep);		port->in_descr2.sw_len = IN_BUFFER_SIZE/2;		port->in_descr2.buf = virt_to_phys(port->in_buffer + IN_BUFFER_SIZE / 2);		*port->input_dma_first = virt_to_phys(&port->in_descr1);	}	*port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);}static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs){	unsigned long ireg = *R_IRQ_MASK2_RD;	int i;	for (i = 0; i < NUMBER_OF_PORTS; i++) 	{		sync_port *port = &ports[i];		if (!port->enabled)			continue;		if (ireg & (1 << port->output_dma_bit)) /* IRQ active for the port? */		{			/* Clear IRQ */			*port->output_dma_clr_irq = 			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) |			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);			wake_up_interruptible(&port->out_wait_q); /* wake up the waiting process */		} 	}}static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs){	unsigned long ireg = *R_IRQ_MASK2_RD;	int i;		for (i = 0; i < NUMBER_OF_PORTS; i++) 	{		sync_port *port = &ports[i];		if (!port->enabled)			continue;		if (ireg & (1 << port->input_dma_descr_bit)) /* Descriptor interrupt */		{			/* DMA has reached end of descriptor */			*port->input_dma_clr_irq = 			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);			/* Find out which descriptor that is ready */			if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2) 			{				/* Descr 2 was ready. Restart DMA at descriptor 1 */				port->writep = port->in_buffer;					/* Throw away data? */				if (port->readp < port->in_buffer + IN_BUFFER_SIZE/2)					port->readp = port->in_buffer + IN_BUFFER_SIZE/2;			}			else			{				/* Descr 1 was ready. Restart DMA at descriptor 2 */				port->writep = port->in_buffer + IN_BUFFER_SIZE/2;				/* Throw away data? */				if (port->readp >= port->in_buffer + IN_BUFFER_SIZE/2)					port->readp = port->in_buffer;			}			start_dma_in(port);			wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */		}	}}static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs){	int i;	for (i = 0; i < NUMBER_OF_PORTS; i++)	{		sync_port* port = &ports[i];		if (!port->enabled)		{			continue;		}		if (*R_IRQ_MASK1_RD & (1 << port->data_avail_bit))	/* Data received? */		{			/* Read data */			switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))			{				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):					*port->writep++ = *(volatile char *)port->data_in;					break;				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):				{					int data = *(unsigned short *)port->data_in;					*port->writep = (data & 0x0ff0) >> 4;					*(port->writep + 1) = data & 0x0f;					port->writep+=2;				}				break;				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):					*(unsigned short*)port->writep = *(volatile unsigned short *)port->data_in;					port->writep+=2;					break;				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):					*(unsigned int*)port->writep = *port->data_in;					port->writep+=3;					break;				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):					*(unsigned int*)port->writep = *port->data_in;					port->writep+=4;					break;			}			if (port->writep >= port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */				port->writep = port->in_buffer;			wake_up_interruptible(&port->in_wait_q); /* Wake up application */		}		if (*R_IRQ_MASK1_RD & (1 << port->transmitter_ready_bit)) /* Transmitter ready? */		{			if (port->out_count > 0) /* More data to send */				send_word(port);			else /* transmission finished */			{				*R_IRQ_MASK1_CLR = 1 << port->ready_irq_bit; /* Turn off IRQ */				wake_up_interruptible(&port->out_wait_q); /* Wake up application */			}		}	}}module_init(etrax_sync_serial_init);

⌨️ 快捷键说明

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