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

📄 esp.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	tmp.flags = info->flags;	tmp.xmit_fifo_size = 1024;	tmp.baud_base = BASE_BAUD;	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 get_esp_config(struct esp_struct * info,			  struct hayes_esp_config * retinfo){	struct hayes_esp_config tmp;  	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.rx_timeout = info->config.rx_timeout;	tmp.rx_trigger = info->config.rx_trigger;	tmp.tx_trigger = info->config.tx_trigger;	tmp.flow_off = info->config.flow_off;	tmp.flow_on = info->config.flow_on;	tmp.pio_threshold = info->config.pio_threshold;	tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma);	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;}static int set_serial_info(struct esp_struct * info,			   struct serial_struct * new_info){	struct serial_struct new_serial;	struct esp_struct old_info;	unsigned int change_irq;	int retval = 0;	struct esp_struct *current_async;	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))		return -EFAULT;	old_info = *info;	if ((new_serial.type != PORT_16550A) ||	    (new_serial.hub6) ||	    (info->port != new_serial.port) ||	    (new_serial.baud_base != BASE_BAUD) ||	    (new_serial.irq > 15) ||	    (new_serial.irq < 2) ||	    (new_serial.irq == 6) ||	    (new_serial.irq == 8) ||	    (new_serial.irq == 13))		return -EINVAL;	change_irq = new_serial.irq != info->irq;	if (change_irq && (info->line % 8))		return -EINVAL;	if (!capable(CAP_SYS_ADMIN)) {		if (change_irq || 		    (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;	} else {		if (new_serial.irq == 2)			new_serial.irq = 9;		if (change_irq) {			current_async = ports;			while (current_async) {				if ((current_async->line >= info->line) &&				    (current_async->line < (info->line + 8))) {					if (current_async == info) {						if (current_async->count > 1)							return -EBUSY;					} else if (current_async->count)						return -EBUSY;				}				current_async = current_async->next_port;			}		}		/*		 * OK, past this point, all the error checking has been done.		 * At this point, we start making changes.....		 */		info->flags = ((info->flags & ~ASYNC_FLAGS) |			       (new_serial.flags & ASYNC_FLAGS));		info->custom_divisor = new_serial.custom_divisor;		info->close_delay = new_serial.close_delay * HZ/100;		info->closing_wait = new_serial.closing_wait * HZ/100;		if (change_irq) {			/*			 * We need to shutdown the serial port at the old			 * port/irq combination.			 */			shutdown(info);			current_async = ports;			while (current_async) {				if ((current_async->line >= info->line) &&				    (current_async->line < (info->line + 8)))					current_async->irq = new_serial.irq;				current_async = current_async->next_port;			}			serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ);			if (info->irq == 9)				serial_out(info, UART_ESI_CMD2, 0x02);			else				serial_out(info, UART_ESI_CMD2, info->irq);		}	}	if (info->flags & ASYNC_INITIALIZED) {		if (((old_info.flags & ASYNC_SPD_MASK) !=		     (info->flags & ASYNC_SPD_MASK)) ||		    (old_info.custom_divisor != info->custom_divisor)) {			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;			change_speed(info);		}	} else		retval = startup(info);	return retval;}static int set_esp_config(struct esp_struct * info,			  struct hayes_esp_config * new_info){	struct hayes_esp_config new_config;	unsigned int change_dma;	int retval = 0;	struct esp_struct *current_async;	/* Perhaps a non-sysadmin user should be able to do some of these */	/* operations.  I haven't decided yet. */	if (!capable(CAP_SYS_ADMIN))		return -EPERM;	if (copy_from_user(&new_config, new_info, sizeof(new_config)))		return -EFAULT;	if ((new_config.flow_on >= new_config.flow_off) ||	    (new_config.rx_trigger < 1) ||	    (new_config.tx_trigger < 1) ||	    (new_config.flow_off < 1) ||	    (new_config.flow_on < 1) ||	    (new_config.rx_trigger > 1023) ||	    (new_config.tx_trigger > 1023) ||	    (new_config.flow_off > 1023) ||	    (new_config.flow_on > 1023) ||	    (new_config.pio_threshold < 0) ||	    (new_config.pio_threshold > 1024))		return -EINVAL;	if ((new_config.dma_channel != 1) && (new_config.dma_channel != 3))		new_config.dma_channel = 0;	if (info->stat_flags & ESP_STAT_NEVER_DMA)		change_dma = new_config.dma_channel;	else		change_dma = (new_config.dma_channel != dma);	if (change_dma) {		if (new_config.dma_channel) {			/* PIO mode to DMA mode transition OR */			/* change current DMA channel */						current_async = ports;			while (current_async) {				if (current_async == info) {					if (current_async->count > 1)						return -EBUSY;				} else if (current_async->count)					return -EBUSY;									current_async =					current_async->next_port;			}			shutdown(info);			dma = new_config.dma_channel;			info->stat_flags &= ~ESP_STAT_NEVER_DMA;			                        /* all ports must use the same DMA channel */			current_async = ports;			while (current_async) {				esp_basic_init(current_async);				current_async = current_async->next_port;			}		} else {			/* DMA mode to PIO mode only */						if (info->count > 1)				return -EBUSY;			shutdown(info);			info->stat_flags |= ESP_STAT_NEVER_DMA;			esp_basic_init(info);		}	}	info->config.pio_threshold = new_config.pio_threshold;	if ((new_config.flow_off != info->config.flow_off) ||	    (new_config.flow_on != info->config.flow_on)) {		unsigned long flags;		info->config.flow_off = new_config.flow_off;		info->config.flow_on = new_config.flow_on;		save_flags(flags); cli();		serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL);		serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8);		serial_out(info, UART_ESI_CMD2, new_config.flow_off);		serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8);		serial_out(info, UART_ESI_CMD2, new_config.flow_on);		restore_flags(flags);	}	if ((new_config.rx_trigger != info->config.rx_trigger) ||	    (new_config.tx_trigger != info->config.tx_trigger)) {		unsigned long flags;		info->config.rx_trigger = new_config.rx_trigger;		info->config.tx_trigger = new_config.tx_trigger;		save_flags(flags); cli();		serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER);		serial_out(info, UART_ESI_CMD2,			   new_config.rx_trigger >> 8);		serial_out(info, UART_ESI_CMD2, new_config.rx_trigger);		serial_out(info, UART_ESI_CMD2,			   new_config.tx_trigger >> 8);		serial_out(info, UART_ESI_CMD2, new_config.tx_trigger);		restore_flags(flags);	}	if (new_config.rx_timeout != info->config.rx_timeout) {		unsigned long flags;		info->config.rx_timeout = new_config.rx_timeout;		save_flags(flags); cli();		if (info->IER & UART_IER_RDI) {			serial_out(info, UART_ESI_CMD1,				   ESI_SET_RX_TIMEOUT);			serial_out(info, UART_ESI_CMD2,				   new_config.rx_timeout);		}		restore_flags(flags);	}	if (!(info->flags & ASYNC_INITIALIZED))		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 esp_struct * info, unsigned int *value){	unsigned char status;	unsigned int result;	cli();	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);	status = serial_in(info, UART_ESI_STAT1);	sti();	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);	return put_user(result,value);}static int get_modem_info(struct esp_struct * info, unsigned int *value){	unsigned char control, status;	unsigned int result;	control = info->MCR;	cli();	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);	status = serial_in(info, UART_ESI_STAT2);	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);	return put_user(result,value);}static int set_modem_info(struct esp_struct * 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)			info->MCR |= UART_MCR_RTS;		if (arg & TIOCM_DTR)			info->MCR |= UART_MCR_DTR;		break;	case TIOCMBIC:		if (arg & TIOCM_RTS)			info->MCR &= ~UART_MCR_RTS;		if (arg & TIOCM_DTR)			info->MCR &= ~UART_MCR_DTR;		break;	case TIOCMSET:		info->MCR = ((info->MCR & ~(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_ESI_CMD1, ESI_WRITE_UART);	serial_out(info, UART_ESI_CMD2, UART_MCR);	serial_out(info, UART_ESI_CMD2, info->MCR);	sti();	return 0;}/* * rs_break() --- routine which turns the break handling on or off */static void esp_break(struct tty_struct *tty, int break_state){	struct esp_struct * info = (struct esp_struct *)tty->driver_data;	unsigned long flags;		if (serial_paranoia_check(info, tty->device, "esp_break"))		return;	save_flags(flags); cli();	if (break_state == -1) {		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);		serial_out(info, UART_ESI_CMD2, 0x01);		interruptible_sleep_on(&info->break_wait);	} else {		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);		serial_out(info, UART_ESI_CMD2, 0x00);	}	restore_flags(flags);}static int rs_ioctl(struct tty_struct *tty, struct file * file,		    unsigned int cmd, unsigned long arg){	struct esp_struct * info = (struct esp_struct *)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, "rs_ioctl"))		return -ENODEV;	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT) &&	    (cmd != TIOCGHAYESESP) && (cmd != TIOCSHAYESESP)) {		if (tty->flags & (1 << TTY_IO_ERROR))		    return -EIO;	}		switch (cmd) {		case TIOCMGET:			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:			return get_serial_info(info,					       (struct serial_struct *) arg);		case TIOCSSERIAL:			return set_serial_info(info,					       (struct serial_struct *) arg);		case TIOCSERCONFIG:			/* do not reconfigure after initial configuration */			return 0;		case TIOCSERGWILD:			return put_user(0L, (unsigned long *) arg);		case TIOCSERGETLSR: /* Get line status register */			    return get_lsr_info(info, (unsigned int *) arg);		case TIOCSERSWILD:			if (!capable(CAP_SYS_ADMIN))				return -EPERM;			return 0;		/*		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change		 * - mask passed in arg for lines of interest 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)		 * Caller should use TIOCGICOUNT to see which one it was		 */		 case TIOCMIWAIT:			cli();			cprev = info->icount;	/* note the counters on entry */			sti();			while (1) {				interruptible_sleep_on(&info->delta_msr_wait);				/* see if a signal did it */				if (signal_pending(current))					return -ERESTARTSYS;				cli();				cnow = info->icount;	/* atomic copy */				sti();				if (cnow.rng == cprev.rng &&				    cnow.dsr == cprev.dsr && 				    cnow.dcd == cprev.dcd &&				    cnow.cts == cprev.cts)					return -EIO; /* no change => error */				if (((arg & TIOCM_RNG) &&				     (cnow.rng != cprev.rng)) ||				     ((arg & TIOCM_DSR) &&				      (cnow.dsr != cprev.dsr)) ||				     ((arg & TIOCM_CD) &&				      (cnow.dcd != cprev.dcd)) ||				     ((arg & TIOCM_CTS) &&				      (cnow.cts != cprev.cts)) ) {					return 0;				}				cprev = cnow;			}			/* NOTREACHED */		/* 		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)		 * Return: write counters to the user passed counter struct		 * NB: both 1->0 and 0->1 transitions are counted except for		 *     RI where only 0->1 is counted.		 */		case TIOCGICOUNT:			cli();			cnow = info->icount;			sti();			p_cuser = (struct serial_icounter_struct *) arg;			if (put_user(cnow.cts, &p_cuser->cts) ||			    put_user(cnow.dsr, &p_cuser->dsr) ||			    put_user(cnow.rng, &p_cuser->rng) ||			    put_user(cnow.dcd, &p_cuser->dcd))				return -EFAULT;			return 0;	case TIOCGHAYESESP:		return (get_esp_config(info, (struct hayes_esp_config *)arg));

⌨️ 快捷键说明

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