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

📄 jpt_driver.c

📁 这是一个LINUX下多串口驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		}	} 		if(info->tty->termios->c_iflag & IXON)	{		nuart_set_xchar(info->base, &info->reg, START_CHAR(info->tty), STOP_CHAR(info->tty));		pcr |= (NUART_OX | NUART_IX);	}	else	{		pcr_mask |= (NUART_OX | NUART_IX);	}	if (cflag & CLOCAL)		info->flags &= ~ASYNC_CHECK_CD;	else 		info->flags |= ASYNC_CHECK_CD;	/* set up parity check flag */	info->read_status_mask = 0;	if(I_INPCK(info->tty))		info->read_status_mask |= (NUART_FERR | NUART_PERR);	if(I_BRKINT(info->tty) || I_PARMRK(info->tty))		info->read_status_mask |= NUART_IBRK;	info->ignore_status_mask = 0;	if(I_IGNBRK(info->tty))	{		info->read_status_mask |= NUART_IBRK;		info->ignore_status_mask |= NUART_IBRK;		if(I_IGNPAR(info->tty))		{			info->ignore_status_mask |= (NUART_PERR | NUART_FERR);			info->read_status_mask |= (NUART_PERR | NUART_FERR);		}	}	if(quot == 0 || quot == 1)	{		pcr |= NUART_BZO;		if(quot == 0)			pcr |= NUART_BZ;	}	pcr_mask |= (NUART_P_MASK | NUART_SBITS | NUART_PEN | 7);	info->reg.pcr &= ~pcr_mask;	info->reg.pcr |= pcr;	spin_lock_irqsave(&info->lock, flags);	nuart_set_pcr(info->base, &info->reg, info->reg.pcr);	nuart_baud(info->base, &info->reg, quot);	spin_unlock_irqrestore(&info->lock, flags);	return ret;}static int nuart_block_til_ready(struct tty_struct *tty, struct file *filp,				 struct nuart_struct *info){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	int retval;	int do_clocal = 0;	/*	 * If the device is in the middle of being closed, then block	 * until it's done, and then try again.	 *//*	if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) 	{		if (info->flags & ASYNC_CLOSING)			interruptible_sleep_on(&info->close_wait);#ifdef SERIAL_DO_RESTART		if (info->flags & ASYNC_HUP_NOTIFY)			return (-EAGAIN);		else			return (-ERESTARTSYS);#else		return (-EAGAIN);#endif	}*/	/*	 * If non-blocking mode is set, or the port is not enabled,	 * then make the check up front and then exit.	 */	if ((filp->f_flags & O_NONBLOCK) ||	    (tty->flags & (1 << TTY_IO_ERROR))) {		info->flags |= ASYNC_NORMAL_ACTIVE;		return (0);	}	if (tty->termios->c_cflag & CLOCAL)		do_clocal = 1;	retval = 0;	add_wait_queue(&info->open_wait, &wait);	spin_lock_irqsave(&info->lock, flags);	if (!tty_hung_up_p(filp))		info->count--;	spin_unlock_irqrestore(&info->lock, flags);	info->blocked_open++;	while (1) 	{		spin_lock_irqsave(&info->lock, flags);		nuart_dtr(info->base, &info->reg, 1);		nuart_rts(info->base, &info->reg, 1);		spin_unlock_irqrestore(&info->lock, flags);		set_current_state(TASK_INTERRUPTIBLE);		if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) {#ifdef SERIAL_DO_RESTART			if (info->flags & ASYNC_HUP_NOTIFY)				retval = -EAGAIN;			else				retval = -ERESTARTSYS;#else			retval = -EAGAIN;#endif			break;		}		info->reg.mpr = nuart_get_stat(info->base);		if (!(info->flags & ASYNC_CLOSING) &&		    (do_clocal || (info->reg.mpr & NUART_DCD)))			break;		if (signal_pending(current)) {			retval = -ERESTARTSYS;			break;		}		schedule();	}	set_current_state(TASK_RUNNING);	remove_wait_queue(&info->open_wait, &wait);	if (!tty_hung_up_p(filp))		info->count++;	info->blocked_open--;	if (retval)		return (retval);	info->flags |= ASYNC_NORMAL_ACTIVE;	return (0);}static void nuart_close(struct tty_struct *tty, struct file *filp){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	unsigned long flags, timeout;	if (PORTNO(tty) == NUART_PORTS)		return;	if (!info || !info->base)		return;	spin_lock_irqsave(&info->lock, flags);	if (tty_hung_up_p(filp)) {		spin_unlock_irqrestore(&info->lock, flags);		return;	}	if ((tty->count == 1) && (info->count != 1)) {		/*		 * Uh, oh.        tty->count is 1, which means that the tty		 * structure will be freed.  Info->count should always		 * be one in these conditions.  If it's greater than		 * one, we've got real problems, since it means the		 * serial port won't be shutdown.		 */		printk("nuart_close: bad serial port count; tty->count is 1, "		       "info->count is %d\n", info->count);		info->count = 1;	}	if (--info->count < 0) {		printk("nuart_close: bad serial port count for ttys%d: %d\n",		       info->port, info->count);		info->count = 0;	}	if (info->count) {		spin_unlock_irqrestore(&info->lock, flags);		return;	}	info->flags |= ASYNC_CLOSING;	spin_unlock_irqrestore(&info->lock, flags);	info->cflag = tty->termios->c_cflag;	/*	 * Now we wait for the transmit buffer to clear; and we notify	 * the line discipline to only process XON/XOFF characters.	 */	tty->closing = 1;	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)		tty_wait_until_sent(tty, info->closing_wait);	if(info->flags & ASYNC_INITIALIZED)	{		timeout = jiffies + HZ;		spin_lock_irqsave(&info->lock, flags);		info->reg.mpr = nuart_get_stat(info->base);		spin_unlock_irqrestore(&info->lock, flags);		while(info->reg.mpr & NUART_TBUSY)		{			spin_lock_irqsave(&info->lock, flags);			info->reg.mpr = nuart_get_stat(info->base);			spin_unlock_irqrestore(&info->lock, flags);			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(5);			if(time_after(jiffies, timeout))				break;		}	}	nuart_shutdown(info);	if (tty->driver->flush_buffer)		tty->driver->flush_buffer(tty);	if (tty->ldisc.flush_buffer)		tty->ldisc.flush_buffer(tty);	tty->closing = 0;	info->tty = 0;	info->event = 0;	if (info->blocked_open) {		if (info->close_delay) {			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(info->close_delay);		}		wake_up_interruptible(&info->open_wait);	}	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);	wake_up_interruptible(&info->close_wait);}static void nuart_shutdown(struct nuart_struct *info){	unsigned long flags = 0;	if (!(info->flags & ASYNC_INITIALIZED))		return;	spin_lock_irqsave(&info->lock, flags);	/*	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq	 * here so the queue might never be waken up	 */	wake_up_interruptible(&info->delta_msr_wait);	if (info->xmit_buf) {		free_page((unsigned long) info->xmit_buf);		info->xmit_buf = 0;	}	if(!info->tty || (info->tty->termios->c_cflag & HUPCL))		info->reg.pcr &= ~(NUART_RTSC_HIGH | NUART_DTRC_HIGH);	nuart_port_disable(info->base, &info->reg);	if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags &= ~ASYNC_INITIALIZED;	spin_unlock_irqrestore(&info->lock, flags);}int nuart_initbrd(int board, struct nuart_hwconf *hwconf){	struct nuart_struct *info;	int i, n;	nuart_card_disable(hwconf->ioaddr_base);	n = board * NUART_PORTS_PER_BOARD;	info = &nuvar_table[n];	for (i = 0; i < hwconf->ports; i++, n++, info++) 	{		memset(info, 0, sizeof(struct nuart_struct));		info->port = n;		info->base = hwconf->ioaddr_base + i*1024;		info->type = hwconf->board_type;		nuart_port_initial(info->base, &info->reg);				info->baud_base = hwconf->baud_base;		info->flags = 0;		info->close_delay = 5 * HZ / 10;		info->closing_wait = 30 * HZ;		INIT_WORK(&info->tqueue, nuart_do_softint, info);		info->cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;		init_waitqueue_head(&info->open_wait);		init_waitqueue_head(&info->close_wait);		init_waitqueue_head(&info->delta_msr_wait);				spin_lock_init(&info->lock);			if(hwconf->ports >= 16)		{			info->fifo_size = 128;			info->receive_func = nuart16_receive_chars;			info->transmit_func = nuart16_transmit_chars;		}		else		{			info->fifo_size = 256;			info->receive_func = nuart_receive_chars;			info->transmit_func = nuart_transmit_chars;		}	}	nuart_card_enable(hwconf->ioaddr_base);	return 0;}static int nuart_pci_probe(void){	struct pci_dev *pdev = NULL;	struct nuart_hwconf hwconf;	int n, b;	int	card_found = 0;	unsigned long ioaddress;		u32 id;	n = (sizeof(nuart_pcibrds) / sizeof(nuart_pcibrds[0])) - 1;	for (b = 0; b < n; b++) 	{		while ((pdev = pci_find_device(nuart_pcibrds[b].vendor, nuart_pcibrds[b].device, pdev)))		{			if (pci_enable_device(pdev))				continue;					printk("Found Jpt board(BusNo=%d,DevNo=%d)\n", pdev->bus->number, PCI_SLOT(pdev->devfn));			if(card_found >= NUART_BOARDS)			{				printk("Too many Jpt Serial boards find (maximum %d),board not configured\n",NUART_BOARDS);				goto PROBE_OUT;			}			memset(&hwconf, 0, sizeof(struct nuart_hwconf));			hwconf.pdev = pdev;			ioaddress = pci_resource_start (pdev, 0);			if(!ioaddress)				continue;			hwconf.ioaddr_base = (unsigned long)ioremap(ioaddress, 65536);			if (!hwconf.ioaddr_base)				continue;				pci_read_config_dword(pdev, 0x2c, &id);			nuart_get_config(id, &hwconf.board_type, &hwconf.ports);				if(!hwconf.ports)				continue;			if(hwconf.board_type == -1)				continue;			if(hwconf.ports <= 8)				hwconf.baud_base = 14745600/8;			else				hwconf.baud_base = 14745600/hwconf.ports;			printk("type = %s, port = %d, baud base = %ld\n", nuart_typename[hwconf.board_type], hwconf.ports, hwconf.baud_base);			if (nuart_initbrd(card_found, &hwconf) < 0)				continue;			memcpy(&nuartcfg[card_found], &hwconf, sizeof(struct nuart_hwconf));			card_found ++;		}	}PROBE_OUT:	return card_found;}static struct tty_operations nuart_ops = {	.open = nuart_open,	.close = nuart_close,	.write = nuart_write,	.put_char = nuart_put_char,	.flush_chars = nuart_flush_chars,	.write_room = nuart_write_room,	.chars_in_buffer = nuart_chars_in_buffer,	.flush_buffer = nuart_flush_buffer,	.ioctl = nuart_ioctl,	.throttle = nuart_throttle,	.unthrottle = nuart_unthrottle,	.set_termios = nuart_set_termios,	.stop = nuart_stop,	.start = nuart_start,	.hangup = nuart_hangup,	.tiocmget = nuart_tiocmget, 	.tiocmset = nuart_tiocmset,};static int __init nuart_module_init(void){	int i, m;	nuvar_sdriver = alloc_tty_driver(NUART_PORTS + 1);	if (!nuvar_sdriver)		return -ENOMEM;	printk("Jpt serial driver version %s\n", NUART_VERSION);	/* Initialize the tty_driver structure */	nuvar_sdriver->owner = THIS_MODULE;	nuvar_sdriver->name = "ttyN";	nuvar_sdriver->devfs_name = "tts/M";	nuvar_sdriver->major = ttymajor;	nuvar_sdriver->minor_start = 0;	nuvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;	nuvar_sdriver->subtype = SERIAL_TYPE_NORMAL;	nuvar_sdriver->init_termios = tty_std_termios;	nuvar_sdriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	nuvar_sdriver->flags = TTY_DRIVER_REAL_RAW;	tty_set_operations(nuvar_sdriver, &nuart_ops);	printk("Tty devices major number = %d\n", ttymajor);	memset(nuvar_table, 0, NUART_PORTS * sizeof(struct nuart_struct));	for (i = 0; i < NUART_BOARDS; i++) 	{		nuartcfg[i].board_type = -1;	}	m = 0;	/* start finding PCI board here */#ifdef CONFIG_PCI	m = nuart_pci_probe();#endif	if(m == 0)		printk("No Jpt card founded in yout system!\n");	if(m <= 0)		goto init_err_out;	init_MUTEX(&nuvar_tmp_buf_sem);	init_timer(&nuart_timer);	if (!tty_register_driver(nuvar_sdriver))	{		nuart_timer.function = nuart_timeout;		nuart_timer.data = (unsigned long)0;		nuart_timer.expires = jiffies + 1;		add_timer(&nuart_timer);		return 0;	}	printk("Couldn't install Jpt driver !\n");init_err_out:	put_tty_driver(nuvar_sdriver);	for (i = 0; i < NUART_BOARDS; i++) 	{		if (nuartcfg[i].board_type == -1)			continue;		if (nuartcfg[i].ioaddr_base)			iounmap((void *)(nuartcfg[i].ioaddr_base));	}	return -1;}static void __exit nuart_module_exit(void){	int i, err = 0;	if (verbose)		printk("Unloading module Jpt...");	del_timer(&nuart_timer);	if ((err |= tty_unregister_driver(nuvar_sdriver)))		printk("Couldn't unregister Jpt serial driver\n");	put_tty_driver(nuvar_sdriver);	for (i = 0; i < NUART_BOARDS; i++) 	{		if (nuartcfg[i].board_type == -1)			continue;		if(nuartcfg[i].ioaddr_base)		{			iounmap((void *)(nuartcfg[i].ioaddr_base));		}	}	if (verbose)		printk("Done.\n");

⌨️ 快捷键说明

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