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

📄 mxser.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));	mxvar_sdriver.magic = TTY_DRIVER_MAGIC;	mxvar_sdriver.name = "ttyM";	mxvar_sdriver.major = ttymajor;	mxvar_sdriver.minor_start = 0;	mxvar_sdriver.num = MXSER_PORTS + 1;	mxvar_sdriver.type = TTY_DRIVER_TYPE_SERIAL;	mxvar_sdriver.subtype = SERIAL_TYPE_NORMAL;	mxvar_sdriver.init_termios = tty_std_termios;	mxvar_sdriver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	mxvar_sdriver.flags = TTY_DRIVER_REAL_RAW;	mxvar_sdriver.refcount = &mxvar_refcount;	mxvar_sdriver.table = mxvar_tty;	mxvar_sdriver.termios = mxvar_termios;	mxvar_sdriver.termios_locked = mxvar_termios_locked;	mxvar_sdriver.open = mxser_open;	mxvar_sdriver.close = mxser_close;	mxvar_sdriver.write = mxser_write;	mxvar_sdriver.put_char = mxser_put_char;	mxvar_sdriver.flush_chars = mxser_flush_chars;	mxvar_sdriver.write_room = mxser_write_room;	mxvar_sdriver.chars_in_buffer = mxser_chars_in_buffer;	mxvar_sdriver.flush_buffer = mxser_flush_buffer;	mxvar_sdriver.ioctl = mxser_ioctl;	mxvar_sdriver.throttle = mxser_throttle;	mxvar_sdriver.unthrottle = mxser_unthrottle;	mxvar_sdriver.set_termios = mxser_set_termios;	mxvar_sdriver.stop = mxser_stop;	mxvar_sdriver.start = mxser_start;	mxvar_sdriver.hangup = mxser_hangup;	/*	 * The callout device is just like normal device except for	 * major number and the subtype code.	 */	mxvar_cdriver = mxvar_sdriver;	mxvar_cdriver.name = "cum";	mxvar_cdriver.major = calloutmajor;	mxvar_cdriver.subtype = SERIAL_TYPE_CALLOUT;	printk("Tty devices major number = %d, callout devices major number = %d\n", ttymajor, calloutmajor);	mxvar_diagflag = 0;	memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct));	memset(&mxvar_log, 0, sizeof(struct mxser_log));	m = 0;	/* Start finding ISA boards here */	for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {		int cap;		if (!(cap = mxserBoardCAP[b]))			continue;		retval = mxser_get_ISA_conf(cap, &hwconf);		if (retval != 0)			printk("Found MOXA %s board (CAP=0x%x)\n",			       mxser_brdname[hwconf.board_type - 1],			       ioaddr[b]);		if (retval <= 0) {			if (retval == MXSER_ERR_IRQ)				printk("Invalid interrupt number,board not configured\n");			else if (retval == MXSER_ERR_IRQ_CONFLIT)				printk("Invalid interrupt number,board not configured\n");			else if (retval == MXSER_ERR_VECTOR)				printk("Invalid interrupt vector,board not configured\n");			else if (retval == MXSER_ERR_IOADDR)				printk("Invalid I/O address,board not configured\n");			continue;		}		hwconf.pdev = NULL;		if (mxser_initbrd(m, &hwconf) < 0)			continue;		mxser_getcfg(m, &hwconf);		m++;	}	/* Start finding ISA boards from module arg */	for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {		int cap;		if (!(cap = ioaddr[b]))			continue;		retval = mxser_get_ISA_conf(cap, &hwconf);		if (retval != 0)			printk("Found MOXA %s board (CAP=0x%x)\n",			       mxser_brdname[hwconf.board_type - 1],			       ioaddr[b]);		if (retval <= 0) {			if (retval == MXSER_ERR_IRQ)				printk("Invalid interrupt number,board not configured\n");			else if (retval == MXSER_ERR_IRQ_CONFLIT)				printk("Invalid interrupt number,board not configured\n");			else if (retval == MXSER_ERR_VECTOR)				printk("Invalid interrupt vector,board not configured\n");			else if (retval == MXSER_ERR_IOADDR)				printk("Invalid I/O address,board not configured\n");			continue;		}		hwconf.pdev = NULL;		if (mxser_initbrd(m, &hwconf) < 0)			continue;		mxser_getcfg(m, &hwconf);		m++;	}	/* start finding PCI board here */#ifdef CONFIG_PCI	{		struct pci_dev *pdev = NULL;		n = sizeof(mxser_pcibrds) / sizeof(mxser_pciinfo);		index = 0;		b = 0;		while (b < n) {			pdev = pci_find_device(mxser_pcibrds[b].vendor_id,					       mxser_pcibrds[b].device_id, pdev);			if (!pdev)				break;			if (pci_enable_device(pdev))				continue;			b++;			hwconf.pdev = pdev;			printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",				mxser_brdname[mxser_pcibrds[b].board_type - 1],				pdev->bus->number, PCI_SLOT(pdev->devfn >> 3));			if (m >= MXSER_BOARDS) {				printk("Too many Smartio family boards find (maximum %d),board not configured\n", MXSER_BOARDS);			} else {				retval = mxser_get_PCI_conf(pdev,				   mxser_pcibrds[b].board_type, &hwconf);				if (retval < 0) {					if (retval == MXSER_ERR_IRQ)						printk("Invalid interrupt number,board not configured\n");					else if (retval == MXSER_ERR_IRQ_CONFLIT)						printk("Invalid interrupt number,board not configured\n");					else if (retval == MXSER_ERR_VECTOR)						printk("Invalid interrupt vector,board not configured\n");					else if (retval == MXSER_ERR_IOADDR)						printk("Invalid I/O address,board not configured\n");					continue;				}				if (mxser_initbrd(m, &hwconf) < 0)					continue;				mxser_getcfg(m, &hwconf);				m++;			}		}	}#endif	for (i = m; i < MXSER_BOARDS; i++) {		mxsercfg[i].board_type = -1;	}	ret1 = 0;	ret2 = 0;	if (!(ret1 = tty_register_driver(&mxvar_sdriver))) {		if (!(ret2 = tty_register_driver(&mxvar_cdriver))) {			return 0;		} else {			tty_unregister_driver(&mxvar_sdriver);			printk("Couldn't install MOXA Smartio family callout driver !\n");		}	} else		printk("Couldn't install MOXA Smartio family driver !\n");	if (ret1 || ret2) {		for (i = 0; i < MXSER_BOARDS; i++) {			if (mxsercfg[i].board_type == -1)				continue;			else {				free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);			}		}		return -1;	}	return (0);}static void mxser_do_softint(void *private_){	struct mxser_struct *info = (struct mxser_struct *) private_;	struct tty_struct *tty;	tty = info->tty;	if (tty) {		if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&			    tty->ldisc.write_wakeup)				(tty->ldisc.write_wakeup) (tty);			wake_up_interruptible(&tty->write_wait);		}		if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {			tty_hangup(tty);	/* FIXME: module removal race here - AKPM */		}	}	MOD_DEC_USE_COUNT;}/* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain.   It also performs the serial-specific * initialization for the tty structure. */static int mxser_open(struct tty_struct *tty, struct file *filp){	struct mxser_struct *info;	int retval, line;	unsigned long page;	line = PORTNO(tty);	if (line == MXSER_PORTS)		return (0);	if ((line < 0) || (line > MXSER_PORTS))		return (-ENODEV);	info = mxvar_table + line;	if (!info->base)		return (-ENODEV);	info->count++;	tty->driver_data = info;	info->tty = tty;	if (!mxvar_tmp_buf) {		page = get_free_page(GFP_KERNEL);		if (!page)			return (-ENOMEM);		if (mxvar_tmp_buf)			free_page(page);		else			mxvar_tmp_buf = (unsigned char *) page;	}	/*	 * Start up serial port	 */	retval = mxser_startup(info);	if (retval)		return (retval);	retval = mxser_block_til_ready(tty, filp, info);	if (retval)		return (retval);	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = info->normal_termios;		else			*tty->termios = info->callout_termios;		mxser_change_speed(info, 0);	}	info->session = current->session;	info->pgrp = current->pgrp;	MOD_INC_USE_COUNT;	return (0);}/* * This routine is called when the serial port gets closed.  First, we * wait for the last remaining data to be sent.  Then, we unlink its * async structure from the interrupt chain if necessary, and we free * that IRQ if nothing is left in the chain. */static void mxser_close(struct tty_struct *tty, struct file *filp){	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;	unsigned long flags;	unsigned long timeout;	if (PORTNO(tty) == MXSER_PORTS)		return;	if (!info)		return;	save_flags(flags);	cli();	if (tty_hung_up_p(filp)) {		restore_flags(flags);		MOD_DEC_USE_COUNT;		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("mxser_close: bad serial port count; tty->count is 1, "		       "info->count is %d\n", info->count);		info->count = 1;	}	if (--info->count < 0) {		printk("mxser_close: bad serial port count for ttys%d: %d\n",		       info->port, info->count);		info->count = 0;	}	if (info->count) {		restore_flags(flags);		MOD_DEC_USE_COUNT;		return;	}	info->flags |= ASYNC_CLOSING;	/*	 * Save the termios structure, since this port may have	 * separate termios for callout and dialin.	 */	if (info->flags & ASYNC_NORMAL_ACTIVE)		info->normal_termios = *tty->termios;	if (info->flags & ASYNC_CALLOUT_ACTIVE)		info->callout_termios = *tty->termios;	/*	 * 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);	/*	 * At this point we stop accepting input.  To do this, we	 * disable the receive line status interrupts, and tell the	 * interrupt driver to stop checking the data ready bit in the	 * line status register.	 */	info->IER &= ~UART_IER_RLSI;	/* by William	   info->read_status_mask &= ~UART_LSR_DR;	 */	if (info->flags & ASYNC_INITIALIZED) {		outb(info->IER, info->base + UART_IER);		/*		 * Before we drop DTR, make sure the UART transmitter		 * has completely drained; this is especially		 * important if there is a transmit FIFO!		 */		timeout = jiffies + HZ;		while (!(inb(info->base + UART_LSR) & UART_LSR_TEMT)) {			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(5);			if (jiffies > timeout)				break;		}	}	mxser_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->event = 0;	info->tty = 0;	if (info->blocked_open) {		if (info->close_delay) {			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(info->close_delay);		}		wake_up_interruptible(&info->open_wait);	}	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |			 ASYNC_CLOSING);	wake_up_interruptible(&info->close_wait);	restore_flags(flags);	MOD_DEC_USE_COUNT;}static int mxser_write(struct tty_struct *tty, int from_user,		       const unsigned char *buf, int count){	int c, total = 0;	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;	unsigned long flags;	if (!tty || !info->xmit_buf || !mxvar_tmp_buf)		return (0);	if (from_user)		down(&mxvar_tmp_buf_sem);	save_flags(flags);	while (1) {		cli();		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				   SERIAL_XMIT_SIZE - info->xmit_head));		if (c <= 0)			break;		if (from_user) {			copy_from_user(mxvar_tmp_buf, buf, c);			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				    SERIAL_XMIT_SIZE - info->xmit_head));			memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);		} else			memcpy(info->xmit_buf + info->xmit_head, buf, c);		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);		info->xmit_cnt += c;		restore_flags(flags);		buf += c;		count -= c;		total += c;	}	if (from_user)		up(&mxvar_tmp_buf_sem);	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&	    !(info->IER & UART_IER_THRI)) {		info->IER |= UART_IER_THRI;		outb(info->IER, info->base + UART_IER);	}	restore_flags(flags);	return (total);}static void mxser_put_char(struct tty_struct *tty, unsigned char ch){	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;	unsigned long flags;	if (!tty || !info->xmit_buf)		return;	save_flags(flags);	cli();	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {		restore_flags(flags);		return;	}	info->xmit_buf[info->xmit_head++] = ch;	info->xmit_head &= SERIAL_XMIT_SIZE - 1;	info->xmit_cnt++;	/********************************************** why ??? ***********	if ( !tty->stopped && !tty->hw_stopped &&	     !(info->IER & UART_IER_THRI) ) {	    info->IER |= UART_IER_THRI;	    outb(info->IER, info->base + UART_IER);	}	*****************************************************************/	restore_flags(flags);}static void mxser_flush_chars(struct tty_struct *tty){	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;	unsigned long flags;	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||	    !info->xmit_buf)		return;	save_flags(flags);	cli();	info->IER |= UART_IER_THRI;	outb(info->IER, info->base + UART_IER);	restore_flags(flags);}static int mxser_write_room(struct tty_struct *tty){	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;	int ret;	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;	if (ret < 0)

⌨️ 快捷键说明

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