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

📄 esp.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	/*	 * Set up the tty->alt_speed kludge	 */	if (info->tty) {		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)			info->tty->alt_speed = 57600;		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)			info->tty->alt_speed = 115200;		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)			info->tty->alt_speed = 230400;		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)			info->tty->alt_speed = 460800;	}		/*	 * set the speed of the serial port	 */	change_speed(info);	info->flags |= ASYNC_INITIALIZED;	retval = 0;out:	restore_flags(flags);	return retval;}/* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */static void shutdown(struct esp_struct * info){	unsigned long	flags, f;	if (!(info->flags & ASYNC_INITIALIZED))		return;#ifdef SERIAL_DEBUG_OPEN	printk("Shutting down serial port %d (irq %d)....", info->line,	       info->irq);#endif		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);	wake_up_interruptible(&info->break_wait);	/* stop a DMA transfer on the port being closed */	   	if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) {		f=claim_dma_lock();		disable_dma(dma);		clear_dma_ff(dma);		release_dma_lock(f);				dma_bytes = 0;	}		/*	 * Free the IRQ	 */	free_irq(info->irq, info);	if (dma_buffer) {		struct esp_struct *current_port = ports;		while (current_port) {			if ((current_port != info) &&			    (current_port->flags & ASYNC_INITIALIZED))				break;			current_port = current_port->next_port;		}		if (!current_port) {			free_dma(dma);			free_pages((unsigned long)dma_buffer,				   get_order(DMA_BUFFER_SZ));			dma_buffer = 0;		}			}	if (info->xmit_buf) {		free_page((unsigned long) info->xmit_buf);		info->xmit_buf = 0;	}	info->IER = 0;	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);	serial_out(info, UART_ESI_CMD2, 0x00);	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);	info->MCR &= ~UART_MCR_OUT2;	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);	serial_out(info, UART_ESI_CMD2, UART_MCR);	serial_out(info, UART_ESI_CMD2, info->MCR);	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 void change_speed(struct esp_struct *info){	unsigned short port;	int	quot = 0;	unsigned cflag,cval;	int	baud, bits;	unsigned char flow1 = 0, flow2 = 0;	unsigned long flags;	if (!info->tty || !info->tty->termios)		return;	cflag = info->tty->termios->c_cflag;	port = info->port;		/* byte size and parity */	switch (cflag & CSIZE) {	      case CS5: cval = 0x00; bits = 7; break;	      case CS6: cval = 0x01; bits = 8; break;	      case CS7: cval = 0x02; bits = 9; break;	      case CS8: cval = 0x03; bits = 10; break;	      default:  cval = 0x00; bits = 7; break;	}	if (cflag & CSTOPB) {		cval |= 0x04;		bits++;	}	if (cflag & PARENB) {		cval |= UART_LCR_PARITY;		bits++;	}	if (!(cflag & PARODD))		cval |= UART_LCR_EPAR;#ifdef CMSPAR	if (cflag & CMSPAR)		cval |= UART_LCR_SPAR;#endif	baud = tty_get_baud_rate(info->tty);	if (baud == 38400 &&	    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))		quot = info->custom_divisor;	else {		if (baud == 134)			/* Special case since 134 is really 134.5 */			quot = (2*BASE_BAUD / 269);		else if (baud)			quot = BASE_BAUD / baud;	}	/* If the quotient is ever zero, default to 9600 bps */	if (!quot)		quot = BASE_BAUD / 9600;		info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50);	/* CTS flow control flag and modem status interrupts */	/* info->IER &= ~UART_IER_MSI; */	if (cflag & CRTSCTS) {		info->flags |= ASYNC_CTS_FLOW;		/* info->IER |= UART_IER_MSI; */		flow1 = 0x04;		flow2 = 0x10;	} else		info->flags &= ~ASYNC_CTS_FLOW;	if (cflag & CLOCAL)		info->flags &= ~ASYNC_CHECK_CD;	else {		info->flags |= ASYNC_CHECK_CD;		/* info->IER |= UART_IER_MSI; */	}	/*	 * Set up parity check flag	 */#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;	if (I_INPCK(info->tty))		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))		info->read_status_mask |= UART_LSR_BI;		info->ignore_status_mask = 0;#if 0	/* This should be safe, but for some broken bits of hardware... */	if (I_IGNPAR(info->tty)) {		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;		info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;	}#endif	if (I_IGNBRK(info->tty)) {		info->ignore_status_mask |= UART_LSR_BI;		info->read_status_mask |= UART_LSR_BI;		/*		 * If we're ignore parity and break indicators, ignore 		 * overruns too.  (For real raw support).		 */		if (I_IGNPAR(info->tty)) {			info->ignore_status_mask |= UART_LSR_OE | \				UART_LSR_PE | UART_LSR_FE;			info->read_status_mask |= UART_LSR_OE | \				UART_LSR_PE | UART_LSR_FE;		}	}	if (I_IXOFF(info->tty))		flow1 |= 0x81;	save_flags(flags); cli();	/* set baud */	serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD);	serial_out(info, UART_ESI_CMD2, quot >> 8);	serial_out(info, UART_ESI_CMD2, quot & 0xff);	/* set data bits, parity, etc. */	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);	serial_out(info, UART_ESI_CMD2, UART_LCR);	serial_out(info, UART_ESI_CMD2, cval);	/* Enable flow control */	serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CNTL);	serial_out(info, UART_ESI_CMD2, flow1);	serial_out(info, UART_ESI_CMD2, flow2);	/* set flow control characters (XON/XOFF only) */	if (I_IXOFF(info->tty)) {		serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CHARS);		serial_out(info, UART_ESI_CMD2, START_CHAR(info->tty));		serial_out(info, UART_ESI_CMD2, STOP_CHAR(info->tty));		serial_out(info, UART_ESI_CMD2, 0x10);		serial_out(info, UART_ESI_CMD2, 0x21);		switch (cflag & CSIZE) {			case CS5:				serial_out(info, UART_ESI_CMD2, 0x1f);				break;			case CS6:				serial_out(info, UART_ESI_CMD2, 0x3f);				break;			case CS7:			case CS8:				serial_out(info, UART_ESI_CMD2, 0x7f);				break;			default:				serial_out(info, UART_ESI_CMD2, 0xff);				break;		}	}	/* Set high/low water */	serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL);	serial_out(info, UART_ESI_CMD2, info->config.flow_off >> 8);	serial_out(info, UART_ESI_CMD2, info->config.flow_off);	serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8);	serial_out(info, UART_ESI_CMD2, info->config.flow_on);	restore_flags(flags);}static void rs_put_char(struct tty_struct *tty, unsigned char ch){	struct esp_struct *info = (struct esp_struct *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "rs_put_char"))		return;	if (!tty || !info->xmit_buf)		return;	save_flags(flags); cli();	if (info->xmit_cnt >= ESP_XMIT_SIZE - 1) {		restore_flags(flags);		return;	}	info->xmit_buf[info->xmit_head++] = ch;	info->xmit_head &= ESP_XMIT_SIZE-1;	info->xmit_cnt++;	restore_flags(flags);}static void rs_flush_chars(struct tty_struct *tty){	struct esp_struct *info = (struct esp_struct *)tty->driver_data;	unsigned long flags;					if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))		return;	if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf)		return;	save_flags(flags); cli();	if (!(info->IER & UART_IER_THRI)) {		info->IER |= UART_IER_THRI;		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);		serial_out(info, UART_ESI_CMD2, info->IER);	}	restore_flags(flags);}static int rs_write(struct tty_struct * tty, int from_user,		    const unsigned char *buf, int count){	int	c, t, ret = 0;	struct esp_struct *info = (struct esp_struct *)tty->driver_data;	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "rs_write"))		return 0;	if (!tty || !info->xmit_buf || !tmp_buf)		return 0;	    	if (from_user)		down(&tmp_buf_sem);	while (1) {		/* Thanks to R. Wolff for suggesting how to do this with */		/* interrupts enabled */		c = count;		t = ESP_XMIT_SIZE - info->xmit_cnt - 1;				if (t < c)			c = t;		t = ESP_XMIT_SIZE - info->xmit_head;				if (t < c)			c = t;		if (c <= 0)			break;		if (from_user) {			c -= copy_from_user(tmp_buf, buf, c);			if (!c) {				if (!ret)					ret = -EFAULT;				break;			}			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);		} else			memcpy(info->xmit_buf + info->xmit_head, buf, c);		info->xmit_head = (info->xmit_head + c) & (ESP_XMIT_SIZE-1);		info->xmit_cnt += c;		buf += c;		count -= c;		ret += c;	}	if (from_user)		up(&tmp_buf_sem);		save_flags(flags); cli();	if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) {		info->IER |= UART_IER_THRI;		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);		serial_out(info, UART_ESI_CMD2, info->IER);	}	restore_flags(flags);	return ret;}static int rs_write_room(struct tty_struct *tty){	struct esp_struct *info = (struct esp_struct *)tty->driver_data;	int	ret;					if (serial_paranoia_check(info, tty->device, "rs_write_room"))		return 0;	ret = ESP_XMIT_SIZE - info->xmit_cnt - 1;	if (ret < 0)		ret = 0;	return ret;}static int rs_chars_in_buffer(struct tty_struct *tty){	struct esp_struct *info = (struct esp_struct *)tty->driver_data;					if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))		return 0;	return info->xmit_cnt;}static void rs_flush_buffer(struct tty_struct *tty){	struct esp_struct *info = (struct esp_struct *)tty->driver_data;					if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))		return;	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);}/* * ------------------------------------------------------------ * rs_throttle() *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void rs_throttle(struct tty_struct * tty){	struct esp_struct *info = (struct esp_struct *)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, "rs_throttle"))		return;		cli();	info->IER &= ~UART_IER_RDI;	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);	serial_out(info, UART_ESI_CMD2, info->IER);	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);	serial_out(info, UART_ESI_CMD2, 0x00);	sti();}static void rs_unthrottle(struct tty_struct * tty){	struct esp_struct *info = (struct esp_struct *)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, "rs_unthrottle"))		return;		cli();	info->IER |= UART_IER_RDI;	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);	serial_out(info, UART_ESI_CMD2, info->IER);	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);	serial_out(info, UART_ESI_CMD2, info->config.rx_timeout);	sti();}/* * ------------------------------------------------------------ * rs_ioctl() and friends * ------------------------------------------------------------ */static int get_serial_info(struct esp_struct * info,			   struct serial_struct * retinfo){	struct serial_struct tmp;  	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.type = PORT_16550A;	tmp.line = info->line;	tmp.port = info->port;	tmp.irq = info->irq;

⌨️ 快捷键说明

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