* Now we must calculate some speed depended things 
* Now we must calculate some speed depended things 
static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port){	struct tty_struct *tty;	unsigned long baud;	long tmp;	unsigned char cor1 = 0, cor3 = 0;	unsigned char mcor1 = 0, mcor2 = 0;	static unsigned long again;	unsigned long flags;	func_enter();	if (!(tty = port->tty) || !tty->termios) {		func_exit();		return;	}	port->IER  = 0;	port->COR2 = 0;	/* Select port on the board */	spin_lock_irqsave(&bp->lock, flags);	sx_out(bp, CD186x_CAR, port_No(port));	/* The Specialix board doens't implement the RTS lines.	   They are used to set the IRQ level. Don't touch them. */	if (SX_CRTSCTS(tty))		port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);	else		port->MSVR =  (sx_in(bp, CD186x_MSVR) & MSVR_RTS);	spin_unlock_irqrestore(&bp->lock, flags);	dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);	baud = C_BAUD(tty);		if (baud & CBAUDEX) {		baud &= ~CBAUDEX;		if (baud < 1 || baud > 2) 			port->tty->termios->c_cflag &= ~CBAUDEX;		else			baud += 15;	}	if (baud == 15) {		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)			baud ++;		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)			baud += 2;	}			if (!baud_table[baud]) {		/* Drop DTR & exit */		dprintk (SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");		if (!SX_CRTSCTS (tty)) {			port -> MSVR &= ~ MSVR_DTR;			spin_lock_irqsave(&bp->lock, flags);			sx_out(bp, CD186x_MSVR, port->MSVR );			spin_unlock_irqrestore(&bp->lock, flags);		} 		else			dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");		return;	} else {		/* Set DTR on */		if (!SX_CRTSCTS (tty)) {			port ->MSVR |= MSVR_DTR;		}	}		/*	 * Now we must calculate some speed depended things 	 */	/* Set baud rate for port */	tmp = port->custom_divisor ;	if ( tmp )		printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"		                  "This is an untested option, please be carefull.\n",		                  port_No (port), tmp);	else		tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +		         CD186x_TPC/2) / CD186x_TPC);	if ((tmp < 0x10) && time_before(again, jiffies)) { 		again = jiffies + HZ * 60;		/* Page 48 of version 2.0 of the CL-CD1865 databook */		if (tmp >= 12) {			printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"			        "Performance degradation is possible.\n"			        "Read specialix.txt for more info.\n",			        port_No (port), tmp);		} else {			printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"			        "Warning: overstressing Cirrus chip. "			        "This might not work.\n"			        "Read specialix.txt for more info.\n", 			        port_No (port), tmp);		}	}	spin_lock_irqsave(&bp->lock, flags);	sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); 	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); 	sx_out(bp, CD186x_RBPRL, tmp & 0xff); 	sx_out(bp, CD186x_TBPRL, tmp & 0xff);	spin_unlock_irqrestore(&bp->lock, flags);	if (port->custom_divisor) {		baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;		baud = ( baud + 5 ) / 10;	} else 		baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */	/* Two timer ticks seems enough to wakeup something like SLIP driver */	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;			port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?					      SERIAL_XMIT_SIZE - 1 : tmp);		/* Receiver timeout will be transmission time for 1.5 chars */	tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;	tmp = (tmp > 0xff) ? 0xff : tmp;	spin_lock_irqsave(&bp->lock, flags);	sx_out(bp, CD186x_RTPR, tmp);	spin_unlock_irqrestore(&bp->lock, flags);	switch (C_CSIZE(tty)) {	 case CS5:		cor1 |= COR1_5BITS;		break;	 case CS6:		cor1 |= COR1_6BITS;		break;	 case CS7:		cor1 |= COR1_7BITS;		break;	 case CS8:		cor1 |= COR1_8BITS;		break;	}		if (C_CSTOPB(tty)) 		cor1 |= COR1_2SB;		cor1 |= COR1_IGNORE;	if (C_PARENB(tty)) {		cor1 |= COR1_NORMPAR;		if (C_PARODD(tty)) 			cor1 |= COR1_ODDP;		if (I_INPCK(tty)) 			cor1 &= ~COR1_IGNORE;	}	/* Set marking of some errors */	port->mark_mask = RCSR_OE | RCSR_TOUT;	if (I_INPCK(tty)) 		port->mark_mask |= RCSR_FE | RCSR_PE;	if (I_BRKINT(tty) || I_PARMRK(tty)) 		port->mark_mask |= RCSR_BREAK;	if (I_IGNPAR(tty)) 		port->mark_mask &= ~(RCSR_FE | RCSR_PE);	if (I_IGNBRK(tty)) {		port->mark_mask &= ~RCSR_BREAK;		if (I_IGNPAR(tty)) 			/* Real raw mode. Ignore all */			port->mark_mask &= ~RCSR_OE;	}	/* Enable Hardware Flow Control */	if (C_CRTSCTS(tty)) {#ifdef SPECIALIX_BRAIN_DAMAGED_CTS		port->IER |= IER_DSR | IER_CTS;		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;		spin_lock_irqsave(&bp->lock, flags);		tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));		spin_unlock_irqrestore(&bp->lock, flags);#else		port->COR2 |= COR2_CTSAE; #endif	}	/* Enable Software Flow Control. FIXME: I'm not sure about this */	/* Some people reported that it works, but I still doubt it */	if (I_IXON(tty)) {		port->COR2 |= COR2_TXIBE;		cor3 |= (COR3_FCT | COR3_SCDE);		if (I_IXANY(tty))			port->COR2 |= COR2_IXM;		spin_lock_irqsave(&bp->lock, flags);		sx_out(bp, CD186x_SCHR1, START_CHAR(tty));		sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));		sx_out(bp, CD186x_SCHR3, START_CHAR(tty));		sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));		spin_unlock_irqrestore(&bp->lock, flags);	}	if (!C_CLOCAL(tty)) {		/* Enable CD check */		port->IER |= IER_CD;		mcor1 |= MCOR1_CDZD;		mcor2 |= MCOR2_CDOD;	}		if (C_CREAD(tty)) 		/* Enable receiver */		port->IER |= IER_RXD;		/* Set input FIFO size (1-8 bytes) */	cor3 |= sx_rxfifo;	/* Setting up CD186x channel registers */	spin_lock_irqsave(&bp->lock, flags);	sx_out(bp, CD186x_COR1, cor1);	sx_out(bp, CD186x_COR2, port->COR2);	sx_out(bp, CD186x_COR3, cor3);	spin_unlock_irqrestore(&bp->lock, flags);	/* Make CD186x know about registers change */	sx_wait_CCR(bp);	spin_lock_irqsave(&bp->lock, flags);	sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);	/* Setting up modem option registers */	dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);	sx_out(bp, CD186x_MCOR1, mcor1);	sx_out(bp, CD186x_MCOR2, mcor2);	spin_unlock_irqrestore(&bp->lock, flags);	/* Enable CD186x transmitter & receiver */	sx_wait_CCR(bp);	spin_lock_irqsave(&bp->lock, flags);	sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);	/* Enable interrupts */	sx_out(bp, CD186x_IER, port->IER);	/* And finally set the modem lines... */	sx_out(bp, CD186x_MSVR, port->MSVR);	spin_unlock_irqrestore(&bp->lock, flags);	func_exit();}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/d61780c0d384939ef31c46b47442854d5def4623/specialix.c/buggy/drivers/char/specialix.c