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

📄 8253xtty.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
		else 		{			LOWER(port,dtr);		}		break;	default:		restore_flags(flags);		return -EINVAL;	}	restore_flags(flags);	return 0;}/* * This routine sends a break character out the serial port. */static void sab8253x_break(struct tty_struct *tty, int break_state){	struct sab_port *port = (struct sab_port *)tty->driver_data;	unsigned long flags;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_break"))	{		return;	}		if (!port->regs)	{		return;	}		save_flags(flags); 	cli();	if (break_state == -1) 	{		SET_REG_BIT(port,dafo,SAB82532_DAFO_XBRK);	} 	else 	{		CLEAR_REG_BIT(port,dafo,SAB82532_DAFO_XBRK);	}	restore_flags(flags);}static int sab8253x_ioctl(struct tty_struct *tty, struct file * file,			  unsigned int cmd, unsigned long arg){	int error;	unsigned int wordindex;	unsigned short *wordptr;	struct sab_port *port = (struct sab_port *)tty->driver_data;	struct async_icount cprev, cnow;	/* kernel counter temps */	struct serial_icounter_struct *p_cuser;	/* user space */	SAB_BOARD *bptr;	unsigned long flags;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_ioctl"))	{		return -ENODEV;	}		if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) 	{		if (tty->flags & (1 << TTY_IO_ERROR))		{			return -EIO;		}	}		switch (cmd) 	{	case ATIS_IOCSPARAMS:		copy_from_user(&port->ccontrol, (struct channelcontrol*)arg , sizeof(struct channelcontrol));		break;	case ATIS_IOCGPARAMS:		copy_to_user((struct channelcontrol*) arg, &port->ccontrol, sizeof(struct channelcontrol));		break;			case ATIS_IOCSSPEED:		copy_from_user(&port->custspeed, (unsigned long*)arg , sizeof(unsigned long));		break;	case ATIS_IOCGSPEED:		copy_to_user((unsigned long*) arg, &port->custspeed, sizeof(unsigned long));		break;			case ATIS_IOCSSEP9050:		bptr = port->board;		if(bptr->b_type == BD_WANMCS)		{			return -EINVAL;		}		copy_from_user((unsigned char*) bptr->b_eprom, (unsigned char*) arg , sizeof(struct sep9050));				wordptr = (unsigned short*) bptr->b_eprom;		plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl, 				  NM93_WENCMD, NM93_WENADDR, 0);		for(wordindex = 0; wordindex < EPROM9050_SIZE; ++wordindex)		{			plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl, 					  NM93_WRITECMD, 					  wordindex, wordptr[wordindex]);		}		plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl, 				  NM93_WDSCMD, NM93_WDSADDR, 0);		break;	case ATIS_IOCGSEP9050:		bptr = port->board;		if(bptr->b_type == BD_WANMCS)		{			return -EINVAL;		}		if (!plx9050_eprom_read(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl, 					(unsigned short*) bptr->b_eprom,					(unsigned char) 0, EPROM9050_SIZE))		{			printk(KERN_ALERT "auraXX20n: Could not read serial eprom.\n");			return -EIO;		}		copy_to_user((unsigned char*) arg, (unsigned char*) bptr->b_eprom, sizeof(struct sep9050));		break;			case TIOCGSOFTCAR:		return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);			case TIOCSSOFTCAR:		error = get_user(arg, (unsigned int *) arg);		if (error)		{			return error;		}		tty->termios->c_cflag =			((tty->termios->c_cflag & ~CLOCAL) |			 (arg ? CLOCAL : 0));		return 0;	case TIOCMGET:		return sab8253x_get_modem_info(port, (unsigned int *) arg);	case TIOCMBIS:	case TIOCMBIC:	case TIOCMSET:		return sab8253x_set_modem_info(port, cmd, (unsigned int *) arg);	case TIOCGSERIAL:		return sab8253x_get_serial_info(port,						(struct serial_struct *) arg);	case TIOCSSERIAL:		return sab8253x_set_serial_info(port,						(struct serial_struct *) arg);			case TIOCSERGETLSR: /* Get line status register */		return sab8253x_get_lsr_info(port, (unsigned int *) arg);			case TIOCSERGSTRUCT:		if (copy_to_user((struct sab_port *) arg,				 port, sizeof(struct sab_port)))			return -EFAULT;		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:		save_flags(flags);		cli();		/* note the counters on entry */		cprev = port->icount;		restore_flags(flags);		while (1) 		{			interruptible_sleep_on(&port->delta_msr_wait); /* waits for a modem signal change */			/* see if a signal did it */			if (signal_pending(current))			{				return -ERESTARTSYS;			}			save_flags(flags);			cli();			cnow = port->icount; /* atomic copy */			restore_flags(flags);			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 */		break;				/* 		 * 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:		save_flags(flags);		cli();		cnow = port->icount;		restore_flags(flags);		p_cuser = (struct serial_icounter_struct *) arg;		error = put_user(cnow.cts, &p_cuser->cts);		if (error) 		{			return error;		}		error = put_user(cnow.dsr, &p_cuser->dsr);		if (error) 		{			return error;		}		error = put_user(cnow.rng, &p_cuser->rng);		if (error) 		{			return error;		}		error = put_user(cnow.dcd, &p_cuser->dcd);		if (error) 		{			return error;		}		return 0;			case ATIS_IOCSSIGMODE:		if(port->chip->c_cim)		{			if(port->chip->c_cim->ci_type == CIM_SP502)			{				copy_from_user(&port->sigmode, (unsigned int*)arg , sizeof(unsigned int));				return 0;			}		}		return -EINVAL;	case ATIS_IOCGSIGMODE:		if(port->chip->c_cim)		{			if(port->chip->c_cim->ci_type == CIM_SP502)			{				copy_to_user((unsigned int*) arg, &port->sigmode, sizeof(unsigned int));				return 0;			}		}		return -EINVAL;	default:		return -ENOIOCTLCMD;	}	return 0;}static void sab8253x_set_termios(struct tty_struct *tty,				 struct termios *old_termios){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if((tty->termios->c_cflag == old_termios->c_cflag) && 	   (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag)))	{		return;	}	if(!port)	{		return;	}	sab8253x_change_speed(port);		/* Handle transition to B0 status */	if ((old_termios->c_cflag & CBAUD) &&	    !(tty->termios->c_cflag & CBAUD)) 	{		LOWER(port,rts);		LOWER(port,dtr);	}		/* Handle transition away from B0 status */	if (!(old_termios->c_cflag & CBAUD) &&	    (tty->termios->c_cflag & CBAUD)) 	{		RAISE(port, dtr);		if (!tty->hw_stopped ||		    !(tty->termios->c_cflag & CRTSCTS)) 		{			RAISE(port, rts);		}	}		/* Handle turning off CRTSCTS */	if ((old_termios->c_cflag & CRTSCTS) &&	    !(tty->termios->c_cflag & CRTSCTS)) 	{		tty->hw_stopped = 0;		sab8253x_start(tty);	}}/* * ------------------------------------------------------------ * sab8253x_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 sab8253x_close(struct tty_struct *tty, struct file * filp){	struct sab_port *port = (struct sab_port *)tty->driver_data;	unsigned long flags;		MOD_DEC_USE_COUNT;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_close"))	{		return;	}	if(port->open_type == OPEN_SYNC_NET)	{				/* port->tty field should already be NULL */		/* port count was not incremented */		return;	}		--(port->count);		/* have a valid port */	if (tty_hung_up_p(filp)) 	{				if(port->count == 0)	/* shutdown took place in hangup context */		{			port->open_type = OPEN_NOT;		}		else if(port->count < 0)		{			printk(KERN_ALERT "XX20: port->count went negative.\n");			port->count = 0;			port->open_type = OPEN_NOT;		}		return;	}		if (port->count < 0) 	{		printk(KERN_ALERT "sab8253x_close: bad serial port count for ttys%d: %d\n",		       port->line, port->count);		port->count = 0;	}		if (port->count) 	{		return;	}		port->flags |= FLAG8253X_CLOSING;		/*	 * Save the termios structure, since this port may have	 * separate termios for callout and dialin.	 */	if (port->flags & FLAG8253X_NORMAL_ACTIVE)	{		port->normal_termios = *tty->termios;	}	if (port->flags & FLAG8253X_CALLOUT_ACTIVE)	{		port->callout_termios = *tty->termios;	}	/*	 * Now we wait for the transmit buffer to clear; and we notify 	 * the line discipline to only process XON/XOFF characters.	 */	tty->closing = 1;	if (port->closing_wait != SAB8253X_CLOSING_WAIT_NONE) 	{		tty_wait_until_sent(tty, port->closing_wait); /* wait for drain */	}		/*	 * At this point we stop accepting input.  To do this, we	 * disable the receive line status interrupts, and turn off	 * the receiver.	 */		save_flags(flags); 	cli();	port->interrupt_mask0 |= SAB82532_IMR0_TCD;	WRITEB(port,imr0,port->interrupt_mask0);		CLEAR_REG_BIT(port,mode,SAB82532_MODE_RAC); /* ??????? */	restore_flags(flags);		if (port->flags & FLAG8253X_INITIALIZED) 	{		/*		 * Before we drop DTR, make sure the UART transmitter		 * has completely drained; this is especially		 * important if there is a transmit FIFO!		 */		sab8253x_wait_until_sent(tty, port->timeout);	}	sab8253x_shutdown(port);	/* no more ints on port */	Sab8253xCleanUpTransceiveN(port); /* should be okay */	if (tty->driver.flush_buffer)	{		tty->driver.flush_buffer(tty);	}	if (tty->ldisc.flush_buffer)	{		tty->ldisc.flush_buffer(tty);	}	tty->closing = 0;	port->event = 0;	port->tty = 0;	if (port->blocked_open) 	{		if (port->close_delay) 		{			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(port->close_delay);		}		wake_up_interruptible(&port->open_wait); /* deal with open blocks */	}		if((port->flags & (FLAG8253X_CALLOUT_ACTIVE | FLAG8253X_NETWORK)) ==	   (FLAG8253X_CALLOUT_ACTIVE | FLAG8253X_NETWORK) &&	   port->dev)	{		port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE|				 FLAG8253X_CLOSING); /* leave network set */		netif_carrier_off(port->dev);		port->open_type = OPEN_SYNC_NET;		sab8253x_startupN(port);	}	else	{		port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE|				 FLAG8253X_CLOSING);		wake_up_interruptible(&port->close_wait);		port->open_type = OPEN_NOT;	}}/* * sab8253x_hangup() --- called by tty_hangup() when a hangup is signaled. */static void sab8253x_hangup(struct tty_struct *tty){	struct sab_port *port = (struct sab_port *)tty->driver_data;		if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_hangup"))	{		return;	}	#ifdef XCONFIG_SERIAL_CONSOLE	if (port->is_console)	{		return;	}#endif		sab8253x_flush_buffer(tty);	if(port)	{		sab8253x_shutdown(port);		Sab8253xCleanUpTransceiveN(port); /* this logic is a bit contorted						     Are we cleaning up the lists						     because we are waking up a						     blocked open?  There is possibly						     an order problem here perhaps the						     open count should have increased in the						     int handler so that it could decrease here*/		port->event = 0;		port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE);		port->tty = 0;		wake_up_interruptible(&port->open_wait); /* deal with blocking open */	}}/* * ------------------------------------------------------------ * sab8253x_open() and friends * ------------------------------------------------------------ *//* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain.   It also performs the serial-specific * initialization for the tty structure. */static int sab8253x_open(struct tty_struct *tty, struct file * filp){	struct sab_port	*port;	int retval, line;	int counter;	unsigned long flags;		MOD_INC_USE_COUNT;	line = MINOR(tty->device) - tty->driver.minor_start;		for(counter = 0, port = AuraPortRoot; 	    (counter < line) && (port != NULL); 	    ++counter)	{		port = port->next;	}		if (!port) 	{		printk(KERN_ALERT "sab8253x_open: can't find structure for line %d\n",		       line);		return -ENODEV;	}		save_flags(flags);		/* Need to protect the port->tty field */	cli();		if(port->tty == NULL)

⌨️ 快捷键说明

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