亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? serial.c

?? LINUX1.0源代碼,代碼條理清晰
?? C
?? 第 1 頁 / 共 4 頁
字號:
	if (!info || !info->tty || !(info->flags & ASYNC_INITIALIZED)) {
		sti();
		return;
	}
	restart_port(info);
	info->IER = (UART_IER_MSI | UART_IER_RLSI |
		     UART_IER_THRI | UART_IER_RDI);
#ifdef ISR_HACK
	serial_out(info, UART_IER, info->IER);
#endif
	sti();
}

/*
 * ------------------------------------------------------------
 * rs_throttle()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled (and that the throttle
 * should be released).
 * ------------------------------------------------------------
 */
static void rs_throttle(struct tty_struct * tty, int status)
{
	struct async_struct *info;
	unsigned char mcr;
	unsigned long flags;

	save_flags(flags); cli();
#if SERIAL_DEBUG_THROTTLE
	printk("throttle tty%d: %d (%d, %d)....\n", DEV_TO_SL(tty->line),
	       status, LEFT(&tty->read_q), LEFT(&tty->secondary));
#endif
	switch (status) {
	case TTY_THROTTLE_RQ_FULL:
		info = rs_table + DEV_TO_SL(tty->line);
		if (I_IXOFF(tty)) {
			info->x_char = STOP_CHAR(tty);
		} else {
			mcr = serial_inp(info, UART_MCR);
			mcr &= ~UART_MCR_RTS;
			serial_out(info, UART_MCR, mcr);
		}
		break;
	case TTY_THROTTLE_RQ_AVAIL:
		info = rs_table + DEV_TO_SL(tty->line);
		if (I_IXOFF(tty)) {
			if (info->x_char)
				info->x_char = 0;
			else
				info->x_char = START_CHAR(tty);
		} else {
			mcr = serial_in(info, UART_MCR);
			mcr |= UART_MCR_RTS;
			serial_out(info, UART_MCR, mcr);
		}
		break;
	}
	restore_flags(flags);
}

/*
 * ------------------------------------------------------------
 * rs_ioctl() and friends
 * ------------------------------------------------------------
 */

static int get_serial_info(struct async_struct * info,
			   struct serial_struct * retinfo)
{
	struct serial_struct tmp;
  
	if (!retinfo)
		return -EFAULT;
	memset(&tmp, 0, sizeof(tmp));
	tmp.type = info->type;
	tmp.line = info->line;
	tmp.port = info->port;
	tmp.irq = info->irq;
	tmp.flags = info->flags;
	tmp.baud_base = info->baud_base;
	tmp.close_delay = info->close_delay;
	tmp.custom_divisor = info->custom_divisor;
	tmp.hub6 = info->hub6;
	memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
	return 0;
}

static int set_serial_info(struct async_struct * info,
			   struct serial_struct * new_info)
{
	struct serial_struct new_serial;
	struct async_struct old_info;
	unsigned int		i,change_irq,change_port;
	int 			retval;
	struct 			sigaction sa;

	if (!new_info)
		return -EFAULT;
	memcpy_fromfs(&new_serial,new_info,sizeof(new_serial));
	old_info = *info;

	change_irq = new_serial.irq != info->irq;
	change_port = (new_serial.port != info->port) || (new_serial.hub6 != info->hub6);

	if (!suser()) {
		if (change_irq || change_port ||
		    (new_serial.baud_base != info->baud_base) ||
		    (new_serial.type != info->type) ||
		    (new_serial.close_delay != info->close_delay) ||
		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
		     (info->flags & ~ASYNC_USR_MASK)))
			return -EPERM;
		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
			       (new_serial.flags & ASYNC_USR_MASK));
		info->custom_divisor = new_serial.custom_divisor;
		goto check_and_exit;
	}

	if (new_serial.irq == 2)
		new_serial.irq = 9;

	if ((new_serial.irq > 15) || (new_serial.port > 0xffff) ||
	    (new_serial.type < PORT_UNKNOWN) || (new_serial.type > PORT_MAX)) {
		return -EINVAL;
	}

	/* Make sure address is not already in use */
	for (i = 0 ; i < NR_PORTS; i++)
		if ((info != &rs_table[i]) &&
		    (rs_table[i].port == new_serial.port) && rs_table[i].type)
			return -EADDRINUSE;

	/*
	 * If necessary, first we try to grab the new IRQ for serial
	 * interrupts.  (We have to do this early, since we may get an
	 * error trying to do this.)
	 */
	if (new_serial.port && new_serial.type && new_serial.irq &&
	    (change_irq || !(info->flags & ASYNC_INITIALIZED))) {
		if (!IRQ_ports[new_serial.irq]) {
			sa.sa_handler = rs_interrupt;
			sa.sa_flags = (SA_INTERRUPT);
			sa.sa_mask = 0;
			sa.sa_restorer = NULL;
			retval = irqaction(new_serial.irq,&sa);
			if (retval)
				return retval;
		}
	}

	if ((change_port || change_irq) && (info->count > 1))
		return -EBUSY;

	/*
	 * OK, past this point, all the error checking has been done.
	 * At this point, we start making changes.....
	 */

	info->baud_base = new_serial.baud_base;
	info->flags = ((info->flags & ~ASYNC_FLAGS) |
			(new_serial.flags & ASYNC_FLAGS));
	info->custom_divisor = new_serial.custom_divisor;
	info->type = new_serial.type;
	info->close_delay = new_serial.close_delay;

	if (change_port || change_irq) {
		/*
		 * We need to shutdown the serial port at the old
		 * port/irq combination.
		 */
		shutdown(info, change_irq);
		info->irq = new_serial.irq;
		info->port = new_serial.port;
		info->hub6 = new_serial.hub6;
	}
	
check_and_exit:
	if (!info->port || !info->type)
		return 0;
	if (info->flags & ASYNC_INITIALIZED) {
		if (((old_info.flags & ASYNC_SPD_MASK) !=
		     (info->flags & ASYNC_SPD_MASK)) ||
		    (old_info.custom_divisor != info->custom_divisor))
			change_speed(info->line);
	} else
		(void) startup(info, 0);
	return 0;
}

static int get_modem_info(struct async_struct * info, unsigned int *value)
{
	unsigned char control, status;
	unsigned int result;

	cli();
	control = serial_in(info, UART_MCR);
	status = serial_in(info, UART_MSR);
	sti();
	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
	put_fs_long(result,(unsigned long *) value);
	return 0;
}

static int set_modem_info(struct async_struct * info, unsigned int cmd,
			  unsigned int *value)
{
	unsigned char control;
	unsigned int arg = get_fs_long((unsigned long *) value);
	
	cli();
	control = serial_in(info, UART_MCR);
	sti();

	switch (cmd) {
		case TIOCMBIS:
			if (arg & TIOCM_RTS)
				control |= UART_MCR_RTS;
			if (arg & TIOCM_DTR)
				control |= UART_MCR_DTR;
			break;
		case TIOCMBIC:
			if (arg & TIOCM_RTS)
				control &= ~UART_MCR_RTS;
			if (arg & TIOCM_DTR)
				control &= ~UART_MCR_DTR;
			break;
		case TIOCMSET:
			control = (control & ~(UART_MCR_RTS | UART_MCR_DTR))
				| ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
				| ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0);
			break;
		default:
			return -EINVAL;
	}
	cli();
	serial_out(info, UART_MCR, control);
	sti();
	return 0;
}

static int do_autoconfig(struct async_struct * info)
{
	int			retval;
	
	if (!suser())
		return -EPERM;
	
	if (info->count > 1)
		return -EBUSY;
	
	shutdown(info, 1);

	cli();
	autoconfig(info);
	sti();

	retval = startup(info, 1);
	if (retval)
		return retval;
	return 0;
}


/*
 * This routine sends a break character out the serial port.
 */
static void send_break(	struct async_struct * info, int duration)
{
	if (!info->port)
		return;
	current->state = TASK_INTERRUPTIBLE;
	current->timeout = jiffies + duration;
	cli();
	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) | UART_LCR_SBC);
	schedule();
	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
	sti();
}

/*
 * This routine returns a bitfield of "wild interrupts".  Basically,
 * any unclaimed interrupts which is flapping around.
 */
static int check_wild_interrupts(int doprint)
{
	int	i, mask;
	int	wild_interrupts = 0;
	int	irq_lines;
	unsigned long timeout;
	unsigned long flags;
	
	/* Turn on interrupts (they may be off) */
	save_flags(flags); sti();

	irq_lines = grab_all_interrupts(0);
	
	/*
	 * Delay for 0.1 seconds -- we use a busy loop since this may 
	 * occur during the bootup sequence
	 */
	timeout = jiffies+10;
	while (timeout >= jiffies)
		;
	
	rs_triggered = 0;	/* Reset after letting things settle */

	timeout = jiffies+10;
	while (timeout >= jiffies)
		;
	
	for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
		if ((rs_triggered & (1 << i)) &&
		    (irq_lines & (1 << i))) {
			wild_interrupts |= mask;
			if (doprint)
				printk("Wild interrupt?  (IRQ %d)\n", i);
		}
	}
	free_all_interrupts(irq_lines);
	restore_flags(flags);
	return wild_interrupts;
}

static int rs_ioctl(struct tty_struct *tty, struct file * file,
		    unsigned int cmd, unsigned long arg)
{
	int error, line;
	struct async_struct * info;

	line = DEV_TO_SL(tty->line);
	if (line < 0 || line >= NR_PORTS)
		return -ENODEV;
	info = rs_table + line;
	
	switch (cmd) {
		case TCSBRK:	/* SVID version: non-zero arg --> no break */
			if (!arg)
				send_break(info, HZ/4);	/* 1/4 second */
			return 0;
		case TCSBRKP:	/* support for POSIX tcsendbreak() */
			send_break(info, arg ? arg*(HZ/10) : HZ/4);
			return 0;
		case TIOCGSOFTCAR:
			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
			if (error)
				return error;
			put_fs_long(C_CLOCAL(tty) ? 1 : 0,
				    (unsigned long *) arg);
			return 0;
		case TIOCSSOFTCAR:
			arg = get_fs_long((unsigned long *) arg);
			tty->termios->c_cflag =
				((tty->termios->c_cflag & ~CLOCAL) |
				 (arg ? CLOCAL : 0));
			return 0;
		case TIOCMGET:
			error = verify_area(VERIFY_WRITE, (void *) arg,
				sizeof(unsigned int));
			if (error)
				return error;
			return get_modem_info(info, (unsigned int *) arg);
		case TIOCMBIS:
		case TIOCMBIC:
		case TIOCMSET:
			return set_modem_info(info, cmd, (unsigned int *) arg);
		case TIOCGSERIAL:
			error = verify_area(VERIFY_WRITE, (void *) arg,
						sizeof(struct serial_struct));
			if (error)
				return error;
			return get_serial_info(info,
					       (struct serial_struct *) arg);
		case TIOCSSERIAL:
			return set_serial_info(info,
					       (struct serial_struct *) arg);
		case TIOCSERCONFIG:
			return do_autoconfig(info);

		case TIOCSERGWILD:
			error = verify_area(VERIFY_WRITE, (void *) arg,
					    sizeof(int));
			if (error)
				return error;
			put_fs_long(rs_wild_int_mask, (unsigned long *) arg);
			return 0;

		case TIOCSERSWILD:
			if (!suser())
				return -EPERM;
			rs_wild_int_mask = get_fs_long((unsigned long *) arg);
			if (rs_wild_int_mask < 0)
				rs_wild_int_mask = check_wild_interrupts(0);
			return 0;

		default:
			return -EINVAL;
		}
	return 0;
}

static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
	struct async_struct *info;

	if (tty->termios->c_cflag == old_termios->c_cflag)
		return;

	info = &rs_table[DEV_TO_SL(tty->line)];

	change_speed(DEV_TO_SL(tty->line));
	
	if ((old_termios->c_cflag & CRTSCTS) &&
	    !(tty->termios->c_cflag & CRTSCTS)) {
		tty->hw_stopped = 0;
		rs_write(tty);
	}

	if (!(old_termios->c_cflag & CLOCAL) &&
	    (tty->termios->c_cflag & CLOCAL))
		wake_up_interruptible(&info->open_wait);

	if (I_INPCK(tty))
		info->read_status_mask = (UART_LSR_OE | UART_LSR_BI |
					  UART_LSR_FE | UART_LSR_PE);
	else
		info->read_status_mask = (UART_LSR_OE | UART_LSR_BI |
					  UART_LSR_FE);
}

/*
 * ------------------------------------------------------------
 * rs_close()
 * 
 * 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 rs_close(struct tty_struct *tty, struct file * filp)
{
	struct async_struct * info;
	int line;

	if (tty_hung_up_p(filp))
		return;
	
	line = DEV_TO_SL(tty->line);
	if ((line < 0) || (line >= NR_PORTS))
		return;
	info = rs_table + line;
#ifdef SERIAL_DEBUG_OPEN
	printk("rs_close ttys%d, count = %d\n", info->line, info->count);
#endif
	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("rs_close: bad serial port count; tty->count is 1, "
		       "info->count is %d\n", info->count);
		info->count = 1;
	}
	if (--info->count < 0) {
		printk("rs_close: bad serial port count for ttys%d: %d\n",
		       info->line, info->count);
		info->count = 0;
	}
	if (info->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;
	tty->stopped = 0;		/* Force flush to succeed */
	tty->hw_stopped = 0;
	if (info->flags & ASYNC_INITIALIZED) {
		rs_start(tty);
		wait_until_sent(tty, 6000); /* 60 seconds timeout */
	} else
		flush_output(tty);
	flush_input(tty);
	cli();
	/*
	 * Make sure the UART transmitter has completely drained; this
	 * is especially important if there is a transmit FIFO!
	 */
	if (!(serial_inp(info, UART_LSR) & UART_LSR_THRE)) {
		rs_start(tty);	/* Make sure THRI interrupt enabled */
		interruptible_sleep_on(&info->xmit_wait);
	}
	sti();
	shutdown(info, 1);
	clear_bit(line, rs_event);
	info->event = 0;
	info->tty = 0;
	if (info->blocked_open) {
		if (info->close_delay) {
			tty->count++; /* avoid race condition */
			current->state = TASK_INTERRUPTIBLE;
			current->timeout = jiffies + info->close_delay;
			schedule();
			tty->count--;
		}
		wake_up_interruptible(&info->open_wait);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美精品高清视频| 精品一区二区免费在线观看| 色综合久久综合| 亚洲欧美在线视频观看| 在线免费亚洲电影| 天堂资源在线中文精品| 欧美一级久久久| 国产成人av福利| 亚洲日本韩国一区| 制服丝袜中文字幕一区| 精品一区二区三区影院在线午夜| 久久综合视频网| 99精品久久99久久久久| 午夜精品久久久久久久99樱桃| 欧美成va人片在线观看| 91在线观看污| 奇米四色…亚洲| 国产精品天天摸av网| 欧美日韩高清不卡| 国产福利一区二区三区视频| 一区二区三区四区亚洲| 日韩一区二区在线观看视频| 成人晚上爱看视频| 香蕉久久夜色精品国产使用方法 | 97久久精品人人做人人爽| 一区二区三区波多野结衣在线观看| 欧美日韩和欧美的一区二区| 国产精品小仙女| 一区二区三区四区激情| 精品国产乱码久久久久久影片| 一本大道av伊人久久综合| 毛片基地黄久久久久久天堂| 最好看的中文字幕久久| 日韩免费在线观看| 色婷婷综合久久| 国产剧情一区在线| 视频一区二区欧美| 自拍偷拍欧美激情| 久久天天做天天爱综合色| 91黄色免费观看| 国产iv一区二区三区| 日本伊人精品一区二区三区观看方式| 国产精品国产精品国产专区不片| 日韩视频免费观看高清完整版 | av在线免费不卡| 日本欧美在线看| 亚洲小少妇裸体bbw| 中文字幕日韩欧美一区二区三区| 精品久久人人做人人爰| 777欧美精品| 日本国产一区二区| 成人夜色视频网站在线观看| 狠狠色丁香婷综合久久| 偷拍日韩校园综合在线| 洋洋成人永久网站入口| 中文字幕日本不卡| 久久综合av免费| 91精品国产黑色紧身裤美女| 欧美伊人精品成人久久综合97| 处破女av一区二区| 激情五月播播久久久精品| 免费人成网站在线观看欧美高清| 亚洲尤物视频在线| 亚洲精品免费视频| 成人欧美一区二区三区黑人麻豆| 国产日韩欧美在线一区| 26uuu精品一区二区| 日韩精品一区二区三区视频在线观看| 欧美三级一区二区| 欧洲精品在线观看| 色爱区综合激月婷婷| 色悠悠亚洲一区二区| 色综合久久综合网97色综合| 一本一道综合狠狠老| 一本久久a久久精品亚洲| 色天天综合久久久久综合片| 91美女片黄在线观看91美女| 色噜噜狠狠成人中文综合| 成人免费视频一区二区| jlzzjlzz欧美大全| 日本精品裸体写真集在线观看| 日本韩国欧美在线| 在线观看视频91| 91麻豆精品国产| 精品三级av在线| 国产欧美精品在线观看| 亚洲丝袜制服诱惑| 一区二区三区国产精品| 亚洲成在线观看| 日韩成人免费电影| 久久99国产精品麻豆| 国产精品一区二区久久精品爱涩 | 成人久久18免费网站麻豆| 91香蕉视频mp4| 欧美午夜不卡在线观看免费| 91精品国产色综合久久久蜜香臀| 日韩精品一区二区三区四区视频| 国产欧美日韩亚州综合 | 国产欧美日韩精品在线| 综合在线观看色| 亚洲一级不卡视频| 麻豆成人综合网| 成人在线视频一区二区| 色天使久久综合网天天| 91精品国产综合久久久久久漫画 | 国产精品久久网站| 亚洲国产欧美在线人成| 精品午夜一区二区三区在线观看| 懂色av一区二区三区免费观看| 一本久久a久久免费精品不卡| 欧美日韩精品二区第二页| 26uuu亚洲| 一区二区在线观看视频| 狠狠网亚洲精品| 在线精品视频一区二区| 久久在线观看免费| 亚洲黄色小说网站| 国内精品久久久久影院色| 欧美亚洲综合一区| 国产日韩欧美高清在线| 丝袜亚洲另类欧美综合| 成人自拍视频在线| 欧美一区二区播放| 亚洲欧美偷拍卡通变态| 国产盗摄视频一区二区三区| 欧美无人高清视频在线观看| 久久精品日韩一区二区三区| 性做久久久久久久免费看| 国产成人在线视频网站| 91精品国产一区二区| 亚洲精品免费播放| 高潮精品一区videoshd| 日韩一区二区三区观看| 亚洲精品精品亚洲| 国产成人在线视频播放| 日韩欧美aaaaaa| 亚洲高清免费在线| 91麻豆国产自产在线观看| 久久久久久免费网| 久久精品国产精品青草| 欧美绝品在线观看成人午夜影视| 亚洲三级久久久| 成人免费看黄yyy456| 久久久久青草大香线综合精品| 婷婷久久综合九色综合伊人色| 97国产精品videossex| 国产精品视频yy9299一区| 国产一区二区美女诱惑| 欧美精品一区男女天堂| 免费人成黄页网站在线一区二区 | 91年精品国产| 久久精品夜色噜噜亚洲aⅴ| 蜜桃视频免费观看一区| 欧美一区二区视频网站| 亚洲第一狼人社区| 精品视频一区二区三区免费| 亚洲资源在线观看| 91免费观看视频| 亚洲色图自拍偷拍美腿丝袜制服诱惑麻豆 | 欧美久久久久久久久中文字幕| 亚洲欧洲日产国产综合网| 床上的激情91.| 日本一区二区三区四区在线视频 | 亚洲第一会所有码转帖| 精品视频全国免费看| 亚洲一区在线观看免费观看电影高清| 色视频成人在线观看免| 一区二区高清免费观看影视大全| 一本色道a无线码一区v| 亚洲愉拍自拍另类高清精品| 欧美日本在线观看| 日韩黄色在线观看| 欧美一区二区三区在线观看| 久久精品国产亚洲高清剧情介绍 | 91在线视频官网| 欧美激情综合在线| 成人毛片在线观看| 亚洲人成电影网站色mp4| 91极品美女在线| 蜜桃视频一区二区三区在线观看| 欧美tickling网站挠脚心| 国产自产视频一区二区三区| 国产天堂亚洲国产碰碰| gogo大胆日本视频一区| 亚洲国产成人av好男人在线观看| 欧美日韩国产一级| 久久精品国产一区二区三| 亚洲国产精品国自产拍av| 一本在线高清不卡dvd| 日韩成人一区二区三区在线观看| 精品福利视频一区二区三区| 成人精品鲁一区一区二区| 一区二区三区在线视频观看58| 91精品久久久久久久久99蜜臂| 国产乱人伦精品一区二区在线观看| 中文字幕永久在线不卡| 欧美美女bb生活片| 国产精品羞羞答答xxdd| 亚洲一区二区免费视频| 久久久久久一二三区|