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

📄 mxser.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (info->xmit_cnt <= 0) {		info->IER &= ~UART_IER_THRI;		outb(info->IER, info->base + UART_IER);	}}static inline void mxser_check_modem_status(struct mxser_struct *info,					      int status){	/* update input line counters */	if (status & UART_MSR_TERI)		info->icount.rng++;	if (status & UART_MSR_DDSR)		info->icount.dsr++;	if (status & UART_MSR_DDCD)		info->icount.dcd++;	if (status & UART_MSR_DCTS)		info->icount.cts++;	wake_up_interruptible(&info->delta_msr_wait);	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {		if (status & UART_MSR_DCD)			wake_up_interruptible(&info->open_wait);		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&			   (info->flags & ASYNC_CALLOUT_NOHUP)))			set_bit(MXSER_EVENT_HANGUP, &info->event);		schedule_task(&info->tqueue);	}	if (info->flags & ASYNC_CTS_FLOW) {		if (info->tty->hw_stopped) {			if (status & UART_MSR_CTS) {				info->tty->hw_stopped = 0;				info->IER |= UART_IER_THRI;				outb(info->IER, info->base + UART_IER);				set_bit(MXSER_EVENT_TXLOW, &info->event);				MOD_INC_USE_COUNT;				if (schedule_task(&info->tqueue) == 0)					MOD_DEC_USE_COUNT;			}		} else {			if (!(status & UART_MSR_CTS)) {				info->tty->hw_stopped = 1;				info->IER &= ~UART_IER_THRI;				outb(info->IER, info->base + UART_IER);			}		}	}}static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,				 struct mxser_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 this is a callout device, then just make sure the normal	 * device isn't being used.	 */	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {		if (info->flags & ASYNC_NORMAL_ACTIVE)			return (-EBUSY);		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&		    (info->flags & ASYNC_SESSION_LOCKOUT) &&		    (info->session != current->session))			return (-EBUSY);		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&		    (info->flags & ASYNC_PGRP_LOCKOUT) &&		    (info->pgrp != current->pgrp))			return (-EBUSY);		info->flags |= ASYNC_CALLOUT_ACTIVE;		return (0);	}	/*	 * 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))) {		if (info->flags & ASYNC_CALLOUT_ACTIVE)			return (-EBUSY);		info->flags |= ASYNC_NORMAL_ACTIVE;		return (0);	}	if (info->flags & ASYNC_CALLOUT_ACTIVE) {		if (info->normal_termios.c_cflag & CLOCAL)			do_clocal = 1;	} else {		if (tty->termios->c_cflag & CLOCAL)			do_clocal = 1;	}	/*	 * Block waiting for the carrier detect and the line to become	 * free (i.e., not in use by the callout).  While we are in	 * this loop, info->count is dropped by one, so that	 * mxser_close() knows when to free things.  We restore it upon	 * exit, either normal or abnormal.	 */	retval = 0;	add_wait_queue(&info->open_wait, &wait);	save_flags(flags);	cli();	if (!tty_hung_up_p(filp))		info->count--;	restore_flags(flags);	info->blocked_open++;	while (1) {		save_flags(flags);		cli();		if (!(info->flags & ASYNC_CALLOUT_ACTIVE))			outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS,			     info->base + UART_MCR);		restore_flags(flags);		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;		}		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&		    !(info->flags & ASYNC_CLOSING) &&		    (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)))			break;		if (signal_pending(current)) {			retval = -ERESTARTSYS;			break;		}		schedule();	}	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 int mxser_startup(struct mxser_struct *info){	unsigned long flags;	unsigned long page;	page = get_free_page(GFP_KERNEL);	if (!page)		return (-ENOMEM);	save_flags(flags);	cli();	if (info->flags & ASYNC_INITIALIZED) {		free_page(page);		restore_flags(flags);		return (0);	}	if (!info->base || !info->type) {		if (info->tty)			set_bit(TTY_IO_ERROR, &info->tty->flags);		free_page(page);		restore_flags(flags);		return (0);	}	if (info->xmit_buf)		free_page(page);	else		info->xmit_buf = (unsigned char *) page;	/*	 * Clear the FIFO buffers and disable them	 * (they will be reenabled in mxser_change_speed())	 */	if (info->xmit_fifo_size == 16)		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),		     info->base + UART_FCR);	/*	 * At this point there's no way the LSR could still be 0xFF;	 * if it is, then bail out, because there's likely no UART	 * here.	 */	if (inb(info->base + UART_LSR) == 0xff) {		restore_flags(flags);		if (suser()) {			if (info->tty)				set_bit(TTY_IO_ERROR, &info->tty->flags);			return (0);		} else			return (-ENODEV);	}	/*	 * Clear the interrupt registers.	 */	(void) inb(info->base + UART_LSR);	(void) inb(info->base + UART_RX);	(void) inb(info->base + UART_IIR);	(void) inb(info->base + UART_MSR);	/*	 * Now, initialize the UART	 */	outb(UART_LCR_WLEN8, info->base + UART_LCR);	/* reset DLAB */	info->MCR = UART_MCR_DTR | UART_MCR_RTS;	outb(info->MCR, info->base + UART_MCR);	/*	 * Finally, enable interrupts	 */	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;	outb(info->IER, info->base + UART_IER);		/* enable interrupts */	/*	 * And clear the interrupt registers again for luck.	 */	(void) inb(info->base + UART_LSR);	(void) inb(info->base + UART_RX);	(void) inb(info->base + UART_IIR);	(void) inb(info->base + UART_MSR);	if (info->tty)		test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags);	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	/*	 * and set the speed of the serial port	 */	mxser_change_speed(info, 0);	info->flags |= ASYNC_INITIALIZED;	restore_flags(flags);	return (0);}/* * This routine will shutdown a serial port; interrupts maybe disabled, and * DTR is dropped if the hangup on close termio flag is on. */static void mxser_shutdown(struct mxser_struct *info){	unsigned long flags;	if (!(info->flags & ASYNC_INITIALIZED))		return;	save_flags(flags);	cli();			/* Disable interrupts */	/*	 * 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);	/*	 * Free the IRQ, if necessary	 */	if (info->xmit_buf) {		free_page((unsigned long) info->xmit_buf);		info->xmit_buf = 0;	}	info->IER = 0;	outb(0x00, info->base + UART_IER);	/* disable all intrs */	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))		info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);	outb(info->MCR, info->base + UART_MCR);	/* clear Rx/Tx FIFO's */	outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);	/* read data port to reset things */	(void) inb(info->base + UART_RX);	if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags &= ~ASYNC_INITIALIZED;	restore_flags(flags);}/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */static int mxser_change_speed(struct mxser_struct *info,			      struct termios *old_termios){	int quot = 0;	unsigned cflag, cval, fcr;	int i;	int ret = 0;	unsigned long flags;	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;	/* 57600 bps */		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)			i = 17;	/* 115200 bps */#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 (mxvar_baud_table[i] == 134) {		quot = (2 * info->baud_base / 269);	} else if (mxvar_baud_table[i]) {		quot = info->baud_base / mxvar_baud_table[i];		if (!quot && old_termios) {			/* re-calculate */			info->tty->termios->c_cflag &= ~CBAUD;			info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);			switch (info->tty->termios->c_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) {

⌨️ 快捷键说明

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