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

📄 sync_serial.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 (file->f_flags & O_NONBLOCK)	{		save_flags(flags);		cli();		if (!port->tr_running) {			if (!port->use_dma) {				/* Start sender by writing data */				send_word(port);				/* and enable transmitter ready IRQ */				*R_IRQ_MASK1_SET = 1 << port->transmitter_ready_bit;			} else {				start_dma(port, (unsigned char* volatile )port->outp, c);			}		}		restore_flags(flags);		DEBUGWRITE(printk("w d%d c %lu NB\n",				  port->port_nbr, count));		return count;	}	/* Sleep until all sent */		add_wait_queue(&port->out_wait_q, &wait);	set_current_state(TASK_INTERRUPTIBLE);	save_flags(flags);	cli();	if (!port->tr_running) {		if (!port->use_dma) {			/* Start sender by writing data */			send_word(port);			/* and enable transmitter ready IRQ */			*R_IRQ_MASK1_SET = 1 << port->transmitter_ready_bit;		} else {			start_dma(port, port->outp, c);		}	}	restore_flags(flags);	schedule();	set_current_state(TASK_RUNNING);	remove_wait_queue(&port->out_wait_q, &wait);	if (signal_pending(current))	{		return -EINTR;	}	DEBUGWRITE(printk("w d%d c %lu\n", port->port_nbr, count));	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;	unsigned char* start; 	unsigned 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];	DEBUGREAD(printk("R%d c %d ri %lu wi %lu /%lu\n", dev, count, port->readp - port->in_buffer, port->writep - port->in_buffer, port->in_buffer_size));	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 */	/* Save pointers to avoid that they are modified by interrupt */	save_flags(flags);	cli();		start = (unsigned char*)port->readp; /* cast away volatile */	end = (unsigned char*)port->writep;  /* cast away volatile */	restore_flags(flags);	while (start == end) /* No data */	{		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		interruptible_sleep_on(&port->in_wait_q);		if (signal_pending(current))		{			return -EINTR;		}		save_flags(flags);		cli();			start = (unsigned char*)port->readp; /* cast away volatile */		end = (unsigned char*)port->writep;  /* cast away volatile */		restore_flags(flags);	}	/* Lazy read, never return wrapped data. */	if (end > start)		avail = end - start;	else 		avail = port->in_buffer + port->in_buffer_size - start;  	count = count > avail ? avail : count;	if (copy_to_user(buf, start, count))		return -EFAULT;	/* Disable interrupts while updating readp */	save_flags(flags);	cli();		port->readp += count;	if (port->readp >= port->in_buffer + port->in_buffer_size) /* Wrap? */		port->readp = port->in_buffer;	restore_flags(flags);	DEBUGREAD(printk("r %d\n", count));	return count;}static void send_word(sync_port* port){	switch(IO_EXTRACT(R_SYNC_SERIAL1_CTRL, wordsize, port->ctrl_data_shadow))	{	 case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):		 port->out_count--;		 *port->data_out = *port->outp++;		 if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)			 port->outp = port->out_buffer;		 break;	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):	{		int data = (*port->outp++) << 8;		data |= *port->outp++;		port->out_count-=2;  		*port->data_out = data;		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)			port->outp = port->out_buffer;	}	break;	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):		port->out_count-=2;		*port->data_out = *(unsigned short *)port->outp;		port->outp+=2;		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)			port->outp = port->out_buffer;		break;	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):		port->out_count-=3;		*port->data_out = *(unsigned int *)port->outp;		port->outp+=3;		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)			port->outp = port->out_buffer;		break;	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):		port->out_count-=4;		*port->data_out = *(unsigned int *)port->outp;		port->outp+=4;		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)			port->outp = port->out_buffer;		break;	}}static void start_dma(struct sync_port* port, const char* data, int count){	port->tr_running = 1;	port->out_descr.hw_len = 0;	port->out_descr.next = 0;	port->out_descr.ctrl = d_eol | d_eop; /* No d_wait to avoid glitches */	port->out_descr.sw_len = count;	port->out_descr.buf = virt_to_phys((char*)data);	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);	DEBUGTXINT(printk("dma %08lX c %d\n", (unsigned long)data, count));}static void start_dma_in(sync_port* port){	int i;	unsigned long buf;	port->cur_in_descr = 0;	port->writep = port->in_buffer;		if (port->writep > port->in_buffer + port->in_buffer_size)	{		panic("Offset too large in sync serial driver\n");		return;	}	buf = virt_to_phys(port->in_buffer);	for (i = 0; i < NUM_IN_DESCR; i++) {		port->in_descr[i].sw_len = port->inbufchunk;		port->in_descr[i].ctrl = d_int;		port->in_descr[i].next = virt_to_phys(&port->in_descr[i+1]);		port->in_descr[i].buf = buf;		port->in_descr[i].hw_len = 0;		port->in_descr[i].status = 0;		port->in_descr[i].fifo_len = 0;		buf += port->inbufchunk;		prepare_rx_descriptor(&port->in_descr[i]);	}	/* Link the last descriptor to the first */	port->in_descr[i-1].next = virt_to_phys(&port->in_descr[0]);	*port->input_dma_first = virt_to_phys(&port->in_descr[(int)port->cur_in_descr]);	*port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);}#ifdef SYNC_SER_DMAstatic void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs){	unsigned long ireg = *R_IRQ_MASK2_RD;	int i;	struct etrax_dma_descr *descr;	unsigned int sentl;		for (i = 0; i < NUMBER_OF_PORTS; i++) 	{		sync_port *port = &ports[i];		if (!port->enabled  || !port->use_dma )			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);			descr = &port->out_descr;			if (!(descr->status & d_stop)) {				sentl = descr->sw_len;			} else 				/* otherwise we find the amount of data sent here */				sentl = descr->hw_len;			port->out_count -= sentl;			port->outp += sentl;			if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)				port->outp = port->out_buffer;			if (port->out_count)  {				int c;				c = port->out_buffer + OUT_BUFFER_SIZE - port->outp;				if (c > port->out_count)					c = port->out_count;				DEBUGTXINT(printk("tx_int DMAWRITE %i %i\n", sentl, c));				start_dma(port, port->outp, c);			} else  {				DEBUGTXINT(printk("tx_int DMA stop %i\n", sentl));								port->tr_running = 0;			}			wake_up_interruptible(&port->out_wait_q); /* wake up the waiting process */		} 	}} /* tr_interrupt */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 || !port->use_dma )			continue;		if (ireg & (1 << port->input_dma_descr_bit)) /* Descriptor interrupt */		{			struct etrax_dma_descr *descr;			unsigned recvl;			unsigned long oldbuf, buf;			/* DMA has reached end of descriptor */			*port->input_dma_clr_irq = 			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);						descr = &port->in_descr[(int)port->cur_in_descr];			if (descr == phys_to_virt(*port->input_dma_descr)) 				printk("sser: desc = *input_dma_descr\n");			if (!(descr->status & d_eop)) {				recvl = descr->sw_len;			} else {				/* otherwise we find the amount of data received here */				recvl = descr->hw_len;			}			port->writep += recvl;			if (port->writep >= port->in_buffer+ port->in_buffer_size)				port->writep = port->in_buffer;			descr->sw_len = port->inbufchunk;			/* Reset the status information */			descr->status = 0;			/* Change the buf pointer to new position */			oldbuf = descr->buf;						descr->buf += NUM_IN_DESCR * port->inbufchunk;			buf = virt_to_phys(port->in_buffer);			if (descr->buf >= buf + port->in_buffer_size)				descr->buf -= port->in_buffer_size;			DEBUGRXINT(printk("rx_int descr %i %X recvl: %i writep %lu obuf %lu %08lX buf 0x%08lX\n", port->cur_in_descr, (unsigned long) (*port->input_dma_descr), recvl, (unsigned long)(port->writep - port->in_buffer), oldbuf, oldbuf, (unsigned long)descr->buf));			if (++port->cur_in_descr == NUM_IN_DESCR)				port->cur_in_descr = 0;							wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */		}	}} /* rx_interrupt */#endif /* SYNC_SER_DMA */#ifdef SYNC_SER_MANUALstatic 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 || port->use_dma)		{			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 + port->in_buffer_size) /* Wrap? */				port->writep = port->in_buffer;			if (port->writep == port->readp) {				/* receive buffer overrun, discard oldest data				 */				port->readp++;				if (port->readp >= port->in_buffer + port->in_buffer_size) /* Wrap? */					port->readp = port->in_buffer;			}			if (sync_data_avail(port) >= port->inbufchunk)				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->transmitter_ready_bit; /* Turn off IRQ */				wake_up_interruptible(&port->out_wait_q); /* Wake up application */			}		}	}}#endifmodule_init(etrax_sync_serial_init);

⌨️ 快捷键说明

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