patch-2.4.25 linux-2.4.25/drivers/tc/zs.c

Next file: linux-2.4.25/drivers/tc/zs.h
Previous file: linux-2.4.25/drivers/tc/lk201.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.24/drivers/tc/zs.c linux-2.4.25/drivers/tc/zs.c
@@ -6,7 +6,7 @@
  *
  * DECstation changes
  * Copyright (C) 1998-2000 Harald Koerfgen
- * Copyright (C) 2000, 2001, 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004  Maciej W. Rozycki
  *
  * For the rest of the code the original Copyright applies:
  * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
@@ -166,19 +166,19 @@
 #endif
 
 static unsigned char zs_init_regs[16] __initdata = {
-	0,                           /* write 0 */
-	0,			     /* write 1 */
-	0xf0,                        /* write 2 */
-	(Rx8),                       /* write 3 */
-	(X16CLK | SB1),              /* write 4 */
-	(Tx8),                       /* write 5 */
-	0, 0, 0,                     /* write 6, 7, 8 */
-	(VIS),                       /* write 9 */
-	(NRZ),                       /* write 10 */
-	(TCBR | RCBR),               /* write 11 */
-	0, 0,                        /* BRG time constant, write 12 + 13 */
-	(BRSRC | BRENABL),           /* write 14 */
-	0 			     /* write 15 */
+	0,				/* write 0 */
+	0,				/* write 1 */
+	0,				/* write 2 */
+	0,				/* write 3 */
+	(X16CLK),			/* write 4 */
+	0,				/* write 5 */
+	0, 0, 0,			/* write 6, 7, 8 */
+	(MIE | DLC | NV),		/* write 9 */
+	(NRZ),				/* write 10 */
+	(TCBR | RCBR),			/* write 11 */
+	0, 0,				/* BRG time constant, write 12 + 13 */
+	(BRSRC | BRENABL),		/* write 14 */
+	0				/* write 15 */
 };
 
 DECLARE_TASK_QUEUE(tq_zs_serial);
@@ -317,9 +317,9 @@
 /*	ZS_CLEARERR(channel);
 	ZS_CLEARFIFO(channel); */
 	/* Load 'em up */
-	write_zsreg(channel, R4, regs[R4]);
 	write_zsreg(channel, R3, regs[R3] & ~RxENABLE);
 	write_zsreg(channel, R5, regs[R5] & ~TxENAB);
+	write_zsreg(channel, R4, regs[R4]);
 	write_zsreg(channel, R9, regs[R9]);
 	write_zsreg(channel, R1, regs[R1]);
 	write_zsreg(channel, R2, regs[R2]);
@@ -730,8 +730,13 @@
 	/*
 	 * Clear the interrupt registers.
 	 */
-	write_zsreg(info->zs_channel, 0, ERR_RES);
-	write_zsreg(info->zs_channel, 0, RES_H_IUS);
+	write_zsreg(info->zs_channel, R0, ERR_RES);
+	write_zsreg(info->zs_channel, R0, RES_H_IUS);
+
+	/*
+	 * Set the speed of the serial port
+	 */
+	change_speed(info);
 
 	/*
 	 * Turn on RTS and DTR.
@@ -741,35 +746,30 @@
 	/*
 	 * Finally, enable sequencing and interrupts
 	 */
-	info->zs_channel->curregs[1] = (info->zs_channel->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);
-	info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
-	info->zs_channel->curregs[5] |= (TxENAB | Tx8);
-	info->zs_channel->curregs[15] |= (DCDIE | CTSIE | TxUIE | BRKIE);
-	info->zs_channel->curregs[9] |= (VIS | MIE);
-	write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]);
-	write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
-	write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
-	write_zsreg(info->zs_channel, 15, info->zs_channel->curregs[15]);
-	write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+	info->zs_channel->curregs[R1] &= ~RxINT_MASK;
+	info->zs_channel->curregs[R1] |= (RxINT_ALL | TxINT_ENAB |
+					  EXT_INT_ENAB);
+	info->zs_channel->curregs[R3] |= RxENABLE;
+	info->zs_channel->curregs[R5] |= TxENAB;
+	info->zs_channel->curregs[R15] |= (DCDIE | CTSIE | TxUIE | BRKIE);
+	write_zsreg(info->zs_channel, R1, info->zs_channel->curregs[R1]);
+	write_zsreg(info->zs_channel, R3, info->zs_channel->curregs[R3]);
+	write_zsreg(info->zs_channel, R5, info->zs_channel->curregs[R5]);
+	write_zsreg(info->zs_channel, R15, info->zs_channel->curregs[R15]);
 
 	/*
 	 * And clear the interrupt registers again for luck.
 	 */
-	write_zsreg(info->zs_channel, 0, ERR_RES);
-	write_zsreg(info->zs_channel, 0, RES_H_IUS);
+	write_zsreg(info->zs_channel, R0, ERR_RES);
+	write_zsreg(info->zs_channel, R0, RES_H_IUS);
+
+	/* Save the current value of RR0 */
+	info->read_reg_zero = read_zsreg(info->zs_channel, R0);
 
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 
-	/*
-	 * Set the speed of the serial port
-	 */
-	change_speed(info);
-
-	/* Save the current value of RR0 */
-	info->read_reg_zero = read_zsreg(info->zs_channel, 0);
-
 	info->flags |= ZILOG_INITIALIZED;
 	restore_flags(flags);
 	return 0;
@@ -852,9 +852,7 @@
 
 	save_flags(flags); cli();
 	info->zs_baud = baud_table[i];
-	info->clk_divisor = 16;
 	if (info->zs_baud) {
-		info->zs_channel->curregs[4] = X16CLK;
 		brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor);
 		info->zs_channel->curregs[12] = (brg & 255);
 		info->zs_channel->curregs[13] = ((brg >> 8) & 255);
@@ -1723,7 +1721,7 @@
 
 static void __init show_serial_version(void)
 {
-	printk("DECstation Z8530 serial driver version 0.07\n");
+	printk("DECstation Z8530 serial driver version 0.08\n");
 }
 
 /*  Initialize Z8530s zs_channels
@@ -1733,6 +1731,7 @@
 {
 	struct dec_serial **pp;
 	int i, n, n_chips = 0, n_channels, chip, channel;
+	unsigned long flags;
 
 	/*
 	 * did we get here by accident?
@@ -1852,23 +1851,23 @@
 		}
 	}
 
-/*	save_and_cli(flags);
+	save_and_cli(flags);
 	for (n = 0; n < zs_channels_found; n++) {
-		if (((int)zs_channels[n].control & 0xf) == 1) {
+		if (n % 2 == 0) {
 			write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES);
-			mdelay(10);
+			udelay(10);
 			write_zsreg(zs_soft[n].zs_chan_a, R9, 0);
 		}
-		load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs);
+		load_zsregs(zs_soft[n].zs_channel,
+			    zs_soft[n].zs_channel->curregs);
 	}
-	restore_flags(flags); */
+	restore_flags(flags);
 }
 
 /* zs_init inits the driver */
 int __init zs_init(void)
 {
 	int channel, i;
-	unsigned long flags;
 	struct dec_serial *info;
 
 	if(!BUS_PRESENT)
@@ -1949,8 +1948,10 @@
 		info->tty = 0;
 		info->x_char = 0;
 
-		if (info->hook && info->hook->init_info)
+		if (info->hook && info->hook->init_info) {
+			(*info->hook->init_info)(info);
 			continue;
+		}
 
 		info->magic = SERIAL_MAGIC;
 		info->port = (int) info->zs_channel->control;
@@ -1985,15 +1986,12 @@
 			printk(KERN_ERR "decserial: can't get irq %d\n",
 			       zs_soft[channel].irq);
 
-		if (zs_soft[channel].hook &&
-		    zs_soft[channel].hook->init_channel)
-			(*zs_soft[channel].hook->init_channel)
-				(&zs_soft[channel]);
-	}
-
-	for (info = zs_chain, i = 0; info; info = info->zs_next, i++) {
-		if (info->hook && info->hook->init_info)
-			(*info->hook->init_info)(info);
+		if (zs_soft[channel].hook) {
+			zs_startup(&zs_soft[channel]);
+			if (zs_soft[channel].hook->init_channel)
+				(*zs_soft[channel].hook->init_channel)
+					(&zs_soft[channel]);
+		}
 	}
 
 	return 0;
@@ -2056,16 +2054,9 @@
 
 		return 0;
 	} else {
-		info->hook = hook;
-
-		if (zs_chain == 0)
-			probe_sccs();
-
-		if (!(info->flags & ZILOG_INITIALIZED))
-			zs_startup(info);
-
 		hook->poll_rx_char = zs_poll_rx_char;
 		hook->poll_tx_char = zs_poll_tx_char;
+		info->hook = hook;
 
 		return 1;
 	}
@@ -2126,11 +2117,13 @@
 static int __init serial_console_setup(struct console *co, char *options)
 {
 	struct dec_serial *info;
-	int	baud = 9600;
-	int	bits = 8;
-	int	parity = 'n';
-	int	cflag = CREAD | HUPCL | CLOCAL;
-	char	*s;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int cflag = CREAD | HUPCL | CLOCAL;
+	int clk_divisor = 16;
+	int brg;
+	char *s;
 	unsigned long flags;
 
 	if(!BUS_PRESENT)
@@ -2182,6 +2175,10 @@
 	case 9600:
 	default:
 		cflag |= B9600;
+		/*
+		 * Set this to a sane value to prevent a divide error.
+		 */
+		baud  = 9600;
 		break;
 	}
 	switch(bits) {
@@ -2202,43 +2199,64 @@
 		break;
 	}
 	co->cflag = cflag;
-#if 1
+
 	save_and_cli(flags);
 
 	/*
+	 * Set up the baud rate generator.
+	 */
+	brg = BPS_TO_BRG(baud, zs_parms->clock / clk_divisor);
+	info->zs_channel->curregs[R12] = (brg & 255);
+	info->zs_channel->curregs[R13] = ((brg >> 8) & 255);
+
+	/*
+	 * Set byte size and parity.
+	 */
+	if (bits == 7) {
+		info->zs_channel->curregs[R3] |= Rx7;
+		info->zs_channel->curregs[R5] |= Tx7;
+	} else {
+		info->zs_channel->curregs[R3] |= Rx8;
+		info->zs_channel->curregs[R5] |= Tx8;
+	}
+	if (cflag & PARENB) {
+		info->zs_channel->curregs[R4] |= PAR_ENA;
+	}
+	if (!(cflag & PARODD)) {
+		info->zs_channel->curregs[R4] |= PAR_EVEN;
+	}
+	info->zs_channel->curregs[R4] |= SB1;
+
+	/*
 	 * Turn on RTS and DTR.
 	 */
 	zs_rtsdtr(info, RTS | DTR, 1);
 
 	/*
-	 * Finally, enable sequencing
+	 * Finally, enable sequencing.
 	 */
-	info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
-	info->zs_channel->curregs[5] |= (TxENAB | Tx8);
-	info->zs_channel->curregs[9] |= (VIS);
-	write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
-	write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
-	write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+	info->zs_channel->curregs[R3] |= RxENABLE;
+	info->zs_channel->curregs[R5] |= TxENAB;
 
 	/*
 	 * Clear the interrupt registers.
 	 */
-	write_zsreg(info->zs_channel, 0, ERR_RES);
-	write_zsreg(info->zs_channel, 0, RES_H_IUS);
+	write_zsreg(info->zs_channel, R0, ERR_RES);
+	write_zsreg(info->zs_channel, R0, RES_H_IUS);
 
 	/*
-	 * Set the speed of the serial port
+	 * Load up the new values.
 	 */
-	change_speed(info);
+	load_zsregs(info->zs_channel, info->zs_channel->curregs);
 
 	/* Save the current value of RR0 */
-	info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+	info->read_reg_zero = read_zsreg(info->zs_channel, R0);
 
-	zs_soft[co->index].clk_divisor = 16;
+	zs_soft[co->index].clk_divisor = clk_divisor;
 	zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);
 
 	restore_flags(flags);
-#endif
+
 	return 0;
 }
 
@@ -2296,7 +2314,7 @@
 	int one, nine;
 	nine = read_zsreg(chan, 9);
 	if (yes == 1) {
-		one = EXT_INT_ENAB|INT_ALL_Rx;
+		one = EXT_INT_ENAB|RxINT_ALL;
 		nine |= MIE;
 		printk("turning serial ints on\n");
 	} else {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)