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

📄 sync_serial.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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));	/* Make sure receiver is running */	SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);	SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, enable);	*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):			port->out_count--;			if (port->odd_output)				*port->data_out = ((*port->outp) << 16) | (*(unsigned short *)(port->outp + 1));			else				*port->data_out = ((*(unsigned short *)port->outp) << 8) | (*(port->outp + 1));			port->odd_output = !port->odd_output;			port->outp++;			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_int | 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 (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++) 	{		int update = 0;		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_eop, do) | 			  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;					if (port->odd_input)					{						*port->writep |= (data & 0x0f00) >> 8;						*(port->writep + 1) = data & 0xff;					}					else					{						*port->writep = (data & 0x0ff0) >> 4;						*(port->writep + 1) = (data & 0x0f) << 4;					}					port->odd_input = !port->odd_input;					port->writep+=1;				}				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) /* 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 + -