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

📄 sab82532.c

📁 移植到2410开发板上的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (cflag & PARENB) {		dafo |= SAB82532_DAFO_PARE;		bits++;	}	if (cflag & PARODD) {#ifdef CMSPAR		if (cflag & CMSPAR)			dafo |= SAB82532_DAFO_PAR_MARK;		else#endif			dafo |= SAB82532_DAFO_PAR_ODD;	} else {#ifdef CMSPAR		if (cflag & CMSPAR)			dafo |= SAB82532_DAFO_PAR_SPACE;		else#endif			dafo |= SAB82532_DAFO_PAR_EVEN;	}	/* Determine EBRG values based on baud rate */	info->baud = tty_get_baud_rate(info->tty);	calc_ebrg(info->baud, &n, &m);		ebrg = n | (m << 6);	if (info->baud) {		info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;		info->tec_timeout = (10 * 1000000) / info->baud;		info->cec_timeout = info->tec_timeout >> 2;	} else {		info->timeout = 0;		info->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;		info->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;	}	info->timeout += HZ / 50;		/* Add .02 seconds of slop */	/* CTS flow control flags */	if (cflag & CRTSCTS)		info->flags |= ASYNC_CTS_FLOW;	else		info->flags &= ~(ASYNC_CTS_FLOW);	if (cflag & CLOCAL)		info->flags &= ~(ASYNC_CHECK_CD);	else		info->flags |= ASYNC_CHECK_CD;	if (info->tty)		info->tty->hw_stopped = 0;	/*	 * Set up parity check flag	 * XXX: not implemented, yet.	 */#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))	/*	 * Characters to ignore	 * XXX: not implemented, yet.	 */	/*	 * !!! ignore all characters if CREAD is not set	 * XXX: not implemented, yet.	 */	if ((cflag & CREAD) == 0)		info->ignore_status_mask |= SAB82532_ISR0_RPF |					    SAB82532_ISR0_TCD |					    SAB82532_ISR0_TIME;	save_flags(flags); cli();	sab82532_cec_wait(info);	sab82532_tec_wait(info);	writeb(dafo, &info->regs->w.dafo);	writeb(ebrg & 0xff, &info->regs->w.bgr);	writeb(readb(&info->regs->rw.ccr2) & ~(0xc0), &info->regs->rw.ccr2);	writeb(readb(&info->regs->rw.ccr2) | ((ebrg >> 2) & 0xc0), &info->regs->rw.ccr2);	if (info->flags & ASYNC_CTS_FLOW) {		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode);		info->interrupt_mask1 &= ~(SAB82532_IMR1_CSC);		writeb(info->interrupt_mask1, &info->regs->w.imr1);	} else {		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode);		info->interrupt_mask1 |= SAB82532_IMR1_CSC;		writeb(info->interrupt_mask1, &info->regs->w.imr1);	}	writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode);	restore_flags(flags);}static void sab82532_put_char(struct tty_struct *tty, unsigned char ch){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "sab82532_put_char"))		return;	if (!tty || !info->xmit.buf)		return;	save_flags(flags); cli();	if (!CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE)) {		restore_flags(flags);		return;	}	info->xmit.buf[info->xmit.head] = ch;	info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);	restore_flags(flags);}static void sab82532_flush_chars(struct tty_struct *tty){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "sab82532_flush_chars"))		return;	if ((info->xmit.head == info->xmit.tail) ||	    tty->stopped || tty->hw_stopped || !info->xmit.buf)		return;	save_flags(flags); cli();	info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);	writeb(info->interrupt_mask1, &info->regs->w.imr1);	sab82532_start_tx(info);	restore_flags(flags);}static int sab82532_write(struct tty_struct * tty, int from_user,			  const unsigned char *buf, int count){	int c, ret = 0;	struct sab82532 *info = (struct sab82532 *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "sab82532_write"))		return 0;	if (!tty || !info->xmit.buf || !tmp_buf)		return 0;	    	save_flags(flags);	if (from_user) {		down(&tmp_buf_sem);		while (1) {			int c1;			c = CIRC_SPACE_TO_END(info->xmit.head,					      info->xmit.tail,					      SERIAL_XMIT_SIZE);			if (count < c)				c = count;			if (c <= 0)				break;			c -= copy_from_user(tmp_buf, buf, c);			if (!c) {				if (!ret)					ret = -EFAULT;				break;			}			cli();			c1 = CIRC_SPACE_TO_END(info->xmit.head,					       info->xmit.tail,					       SERIAL_XMIT_SIZE);			if (c1 < c)				c = c1;			memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);			info->xmit.head = (info->xmit.head + c) & (SERIAL_XMIT_SIZE-1);			restore_flags(flags);			buf += c;			count -= c;			ret += c;		}		up(&tmp_buf_sem);	} else {		cli();		while (1) {			c = CIRC_SPACE_TO_END(info->xmit.head,					      info->xmit.tail,					      SERIAL_XMIT_SIZE);			if (count < c)				c = count;			if (c <= 0)				break;			memcpy(info->xmit.buf + info->xmit.head, buf, c);			info->xmit.head = (info->xmit.head + c) & (SERIAL_XMIT_SIZE-1);			buf += c;			count -= c;			ret += c;		}		restore_flags(flags);	}	if ((info->xmit.head != info->xmit.tail) &&	    !tty->stopped && !tty->hw_stopped) {		info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);		writeb(info->interrupt_mask1, &info->regs->w.imr1);		sab82532_start_tx(info);	}	restore_flags(flags);	return ret;}static int sab82532_write_room(struct tty_struct *tty){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;	if (serial_paranoia_check(info, tty->device, "sab82532_write_room"))		return 0;	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);}static int sab82532_chars_in_buffer(struct tty_struct *tty){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;					if (serial_paranoia_check(info, tty->device, "sab82532_chars_in_buffer"))		return 0;	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);}static void sab82532_flush_buffer(struct tty_struct *tty){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "sab82532_flush_buffer"))		return;	save_flags(flags); cli();	info->xmit.head = info->xmit.tail = 0;	restore_flags(flags);	wake_up_interruptible(&tty->write_wait);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_wakeup)(tty);}/* * This function is used to send a high-priority XON/XOFF character to * the device */static void sab82532_send_xchar(struct tty_struct *tty, char ch){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "sab82532_send_xchar"))		return;	save_flags(flags); cli();	sab82532_tec_wait(info);	writeb(ch, &info->regs->w.tic);	restore_flags(flags);}/* * ------------------------------------------------------------ * sab82532_throttle() *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void sab82532_throttle(struct tty_struct * tty){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;#ifdef SERIAL_DEBUG_THROTTLE	char	buf[64];		printk("throttle %s: %d....\n", _tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	if (serial_paranoia_check(info, tty->device, "sab82532_throttle"))		return;		if (I_IXOFF(tty))		sab82532_send_xchar(tty, STOP_CHAR(tty));	if (tty->termios->c_cflag & CRTSCTS) {		u8 mode = readb(&info->regs->r.mode);		mode &= ~(SAB82532_MODE_FRTS | SAB82532_MODE_RTS);		writeb(mode, &info->regs->w.mode);	}}static void sab82532_unthrottle(struct tty_struct * tty){	struct sab82532 *info = (struct sab82532 *)tty->driver_data;#ifdef SERIAL_DEBUG_THROTTLE	char	buf[64];		printk("unthrottle %s: %d....\n", _tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif	if (serial_paranoia_check(info, tty->device, "sab82532_unthrottle"))		return;		if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			sab82532_send_xchar(tty, START_CHAR(tty));	}	if (tty->termios->c_cflag & CRTSCTS) {		u8 mode = readb(&info->regs->r.mode);		mode &= ~(SAB82532_MODE_RTS);		mode |= SAB82532_MODE_FRTS;		writeb(mode, &info->regs->w.mode);	}}/* * ------------------------------------------------------------ * sab82532_ioctl() and friends * ------------------------------------------------------------ */static int get_serial_info(struct sab82532 *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 = (unsigned long)info->regs;	tmp.irq = info->irq;	tmp.flags = info->flags;	tmp.xmit_fifo_size = info->xmit_fifo_size;	tmp.baud_base = info->baud_base;	tmp.close_delay = info->close_delay;	tmp.closing_wait = info->closing_wait;	tmp.custom_divisor = info->custom_divisor;	tmp.hub6 = 0;	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))		return -EFAULT;	return 0;}static int set_serial_info(struct sab82532 *info,			   struct serial_struct *new_info){	return 0;}/* * 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 sab82532 * info, unsigned int *value){	unsigned int result;	result = (!info->xmit.buf && test_bit(SAB82532_ALLS, &info->irqflags))							? TIOCSER_TEMT : 0;	return put_user(result, value);}static int get_modem_info(struct sab82532 * info, unsigned int *value){	unsigned int result;	result =  ((readb(&info->regs->r.mode) & SAB82532_MODE_RTS) ? 		    ((readb(&info->regs->r.mode) & SAB82532_MODE_FRTS) ? 0 : TIOCM_RTS)							    : TIOCM_RTS)		| ((readb(&info->regs->r.pvr) & info->pvr_dtr_bit) ? 0 : TIOCM_DTR)		| ((readb(&info->regs->r.vstr) & SAB82532_VSTR_CD) ? 0 : TIOCM_CAR)		| ((readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ? 0 : TIOCM_DSR)		| ((readb(&info->regs->r.star) & SAB82532_STAR_CTS) ? TIOCM_CTS : 0);	return put_user(result,value);}static int set_modem_info(struct sab82532 * info, unsigned int cmd,			  unsigned int *value){	unsigned int arg;	if (get_user(arg, value))		return -EFAULT;	switch (cmd) {	case TIOCMBIS: 		if (arg & TIOCM_RTS) {			writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);		}		if (arg & TIOCM_DTR) {			writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr);		}		break;	case TIOCMBIC:		if (arg & TIOCM_RTS) {			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);		}		if (arg & TIOCM_DTR) {			writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr);		}		break;	case TIOCMSET:		if (arg & TIOCM_RTS) {			writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);		} else {			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);		}		if (arg & TIOCM_DTR) {			writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr);		} else {			writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr);		}		break;	default:		return -EINVAL;	}	return 0;}/* * This routine sends a break character out the serial port. */static void sab82532_break(struct tty_struct *tty, int break_state){	struct sab82532 * info = (struct sab82532 *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "sab82532_break"))		return;	if (!info->regs)		return;#ifdef SERIAL_DEBUG_SEND_BREAK	printk("sab82532_break(%d) jiff=%lu...", break_state, jiffies);#endif	save_flags(flags); cli();	if (break_state == -1)		writeb(readb(&info->regs->rw.dafo) | SAB82532_DAFO_XBRK, &info->regs->rw.dafo);	else		writeb(readb(&info->regs->rw.dafo) & ~(SAB82532_DAFO_XBRK), &info->regs->rw.dafo);	restore_flags(flags);}static int sab82532_ioctl(struct tty_struct *tty, struct file * file,		    unsigned int cmd, unsigned long arg){	struct sab82532 * info = (struct sab82532 *)tty->driver_data;	struct async_icount cprev, cnow;	/* kernel counter temps */	struct serial_icounter_struct *p_cuser;	/* user space */	if (serial_paranoia_check(info, tty->device, "sab82532_ioctl"))		return -ENODEV;	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {

⌨️ 快捷键说明

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