patch-1.3.25 linux/drivers/char/cyclades.c

Next file: linux/drivers/char/scc.c
Previous file: linux/drivers/char/README.scc
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.24/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
@@ -1,11 +1,17 @@
 static char rcsid[] =
-"$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
+"$Revision: 1.36.3.2 $$Date: 1995/09/08 22:07:14 $";
 /*
- *  linux/kernel/cyclades.c
+ *  linux/drivers/char/cyclades.c
  *
- * Maintained by Marcio Saito (cyclades@netcom.com) and
+ * This file contains the driver for the Cyclades Cyclom-Y multiport
+ * serial boards.
+ *
+ * Maintained by Marcio Saito (marcio@cyclades.com) and
  * Randolph Bentson (bentson@grieg.seaslug.org)
  *
+ * For Technical support and installation problems, please send e-mail
+ * to support@cyclades.com.
+ *
  * Much of the design and some of the code came from serial.c
  * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
  * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
@@ -18,6 +24,19 @@
  *   int  cy_open(struct tty_struct *tty, struct file *filp);
  *
  * $Log: cyclades.c,v $
+ * Revision 1.36.3.2  1995/09/08  22:07:14  bentson
+ * remove printk from ISR; fix typo
+ *
+ * Revision 1.36.3.1  1995/09/01  12:00:42  marcio
+ * Minor fixes in the PCI board support. PCI function calls in
+ * conditional compilation (CONFIG_PCI). Thanks to Jim Duncan
+ * <duncan@okay.com>. "bad serial count" message removed.
+ *
+ * Revision 1.36.3  1995/08/22  09:19:42  marcio
+ * Cyclom-Y/PCI support added. Changes in the cy_init routine and
+ * board initialization. Changes in the boot messages. The driver
+ * supports up to 4 boards and 64 ports by default.
+ *
  * Revision 1.36.1.4  1995/03/29  06:14:14  bentson
  * disambiguate between Cyclom-16Y and Cyclom-32Ye;
  *
@@ -224,6 +243,12 @@
 #include <asm/segment.h>
 #include <asm/bitops.h>
 
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+
 #define small_delay(x) for(j=0;j<x;j++)k++;
 
 
@@ -258,28 +283,48 @@
 static int cy_wild_int_mask;
 static unsigned char *intr_base_addr;
 
-/* This is the per-card data structure containing a card's base
-   address.  Here are declarations for some common addresses.
-   Add entries to match your configuration (there are sixty-
-   four possible from 0x80000 to 0xFE000) */
-struct cyclades_card cy_card[] = {
- /* BASE_ADDR */
-    {0xD0000},
-    {0xD2000},
-    {0xD4000},
-    {0xD6000},
-    {0xD8000},
-    {0xDA000},
-    {0xDC000},
-    {0xDE000}
+
+/* This is the address lockup table. The driver will probe for Cyclom-Y/ISA
+   boards at all addresses in here. If you want the driver to probe addresses
+   in a different address, add it to this table.
+   If the driver is probing some other board and causing problems, remove the
+   address from this table.  */
+
+static unsigned char *cy_isa_addresses[] = {
+	(unsigned char *) 0xD0000,
+	(unsigned char *) 0xD2000,
+	(unsigned char *) 0xD4000,
+	(unsigned char *) 0xD6000,
+	(unsigned char *) 0xD8000,
+	(unsigned char *) 0xDA000,
+	(unsigned char *) 0xDC000,
+	(unsigned char *) 0xDE000,
 };
+#define	NR_ISA_ADDRESSES	(sizeof(cy_isa_addresses)/sizeof(unsigned char *))
+
+/* This is the per-card data structure containing address, irq, number of
+   channels, etc. This driver supports a maximum of NR_CARDS cards. If
+   you need to install more boards, change this constant in the definition
+   bellow. No other change is necesary to support more boards. */
 
-#define NR_CARDS        (sizeof(cy_card)/sizeof(struct cyclades_card))
+#define NR_CARDS	4
+
+static struct cyclades_card cy_card[NR_CARDS];
+
+/* This is the per-channel data structure containing pointers, flags
+   and variables for the port. This driver supports a maximum of NR_PORTS.
+   If the total number of ports is larger than NR_PORTS, change this
+   constant in the definition bellow. No other change is necessary to
+   support more boards/ports. */
+
+#define NR_PORTS        64
+
+static struct cyclades_port cy_port[NR_PORTS];
 
 /*  The Cyclom-Ye has placed the sequential chips in non-sequential
  *  address order.  This look-up table overcomes that problem.
  */
-int cy_chip_offset [] =
+static int cy_chip_offset [] =
     { 0x0000,
       0x0400,
       0x0800,
@@ -290,43 +335,16 @@
       0x0E00
     };
 
-/* This is the per-port data structure */
-struct cyclades_port cy_port[] = {
-      /* CARD#  */
-        {-1 },      /* ttyC0 */
-        {-1 },      /* ttyC1 */
-        {-1 },      /* ttyC2 */
-        {-1 },      /* ttyC3 */
-        {-1 },      /* ttyC4 */
-        {-1 },      /* ttyC5 */
-        {-1 },      /* ttyC6 */
-        {-1 },      /* ttyC7 */
-        {-1 },      /* ttyC8 */
-        {-1 },      /* ttyC9 */
-        {-1 },      /* ttyC10 */
-        {-1 },      /* ttyC11 */
-        {-1 },      /* ttyC12 */
-        {-1 },      /* ttyC13 */
-        {-1 },      /* ttyC14 */
-        {-1 },      /* ttyC15 */
-        {-1 },      /* ttyC16 */
-        {-1 },      /* ttyC17 */
-        {-1 },      /* ttyC18 */
-        {-1 },      /* ttyC19 */
-        {-1 },      /* ttyC20 */
-        {-1 },      /* ttyC21 */
-        {-1 },      /* ttyC22 */
-        {-1 },      /* ttyC23 */
-        {-1 },      /* ttyC24 */
-        {-1 },      /* ttyC25 */
-        {-1 },      /* ttyC26 */
-        {-1 },      /* ttyC27 */
-        {-1 },      /* ttyC28 */
-        {-1 },      /* ttyC29 */
-        {-1 },      /* ttyC30 */
-        {-1 }       /* ttyC31 */
-};
-#define NR_PORTS        (sizeof(cy_port)/sizeof(struct cyclades_port))
+/* PCI related definitions */
+
+static unsigned short	cy_pci_nboard = 0;
+static unsigned short	cy_isa_nboard = 0;
+static unsigned short	cy_nboard = 0;
+
+int			cy_detect_isa(void);
+int			cy_detect_pci(void);
+
+static int		cy_next_channel = 0;	/* next minor available */
 
 static int serial_refcount;
 
@@ -334,10 +352,10 @@
 static struct termios *serial_termios[NR_PORTS];
 static struct termios *serial_termios_locked[NR_PORTS];
 
-
 /* This is the per-irq data structure,
-               it maps an irq to the corresponding card */
-struct cyclades_card * IRQ_cards[16];
+   it maps an irq to the corresponding card */
+
+struct cyclades_card	*IRQ_cards[16];
 
 
 /*
@@ -392,7 +410,6 @@
 #endif
 
 
-
 static inline int
 serial_paranoia_check(struct cyclades_port *info,
 			dev_t device, const char *routine)
@@ -456,7 +473,7 @@
    didn't finish within the time limit.
  */
 u_short
-write_cy_cmd(u_char *base_addr, u_char cmd)
+write_cy_cmd(u_char *base_addr, u_char cmd, int index)
 {
   unsigned long flags;
   volatile int  i;
@@ -464,20 +481,20 @@
     save_flags(flags); cli();
 	/* Check to see that the previous command has completed */
 	for(i = 0 ; i < 100 ; i++){
-	    if (base_addr[CyCCR] == 0){
+	    if (base_addr[CyCCR<<index] == 0){
 		break;
 	    }
 	    udelay(10L);
 	}
 	/* if the CCR never cleared, the previous command
 	    didn't finish within the "reasonable time" */
-	if ( i == 10 ) {
+	if ( i == 100 ) {
 	    restore_flags(flags);
 	    return (-1);
 	}
 
 	/* Issue the new command */
-	base_addr[CyCCR] = cmd;
+	base_addr[CyCCR<<index] = cmd;
     restore_flags(flags);
     return(0);
 } /* write_cy_cmd */
@@ -492,7 +509,7 @@
   struct cyclades_card *cinfo;
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned char *base_addr;
-  int chip,channel;
+  int chip,channel,index;
   unsigned long flags;
 
 #ifdef SERIAL_DEBUG_OTHER
@@ -503,15 +520,16 @@
 	return;
 	
     cinfo = &cy_card[info->card];
+    index = cinfo->bus_index;
     channel = info->line - cinfo->first_line;
     chip = channel>>2;
     channel &= 0x03;
     base_addr = (unsigned char*)
-                   (cy_card[info->card].base_addr + cy_chip_offset[chip]);
+                   (cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index));
 
     save_flags(flags); cli();
-        base_addr[CyCAR] = (u_char)(channel & 0x0003); /* index channel */
-        base_addr[CySRER] &= ~CyTxMpty;
+        base_addr[CyCAR<<index] = (u_char)(channel & 0x0003); /* index channel */
+        base_addr[CySRER<<index] &= ~CyTxMpty;
     restore_flags(flags);
 
     return;
@@ -523,7 +541,7 @@
   struct cyclades_card *cinfo;
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned char *base_addr;
-  int chip,channel;
+  int chip,channel,index;
   unsigned long flags;
 
 #ifdef SERIAL_DEBUG_OTHER
@@ -534,15 +552,16 @@
 	return;
 	
     cinfo = &cy_card[info->card];
+    index = cinfo->bus_index;
     channel = info->line - cinfo->first_line;
     chip = channel>>2;
     channel &= 0x03;
     base_addr = (unsigned char*)
-                   (cy_card[info->card].base_addr + cy_chip_offset[chip]);
+                   (cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index));
 
     save_flags(flags); cli();
-        base_addr[CyCAR] = (u_char)(channel & 0x0003);
-        base_addr[CySRER] |= CyTxMpty;
+        base_addr[CyCAR<<index] = (u_char)(channel & 0x0003);
+        base_addr[CySRER<<index] |= CyTxMpty;
     restore_flags(flags);
 
     return;
@@ -572,8 +591,26 @@
 static void
 cy_probe(int irq, struct pt_regs *regs)
 {
+  int save_xir, save_car;
+  int index = 0;	/* probing interrupts is only for ISA */
+
     cy_irq_triggered = irq;
     cy_triggered |= 1 << irq;
+
+	if(intr_base_addr[CySVRR<<index] != 0) {
+	    save_xir = (u_char) intr_base_addr[CyTIR<<index];
+	    save_car = intr_base_addr[CyCAR<<index];
+	    if ((save_xir & 0x3) != 0){
+		SP("channel ");
+		CP2(save_xir);
+		SP(" requesting unexpected interrupt\n");
+	    }
+	    intr_base_addr[CyCAR<<index] = (save_xir & 0x3);
+	    intr_base_addr[CySRER<<index] &= ~CyTxMpty;
+	    intr_base_addr[CyTIR<<index] = (save_xir & 0x3f);
+	    intr_base_addr[CyCAR<<index] = (save_car);
+	    *(intr_base_addr + (Cy_ClrIntr<<index)) = 0; /* Cy_ClrIntr is 0x1800 */
+	}
     return;
 } /* cy_probe */
 
@@ -592,10 +629,9 @@
   int chip;
   int save_xir, channel, save_car;
   char data;
-  volatile char vdata;
   int char_count;
   int outch;
-  int i,j;
+  int i,j,index;
   int too_many;
   int had_work;
   int mdm_change;
@@ -605,6 +641,9 @@
         return; /* spurious interrupt */
     }
 
+    card_base_addr = (unsigned char *)cinfo->base_addr;
+    index = cinfo->bus_index;
+
     /* This loop checks all chips in the card.  Make a note whenever
        _any_ chip had some work to do, as this is considered an
        indication that there will be more to do.  Only when no chip
@@ -614,9 +653,9 @@
         had_work = 0;
         for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
 	    base_addr = (unsigned char *)
-	                   (cinfo->base_addr + cy_chip_offset[chip]);
+	                   (cinfo->base_addr + (cy_chip_offset[chip]<<index));
             too_many = 0;
-            while ( (status = base_addr[CySVRR]) != 0x00) {
+            while ( (status = base_addr[CySVRR<<index]) != 0x00) {
                 had_work++;
                 /* The purpose of the following test is to ensure that
                    no chip can monopolize the driver.  This forces the
@@ -627,32 +666,31 @@
                     break;
                 }
                 if (status & CySRReceive) {      /* reception interrupt */
-
                     /* determine the channel and change to that context */
-                    save_xir = (u_char) base_addr[CyRIR];
+                    save_xir = (u_char) base_addr[CyRIR<<index];
                     channel = (u_short ) (save_xir & CyIRChannel);
                     i = channel + chip * 4 + cinfo->first_line;
                     info = &cy_port[i];
                     info->last_active = jiffies;
-                    save_car = base_addr[CyCAR];
-                    base_addr[CyCAR] = save_xir;
+                    save_car = base_addr[CyCAR<<index];
+                    base_addr[CyCAR<<index] = save_xir;
 
                     /* if there is nowhere to put the data, discard it */
                     if(info->tty == 0){
-                        j = (base_addr[CyRIVR] & CyIVRMask);
+                        j = (base_addr[CyRIVR<<index] & CyIVRMask);
                         if ( j == CyIVRRxEx ) { /* exception */
-                            data = base_addr[CyRDSR];
+                            data = base_addr[CyRDSR<<index];
                         } else { /* normal character reception */
-                            char_count = base_addr[CyRDCR];
+                            char_count = base_addr[CyRDCR<<index];
                             while(char_count--){
-                                data = base_addr[CyRDSR];
+                                data = base_addr[CyRDSR<<index];
                             }
                         }
                     }else{ /* there is an open port for this data */
                         tty = info->tty;
-                        j = (base_addr[CyRIVR] & CyIVRMask);
+                        j = (base_addr[CyRIVR<<index] & CyIVRMask);
                         if ( j == CyIVRRxEx ) { /* exception */
-                            data = base_addr[CyRDSR];
+                            data = base_addr[CyRDSR<<index];
                             if(data & info->ignore_status_mask){
                                 continue;
                             }
@@ -663,7 +701,7 @@
 					*tty->flip.flag_buf_ptr++ =
 								TTY_BREAK;
 					*tty->flip.char_buf_ptr++ =
-							base_addr[CyRDSR];
+							base_addr[CyRDSR<<index];
 					if (info->flags & ASYNC_SAK){
 					    do_SAK(tty);
 					}
@@ -671,12 +709,12 @@
 					*tty->flip.flag_buf_ptr++ =
 								TTY_FRAME;
 					*tty->flip.char_buf_ptr++ =
-							base_addr[CyRDSR];
+							base_addr[CyRDSR<<index];
 				    }else if(data & CyPARITY){
 					*tty->flip.flag_buf_ptr++ =
 								TTY_PARITY;
 					*tty->flip.char_buf_ptr++ =
-							base_addr[CyRDSR];
+							base_addr[CyRDSR<<index];
 				    }else if(data & CyOVERRUN){
 					*tty->flip.flag_buf_ptr++ =
 								TTY_OVERRUN;
@@ -690,7 +728,7 @@
 					    *tty->flip.flag_buf_ptr++ =
 					                         TTY_NORMAL;
 					    *tty->flip.char_buf_ptr++ =
-							base_addr[CyRDSR];
+							base_addr[CyRDSR<<index];
 					}
 				    /* These two conditions may imply */
 				    /* a normal read should be done. */
@@ -710,7 +748,7 @@
                             }
                         } else { /* normal character reception */
                             /* load # characters available from the chip */
-                            char_count = base_addr[CyRDCR];
+                            char_count = base_addr[CyRDCR<<index];
 
 #ifdef CYCLOM_ENABLE_MONITORING
 			    ++info->mon.int_count;
@@ -724,7 +762,7 @@
                                         break;
                                 }
 				tty->flip.count++;
-                                data = base_addr[CyRDSR];
+                                data = base_addr[CyRDSR<<index];
 				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 				*tty->flip.char_buf_ptr++ = data;
 #ifdef CYCLOM_16Y_HACK
@@ -735,8 +773,8 @@
                         queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
                     }
                     /* end of service */
-                    base_addr[CyRIR] = (save_xir & 0x3f);
-                    base_addr[CyCAR] = (save_car);
+                    base_addr[CyRIR<<index] = (save_xir & 0x3f);
+                    base_addr[CyCAR<<index] = (save_car);
                 }
 
 
@@ -745,21 +783,21 @@
                         we know we can always stuff a dozen characters. */
 
                     /* determine the channel and change to that context */
-                    save_xir = (u_char) base_addr[CyTIR];
+                    save_xir = (u_char) base_addr[CyTIR<<index];
                     channel = (u_short ) (save_xir & CyIRChannel);
                     i = channel + chip * 4 + cinfo->first_line;
-                    save_car = base_addr[CyCAR];
-                    base_addr[CyCAR] = save_xir;
+                    save_car = base_addr[CyCAR<<index];
+                    base_addr[CyCAR<<index] = save_xir;
 
                     /* validate the port number (as configured and open) */
                     if( (i < 0) || (NR_PORTS <= i) ){
-                        base_addr[CySRER] &= ~CyTxMpty;
+                        base_addr[CySRER<<index] &= ~CyTxMpty;
                         goto txend;
                     }
                     info = &cy_port[i];
                     info->last_active = jiffies;
                     if(info->tty == 0){
-                        base_addr[CySRER] &= ~CyTxMpty;
+                        base_addr[CySRER<<index] &= ~CyTxMpty;
                         goto txdone;
                     }
 
@@ -769,7 +807,7 @@
 
                     if(info->x_char) { /* send special char */
                         outch = info->x_char;
-                        base_addr[CyTDR] = outch;
+                        base_addr[CyTDR<<index] = outch;
                         char_count--;
                         info->x_char = 0;
                     }
@@ -783,28 +821,28 @@
 			    so the delay is duration * 200/HZ, and thus a
 			    break can run from 1/100 sec to about 5/4 sec.
 			 */
-			base_addr[CyTDR] = 0; /* start break */
-			base_addr[CyTDR] = 0x81;
-			base_addr[CyTDR] = 0; /* delay a bit */
-			base_addr[CyTDR] = 0x82;
-			base_addr[CyTDR] = info->x_break*200/HZ;
-			base_addr[CyTDR] = 0; /* terminate break */
-			base_addr[CyTDR] = 0x83;
+			base_addr[CyTDR<<index] = 0; /* start break */
+			base_addr[CyTDR<<index] = 0x81;
+			base_addr[CyTDR<<index] = 0; /* delay a bit */
+			base_addr[CyTDR<<index] = 0x82;
+			base_addr[CyTDR<<index] = info->x_break*200/HZ;
+			base_addr[CyTDR<<index] = 0; /* terminate break */
+			base_addr[CyTDR<<index] = 0x83;
 			char_count -= 7;
 			info->x_break = 0;
 		    }
 
                     while (char_count-- > 0){
                         if (!info->xmit_cnt){
-			    base_addr[CySRER] &= ~CyTxMpty;
+			    base_addr[CySRER<<index] &= ~CyTxMpty;
 			    goto txdone;
                         }
 			if (info->xmit_buf == 0){
-			    base_addr[CySRER] &= ~CyTxMpty;
+			    base_addr[CySRER<<index] &= ~CyTxMpty;
 			    goto txdone;
 			}
 			if (info->tty->stopped || info->tty->hw_stopped){
-			    base_addr[CySRER] &= ~CyTxMpty;
+			    base_addr[CySRER<<index] &= ~CyTxMpty;
 			    goto txdone;
 			}
                         /* Because the Embedded Transmit Commands have been
@@ -823,14 +861,14 @@
 			    info->xmit_cnt--;
 			    info->xmit_tail = (info->xmit_tail + 1)
 						      & (PAGE_SIZE - 1);
-			    base_addr[CyTDR] = outch;
+			    base_addr[CyTDR<<index] = outch;
                         }else{
                             if(char_count > 1){
 				info->xmit_cnt--;
 				info->xmit_tail = (info->xmit_tail + 1)
 							  & (PAGE_SIZE - 1);
-				base_addr[CyTDR] = outch;
-				base_addr[CyTDR] = 0;
+				base_addr[CyTDR<<index] = outch;
+				base_addr[CyTDR<<index] = 0;
 				char_count--;
                             }else{
                             }
@@ -844,22 +882,22 @@
 
         txend:
                     /* end of service */
-                    base_addr[CyTIR] = (save_xir & 0x3f);
-                    base_addr[CyCAR] = (save_car);
+                    base_addr[CyTIR<<index] = (save_xir & 0x3f);
+                    base_addr[CyCAR<<index] = (save_car);
                 }
 
                 if (status & CySRModem) {        /* modem interrupt */
 
                     /* determine the channel and change to that context */
-                    save_xir = (u_char) base_addr[CyMIR];
+                    save_xir = (u_char) base_addr[CyMIR<<index];
                     channel = (u_short ) (save_xir & CyIRChannel);
                     info = &cy_port[channel + chip * 4 + cinfo->first_line];
                     info->last_active = jiffies;
-                    save_car = base_addr[CyCAR];
-                    base_addr[CyCAR] = save_xir;
+                    save_car = base_addr[CyCAR<<index];
+                    base_addr[CyCAR<<index] = save_xir;
 
-                    mdm_change = base_addr[CyMISR];
-                    mdm_status = base_addr[CyMSVR1];
+                    mdm_change = base_addr[CyMISR<<index];
+                    mdm_status = base_addr[CyMSVR1<<index];
 
                     if(info->tty == 0){ /* nowhere to put the data, ignore it */
                         ;
@@ -881,14 +919,14 @@
                                 if(mdm_status & CyCTS){
                                     /* !!! cy_start isn't used because... */
                                     info->tty->stopped = 0;
-				    base_addr[CySRER] |= CyTxMpty;
+				    base_addr[CySRER<<index] |= CyTxMpty;
 				    cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
                                 }
                             }else{
                                 if(!(mdm_status & CyCTS)){
                                     /* !!! cy_stop isn't used because... */
                                     info->tty->stopped = 1;
-				    base_addr[CySRER] &= ~CyTxMpty;
+				    base_addr[CySRER<<index] &= ~CyTxMpty;
                                 }
                             }
                         }
@@ -898,16 +936,15 @@
                         }
                     }
                     /* end of service */
-                    base_addr[CyMIR] = (save_xir & 0x3f);
-                    base_addr[CyCAR] = save_car;
+                    base_addr[CyMIR<<index] = (save_xir & 0x3f);
+                    base_addr[CyCAR<<index] = save_car;
                 }
             }          /* end while status != 0 */
         }            /* end loop for chips... */
     } while(had_work);
 
    /* clear interrupts */
-    card_base_addr = (unsigned char *)cinfo->base_addr;
-   vdata = *(card_base_addr + Cy_ClrIntr); /* Cy_ClrIntr is 0x1800 */
+   *(card_base_addr + (Cy_ClrIntr<<index)) = 0; /* Cy_ClrIntr is 0x1800 */
 
 } /* cy_interrupt */
 
@@ -1025,13 +1062,13 @@
 	 * Delay for 0.1 seconds -- we use a busy loop since this may 
 	 * occur during the bootup sequence
 	 */
-	timeout = jiffies+HZ/10;
+	timeout = jiffies+10;
 	while (timeout >= jiffies)
 	    ;
 	
 	cy_triggered = 0;	/* Reset after letting things settle */
 
-	timeout = jiffies+HZ/10;
+	timeout = jiffies+10;
 	while (timeout >= jiffies)
 		;
 	
@@ -1052,49 +1089,31 @@
  * fool-proof, but it works a large part of the time.
  */
 static int
-get_auto_irq(int card)
+get_auto_irq(unsigned char *address)
 {
   unsigned long timeout;
   unsigned char *base_addr;
-  int save_xir, save_car;
-  volatile char vdata;
+  int		index;
 
-    base_addr = (unsigned char*) (cy_card[card].base_addr);
-    intr_base_addr = base_addr;
+    index = 0;	/* IRQ probing is only for ISA */
+    base_addr = address;
+    intr_base_addr = address;
 	
     /*
      * Enable interrupts and see who answers
      */
     cy_irq_triggered = 0;
     cli();
-	base_addr[CyCAR] = 0;
-	write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_XMTR);
-	base_addr[CySRER] |= CyTxMpty;
+	base_addr[CyCAR<<index] = 0;
+	write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_XMTR,index);
+	base_addr[CySRER<<index] |= CyTxMpty;
     sti();
     
-    timeout = jiffies+2*HZ/100;
+    timeout = jiffies+2;
     while (timeout >= jiffies) {
 	if (cy_irq_triggered)
 	    break;
     }
-    /*
-     * Now check to see if we got any business, and clean up.
-     */
-    cli();
-	if(intr_base_addr[CySVRR] != 0){
-	    save_xir = (u_char) intr_base_addr[CyTIR];
-	    save_car = intr_base_addr[CyCAR];
-	    if ((save_xir & 0x3) != 0){
-		printk("channel %x requesting unexpected interrupt\n",save_xir);
-	    }
-	    intr_base_addr[CyCAR] = (save_xir & 0x3);
-	    intr_base_addr[CySRER] &= ~CyTxMpty;
-	    intr_base_addr[CyTIR] = (save_xir & 0x3f);
-	    intr_base_addr[CyCAR] = (save_car);
-	    vdata = *(intr_base_addr + Cy_ClrIntr); /* Cy_ClrIntr is 0x1800 */
-	}
-    sti();
-
     return(cy_irq_triggered);
 } /* get_auto_irq */
 
@@ -1103,7 +1122,7 @@
  * faked out by random interrupts
  */
 static int
-do_auto_irq(int card)
+do_auto_irq(unsigned char *address)
 {
   int 			irq_lines = 0;
   int			irq_try_1 = 0, irq_try_2 = 0;
@@ -1119,9 +1138,9 @@
 	
 	for (retries = 0; retries < 5; retries++) {
 	    if (!irq_try_1)
-		irq_try_1 = get_auto_irq(card);
+		irq_try_1 = get_auto_irq(address);
 	    if (!irq_try_2)
-		irq_try_2 = get_auto_irq(card);
+		irq_try_2 = get_auto_irq(address);
 	    if (irq_try_1 && irq_try_2) {
 		if (irq_try_1 == irq_try_2)
 		    break;
@@ -1142,7 +1161,7 @@
 {
   unsigned long flags;
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
 
     if (info->flags & ASYNC_INITIALIZED){
 	return 0;
@@ -1167,8 +1186,9 @@
     channel = (info->line) - (cy_card[card].first_line);
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
 #ifdef SERIAL_DEBUG_OPEN
     printk("startup card %d, chip %d, channel %d, base_addr %lx",
@@ -1176,25 +1196,25 @@
 #endif
 
     save_flags(flags); cli();
-	base_addr[CyCAR] = (u_char)channel;
+	base_addr[CyCAR<<index] = (u_char)channel;
 
-	base_addr[CyRTPR] = (info->default_timeout
+	base_addr[CyRTPR<<index] = (info->default_timeout
 			     ? info->default_timeout
 			     : 0x02); /* 10ms rx timeout */
 
-	write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR);
+	write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
 
-	base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */
-	base_addr[CyMSVR1] = CyRTS;
+	base_addr[CyCAR<<index] = (u_char)channel; /* !!! Is this needed? */
+	base_addr[CyMSVR1<<index] = CyRTS;
 /* CP('S');CP('1'); */
-	base_addr[CyMSVR2] = CyDTR;
+	base_addr[CyMSVR2<<index] = CyDTR;
 
 #ifdef SERIAL_DEBUG_DTR
         printk("cyc: %d: raising DTR\n", __LINE__);
-        printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+        printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 
-	base_addr[CySRER] |= CyRxData;
+	base_addr[CySRER<<index] |= CyRxData;
 	info->flags |= ASYNC_INITIALIZED;
 
 	if (info->tty){
@@ -1215,17 +1235,19 @@
 {
   unsigned long flags;
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
 
     card = info->card;
     channel = (info->line) - (cy_card[card].first_line);
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+
     save_flags(flags); cli();
-	base_addr[CyCAR] = channel;
-	base_addr[CySRER] |= CyTxMpty;
+	base_addr[CyCAR<<index] = channel;
+	base_addr[CySRER<<index] |= CyTxMpty;
     restore_flags(flags);
 } /* start_xmit */
 
@@ -1238,7 +1260,7 @@
 {
   unsigned long flags;
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
 
     if (!(info->flags & ASYNC_INITIALIZED)){
 /* CP('$'); */
@@ -1249,8 +1271,9 @@
     channel = info->line - cy_card[card].first_line;
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
 #ifdef SERIAL_DEBUG_OPEN
     printk("shutdown card %d, chip %d, channel %d, base_addr %lx\n",
@@ -1269,17 +1292,16 @@
 	    info->xmit_buf = 0;
 	}
 
-	base_addr[CyCAR] = (u_char)channel;
+	base_addr[CyCAR<<index] = (u_char)channel;
 	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-	    base_addr[CyMSVR1] = ~CyRTS;
-/* CP('C');CP('1'); */
-	    base_addr[CyMSVR2] = ~CyDTR;
+	    base_addr[CyMSVR1<<index] = ~CyRTS;
+	    base_addr[CyMSVR2<<index] = ~CyDTR;
 #ifdef SERIAL_DEBUG_DTR
             printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
         }
-	write_cy_cmd(base_addr,CyCHAN_CTL|CyDIS_RCVR);
+	write_cy_cmd(base_addr,CyCHAN_CTL|CyDIS_RCVR,index);
          /* it may be appropriate to clear _XMIT at
            some later date (after testing)!!! */
 
@@ -1303,7 +1325,7 @@
 {
   unsigned long flags;
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
   unsigned cflag;
   int   i;
 
@@ -1423,62 +1445,63 @@
     channel = (info->line) - (cy_card[card].first_line);
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
     save_flags(flags); cli();
-	base_addr[CyCAR] = (u_char)channel;
+	base_addr[CyCAR<<index] = (u_char)channel;
 
        /* tx and rx baud rate */
 
-	base_addr[CyTCOR] = info->tco;
-	base_addr[CyTBPR] = info->tbpr;
-	base_addr[CyRCOR] = info->rco;
-	base_addr[CyRBPR] = info->rbpr;
+	base_addr[CyTCOR<<index] = info->tco;
+	base_addr[CyTBPR<<index] = info->tbpr;
+	base_addr[CyRCOR<<index] = info->rco;
+	base_addr[CyRBPR<<index] = info->rbpr;
 
 	/* set line characteristics  according configuration */
 
-	base_addr[CySCHR1] = START_CHAR(info->tty);
-	base_addr[CySCHR2] = STOP_CHAR(info->tty);
-	base_addr[CyCOR1] = info->cor1;
-	base_addr[CyCOR2] = info->cor2;
-	base_addr[CyCOR3] = info->cor3;
-	base_addr[CyCOR4] = info->cor4;
-	base_addr[CyCOR5] = info->cor5;
+	base_addr[CySCHR1<<index] = START_CHAR(info->tty);
+	base_addr[CySCHR2<<index] = STOP_CHAR(info->tty);
+	base_addr[CyCOR1<<index] = info->cor1;
+	base_addr[CyCOR2<<index] = info->cor2;
+	base_addr[CyCOR3<<index] = info->cor3;
+	base_addr[CyCOR4<<index] = info->cor4;
+	base_addr[CyCOR5<<index] = info->cor5;
 
-	write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch);
+	write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index);
 
-	base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */
+	base_addr[CyCAR<<index] = (u_char)channel; /* !!! Is this needed? */
 
-	base_addr[CyRTPR] = (info->default_timeout
+	base_addr[CyRTPR<<index] = (info->default_timeout
 			     ? info->default_timeout
 			     : 0x02); /* 10ms rx timeout */
 
 	if (C_CLOCAL(info->tty)) {
-	    base_addr[CySRER] |= 0; /* without modem intr */
+	    base_addr[CySRER<<index] |= 0; /* without modem intr */
 				    /* ignore 1->0 modem transitions */
-	    base_addr[CyMCOR1] = 0x0;
+	    base_addr[CyMCOR1<<index] = 0x0;
 				    /* ignore 0->1 modem transitions */
-	    base_addr[CyMCOR2] = 0x0;
+	    base_addr[CyMCOR2<<index] = 0x0;
 	} else {
-	    base_addr[CySRER] |= CyMdmCh; /* with modem intr */
+	    base_addr[CySRER<<index] |= CyMdmCh; /* with modem intr */
 				    /* act on 1->0 modem transitions */
-	    base_addr[CyMCOR1] = CyDSR|CyCTS|CyRI|CyDCD;
+	    base_addr[CyMCOR1<<index] = CyDSR|CyCTS|CyRI|CyDCD;
 				    /* act on 0->1 modem transitions */
-	    base_addr[CyMCOR2] = CyDSR|CyCTS|CyRI|CyDCD;
+	    base_addr[CyMCOR2<<index] = CyDSR|CyCTS|CyRI|CyDCD;
 	}
 
 	if(i == 0){ /* baud rate is zero, turn off line */
-	    base_addr[CyMSVR2] = ~CyDTR;
+	    base_addr[CyMSVR2<<index] = ~CyDTR;
 #ifdef SERIAL_DEBUG_DTR
             printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 	}else{
-	    base_addr[CyMSVR2] = CyDTR;
+	    base_addr[CyMSVR2<<index] = CyDTR;
 #ifdef SERIAL_DEBUG_DTR
             printk("cyc: %d: raising DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 	}
 
@@ -1526,7 +1549,7 @@
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
 				
 #ifdef SERIAL_DEBUG_IO
     printk("cy_flush_chars ttyC%d\n", info->line); /* */
@@ -1543,12 +1566,13 @@
     channel = info->line - cy_card[card].first_line;
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
     save_flags(flags); cli();
-	base_addr[CyCAR] = channel;
-	base_addr[CySRER] |= CyTxMpty;
+	base_addr[CyCAR<<index] = channel;
+	base_addr[CySRER<<index] |= CyTxMpty;
     restore_flags(flags);
 } /* cy_flush_chars */
 
@@ -1561,7 +1585,7 @@
  */
 static int
 cy_write(struct tty_struct * tty, int from_user,
-          const unsigned char *buf, int count)
+           unsigned char *buf, int count)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
@@ -1682,7 +1706,7 @@
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
 
 #ifdef SERIAL_DEBUG_THROTTLE
   char buf[64];
@@ -1705,12 +1729,13 @@
     channel = info->line - cy_card[card].first_line;
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
     save_flags(flags); cli();
-	base_addr[CyCAR] = (u_char)channel;
-	base_addr[CyMSVR1] = ~CyRTS;
+	base_addr[CyCAR<<index] = (u_char)channel;
+	base_addr[CyMSVR1<<index] = ~CyRTS;
     restore_flags(flags);
 
     return;
@@ -1723,7 +1748,7 @@
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
 
 #ifdef SERIAL_DEBUG_THROTTLE
   char buf[64];
@@ -1746,12 +1771,13 @@
     channel = info->line - cy_card[card].first_line;
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
     save_flags(flags); cli();
-	base_addr[CyCAR] = (u_char)channel;
-	base_addr[CyMSVR1] = CyRTS;
+	base_addr[CyCAR<<index] = (u_char)channel;
+	base_addr[CyMSVR1<<index] = CyRTS;
     restore_flags(flags);
 
     return;
@@ -1827,7 +1853,7 @@
 static int
 get_modem_info(struct cyclades_port * info, unsigned int *value)
 {
-  int card,chip,channel;
+  int card,chip,channel,index;
   unsigned char *base_addr;
   unsigned long flags;
   unsigned char status;
@@ -1837,12 +1863,14 @@
     channel = (info->line) - (cy_card[card].first_line);
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-                   (cy_card[card].base_addr + cy_chip_offset[chip]);
+                   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
     save_flags(flags); cli();
-        base_addr[CyCAR] = (u_char)channel;
-        status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
+        base_addr[CyCAR<<index] = (u_char)channel;
+        status = base_addr[CyMSVR1<<index];
+	status |= base_addr[CyMSVR2<<index];
     restore_flags(flags);
 
     result =  ((status  & CyRTS) ? TIOCM_RTS : 0)
@@ -1851,7 +1879,7 @@
             | ((status  & CyRI) ? TIOCM_RNG : 0)
             | ((status  & CyDSR) ? TIOCM_DSR : 0)
             | ((status  & CyCTS) ? TIOCM_CTS : 0);
-    put_user(result,value);
+    put_fs_long(result,(unsigned long *) value);
     return 0;
 } /* get_modem_info */
 
@@ -1859,34 +1887,35 @@
 set_modem_info(struct cyclades_port * info, unsigned int cmd,
                           unsigned int *value)
 {
-  int card,chip,channel;
+  int card,chip,channel,index;
   unsigned char *base_addr;
   unsigned long flags;
-  unsigned int arg = get_user(value);
+  unsigned int arg = get_fs_long((unsigned long *) value);
 
     card = info->card;
     channel = (info->line) - (cy_card[card].first_line);
     chip = channel>>2;
     channel &= 0x03;
+    index = cy_card[card].bus_index;
     base_addr = (unsigned char*)
-                   (cy_card[card].base_addr + cy_chip_offset[chip]);
+                   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
     switch (cmd) {
     case TIOCMBIS:
 	if (arg & TIOCM_RTS){
 	    save_flags(flags); cli();
-		base_addr[CyCAR] = (u_char)channel;
-		base_addr[CyMSVR1] = CyRTS;
+		base_addr[CyCAR<<index] = (u_char)channel;
+		base_addr[CyMSVR1<<index] = CyRTS;
 	    restore_flags(flags);
 	}
 	if (arg & TIOCM_DTR){
 	    save_flags(flags); cli();
-	    base_addr[CyCAR] = (u_char)channel;
+	    base_addr[CyCAR<<index] = (u_char)channel;
 /* CP('S');CP('2'); */
-	    base_addr[CyMSVR2] = CyDTR;
+	    base_addr[CyMSVR2<<index] = CyDTR;
 #ifdef SERIAL_DEBUG_DTR
             printk("cyc: %d: raising DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 	    restore_flags(flags);
 	}
@@ -1894,18 +1923,18 @@
     case TIOCMBIC:
 	if (arg & TIOCM_RTS){
 	    save_flags(flags); cli();
-		base_addr[CyCAR] = (u_char)channel;
-		base_addr[CyMSVR1] = ~CyRTS;
+		base_addr[CyCAR<<index] = (u_char)channel;
+		base_addr[CyMSVR1<<index] = ~CyRTS;
 	    restore_flags(flags);
 	}
 	if (arg & TIOCM_DTR){
 	    save_flags(flags); cli();
-	    base_addr[CyCAR] = (u_char)channel;
+	    base_addr[CyCAR<<index] = (u_char)channel;
 /* CP('C');CP('2'); */
-	    base_addr[CyMSVR2] = ~CyDTR;
+	    base_addr[CyMSVR2<<index] = ~CyDTR;
 #ifdef SERIAL_DEBUG_DTR
             printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 	    restore_flags(flags);
 	}
@@ -1913,33 +1942,33 @@
     case TIOCMSET:
 	if (arg & TIOCM_RTS){
 	    save_flags(flags); cli();
-		base_addr[CyCAR] = (u_char)channel;
-		base_addr[CyMSVR1] = CyRTS;
+		base_addr[CyCAR<<index] = (u_char)channel;
+		base_addr[CyMSVR1<<index] = CyRTS;
 	    restore_flags(flags);
 	}else{
 	    save_flags(flags); cli();
-		base_addr[CyCAR] = (u_char)channel;
-		base_addr[CyMSVR1] = ~CyRTS;
+		base_addr[CyCAR<<index] = (u_char)channel;
+		base_addr[CyMSVR1<<index] = ~CyRTS;
 	    restore_flags(flags);
 	}
 	if (arg & TIOCM_DTR){
 	    save_flags(flags); cli();
-	    base_addr[CyCAR] = (u_char)channel;
+	    base_addr[CyCAR<<index] = (u_char)channel;
 /* CP('S');CP('3'); */
-	    base_addr[CyMSVR2] = CyDTR;
+	    base_addr[CyMSVR2<<index] = CyDTR;
 #ifdef SERIAL_DEBUG_DTR
             printk("cyc: %d: raising DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 	    restore_flags(flags);
 	}else{
 	    save_flags(flags); cli();
-	    base_addr[CyCAR] = (u_char)channel;
+	    base_addr[CyCAR<<index] = (u_char)channel;
 /* CP('C');CP('3'); */
-	    base_addr[CyMSVR2] = ~CyDTR;
+	    base_addr[CyMSVR2<<index] = ~CyDTR;
 #ifdef SERIAL_DEBUG_DTR
             printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 	    restore_flags(flags);
 	}
@@ -1977,19 +2006,20 @@
 set_threshold(struct cyclades_port * info, unsigned long value)
 {
    unsigned char *base_addr;
-   int card,channel,chip;
+   int card,channel,chip,index;
    
    card = info->card;
    channel = info->line - cy_card[card].first_line;
    chip = channel>>2;
    channel &= 0x03;
+   index = cy_card[card].bus_index;
    base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
    info->cor3 &= ~CyREC_FIFO;
    info->cor3 |= value & CyREC_FIFO;
-   base_addr[CyCOR3] = info->cor3;
-   write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch);
+   base_addr[CyCOR3<<index] = info->cor3;
+   write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index);
    return 0;
 }
 
@@ -1997,17 +2027,18 @@
 get_threshold(struct cyclades_port * info, unsigned long *value)
 {
    unsigned char *base_addr;
-   int card,channel,chip;
+   int card,channel,chip,index;
    unsigned long tmp;
    
    card = info->card;
    channel = info->line - cy_card[card].first_line;
    chip = channel>>2;
    channel &= 0x03;
+   index = cy_card[card].bus_index;
    base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
-   tmp = base_addr[CyCOR3] & CyREC_FIFO;
+   tmp = base_addr[CyCOR3<<index] & CyREC_FIFO;
    put_fs_long(tmp,value);
    return 0;
 }
@@ -2030,16 +2061,17 @@
 set_timeout(struct cyclades_port * info, unsigned long value)
 {
    unsigned char *base_addr;
-   int card,channel,chip;
+   int card,channel,chip,index;
    
    card = info->card;
    channel = info->line - cy_card[card].first_line;
    chip = channel>>2;
    channel &= 0x03;
+   index = cy_card[card].bus_index;
    base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
-   base_addr[CyRTPR] = value & 0xff;
+   base_addr[CyRTPR<<index] = value & 0xff;
    return 0;
 }
 
@@ -2047,17 +2079,18 @@
 get_timeout(struct cyclades_port * info, unsigned long *value)
 {
    unsigned char *base_addr;
-   int card,channel,chip;
+   int card,channel,chip,index;
    unsigned long tmp;
    
    card = info->card;
    channel = info->line - cy_card[card].first_line;
    chip = channel>>2;
    channel &= 0x03;
+   index = cy_card[card].bus_index;
    base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + cy_chip_offset[chip]);
+		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
-   tmp = base_addr[CyRTPR];
+   tmp = base_addr[CyRTPR<<index];
    put_fs_long(tmp,value);
    return 0;
 }
@@ -2175,8 +2208,8 @@
                 ret_val = error;
                 break;
             }
-            put_user(C_CLOCAL(tty) ? 1 : 0,
-                        (unsigned int *) arg);
+            put_fs_long(C_CLOCAL(tty) ? 1 : 0,
+                        (unsigned long *) arg);
             break;
         case TIOCSSOFTCAR:
             arg = get_fs_long((unsigned long *) arg);
@@ -2283,8 +2316,6 @@
     printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1);
 #endif
     if (--info->count < 0) {
-	printk("cy_close: bad serial port count for ttys%d: %d\n",
-	       info->line, info->count);
 #ifdef SERIAL_DEBUG_COUNT
     printk("cyc: %d: setting count to 0\n", __LINE__);
 #endif
@@ -2302,7 +2333,7 @@
     if (info->flags & ASYNC_CALLOUT_ACTIVE)
 	info->callout_termios = *tty->termios;
     if (info->flags & ASYNC_INITIALIZED)
-	tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */
+	tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
     shutdown(info);
     if (tty->driver.flush_buffer)
 	tty->driver.flush_buffer(tty);
@@ -2380,7 +2411,7 @@
   struct wait_queue wait = { current, NULL };
   struct cyclades_card *cinfo;
   unsigned long flags;
-  int chip, channel;
+  int chip, channel,index;
   int retval;
   char *base_addr;
 
@@ -2454,18 +2485,19 @@
     channel = info->line - cinfo->first_line;
     chip = channel>>2;
     channel &= 0x03;
-    base_addr = (char *) (cinfo->base_addr + cy_chip_offset[chip]);
+    index = cinfo->bus_index;
+    base_addr = (char *) (cinfo->base_addr + (cy_chip_offset[chip]<<index));
 
     while (1) {
 	save_flags(flags); cli();
 	    if (!(info->flags & ASYNC_CALLOUT_ACTIVE)){
-		base_addr[CyCAR] = (u_char)channel;
-		base_addr[CyMSVR1] = CyRTS;
+		base_addr[CyCAR<<index] = (u_char)channel;
+		base_addr[CyMSVR1<<index] = CyRTS;
 /* CP('S');CP('4'); */
-		base_addr[CyMSVR2] = CyDTR;
+		base_addr[CyMSVR2<<index] = CyDTR;
 #ifdef SERIAL_DEBUG_DTR
                 printk("cyc: %d: raising DTR\n", __LINE__);
-                printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+                printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
 #endif
 	    }
 	restore_flags(flags);
@@ -2480,12 +2512,12 @@
 	    break;
 	}
 	save_flags(flags); cli();
-	    base_addr[CyCAR] = (u_char)channel;
-/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
+	    base_addr[CyCAR<<index] = (u_char)channel;
+/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1<<index] & CyDCD) ); */
 	    if (!(info->flags & ASYNC_CALLOUT_ACTIVE)
 	    && !(info->flags & ASYNC_CLOSING)
 	    && (C_CLOCAL(tty)
-	        || (base_addr[CyMSVR1] & CyDCD))) {
+	        || (base_addr[CyMSVR1<<index] & CyDCD))) {
 		    restore_flags(flags);
 		    break;
 	    }
@@ -2617,20 +2649,19 @@
 /* initialize chips on card -- return number of valid
    chips (which is number of ports/4) */
 int
-cy_init_card(unsigned char *true_base_addr)
+cy_init_card(unsigned char *true_base_addr,int index)
 {
-  volatile unsigned short discard;
   unsigned int chip_number;
   unsigned char* base_addr;
 
-    discard = true_base_addr[Cy_HwReset]; /* Cy_HwReset is 0x1400 */
-    discard = true_base_addr[Cy_ClrIntr]; /* Cy_ClrIntr is 0x1800 */
+    true_base_addr[Cy_HwReset<<index] = 0; /* Cy_HwReset is 0x1400 */
+    true_base_addr[Cy_ClrIntr<<index] = 0; /* Cy_ClrIntr is 0x1800 */
     udelay(500L);
 
     for(chip_number=0; chip_number<CyMaxChipsPerCard; chip_number++){
-        base_addr = true_base_addr + cy_chip_offset[chip_number];
+        base_addr = true_base_addr + (cy_chip_offset[chip_number]<<index);
         udelay(1000L);
-        if(base_addr[CyCCR] != 0x00){
+        if(base_addr[CyCCR<<index] != 0x00){
             /*************
             printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
                chip_number, (unsigned long)base_addr);
@@ -2638,7 +2669,7 @@
             return chip_number;
         }
 
-        base_addr[CyGFRCR] = 0;
+        base_addr[CyGFRCR<<index] = 0;
         udelay(10L);
 
         /* The Cyclom-16Y does not decode address bit 9 and therefore
@@ -2652,25 +2683,31 @@
 	    return chip_number;
         }
 
-        base_addr[CyCCR] = CyCHIP_RESET;
+        base_addr[CyCCR<<index] = CyCHIP_RESET;
         udelay(1000L);
 
-        if(base_addr[CyGFRCR] == 0x00){
+        if(base_addr[CyGFRCR<<index] == 0x00){
+	    /*
             printk(" chip #%d at %#6lx is not responding (GFRCR stayed 0)\n",
                chip_number, (unsigned long)base_addr);
+	    */
             return chip_number;
         }
-        if((0xf0 & base_addr[CyGFRCR]) != 0x40){
+        if((0xf0 & base_addr[CyGFRCR<<index]) != 0x40){
+	    /*
             printk(" chip #%d at %#6lx is not valid (GFRCR == %#2x)\n",
-               chip_number, (unsigned long)base_addr, base_addr[CyGFRCR]);
+               chip_number, (unsigned long)base_addr, base_addr[CyGFRCR<<index]);
+	    */
             return chip_number;
         }
-        base_addr[CyGCR] = CyCH0_SERIAL;
-        base_addr[CyPPR] = 244; /* better value than CyCLOCK_25_1MS * 5
+        base_addr[CyGCR<<index] = CyCH0_SERIAL;
+        base_addr[CyPPR<<index] = 244; /* better value than CyCLOCK_25_1MS * 5
                                                   to run clock at 200 Hz */
 
+	/*
         printk(" chip #%d at %#6lx is rev 0x%2x\n",
-               chip_number, (unsigned long)base_addr, base_addr[CyGFRCR]);
+               chip_number, (unsigned long)base_addr, base_addr[CyGFRCR<<index]);
+	*/
     }
 
     return chip_number;
@@ -2695,15 +2732,9 @@
 long
 cy_init(long kmem_start)
 {
-  struct cyclades_port *info;
+  struct cyclades_port	*info;
   struct cyclades_card *cinfo;
-  int good_ports = 0;
-  int port_num = 0;
-  int index;
-#ifdef notyet
-  struct sigaction sa;
-#endif
-  int retval;
+  int			board,port,i;
 
 scrn[1] = '\0';
     show_version();
@@ -2759,50 +2790,54 @@
     bh_base[CYCLADES_BH].routine = do_cyclades_bh;
     enable_bh(CYCLADES_BH);
 
-    for (index = 0; index < 16; index++) {
-	    IRQ_cards[index] = 0;
+    for (i = 0; i < 16; i++) {
+	    IRQ_cards[i] = 0;
     }
 
-    port_num = 0;
-    info = cy_port;
-    for (index = 0, cinfo = cy_card; index < NR_CARDS; index++,cinfo++) {
-	/*** initialize card ***/
-	if(0 == (cinfo->num_chips =
-		    cy_init_card((unsigned char *)cinfo->base_addr))){
-	    /* this card is not present */
-	    continue;
-	}
-
-#ifndef CY_DONT_PROBE
-	/* find out the board's irq by probing */
-	cinfo->irq = do_auto_irq(index);
-#endif
-
-	/** bind IRQ to card **/
-	if (cinfo->irq) {
-	    retval = request_irq(cinfo->irq, cy_interrupt,
-				SA_INTERRUPT, "cyclades");
-	    if (retval){
-		printk("request_irq returned %d\n",retval);
-		/* return retval; */
-	    }
-	    IRQ_cards[cinfo->irq] = cinfo;
-        }else{
-	    printk("couldn't get board's irq\n");
-	    continue;
-	}
+    for (i = 0; i < NR_CARDS; i++) {
+	    /* base_addr=0 indicates board not found */
+	    cy_card[i].base_addr = 0;
+    }
+
+    /* the code below is responsible to find the boards. Each different
+       type of board has its own detection routine. If a board is found,
+       the next cy_card structure available is set by the detection
+       routine. These funcions are responsible for checking the availability
+       of cy_card and cy_port data structures and updating the
+       cy_next_channel. */
+
+    /* look for isa boards */
+    cy_isa_nboard = cy_detect_isa();
+
+    /* look for pci boards */
+    cy_pci_nboard = cy_detect_pci();
 
-	printk("  share IRQ %d: ", cinfo->irq);
-	good_ports = 4 * cinfo->num_chips;
+    cy_nboard = cy_isa_nboard + cy_pci_nboard;
 
-	if(port_num < NR_PORTS){
-	    cinfo->first_line = port_num;
-	    while( good_ports-- && port_num < NR_PORTS){
-		/*** initialize port ***/
+    /* invalidate remaining cy_card structures */
+    for (i = 0 ; i < NR_CARDS ; i++) {
+	if (cy_card[i].base_addr == 0) {
+		cy_card[i].first_line = -1;
+	}
+    }
+    /* invalidate remaining cy_port structures */
+    for (i = cy_next_channel ; i < NR_PORTS ; i++) {
+	cy_port[i].line = -1;
+	cy_port[i].magic = -1;
+    }
+
+    /* initialize per-port data structures for each valid board found */
+    for (board = 0 ; board < cy_nboard ; board++) {
+	    cinfo = &cy_card[board];
+	    for (port = cinfo->first_line ;
+		 port < cinfo->first_line + 4*cinfo->num_chips ;
+		 port++)
+	    {
+		info = &cy_port[port];
 		info->magic = CYCLADES_MAGIC;
 		info->type = PORT_CIRRUS;
-		info->card = index;
-		info->line = port_num;
+		info->card = board;
+		info->line = port;
 		info->flags = STD_COM_FLAGS;
 		info->tty = 0;
 		info->xmit_fifo_size = 12;
@@ -2833,41 +2868,208 @@
 		info->close_wait = 0;
 		/* info->session */
 		/* info->pgrp */
-/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
 		info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK
                                        | CyPARITY| CyFRAME| CyOVERRUN;
 		/* info->timeout */
-
-		printk("ttyC%1d ", info->line);
-		port_num++;info++;
-		if(!(port_num & 7)){
-		    printk("\n               ");
-		}
 	    }
-	}else{
-	    cinfo->first_line = -1;
-	}
-	printk("\n");
-    }
-    while( port_num < NR_PORTS){
-	info->line = -1;
-	port_num++;info++;
     }
     return kmem_start;
     
 } /* cy_init */
 
+/*
+ * ---------------------------------------------------------------------
+ * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
+ * sets global variables and return the number of ISA boards found.
+ * ---------------------------------------------------------------------
+ */
+int
+cy_detect_isa()
+{
+  unsigned int		cy_isa_irq,nboard;
+  unsigned char		*cy_isa_address;
+  unsigned short	i,j,cy_isa_nchan;
+
+	nboard = 0;
+
+	/* scan the address table probing for Cyclom-Y/ISA boards */
+	for (i = 0 ; i < NR_ISA_ADDRESSES ; i++) {
+		cy_isa_address = cy_isa_addresses[i];
+		if (cy_isa_address  == 0x0000) {
+			return(nboard);
+		}
+
+		/* probe for CD1400... */
+		cy_isa_nchan = 4 * cy_init_card(cy_isa_address,0);
+		if (cy_isa_nchan == 0) {
+			continue;
+		}
+
+		/* find out the board's irq by probing */
+		cy_isa_irq = do_auto_irq(cy_isa_address);
+		if (cy_isa_irq == 0) {
+			printk("Cyclom-Y/ISA found at 0x%x but the IRQ could not be detected.\n",
+				(unsigned int) cy_isa_address);
+			continue;
+		}
+
+		if((cy_next_channel+cy_isa_nchan) > NR_PORTS) {
+			printk("Cyclom-Y/ISA found at 0x%x but no more channel structures are available.\n",
+				(unsigned int) cy_isa_address);
+			return(nboard);
+		}
+		/* fill the next cy_card structure available */
+		for (j = 0 ; j < NR_CARDS ; j++) {
+			if (cy_card[j].base_addr == 0)	break;
+		}
+		if (j == NR_CARDS) {	/* no more cy_cards available */
+			printk("Cyclom-Y/ISA found at 0x%x but no more card structures are available.\n",
+				(unsigned int) cy_isa_address);
+			return(nboard);
+		}
+
+		/* allocate IRQ */
+		if(request_irq(cy_isa_irq,cy_interrupt,SA_INTERRUPT,"cyclades"))
+		{
+			printk("Cyclom-Y/ISA found at 0x%x but could not allocate interrupt IRQ#%d.\n",
+				(unsigned int) cy_isa_address,cy_isa_irq);
+			return(nboard);
+		}
+
+		/* set cy_card */
+		cy_card[j].base_addr = (int) cy_isa_address;
+		cy_card[j].irq = (int) cy_isa_irq;
+		cy_card[j].bus_index = 0;
+		cy_card[j].first_line = cy_next_channel;
+		cy_card[j].num_chips = cy_isa_nchan/4;
+	        IRQ_cards[cy_isa_irq] = &cy_card[j];
+		nboard++;
+			
+		/* print message */
+		printk("Cyclom-Y/ISA #%d: 0x%x-0x%x, IRQ%d, %d channels starting from port %d.\n",
+			j+1,(unsigned int) cy_isa_address,
+			(unsigned int)(cy_isa_address + 0x1fff),
+			cy_isa_irq,cy_isa_nchan,cy_next_channel);
+		cy_next_channel += cy_isa_nchan;
+	}
+	return(nboard);
+
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI.
+ * sets global variables and return the number of PCI boards found.
+ * ---------------------------------------------------------------------
+ */
+int
+cy_detect_pci()
+{
+  unsigned char		cyy_bus, cyy_dev_fn, cyy_rev_id;
+  unsigned long		pci_intr_ctrl;
+  unsigned char		cy_pci_irq;
+  unsigned long		cy_pci_address,cy_pci_io;
+  unsigned short	i,j,cy_pci_nchan;
+
+#ifndef CONFIG_PCI
+	printk ("Kernel without PCI support.\n");
+	return(0);
+#else
+	if(pcibios_present() == 0) {	/* PCI bus not present */
+	 	return(0);
+	}
+	for (i = 0; i < NR_CARDS; i++) {
+		/* look for a Cyclom-Y card by vendor and device id */
+		if(pcibios_find_device (PCI_VENDOR_ID_CYCLADES,
+					PCI_DEVICE_ID_CYCLOMY,i,
+					&cyy_bus, &cyy_dev_fn) != 0)
+		{
+			break;
+		}
+		/* read PCI configuration area */
+		pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
+				 PCI_INTERRUPT_LINE, &cy_pci_irq);
+		pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
+				  PCI_BASE_ADDRESS_1, &cy_pci_io);
+		pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
+				  PCI_BASE_ADDRESS_2, &cy_pci_address);
+		pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
+				  PCI_REVISION_ID, &cyy_rev_id);
+		cy_pci_address &= 0xfffffff0;
+		cy_pci_io  &= 0xfffffffc;
+		cy_pci_nchan = 4 * cy_init_card((unsigned char *)
+						cy_pci_address,1);
+		if(cy_pci_nchan == 0) {
+			printk("Cyclom-Y PCI host card with no Serial-Modules at 0x%x.\n",
+				(unsigned int) cy_pci_address);
+			continue;
+		}
+		if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
+			printk("Cyclom-Y/PCI found at 0x%x but no more channel structures are available.\n",
+				(unsigned int) cy_pci_address);
+			return(i);
+		}
+#ifdef CY_PCI_DEBUG
+		printk("Cyclom-Ye/PCI #%d (bus=0x0%x, pci_id=0x%x, rev_id=%d).\n",
+			i+1,cyy_bus,cyy_dev_fn,cyy_rev_id);
+		printk("Cyclom-Ye/PCI: found at 0x%x, IRQ%d, ioaddr = 0x%lx.\n",
+			cy_pci_address,(int)cy_pci_irq,cy_pci_io);
+#endif
+		/* fill the next cy_card structure available */
+		for (j = 0 ; j < NR_CARDS ; j++) {
+			if (cy_card[j].base_addr == 0)	break;
+		}
+		if (j == NR_CARDS) {	/* no more cy_cards available */
+			printk("Cyclom-Y/PCI found at 0x%x but no more card structures are available.\n",
+				(unsigned int) cy_pci_address);
+			return(i);
+		}
+
+		/* allocate IRQ */
+		if(request_irq(cy_pci_irq,cy_interrupt,SA_INTERRUPT,"cyclades"))
+		{
+			printk("Cyclom-Y/PCI found at 0x%x but could not allocate interrupt IRQ%d.\n",
+				(unsigned int) cy_pci_address,cy_pci_irq);
+			return(i);
+		}
+
+		/* set cy_card */
+		cy_card[j].base_addr = (int) cy_pci_address;
+		cy_card[j].irq = (int) cy_pci_irq;
+		cy_card[j].bus_index = 1;
+		cy_card[j].first_line = cy_next_channel;
+		cy_card[j].num_chips = cy_pci_nchan/4;
+	        IRQ_cards[cy_pci_irq] = &cy_card[j];
+
+		/* enable interrupts in the PCI interface */
+		outw(inw(cy_pci_io+0x68)|0x0900,cy_pci_io+0x68);
+		pci_intr_ctrl = (unsigned long)(inw(cy_pci_io+0x68) | inw(cy_pci_io+0x6a)<<16);
+
+		/* print message */
+		printk("Cyclom-Y/PCI #%d: 0x%x-0x%x, IRQ%d, %d channels starting from port %d.\n",
+			j+1,(unsigned int) cy_pci_address,
+			(unsigned int)(cy_pci_address + 0x3fff),
+			(int)cy_pci_irq,cy_pci_nchan,cy_next_channel);
+
+		cy_next_channel += cy_pci_nchan;
+	}
+	return(i);
+#endif /* ifndef CONFIG_PCI */
+}
+
+
 #ifdef CYCLOM_SHOW_STATUS
 static void
 show_status(int line_num)
 {
   unsigned char *base_addr;
-  int card,chip,channel;
+  int card,chip,channel,index;
   struct cyclades_port * info;
   unsigned long flags;
 
     info = &cy_port[line_num];
     card = info->card;
+    index = cy_card[card].bus_index;
     channel = (info->line) - (cy_card[card].first_line);
     chip = channel>>2;
     channel &= 0x03;
@@ -2899,58 +3101,58 @@
     save_flags(flags); cli();
 
 	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr + cy_chip_offset[chip]);
+		       (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
 /* Global Registers */
 
-	printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
-	printk(" CyCAR %x\n", base_addr[CyCAR]);
-	printk(" CyGCR %x\n", base_addr[CyGCR]);
-	printk(" CySVRR %x\n", base_addr[CySVRR]);
-	printk(" CyRICR %x\n", base_addr[CyRICR]);
-	printk(" CyTICR %x\n", base_addr[CyTICR]);
-	printk(" CyMICR %x\n", base_addr[CyMICR]);
-	printk(" CyRIR %x\n", base_addr[CyRIR]);
-	printk(" CyTIR %x\n", base_addr[CyTIR]);
-	printk(" CyMIR %x\n", base_addr[CyMIR]);
-	printk(" CyPPR %x\n", base_addr[CyPPR]);
+	printk(" CyGFRCR %x\n", base_addr[CyGFRCR<<index]);
+	printk(" CyCAR %x\n", base_addr[CyCAR<<index]);
+	printk(" CyGCR %x\n", base_addr[CyGCR<<index]);
+	printk(" CySVRR %x\n", base_addr[CySVRR<<index]);
+	printk(" CyRICR %x\n", base_addr[CyRICR<<index]);
+	printk(" CyTICR %x\n", base_addr[CyTICR<<index]);
+	printk(" CyMICR %x\n", base_addr[CyMICR<<index]);
+	printk(" CyRIR %x\n", base_addr[CyRIR<<index]);
+	printk(" CyTIR %x\n", base_addr[CyTIR<<index]);
+	printk(" CyMIR %x\n", base_addr[CyMIR<<index]);
+	printk(" CyPPR %x\n", base_addr[CyPPR<<index]);
 
-	base_addr[CyCAR] = (u_char)channel;
+	base_addr[CyCAR<<index] = (u_char)channel;
 
 /* Virtual Registers */
 
-	printk(" CyRIVR %x\n", base_addr[CyRIVR]);
-	printk(" CyTIVR %x\n", base_addr[CyTIVR]);
-	printk(" CyMIVR %x\n", base_addr[CyMIVR]);
-	printk(" CyMISR %x\n", base_addr[CyMISR]);
+	printk(" CyRIVR %x\n", base_addr[CyRIVR<<index]);
+	printk(" CyTIVR %x\n", base_addr[CyTIVR<<index]);
+	printk(" CyMIVR %x\n", base_addr[CyMIVR<<index]);
+	printk(" CyMISR %x\n", base_addr[CyMISR<<index]);
 
 /* Channel Registers */
 
-	printk(" CyCCR %x\n", base_addr[CyCCR]);
-	printk(" CySRER %x\n", base_addr[CySRER]);
-	printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
-	printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
-	printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
-	printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
-	printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
-	printk(" CyCCSR %x\n", base_addr[CyCCSR]);
-	printk(" CyRDCR %x\n", base_addr[CyRDCR]);
-	printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
-	printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
-	printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
-	printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
-	printk(" CySCRL %x\n", base_addr[CySCRL]);
-	printk(" CySCRH %x\n", base_addr[CySCRH]);
-	printk(" CyLNC %x\n", base_addr[CyLNC]);
-	printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
-	printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
-	printk(" CyRTPR %x\n", base_addr[CyRTPR]);
-	printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
-	printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
-	printk(" CyRBPR %x\n", base_addr[CyRBPR]);
-	printk(" CyRCOR %x\n", base_addr[CyRCOR]);
-	printk(" CyTBPR %x\n", base_addr[CyTBPR]);
-	printk(" CyTCOR %x\n", base_addr[CyTCOR]);
+	printk(" CyCCR %x\n", base_addr[CyCCR<<index]);
+	printk(" CySRER %x\n", base_addr[CySRER<<index]);
+	printk(" CyCOR1 %x\n", base_addr[CyCOR1<<index]);
+	printk(" CyCOR2 %x\n", base_addr[CyCOR2<<index]);
+	printk(" CyCOR3 %x\n", base_addr[CyCOR3<<index]);
+	printk(" CyCOR4 %x\n", base_addr[CyCOR4<<index]);
+	printk(" CyCOR5 %x\n", base_addr[CyCOR5<<index]);
+	printk(" CyCCSR %x\n", base_addr[CyCCSR<<index]);
+	printk(" CyRDCR %x\n", base_addr[CyRDCR<<index]);
+	printk(" CySCHR1 %x\n", base_addr[CySCHR1<<index]);
+	printk(" CySCHR2 %x\n", base_addr[CySCHR2<<index]);
+	printk(" CySCHR3 %x\n", base_addr[CySCHR3<<index]);
+	printk(" CySCHR4 %x\n", base_addr[CySCHR4<<index]);
+	printk(" CySCRL %x\n", base_addr[CySCRL<<index]);
+	printk(" CySCRH %x\n", base_addr[CySCRH<<index]);
+	printk(" CyLNC %x\n", base_addr[CyLNC<<index]);
+	printk(" CyMCOR1 %x\n", base_addr[CyMCOR1<<index]);
+	printk(" CyMCOR2 %x\n", base_addr[CyMCOR2<<index]);
+	printk(" CyRTPR %x\n", base_addr[CyRTPR<<index]);
+	printk(" CyMSVR1 %x\n", base_addr[CyMSVR1<<index]);
+	printk(" CyMSVR2 %x\n", base_addr[CyMSVR2<<index]);
+	printk(" CyRBPR %x\n", base_addr[CyRBPR<<index]);
+	printk(" CyRCOR %x\n", base_addr[CyRCOR<<index]);
+	printk(" CyTBPR %x\n", base_addr[CyTBPR<<index]);
+	printk(" CyTCOR %x\n", base_addr[CyTCOR<<index]);
 
     restore_flags(flags);
 } /* show_status */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this