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

📄 dz.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	restore_flags (flags);}/*  * ------------------------------------------------------------------- * change_speed () * * set the baud rate. * -------------------------------------------------------------------  */static void change_speed (struct dz_serial *info){	unsigned long flags;	unsigned cflag;	int baud;	if (!info->tty || !info->tty->termios)		return;  	save_and_cli(flags);  	info->cflags = info->line;	cflag = info->tty->termios->c_cflag;	switch (cflag & CSIZE) {		case CS5:			info->cflags |= DZ_CS5;			break;		case CS6:			info->cflags |= DZ_CS6;			break;		case CS7:			info->cflags |= DZ_CS7;			break;		case CS8: 		default:			info->cflags |= DZ_CS8;	}	if (cflag & CSTOPB)		info->cflags |= DZ_CSTOPB;	if (cflag & PARENB)		info->cflags |= DZ_PARENB;	if (cflag & PARODD)		info->cflags |= DZ_PARODD;  	baud = tty_get_baud_rate(info->tty);	switch (baud) {	case 50:		info->cflags |= DZ_B50;		break;	case 75:		info->cflags |= DZ_B75;		break;	case 110:		info->cflags |= DZ_B110;		break;	case 134:		info->cflags |= DZ_B134;		break; 	case 150:		info->cflags |= DZ_B150;		break;	case 300:		info->cflags |= DZ_B300;		break; 	case 600:		info->cflags |= DZ_B600;		break;	case 1200:		info->cflags |= DZ_B1200;		break; 	case 1800:		info->cflags |= DZ_B1800;		break;	case 2000:		info->cflags |= DZ_B2000;		break;	case 2400:		info->cflags |= DZ_B2400;		break;	case 3600:		info->cflags |= DZ_B3600;		break; 	case 4800:		info->cflags |= DZ_B4800;		break;	case 7200:		info->cflags |= DZ_B7200;		break; 	case 9600: 	default:		info->cflags |= DZ_B9600; 	}	info->cflags |= DZ_RXENAB;	dz_out(info, DZ_LPR, info->cflags);	/* setup accept flag */	info->read_status_mask = DZ_OERR;	if (I_INPCK(info->tty))		info->read_status_mask |= (DZ_FERR | DZ_PERR);   	/* characters to ignore */	info->ignore_status_mask = 0;	if (I_IGNPAR(info->tty))		info->ignore_status_mask |= (DZ_FERR | DZ_PERR);	restore_flags(flags);}/*  * ------------------------------------------------------------------- * dz_flush_char () * * Flush the buffer. * -------------------------------------------------------------------  */static void dz_flush_chars (struct tty_struct *tty){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;	unsigned long flags;	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||	    !info->xmit_buf)		return;	save_and_cli(flags);	dz_start (info->tty);	restore_flags(flags);}/*  * ------------------------------------------------------------------- * dz_write () * * main output routine. * -------------------------------------------------------------------  */static int dz_write (struct tty_struct *tty, int from_user,                     const unsigned char *buf, int count){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;	unsigned long flags;	int c, ret = 0;	if (!tty )		return ret;	if (!info->xmit_buf)		return ret;	if (!tmp_buf)		tmp_buf = tmp_buffer;	if (from_user) {		down (&tmp_buf_sem);		while (1) {			c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1,			                   DZ_XMIT_SIZE - info->xmit_head));			if (c <= 0)				break;			c -= copy_from_user (tmp_buf, buf, c);			if (!c) {				if (!ret)					ret = -EFAULT;				break;			}			save_and_cli(flags);			c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1,			               DZ_XMIT_SIZE - info->xmit_head));			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);			info->xmit_head = ((info->xmit_head + c) &					   (DZ_XMIT_SIZE - 1));			info->xmit_cnt += c;			restore_flags(flags);			buf += c;			count -= c;			ret += c;		}		up(&tmp_buf_sem);	} else {		while (1) {			save_and_cli(flags);			c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1,			                   DZ_XMIT_SIZE - info->xmit_head));			if (c <= 0) {				restore_flags (flags);				break;			}			memcpy(info->xmit_buf + info->xmit_head, buf, c);			info->xmit_head = ((info->xmit_head + c) &			                   (DZ_XMIT_SIZE-1));			info->xmit_cnt += c;			restore_flags(flags);			buf += c;			count -= c;			ret += c;		}	}	if (info->xmit_cnt) {		if (!tty->stopped) {			if (!tty->hw_stopped) {				dz_start (info->tty);			}		}	}	return ret;}/*  * ------------------------------------------------------------------- * dz_write_room () * * compute the amount of space available for writing. * -------------------------------------------------------------------  */static int dz_write_room (struct tty_struct *tty){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;	int ret;	ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;	if (ret < 0)		ret = 0;	return ret;}/*  * ------------------------------------------------------------------- * dz_chars_in_buffer () * * compute the amount of char left to be transmitted * -------------------------------------------------------------------  */static int dz_chars_in_buffer (struct tty_struct *tty){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;  	return info->xmit_cnt;}/*  * ------------------------------------------------------------------- * dz_flush_buffer () * * Empty the output buffer * -------------------------------------------------------------------  */static void dz_flush_buffer (struct tty_struct *tty){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;                                	cli();	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	sti();	wake_up_interruptible (&tty->write_wait);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	     tty->ldisc.write_wakeup)		tty->ldisc.write_wakeup(tty);}/* * ------------------------------------------------------------ * dz_throttle () and dz_unthrottle () *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled (or not). * ------------------------------------------------------------ */static void dz_throttle (struct tty_struct *tty){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;  	if (I_IXOFF(tty))		info->x_char = STOP_CHAR(tty);}static void dz_unthrottle (struct tty_struct *tty){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;  	if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			info->x_char = START_CHAR(tty);	}}static void dz_send_xchar (struct tty_struct *tty, char ch){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;	info->x_char = ch;	if (ch)		dz_start(info->tty);}/* * ------------------------------------------------------------ * rs_ioctl () and friends * ------------------------------------------------------------ */static int get_serial_info(struct dz_serial *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 = SERIAL;	tmp.flags = info->flags;	tmp.baud_base = info->baud_base;	tmp.close_delay = info->close_delay;	tmp.closing_wait = info->closing_wait;	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;}static int set_serial_info (struct dz_serial *info,                            struct serial_struct *new_info){	struct serial_struct new_serial;	struct dz_serial old_info;	int retval = 0;	if (!new_info)		return -EFAULT;	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))		return -EFAULT;	old_info = *info;	if (!capable(CAP_SYS_ADMIN))		return -EPERM;	if (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->type = new_serial.type;	info->close_delay = new_serial.close_delay;	info->closing_wait = new_serial.closing_wait;	retval = startup(info);	return retval;}/* * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically *          is emptied.  On bus types like RS485, the transmitter must *          release the bus after transmitting. This must be done when *          the transmit shift register is empty, not be done when the *          transmit holding register is empty.  This functionality *          allows an RS485 driver to be written in user space.  */static int get_lsr_info (struct dz_serial *info, unsigned int *value){	unsigned short status = dz_in (info, DZ_LPR);	return put_user (status, value);}/* * This routine sends a break character out the serial port. */static void send_break (struct dz_serial *info, int duration){	unsigned long flags;	unsigned short tmp, mask;	if (!info->port)		return;	mask = 1 << info->line;	tmp = dz_in (info, DZ_TCR);	tmp |= mask;	current->state = TASK_INTERRUPTIBLE;	save_and_cli(flags);	dz_out(info, DZ_TCR, tmp);	schedule_timeout(duration);	tmp &= ~mask;	dz_out(info, DZ_TCR, tmp);	restore_flags(flags);}static int dz_ioctl(struct tty_struct *tty, struct file *file,                    unsigned int cmd, unsigned long arg){	int error;	struct dz_serial * info = (struct dz_serial *)tty->driver_data;	int retval;	if (cmd != TIOCGSERIAL && cmd != TIOCSSERIAL &&	    cmd != TIOCSERCONFIG && cmd != TIOCSERGWILD  &&	    cmd != TIOCSERSWILD && cmd != TIOCSERGSTRUCT) {		if (tty->flags & (1 << TTY_IO_ERROR))			return -EIO;	}	switch (cmd) {	case TCSBRK:		/* SVID version: non-zero arg --> no break */		retval = tty_check_change(tty);		if (retval)			return retval;		tty_wait_until_sent(tty, 0);		if (!arg)			send_break(info, HZ/4); /* 1/4 second */		return 0;	case TCSBRKP:		/* support for POSIX tcsendbreak() */		retval = tty_check_change(tty);		if (retval)			return retval;		tty_wait_until_sent(tty, 0);		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_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);		return 0;	case TIOCSSOFTCAR:		if (get_user (arg, (unsigned long *)arg))			return -EFAULT;		tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) |		                        (arg ? CLOCAL : 0);		return 0;	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 TIOCSERGETLSR:		/* Get line status register */		return get_lsr_info (info, (unsigned int *)arg);	case TIOCSERGSTRUCT:		return copy_to_user((struct dz_serial *)arg, info,		                    sizeof(struct dz_serial)) ? -EFAULT : 0; 	default:		return -ENOIOCTLCMD;	}	return 0;}static void dz_set_termios (struct tty_struct *tty,			    struct termios *old_termios){	struct dz_serial *info = (struct dz_serial *)tty->driver_data;	if (tty->termios->c_cflag == old_termios->c_cflag)		return;	change_speed (info);	if ((old_termios->c_cflag & CRTSCTS) &&	    !(tty->termios->c_cflag & CRTSCTS)) {		tty->hw_stopped = 0;		dz_start(tty);	}}/* * ------------------------------------------------------------ * dz_close() *  * This routine is called when the serial port gets closed.  First, we * wait for the last remaining data to be sent.  Then, we turn off * the transmit enable and receive enable flags. * ------------------------------------------------------------ */static void dz_close(struct tty_struct *tty, struct file *filp){	struct dz_serial * info = (struct dz_serial *)tty->driver_data;	unsigned long flags;	if (!info)		return; 	save_and_cli(flags); 	if (tty_hung_up_p(filp)) {		restore_flags(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("dz_close: bad serial port count; tty->count is 1, "		       "info->count is %d\n", info->count);		info->count = 1;	}	if (--info->count < 0) {		printk("ds_close: bad serial port count for ttyS%02d: %d\n",		       info->line, info->count);

⌨️ 快捷键说明

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