patch-2.1.34 linux/drivers/sbus/char/sunserial.c
Next file: linux/drivers/sbus/char/sunserial.h
Previous file: linux/drivers/sbus/char/sunmouse.c
Back to the patch index
Back to the overall index
- Lines: 742
- Date:
Mon Apr 14 09:31:09 1997
- Orig file:
v2.1.33/linux/drivers/sbus/char/sunserial.c
- Orig date:
Mon Mar 17 14:54:28 1997
diff -u --recursive --new-file v2.1.33/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.27 1997/03/04 19:33:55 davem Exp $
+/* $Id: sunserial.c,v 1.37 1997/04/12 23:33:14 ecd Exp $
* serial.c: Serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -39,6 +39,8 @@
#define KEYBOARD_LINE 0x2
#define MOUSE_LINE 0x3
+extern struct wait_queue * keypress_wait;
+
struct sun_zslayout **zs_chips;
struct sun_zschannel **zs_channels;
struct sun_zschannel *zs_conschan;
@@ -66,8 +68,8 @@
#define SUNKBD_UP 0x80
#define SUNKBD_A 0x4d
-extern void sunkbd_inchar(unsigned char ch, unsigned char status, struct pt_regs *regs);
-extern void sun_mouse_inbyte(unsigned char byte, unsigned char status);
+extern void sunkbd_inchar(unsigned char ch, struct pt_regs *regs);
+extern void sun_mouse_inbyte(unsigned char byte);
static unsigned char kgdb_regs[16] = {
0, 0, 0, /* write 0, 1, 2 */
@@ -173,7 +175,7 @@
*/
static int baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 0 };
+ 9600, 19200, 38400, 76800, 0 };
/*
* Reading and writing Zilog8530 registers. The delays are to make this
@@ -206,9 +208,20 @@
{
unsigned long flags;
struct sun_zschannel *channel = info->zs_channel;
+ unsigned char stat;
+ int i;
+ for (i = 0; i < 1000; i++) {
+ stat = read_zsreg(channel, R1);
+ if (stat & ALL_SNT)
+ break;
+ udelay(100);
+ }
+ write_zsreg(channel, R3, 0);
+ ZS_CLEARSTAT(channel);
ZS_CLEARERR(channel);
ZS_CLEARFIFO(channel);
+
/* Load 'em up */
save_flags(flags); cli();
if (info->channelA)
@@ -231,7 +244,7 @@
write_zsreg(channel, R5, regs[R5]);
write_zsreg(channel, R15, regs[R15]);
write_zsreg(channel, R0, RES_EXT_INT);
- write_zsreg(channel, R0, RES_EXT_INT);
+ write_zsreg(channel, R0, ERR_RES);
write_zsreg(channel, R1, regs[R1]);
write_zsreg(channel, R9, regs[R9]);
restore_flags(flags);
@@ -349,18 +362,6 @@
return;
}
-/* On receive, this clears errors and the receiver interrupts */
-static inline void rs_recv_clear(struct sun_zschannel *zsc)
-{
- unsigned long flags;
-
- save_flags(flags); cli();
- zsc->control = ERR_RES;
- udelay(5);
- zsc->control = RES_H_IUS;
- udelay(5);
- restore_flags(flags);
-}
/*
* ----------------------------------------------------------------------
@@ -391,7 +392,7 @@
int event)
{
info->event |= 1 << event;
- queue_task_irq_off(&info->tqueue, &tq_serial);
+ queue_task(&info->tqueue, &tq_serial);
mark_bh(SERIAL_BH);
}
@@ -402,90 +403,86 @@
struct tty_struct *tty = info->tty;
unsigned char ch, stat;
- ch = (info->zs_channel->data) & info->parity_mask;
- udelay(5);
- stat = read_zsreg(info->zs_channel, R1);
- udelay(5);
+ do {
+ ch = (info->zs_channel->data) & info->parity_mask;
+ udelay(5);
- /* If this is the console keyboard, we need to handle
- * L1-A's here.
- */
- if(info->cons_keyb) {
- if(ch == SUNKBD_RESET) {
- l1a_state.kbd_id = 1;
- l1a_state.l1_down = 0;
- } else if(l1a_state.kbd_id) {
- l1a_state.kbd_id = 0;
- } else if(ch == SUNKBD_L1) {
- l1a_state.l1_down = 1;
- } else if(ch == (SUNKBD_L1|SUNKBD_UP)) {
- l1a_state.l1_down = 0;
- } else if(ch == SUNKBD_A && l1a_state.l1_down) {
- /* whee... */
- batten_down_hatches();
- /* Clear the line and continue execution... */
- rs_recv_clear(info->zs_channel);
- l1a_state.l1_down = 0;
- l1a_state.kbd_id = 0;
+ /* If this is the console keyboard, we need to handle
+ * L1-A's here.
+ */
+ if(info->cons_keyb) {
+ if(ch == SUNKBD_RESET) {
+ l1a_state.kbd_id = 1;
+ l1a_state.l1_down = 0;
+ } else if(l1a_state.kbd_id) {
+ l1a_state.kbd_id = 0;
+ } else if(ch == SUNKBD_L1) {
+ l1a_state.l1_down = 1;
+ } else if(ch == (SUNKBD_L1|SUNKBD_UP)) {
+ l1a_state.l1_down = 0;
+ } else if(ch == SUNKBD_A && l1a_state.l1_down) {
+ /* whee... */
+ batten_down_hatches();
+ /* Continue execution... */
+ l1a_state.l1_down = 0;
+ l1a_state.kbd_id = 0;
+ return;
+ }
+ sunkbd_inchar(ch, regs);
return;
}
- rs_recv_clear(info->zs_channel);
- sunkbd_inchar(ch, stat, regs);
-
- return;
- }
- if(info->cons_mouse) {
- rs_recv_clear(info->zs_channel);
- sun_mouse_inbyte(ch, stat);
- return;
- }
- if(info->is_cons) {
- if(ch==0) { /* whee, break received */
- batten_down_hatches();
- rs_recv_clear(info->zs_channel);
+ if(info->cons_mouse) {
+ sun_mouse_inbyte(ch);
return;
+ }
+ if(info->is_cons) {
+ if(ch==0) {
+ /* whee, break received */
+ batten_down_hatches();
+ /* Continue execution... */
+ return;
#if 0
- } else if (ch == 1) {
- show_state();
- return;
- } else if (ch == 2) {
- show_buffers();
- return;
+ } else if (ch == 1) {
+ show_state();
+ return;
+ } else if (ch == 2) {
+ show_buffers();
+ return;
#endif
+ }
+ /* It is a 'keyboard interrupt' ;-) */
+ wake_up(&keypress_wait);
+ }
+ /* Look for kgdb 'stop' character, consult the gdb
+ * documentation for remote target debugging and
+ * arch/sparc/kernel/sparc-stub.c to see how all this works.
+ */
+ if((info->kgdb_channel) && (ch =='\003')) {
+ breakpoint();
+ return;
}
- /* It is a 'keyboard interrupt' ;-) */
- wake_up(&keypress_wait);
- }
- /* Look for kgdb 'stop' character, consult the gdb documentation
- * for remote target debugging and arch/sparc/kernel/sparc-stub.c
- * to see how all this works.
- */
- if((info->kgdb_channel) && (ch =='\003')) {
- breakpoint();
- goto clear_and_exit;
- }
- if(!tty)
- goto clear_and_exit;
+ if(!tty)
+ return;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
- tty->flip.count++;
- if(stat & PAR_ERR)
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
- else if(stat & Rx_OVR)
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
- else if(stat & CRC_ERR)
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- else
- *tty->flip.flag_buf_ptr++ = 0; /* XXX */
- *tty->flip.char_buf_ptr++ = ch;
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ break;
- queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+ tty->flip.count++;
+ *tty->flip.flag_buf_ptr++ = 0;
+ *tty->flip.char_buf_ptr++ = ch;
-clear_and_exit:
- rs_recv_clear(info->zs_channel);
- return;
+ /* Check if we have another character... */
+ stat = info->zs_channel->control;
+ udelay(5);
+ if (!(stat & Rx_CH_AV))
+ break;
+
+ /* ... and see if it is clean. */
+ stat = read_zsreg(info->zs_channel, R1);
+ } while (!(stat & (PAR_ERR | Rx_OVR | CRC_ERR)));
+
+ queue_task(&tty->flip.tqueue, &tq_timer);
}
static _INLINE_ void transmit_chars(struct sun_serial *info)
@@ -496,14 +493,14 @@
/* Send next char */
zs_put_char(info->zs_channel, info->x_char);
info->x_char = 0;
- goto clear_and_return;
+ return;
}
if((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) {
/* That's peculiar... */
info->zs_channel->control = RES_Tx_P;
udelay(5);
- goto clear_and_return;
+ return;
}
/* Send char */
@@ -517,14 +514,7 @@
if(info->xmit_cnt <= 0) {
info->zs_channel->control = RES_Tx_P;
udelay(5);
- goto clear_and_return;
}
-
-clear_and_return:
- /* Clear interrupt */
- info->zs_channel->control = RES_H_IUS;
- udelay(5);
- return;
}
static _INLINE_ void status_handle(struct sun_serial *info)
@@ -537,9 +527,6 @@
/* Clear status condition... */
info->zs_channel->control = RES_EXT_INT;
udelay(5);
- /* Clear the interrupt */
- info->zs_channel->control = RES_H_IUS;
- udelay(5);
#if 0
if(status & DCD) {
@@ -568,50 +555,106 @@
return;
}
+static _INLINE_ void special_receive(struct sun_serial *info)
+{
+ struct tty_struct *tty = info->tty;
+ unsigned char ch, stat;
+
+ stat = read_zsreg(info->zs_channel, R1);
+ if (stat & (PAR_ERR | Rx_OVR | CRC_ERR)) {
+ ch = info->zs_channel->data;
+ udelay(5);
+ }
+
+ if (!tty)
+ goto clear;
+
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ goto done;
+
+ tty->flip.count++;
+ if(stat & PAR_ERR)
+ *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ else if(stat & Rx_OVR)
+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ else if(stat & CRC_ERR)
+ *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+
+done:
+ queue_task(&tty->flip.tqueue, &tq_timer);
+clear:
+ info->zs_channel->control = ERR_RES;
+ udelay(5);
+}
+
+
/*
* This is the serial driver's generic interrupt routine
*/
void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
- struct sun_serial * info = (struct sun_serial *)dev_id;
+ struct sun_serial *info;
unsigned char zs_intreg;
int i;
+ info = (struct sun_serial *)dev_id;
for (i = 0; i < NUM_SERIAL; i++) {
- zs_intreg = read_zsreg(info->zs_channel, 3);
+ zs_intreg = read_zsreg(info->zs_next->zs_channel, 2);
+ zs_intreg &= STATUS_MASK;
- /* NOTE: The read register 3, which holds the irq status,
+ /* NOTE: The read register 2, which holds the irq status,
* does so for both channels on each chip. Although
- * the status value itself must be read from the A
- * channel and is only valid when read from channel A.
- * Yes... broken hardware...
+ * the status value itself must be read from the B
+ * channel and is only valid when read from channel B.
+ * When read from channel A, read register 2 contains
+ * the value written to write register 2.
*/
-#define CHAN_A_IRQMASK (CHARxIP | CHATxIP | CHAEXT)
-#define CHAN_B_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT)
/* Channel A -- /dev/ttya or /dev/kbd, could be the console */
- if(zs_intreg & CHAN_A_IRQMASK) {
- if (zs_intreg & CHARxIP)
- receive_chars(info, regs);
- if (zs_intreg & CHATxIP)
- transmit_chars(info);
- if (zs_intreg & CHAEXT)
- status_handle(info);
+ if (zs_intreg == CHA_Rx_AVAIL) {
+ receive_chars(info, regs);
+ return;
+ }
+ if(zs_intreg == CHA_Tx_EMPTY) {
+ transmit_chars(info);
+ return;
+ }
+ if (zs_intreg == CHA_EXT_STAT) {
+ status_handle(info);
+ return;
+ }
+ if (zs_intreg == CHA_SPECIAL) {
+ special_receive(info);
+ return;
}
-
- info=info->zs_next;
/* Channel B -- /dev/ttyb or /dev/mouse, could be the console */
- if(zs_intreg & CHAN_B_IRQMASK) {
- if (zs_intreg & CHBRxIP)
- receive_chars(info, regs);
- if (zs_intreg & CHBTxIP)
- transmit_chars(info);
- if (zs_intreg & CHBEXT)
- status_handle(info);
+ if(zs_intreg == CHB_Rx_AVAIL) {
+ receive_chars(info->zs_next, regs);
+ return;
+ }
+ if(zs_intreg == CHB_Tx_EMPTY) {
+ transmit_chars(info->zs_next);
+ return;
}
+ if (zs_intreg == CHB_EXT_STAT) {
+ status_handle(info->zs_next);
+ return;
+ }
+
+ /* NOTE: The default value for the IRQ status in read register
+ * 2 in channel B is CHB_SPECIAL, so we need to look at
+ * read register 3 in channel A to check if this is a
+ * real interrupt, or just the default value.
+ * Yes... broken hardware...
+ */
- info = info->zs_next;
+ zs_intreg = read_zsreg(info->zs_channel, 3);
+ if (zs_intreg & CHBRxIP) {
+ special_receive(info->zs_next);
+ return;
+ }
+ info = info->zs_next->zs_next;
}
}
@@ -811,6 +854,7 @@
{
unsigned short port;
unsigned cflag;
+ int quot = 0;
int i;
int brg;
@@ -821,13 +865,30 @@
return;
i = cflag & CBAUD;
if (cflag & CBAUDEX) {
- /* XXX CBAUDEX is not obeyed.
- * It is impossible at a 32bits SPARC.
- * But we have to report this to user ... someday.
- */
- i = B9600;
+ i &= ~CBAUDEX;
+ if (i != 1)
+ info->tty->termios->c_cflag &= ~CBAUDEX;
+ else
+ i += 15;
}
- if (baud_table[i]) {
+ if (i == 15) {
+ if ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_HI)
+ i += 1;
+ if ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_CUST)
+ quot = info->custom_divisor;
+ }
+ if (quot) {
+ info->zs_baud = info->baud_base / quot;
+ info->clk_divisor = 16;
+
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = TCBR | RCBR;
+ brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor);
+ info->curregs[12] = (brg & 255);
+ info->curregs[13] = ((brg >> 8) & 255);
+ info->curregs[14] = BRSRC | BRENAB;
+ zs_rtsdtr(info, 1);
+ } else if (baud_table[i]) {
info->zs_baud = baud_table[i];
info->clk_divisor = 16;
@@ -837,8 +898,10 @@
info->curregs[12] = (brg & 255);
info->curregs[13] = ((brg >> 8) & 255);
info->curregs[14] = BRSRC | BRENAB;
- /* } else { */
- /* XXX */
+ zs_rtsdtr(info, 1);
+ } else {
+ zs_rtsdtr(info, 0);
+ return;
}
/* byte size and parity */
@@ -902,7 +965,7 @@
void kbd_put_char(unsigned char ch)
{
struct sun_zschannel *chan = zs_kbdchan;
- int flags;
+ unsigned long flags;
if(!chan)
return;
@@ -915,7 +978,7 @@
void mouse_put_char(char ch)
{
struct sun_zschannel *chan = zs_mousechan;
- int flags;
+ unsigned long flags;
if(!chan)
return;
@@ -930,7 +993,7 @@
static void rs_put_char(char ch)
{
struct sun_zschannel *chan = zs_conschan;
- int flags;
+ unsigned long flags;
if(!chan)
return;
@@ -984,7 +1047,7 @@
rs_put_char(c);
- save_flags(flags); cli();
+ cli();
left = MIN(info->xmit_cnt, left-1);
}
@@ -1262,6 +1325,7 @@
info->baud_base = new_serial.baud_base;
info->flags = ((info->flags & ~ZILOG_FLAGS) |
(new_serial.flags & ZILOG_FLAGS));
+ info->custom_divisor = new_serial.custom_divisor;
info->type = new_serial.type;
info->close_delay = new_serial.close_delay;
info->closing_wait = new_serial.closing_wait;
@@ -1292,6 +1356,56 @@
return 0;
}
+static int get_modem_info(struct sun_serial * info, unsigned int *value)
+{
+ unsigned char status;
+ unsigned int result;
+
+ cli();
+ status = info->zs_channel->control;
+ sti();
+ result = ((info->curregs[5] & RTS) ? TIOCM_RTS : 0)
+ | ((info->curregs[5] & DTR) ? TIOCM_DTR : 0)
+ | ((status & DCD) ? TIOCM_CAR : 0)
+ | ((status & SYNC) ? TIOCM_DSR : 0)
+ | ((status & CTS) ? TIOCM_CTS : 0);
+ put_user_ret(result, value, -EFAULT);
+ return 0;
+}
+
+static int set_modem_info(struct sun_serial * info, unsigned int cmd,
+ unsigned int *value)
+{
+ unsigned int arg;
+
+ get_user_ret(arg, value, -EFAULT);
+ switch (cmd) {
+ case TIOCMBIS:
+ if (arg & TIOCM_RTS)
+ info->curregs[5] |= RTS;
+ if (arg & TIOCM_DTR)
+ info->curregs[5] |= DTR;
+ break;
+ case TIOCMBIC:
+ if (arg & TIOCM_RTS)
+ info->curregs[5] &= ~RTS;
+ if (arg & TIOCM_DTR)
+ info->curregs[5] &= ~DTR;
+ break;
+ case TIOCMSET:
+ info->curregs[5] = ((info->curregs[5] & ~(RTS | DTR))
+ | ((arg & TIOCM_RTS) ? RTS : 0)
+ | ((arg & TIOCM_DTR) ? DTR : 0));
+ break;
+ default:
+ return -EINVAL;
+ }
+ cli();
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ sti();
+ return 0;
+}
+
/*
* This routine sends a break character out the serial port.
*/
@@ -1341,7 +1455,8 @@
send_break(info, arg ? arg*(HZ/10) : HZ/4);
return 0;
case TIOCGSOFTCAR:
- put_user_ret(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg, -EFAULT);
+ put_user_ret(C_CLOCAL(tty) ? 1 : 0,
+ (unsigned long *) arg, -EFAULT);
return 0;
case TIOCSSOFTCAR:
get_user_ret(arg, (unsigned long *) arg, -EFAULT);
@@ -1349,6 +1464,12 @@
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
return 0;
+ 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);
@@ -1736,7 +1857,7 @@
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.27 $";
+ char *revision = "$Revision: 1.37 $";
char *version, *p;
version = strchr(revision, ' ');
@@ -1752,12 +1873,12 @@
* Zilogs, what the second does, I don't know. It does work
* with using only the first number of each property.
*/
-static inline struct sun_zslayout *get_zs(int chip)
+static struct sun_zslayout *get_zs(int chip)
{
struct linux_prom_irqs tmp_irq[2];
- unsigned long paddr = 0;
- unsigned long vaddr[2] = { 0, 0 };
- int zsnode, tmpnode, iospace, slave, len;
+ unsigned int paddr = 0;
+ unsigned int vaddr[2] = { 0, 0 };
+ int zsnode, tmpnode, iospace, slave, len, seen, sun4u_irq;
static int irq = 0;
#if CONFIG_AP1000
@@ -1784,7 +1905,7 @@
if(!irq)
zilog_irq = irq = 12;
vaddr[0] = (unsigned long)
- sparc_alloc_io((char *) paddr, 0, 8,
+ sparc_alloc_io(paddr, 0, 8,
"Zilog Serial", iospace, 0);
} else {
/* Can use the prom for other machine types */
@@ -1806,6 +1927,10 @@
}
if (!tmpnode)
panic ("get_zs: couldn't find board%d's bootbus\n", chip >> 1);
+ } else if (sparc_cpu_model == sun4u) {
+ tmpnode = prom_searchsiblings(zsnode, "sbus");
+ if(tmpnode)
+ zsnode = prom_getchild(tmpnode);
} else {
tmpnode = prom_searchsiblings(zsnode, "obio");
if(tmpnode)
@@ -1813,35 +1938,42 @@
}
if(!zsnode)
panic("get_zs no zs serial prom node");
+ seen = 0;
while(zsnode) {
zsnode = prom_searchsiblings(zsnode, "zs");
slave = prom_getintdefault(zsnode, "slave", -1);
- if(slave==chip) {
+ if((slave == chip) ||
+ (sparc_cpu_model == sun4u && seen == chip)) {
/* The one we want */
len = prom_getproperty(zsnode, "address",
(void *) vaddr,
sizeof(vaddr));
- if (len % sizeof(unsigned long)) {
+ if (len % sizeof(unsigned int)) {
prom_printf("WHOOPS: proplen for %s "
"was %d, need multiple of "
"%d\n", "address", len,
- sizeof(unsigned long));
+ sizeof(unsigned int));
panic("zilog: address property");
}
zs_nodes[chip] = zsnode;
- len = prom_getproperty(zsnode, "intr",
- (char *) tmp_irq,
- sizeof(tmp_irq));
- if (len % sizeof(struct linux_prom_irqs)) {
- prom_printf("WHOOPS: proplen for %s "
- "was %d, need multiple of "
- "%d\n", "address", len,
- sizeof(struct linux_prom_irqs));
- panic("zilog: address property");
+ if(sparc_cpu_model == sun4u) {
+ len = prom_getproperty(zsnode, "interrupts",
+ (char *) &sun4u_irq,
+ sizeof(tmp_irq));
+ tmp_irq[0].pri = sun4u_irq;
+ } else {
+ len = prom_getproperty(zsnode, "intr",
+ (char *) tmp_irq,
+ sizeof(tmp_irq));
+ if (len % sizeof(struct linux_prom_irqs)) {
+ prom_printf(
+ "WHOOPS: proplen for %s "
+ "was %d, need multiple of "
+ "%d\n", "address", len,
+ sizeof(struct linux_prom_irqs));
+ panic("zilog: address property");
+ }
}
-#ifdef OLD_STYLE_IRQ
- tmp_irq[0].pri &= 0xf;
-#endif
if(!irq) {
irq = zilog_irq = tmp_irq[0].pri;
} else {
@@ -1851,6 +1983,7 @@
break;
}
zsnode = prom_getsibling(zsnode);
+ seen++;
}
if(!zsnode)
panic("get_zs whee chip not found");
@@ -2037,8 +2170,8 @@
rs_cons_check(struct sun_serial *ss, int channel)
{
int i, o, io;
- static consout_registered = 0;
- static msg_printed = 0;
+ static int consout_registered = 0;
+ static int msg_printed = 0;
i = o = io = 0;
@@ -2144,7 +2277,8 @@
__initfunc(int rs_init(void))
{
- int chip, channel, brg, i, flags;
+ int chip, channel, brg, i;
+ unsigned long flags;
struct sun_serial *info;
char dummy;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov