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

📄 jpt_driver.c

📁 这是一个LINUX下多串口驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);		info->wbl[i & 3] = c;		tbuf[i] = c;	}		spin_lock_irqsave(&info->lock, flags);	nuart_write_buf(info->base, buf_pos, tbuf, wbl_pos + count);	spin_unlock_irqrestore(&info->lock, flags);	info->xmit_cnt -= count;	info->twp += count;		spin_lock_irqsave(&info->lock, flags);	nuart_set_twp(info->base, &info->reg, info->twp);	spin_unlock_irqrestore(&info->lock, flags);	if(info->xmit_cnt < WAKEUP_CHARS)	{		set_bit(NUART_EVENT_TXLOW, &info->event);			schedule_work(&info->tqueue);	}	return;}static void nuart16_transmit_chars(struct nuart_struct *info){	int count, i;	int wbl_pos;	int buf_pos;	char  tbuf[256];	int c;	unsigned long flags = 0;	count = 120 - ((info->twp - info->trp) & 0x7f);	count = MIN(info->xmit_cnt, count);	if(count <= 0)		return;	wbl_pos = info->twp & 3;	buf_pos = info->twp & (~3);	if(wbl_pos)		memcpy(tbuf,info->wbl,wbl_pos);		for(i = wbl_pos;i < count + wbl_pos; i++)	{		c = info->xmit_buf[info->xmit_tail++];		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);		info->wbl[i & 3] = c;		tbuf[i] = c;	}		spin_lock_irqsave(&info->lock, flags);	nuart_write_buf(info->base, buf_pos, tbuf, wbl_pos + count);	spin_unlock_irqrestore(&info->lock, flags);	info->xmit_cnt -= count;	info->twp += count;		spin_lock_irqsave(&info->lock, flags);	nuart_set_twp(info->base, &info->reg, info->twp);	spin_unlock_irqrestore(&info->lock, flags);	if(info->xmit_cnt < WAKEUP_CHARS)	{		set_bit(NUART_EVENT_TXLOW, &info->event);			schedule_work(&info->tqueue);	}	return;}static void nuart_timeout_port(struct nuart_struct * info){	unsigned long	status, flags;	spin_lock_irqsave(&info->lock, flags);	status = nuart_get_stat(info->base);	spin_unlock_irqrestore(&info->lock, flags);	info->rwp = ((status & 0xff00) >> 8) & 0xff;	info->trp = status & 0xff;	if((status & (NUART_RI | NUART_DSR | NUART_DCD | NUART_CTS)) != 		(info->reg.mpr & (NUART_RI | NUART_DSR | NUART_DCD | NUART_CTS)))		nuart_check_modem_status(info, status);	nuart_receive_chars(info, status);	info->reg.mpr = status;	if (info->xmit_cnt && !info->tty->stopped && !info->tty->hw_stopped)		nuart_transmit_chars(info);		}static void nuart_timeout_single(int board, struct nuart_hwconf *hwconf){	struct nuart_struct *info;	int i, n;	n = board * NUART_PORTS_PER_BOARD;	info = &nuvar_table[n];	for (i = 0; i < hwconf->ports; i++, n++, info++) 	{		if(info->port != n)			continue;		if (info->flags & ASYNC_INITIALIZED)			nuart_timeout_port(info);	}}static void nuart_timeout(unsigned long ptr){	int i;	for (i = 0; i < NUART_BOARDS; i++) 	{		if (nuartcfg[i].board_type == -1)			continue;		nuart_timeout_single(i, &nuartcfg[i]);	}	nuart_timer.function = nuart_timeout;	nuart_timer.data = (unsigned long)0;	nuart_timer.expires = jiffies + 1;  /* 1ms */	add_timer(&nuart_timer);	return;}static int nuart_open(struct tty_struct *tty, struct file *filp){	struct nuart_struct *info;	int retval, line;	unsigned long page;	line = PORTNO(tty);	if ((line < 0) || (line >= NUART_PORTS))		return (-ENODEV);	info = &nuvar_table[line];	if (!info->base)		return (-ENODEV);	tty->driver_data = info;	info->tty = tty;	if (!nuvar_tmp_buf) {		page = get_zeroed_page(GFP_KERNEL);		if (!page)			return (-ENOMEM);		if (nuvar_tmp_buf)			free_page(page);		else			nuvar_tmp_buf = (unsigned char *) page;	}	/*	 * Start up serial port	 */	info->count++;	retval = nuart_startup(info);	if (retval)		return (retval);	return nuart_block_til_ready(tty, filp, info);}static int nuart_get_line(struct file * f, char * buf, ssize_t size, loff_t * off){	int n, i;	loff_t offset = *off;	n = f->f_op->read(f, buf, size, &offset);	if(n <= 0)		return 0;	for(i = 0; i < n ; i++)	{		if(buf[i] == 0xa)			break;	}	buf[i] = 0;	i++;	*off += i;		return i;}static int nuart_atoi(char * s){	int n = 0;	char * p = s;	while((*p == ' ') || (*p == '\t'))		p ++;	while((*p >= '0') && (*p <= '9'))	{		n *= 10;		n += *p - '0';		p ++;	}	return n;} static void nuart_get_mode(struct nuart_struct * info){	struct file * f;		char	buf[256];	char	*s;	mm_segment_t fs;	loff_t offset = 0;	if(info->type == NUART_BOARD_RS232)	{		info->mode = NUART_PORT_RS232;		return;	}	f = filp_open("/etc/jpt.conf",O_RDWR, 0600);	if(IS_ERR(f))	{		printk("WARNING : /etc/jpt.conf does not exist\n");		info->mode = -1;	}	else	{		info->mode = -1;		fs = get_fs();		set_fs(KERNEL_DS);		while(nuart_get_line(f, buf, sizeof(buf), &offset))		{			if(memcmp(buf, "ttyn", 4))				continue;			s = buf + 4;			if(nuart_atoi(s) != info->port)				continue;			while((*s != ' ') && (*s != '\t'))				s++;					info->mode = nuart_atoi(s);			break;		}		set_fs(fs);		filp_close(f, NULL);	}	switch(info->type)	{	case NUART_BOARD_RS232:		break;	case NUART_BOARD_RS485:		if((info->mode != NUART_PORT_RS485F) && (info->mode != NUART_PORT_RS485H))		{			printk("WARNING : set ttyn%d to default mode(rs_485 full)\n", info->port);			info->mode = NUART_PORT_RS485F;		}		break;	case NUART_BOARD_RS422_RS485:		if((info->mode != NUART_PORT_RS422) && (info->mode != NUART_PORT_RS485F) && (info->mode != NUART_PORT_RS485H))		{			printk("WARNING : set ttyn%d to default mode(rs_485 full)\n", info->port);			info->mode = NUART_PORT_RS485F;		}		break;	case NUART_BOARD_RS232_RS422_RS485:		if((info->mode != NUART_PORT_RS232) && (info->mode != NUART_PORT_RS422) && (info->mode != NUART_PORT_RS485F) && (info->mode != NUART_PORT_RS485H))		{			printk("WARNING : set ttyn%d to default mode(rs_232)\n", info->port);			info->mode = NUART_PORT_RS232;		}		break;	default:		printk("WARNING : set ttyn%d to default mode(rs_232)\n", info->port);		info->mode = NUART_PORT_RS232;	}	return;}static int nuart_startup(struct nuart_struct *info){	unsigned long flags = 0;	unsigned long page;	page = get_zeroed_page(GFP_KERNEL);	if (!page)		return (-ENOMEM);	spin_lock_irqsave(&info->lock, flags);	if (info->flags & ASYNC_INITIALIZED) {		free_page(page);		spin_unlock_irqrestore(&info->lock, flags);		return (0);	}	if (!info->base) 	{		if (info->tty)			set_bit(TTY_IO_ERROR, &info->tty->flags);		free_page(page);		spin_unlock_irqrestore(&info->lock, flags);		return (0);	}	if (info->xmit_buf)		free_page(page);	else		info->xmit_buf = (unsigned char *) page;		/* initialize the port */ 	nuart_get_mode(info);		nuart_port_enable_and_init(info->base, &info->reg, info->mode);	nuart_dtr(info->base, &info->reg, 1);	nuart_rts(info->base, &info->reg, 1);	info->lflag = (NUART_LFLAG_RDI | NUART_LFLAG_MSI | NUART_LFLAG_THRI | NUART_LFLAG_RLSI);	if (info->tty)		test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags);	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	spin_unlock_irqrestore(&info->lock, flags);	/*	 * and set the speed of the serial port	 */	nuart_change_speed(info, 0);	info->flags |= ASYNC_INITIALIZED;	return (0);}static int nuart_change_speed(struct nuart_struct *info, struct termios *old_termios){	unsigned cflag, cval;	int i;	int ret = 0;	unsigned long flags;	unsigned long quot = 0;	unsigned long pcr = 0;	unsigned long pcr_mask = 0;	if (!info->tty || !info->tty->termios)		return ret;	cflag = info->tty->termios->c_cflag;	if (!(info->base))		return ret;#ifndef B921600#define B921600 (B460800 +1)#endif	switch (cflag & (CBAUD | CBAUDEX)) 	{	case B921600:		i = 20;		break;	case B460800:		i = 19;		break;	case B230400:		i = 18;		break;	case B115200:		i = 17;		break;	case B57600:		i = 16;		break;	case B38400:		i = 15;		break;	case B19200:		i = 14;		break;	case B9600:		i = 13;		break;	case B4800:		i = 12;		break;	case B2400:		i = 11;		break;	case B1800:		i = 10;		break;	case B1200:		i = 9;		break;	case B600:		i = 8;		break;	case B300:		i = 7;		break;	case B200:		i = 6;		break;	case B150:		i = 5;		break;	case B134:		i = 4;		break;	case B110:		i = 3;		break;	case B75:		i = 2;		break;	case B50:		i = 1;		break;	default:		i = 0;		break;	}	if(i == 15)	{		if((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)			i = 16;		if((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)			i = 17;#ifdef ASYNC_SPD_SHI		if((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)			i = 18;#endif#ifdef ASYNC_SPD_WARP		if((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)			i = 19;#endif	}	if (nuart_baud_table[i]) 		quot = info->baud_base / nuart_baud_table[i];	else 		quot = 0;	if(quot)		quot --;	/* byte size and parity */	pcr = 0;	cval = 9;	if (cflag & CSTOPB)	{		pcr |= NUART_SBITS;	}	if (cflag & PARENB)	{		pcr |= NUART_PEN;		if (!(cflag & PARODD))			pcr |= NUART_P_EVEN;		cval -= 1;	}	switch (cflag & CSIZE) 	{	case CS5:		pcr |= cval  - 5;;		break;	case CS6:		pcr |= cval  - 6;;		break;	case CS7:		pcr |= cval  - 7;		break;	case CS8:		pcr |= cval  - 8;		break;	default:		break;		/* too keep GCC shut... */	}	if (cflag & CRTSCTS) 	{		if(!(info->reg.pcr & NUART_RTSC_FLOW))		{			info->flags |= ASYNC_CTS_FLOW;			pcr_mask |= NUART_RTSC_MASK;			pcr |= (NUART_OCTS | NUART_RTSC_FLOW);

⌨️ 快捷键说明

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