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
- Lines: 348
- Date:
2004-02-18 05:36:31.000000000 -0800
- Orig file:
linux-2.4.24/drivers/tc/zs.c
- Orig date:
2003-08-25 04:44:42.000000000 -0700
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)