## Automatically generated incremental diff
## From:   linux-2.0.39-pre4
## To:     linux-2.0.39-pre5
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.0.39-pre4/Documentation/Configure.help linux-2.0.39-pre5/Documentation/Configure.help
--- linux-2.0.39-pre4/Documentation/Configure.help	2003-08-15 15:04:57.000000000 -0700
+++ linux-2.0.39-pre5/Documentation/Configure.help	2003-08-15 15:04:57.000000000 -0700
@@ -4195,6 +4195,16 @@
   safe to say N. (As of 1.3.9x kernels, this driver's minor numbers
   start at 0 instead of 32.)
 
+Cyclades-Z interrupt mode operation (EXPERIMENTAL)
+CONFIG_CYZ_INTR
+  The Cyclades-Z family of multiport cards allows 2 (two) driver
+  op modes: polling and interrupt. In polling mode, the driver will
+  check the status of the Cyclades-Z ports every certain amount of
+  time (which is called polling cycle and is configurable). In
+  interrupt mode, it will use an interrupt line (IRQ) in order to check
+  the status of the Cyclades-Z ports. The default op mode is polling.
+  If unsure, say N.
+
 Stallion multiport serial support
 CONFIG_STALDRV
   Stallion cards give you many serial ports. You would need something
diff -urN linux-2.0.39-pre4/drivers/block/genhd.c linux-2.0.39-pre5/drivers/block/genhd.c
--- linux-2.0.39-pre4/drivers/block/genhd.c	1999-06-13 10:21:00.000000000 -0700
+++ linux-2.0.39-pre5/drivers/block/genhd.c	2003-08-15 15:04:57.000000000 -0700
@@ -76,6 +76,10 @@
 	 * This requires special handling here.
 	 */
 	switch (hd->major) {
+		case IDE5_MAJOR:
+			unit += 2;
+		case IDE4_MAJOR:
+			unit += 2;
 		case IDE3_MAJOR:
 			unit += 2;
 		case IDE2_MAJOR:
@@ -158,6 +162,8 @@
 	struct partition *p;
 	unsigned long first_sector, first_size, this_sector, this_size;
 	int mask = (1 << hd->minor_shift) - 1;
+	int loopct = 0;		/* number of links followed
+				   without finding a data partition */
 	int i;
 
 	first_sector = hd->part[MINOR(dev)].start_sect;
@@ -165,6 +171,8 @@
 	this_sector = first_sector;
 
 	while (1) {
+		if (++loopct > 100)
+			return;
 		if ((current_minor & mask) == 0)
 			return;
 		if (!(bh = bread(dev,0,1024)))
@@ -209,6 +217,7 @@
 
 		    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
 		    current_minor++;
+		    loopct = 0;
 		    if ((current_minor & mask) == 0)
 		      goto done;
 		}
diff -urN linux-2.0.39-pre4/drivers/block/ide.c linux-2.0.39-pre5/drivers/block/ide.c
--- linux-2.0.39-pre4/drivers/block/ide.c	2003-08-15 15:04:57.000000000 -0700
+++ linux-2.0.39-pre5/drivers/block/ide.c	2003-08-15 15:04:57.000000000 -0700
@@ -283,6 +283,10 @@
  *			to trition.c and added UDMA to current DMA support.
  *			update Promise Ultra33 and added AEC6210U/UF UDMA cards.
  *			add configuration flag to allow booting of either card.
+ * Version 5.53.5	Fixed chipset identifiers.
+ * Version 5.53.6	Added Aladdin IV/V M5229 chipset support.
+ * Version 5.53.7	Added HPT343 basic support with everything at PIO 0.
+ *			This is regardless of DMA capabilties.
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -328,9 +332,9 @@
 #define IS_PROMISE_DRIVE (0)	/* auto-NULLs out Promise code */
 #endif /* CONFIG_BLK_DEV_PROMISE */
 
-static const byte	ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
-static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
-static const byte	default_irqs[MAX_HWIFS]     = {14, 15, 11, 10};
+static const byte	ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR};
+static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160};
+static const byte	default_irqs[MAX_HWIFS]     = {14, 15, 11, 10, 8, 12};
 static int	idebus_parameter; /* holds the "idebus=" parameter */
 static int	system_bus_speed; /* holds what we think is VESA/PCI bus speed */
 
@@ -1596,11 +1600,16 @@
 		goto kill_rq;
 	}
 	block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0;
+
 #if FAKE_FDISK_FOR_EZDRIVE
+	/* Yecch - this will shift the entire interval,
+	   possibly killing some innocent following sector */
 	if (block == 0 && drive->remap_0_to_1)
 		block = 1;  /* redirect MBR access to EZ-Drive partn table */
 #endif /* FAKE_FDISK_FOR_EZDRIVE */
+
 	((ide_hwgroup_t *)hwif->hwgroup)->drive = drive;
+
 #if (DISK_RECOVERY_TIME > 0)
 	while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
 #endif
@@ -1763,6 +1772,20 @@
 }
 #endif
 
+#if MAX_HWIFS > 4
+static void do_ide4_request (void)	/* invoked with cli() */
+{
+	do_hwgroup_request (ide_hwifs[4].hwgroup);
+}
+#endif
+
+#if MAX_HWIFS > 5
+static void do_ide5_request (void)	/* invoked with cli() */
+{
+	do_hwgroup_request (ide_hwifs[5].hwgroup);
+}
+#endif
+
 static void timer_expiry (unsigned long data)
 {
 	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
@@ -2322,10 +2345,18 @@
 					argbuf[3] = args[3];
 				}
 				if (!(err = verify_area(VERIFY_WRITE,(void *)arg, argsize))) {
+					if ((args[0] == WIN_SETFEATURES) &&
+					    (args[1] > 66) &&
+					    (args[2] == 3) &&
+					    ((drive->id->word93 & 0x2000) == 0)) {
+						printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
+						goto abort_speed;
+					}
 					rq.buffer = argbuf;
 					err = ide_do_drive_cmd(drive, &rq, ide_wait);
 					memcpy_tofs((void *)arg, argbuf, argsize);
 				}
+abort_speed:
 				if (argsize > 4)
 					kfree(argbuf);
 			}
@@ -2557,6 +2588,7 @@
 	}
 
 	drive->media = ide_disk;
+
 	/* Extract geometry if we did not already have one for the drive */
 	if (!drive->present) {
 		drive->present = 1;
@@ -2650,8 +2682,12 @@
 		capacity/2048L, id->buf_size/2,
 		drive->bios_cyl, drive->bios_head, drive->bios_sect);
 	if (drive->using_dma) {
-		if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
-			printk(", UDMA");	/* UDMA BIOS-enabled! */
+		if ((id->field_valid & 4) && (id->word93 & 0x2000) &&
+		    (id->dma_ultra & (id->dma_ultra >>  11) & 3)) {
+			printk(", UDMA(66)");	/* UDMA BIOS-enabled! */
+		} else if ((id->field_valid & 4) &&
+			   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+			printk(", UDMA(33)");	/* UDMA BIOS-enabled! */
 		} else if (id->field_valid & 4) {
 			printk(", (U)DMA");	/* Can be BIOS-enabled! */
 		} else {
@@ -2915,6 +2951,12 @@
  * The only "perfect" way to handle this would be to modify the setup.[cS] code
  * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
  * for us during initialization.  I have the necessary docs -- any takers?  -ml
+ * [I did this. But the result is more suited for user space. -aeb]
+ *
+ * Unfortunately the above is far too optimistic. One of the problems is that
+ * drives 1 and 2 may be SCSI disks (even when IDE disks are present), so that
+ * the geometry we read here from BIOS is attributed to the wrong disks.
+ * Eventually the routine below should be removed.
  */
 static void probe_cmos_for_drives (ide_hwif_t *hwif)
 {
@@ -3380,30 +3422,26 @@
 
 	printk("%s ", msg);
 
+#endif
+
 	tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
 	drive->bios_sect = 63;
 	if (xparm > 1) {
 		drive->bios_head = xparm;
 		drive->bios_cyl = tracks / drive->bios_head;
 	} else {
+		heads = (xparm == -1) ? ez_head_vals : dm_head_vals;
 		while (drive->bios_cyl >= 1024) {
 			drive->bios_head = *heads;
 			drive->bios_cyl = tracks / drive->bios_head;
 			if (0 == *++heads)
 				break;
 		}
-#if FAKE_FDISK_FOR_EZDRIVE
-		if (xparm == -1) {
-			drive->remap_0_to_1 = 1;
-			msg = "0->1";
-		} else
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
 		if (xparm == 1) {
 			drive->sect0 = 63;
 			drive->bios_cyl = (tracks - 1) / drive->bios_head;
-			msg = "+63";
+			printk("[remap +63] ");
 		}
-		printk("[remap %s] ", msg);
 	}
 	drive->part[0].nr_sects = current_capacity(drive);
 	printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
@@ -3570,7 +3608,18 @@
 	save_flags(flags);
 	cli();
 	for (index = 0; !pcibios_find_device (vendor, device, index, &bus, &fn); ++index) {
-		init (bus, fn + func_adj);
+		if ((vendor == PCI_VENDOR_ID_TTI) &&
+		    (device == PCI_DEVICE_ID_TTI_HPT343) && (func_adj)) {
+			unsigned short pcicmd = 0;
+
+			pcibios_read_config_word(bus, fn, PCI_COMMAND, &pcicmd);
+			if (pcicmd & PCI_COMMAND_MEMORY)
+				init (bus, fn);
+			else
+				return;
+		} else {
+			init (bus, fn + func_adj);
+		}
 	}
 	restore_flags(flags);
 }
@@ -3605,17 +3654,22 @@
 		 */
 #ifdef CONFIG_BLK_DEV_OFFBOARD
 		ide_probe_pci (PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, &ide_init_triton, 0);
+		ide_probe_pci (PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, &ide_init_triton, 0);
 		ide_probe_pci (PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, &ide_init_triton, 0);
+		ide_probe_pci (PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, &ide_init_triton, 1);
 #endif /* CONFIG_BLK_DEV_OFFBOARD */
 		ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1);
 		ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, &ide_init_triton, 0);
 		ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, &ide_init_triton, 0);
 		ide_probe_pci (PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, &ide_init_triton, 0);
 		ide_probe_pci (PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, &ide_init_triton, 0);
+		ide_probe_pci (PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, &ide_init_triton, 0);
 #ifndef CONFIG_BLK_DEV_OFFBOARD
 		ide_probe_pci (PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, &ide_init_triton, 0);
+		ide_probe_pci (PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, &ide_init_triton, 0);
 		ide_probe_pci (PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, &ide_init_triton, 0);
 #endif /* CONFIG_BLK_DEV_OFFBOARD */
+		ide_probe_pci (PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, &ide_init_triton, 0);
 #endif /* CONFIG_BLK_DEV_TRITON */
 	}
 #endif /* CONFIG_PCI */
@@ -3662,6 +3716,12 @@
 #if MAX_HWIFS > 3
 	case IDE3_MAJOR: rfn = &do_ide3_request; break;
 #endif
+#if MAX_HWIFS > 4
+	case IDE4_MAJOR: rfn = &do_ide4_request; break;
+#endif
+#if MAX_HWIFS > 5
+	case IDE5_MAJOR: rfn = &do_ide5_request; break;
+#endif
 	default:
 		printk("%s: request_fn NOT DEFINED\n", hwif->name);
 		return (hwif->present = 0);
diff -urN linux-2.0.39-pre4/drivers/block/ide.h linux-2.0.39-pre5/drivers/block/ide.h
--- linux-2.0.39-pre4/drivers/block/ide.h	1999-06-13 10:21:00.000000000 -0700
+++ linux-2.0.39-pre5/drivers/block/ide.h	2003-08-15 15:04:57.000000000 -0700
@@ -145,7 +145,7 @@
 #define PARTN_MASK	((1<<PARTN_BITS)-1)	/* a useful bit mask */
 #define MAX_DRIVES	2	/* per interface; 2 assumed by lots of code */
 #ifndef MAX_HWIFS
-#define MAX_HWIFS	4	/* an arbitrary, but realistic limit */
+#define MAX_HWIFS	6	/* an arbitrary, but realistic limit */
 #endif
 #define SECTOR_WORDS	(512 / 4)	/* number of 32bit words per sector */
 
@@ -429,7 +429,8 @@
 typedef enum {	ide_unknown,	ide_generic,	ide_triton,
 		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
 		ide_qd6580,	ide_umc8672,	ide_ht6560b,
-		ide_promise,	ide_udma }
+		ide_promise,	ide_hpt343,	ide_udma,
+		ide_ultra66 }
 	hwif_chipset_t;
 
 typedef struct hwif_s {
diff -urN linux-2.0.39-pre4/drivers/block/ll_rw_blk.c linux-2.0.39-pre5/drivers/block/ll_rw_blk.c
--- linux-2.0.39-pre4/drivers/block/ll_rw_blk.c	1999-06-13 10:21:00.000000000 -0700
+++ linux-2.0.39-pre5/drivers/block/ll_rw_blk.c	2003-08-15 15:04:57.000000000 -0700
@@ -445,6 +445,8 @@
 	     case FLOPPY_MAJOR:
 	     case IDE2_MAJOR:
 	     case IDE3_MAJOR:
+	     case IDE4_MAJOR:
+	     case IDE5_MAJOR:
 		/*
 		 * The scsi disk and cdrom drivers completely remove the request
 		 * from the queue when they start processing an entry.  For this
diff -urN linux-2.0.39-pre4/drivers/block/triton.c linux-2.0.39-pre5/drivers/block/triton.c
--- linux-2.0.39-pre4/drivers/block/triton.c	1999-06-13 10:21:00.000000000 -0700
+++ linux-2.0.39-pre5/drivers/block/triton.c	2003-08-15 15:04:57.000000000 -0700
@@ -2,7 +2,9 @@
  *  linux/drivers/block/triton.c	Version 1.13  Aug 12, 1996
  *					Version 1.13a June 1998 - new chipsets
  *					Version 1.13b July 1998 - DMA blacklist
+ *					Version 1.14  June 22, 1999
  *
+ *  Copyright (c) 1998-1999  Andre Hedrick
  *  Copyright (c) 1995-1996  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
  */
@@ -27,17 +29,24 @@
 
 #include <asm/io.h>
 #include <asm/dma.h>
+#include <asm/irq.h>
 
 #include "ide.h"
 
 #undef DISPLAY_TRITON_TIMINGS	/* define this to display timings */
 #undef DISPLAY_APOLLO_TIMINGS	/* define this for extensive debugging information */
+#undef DISPLAY_ALI15X3_TIMINGS	/* define this for extensive debugging information */
 
-#if defined(CONFIG_PROC_FS) && defined(DISPLAY_APOLLO_TIMINGS)
+#if defined(CONFIG_PROC_FS)
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
+#ifdef DISPLAY_APOLLO_TIMINGS
 #include <linux/via_ide_dma.h>
 #endif
+#ifdef DISPLAY_ALI15X3_TIMINGS
+#include <linux/ali_ide_dma.h>
+#endif
+#endif
 
 /*
  * good_dma_drives() lists the model names (from "hdparm -i")
@@ -90,6 +99,7 @@
 #define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
 #define DEFAULT_BMIBA	0xe800	/* in case BIOS did not init it */
 #define DEFAULT_BMCRBA  0xcc00  /* VIA's default value */
+#define DEFAULT_BMALIBA	0xd400	/* ALI's default value */
 
 /*
  * dma_intr() is the handler for disk read/write DMA interrupts
@@ -194,6 +204,11 @@
 	const char **list;
 	struct hd_driveid *id = drive->id;
 
+	if (HWIF(drive)->chipset == ide_hpt343) {
+		drive->using_dma = 0;	/* no DMA */
+		return 1;	/* DMA disabled */
+	}
+
 	if (id && (id->capability & 1)) {
 		/* Consult the list of known "bad" drives */
 		list = bad_dma_drives;
@@ -204,15 +219,24 @@
 				return 1;	/* DMA disabled */
 			}
 		}
-		/* Enable DMA on any drive that has mode 2 UltraDMA enabled */
-		if (id->field_valid & 4)	/* UltraDMA */
-			if  ((id->dma_ultra & 0x404) == 0x404) {
+		/* Enable DMA on any drive that has mode 4 or 2 UltraDMA enabled */
+		if (id->field_valid & 4) {	/* UltraDMA */
+			/* Enable DMA on any drive that has mode 4 UltraDMA enabled */
+			if (((id->dma_ultra & 0x1010) == 0x1010) &&
+			    (id->word93 & 0x2000) &&
+			    (HWIF(drive)->chipset == ide_ultra66)) {
+				drive->using_dma = 1;
+				return 0;	/* DMA enabled */
+			} else
+			/* Enable DMA on any drive that has mode 2 UltraDMA enabled */
+				if ((id->dma_ultra & 0x404) == 0x404) {
 				drive->using_dma = 1;
 				return 0;	/* DMA enabled */
 			}
+		}
 		/* Enable DMA on any drive that has mode2 DMA enabled */
 		if (id->field_valid & 2)	/* regular DMA */
-			if  ((id->dma_mword & 0x404) == 0x404) {
+			if ((id->dma_mword & 0x404) == 0x404) {
 				drive->using_dma = 1;
 				return 0;	/* DMA enabled */
 			}
@@ -363,6 +387,70 @@
 	return (0);
 }
 
+static int setup_aladdin (byte bus, byte fn)
+{
+	byte confreg0 = 0, confreg1 = 0, progif = 0;
+	int errors = 0;
+
+	if (pcibios_read_config_byte(bus, fn, 0x50, &confreg1))
+		goto veryspecialsettingserror;
+	if (!(confreg1 & 0x02))
+		if (pcibios_write_config_byte(bus, fn, 0x50, confreg1 | 0x02))
+			goto veryspecialsettingserror;
+
+	if (pcibios_read_config_byte(bus, fn, 0x09, &progif))
+		goto veryspecialsettingserror;
+	if (!(progif & 0x40)) {
+		/*
+		 * The way to enable them is to set progif
+		 * writable at 0x4Dh register, and set bit 6
+		 * of progif to 1:
+		 */
+		if (pcibios_read_config_byte(bus, fn, 0x4d, &confreg0))
+			goto veryspecialsettingserror;
+		if (confreg0 & 0x80)
+			if (pcibios_write_config_byte(bus, fn, 0x4d, confreg0 & ~0x80))
+				goto veryspecialsettingserror;
+		if (pcibios_write_config_byte(bus, fn, 0x09, progif | 0x40))
+			goto veryspecialsettingserror;
+		if (confreg0 & 0x80)
+			if (pcibios_write_config_byte(bus, fn, 0x4d, confreg0))
+				errors++;
+	}
+
+	if ((pcibios_read_config_byte(bus, fn, 0x09, &progif)) || (!(progif & 0x40)))
+		goto veryspecialsettingserror;
+
+	printk("ide: ALI15X3: enabled read of IDE channels state (en/dis-abled) %s.\n",
+		errors ? "with Error(s)" : "Succeeded" );
+	return 1;
+veryspecialsettingserror:
+	printk("ide: ALI15X3: impossible to enable read of IDE channels state (en/dis-abled)!\n");
+	return 0;
+}
+
+void set_promise_hpt343_extra (unsigned short device, unsigned int bmiba)
+{
+	switch(device) {
+		case PCI_DEVICE_ID_PROMISE_20246:
+			if(!check_region((bmiba+16), 16))
+				request_region((bmiba+16), 16, "PDC20246");
+			break;
+		case PCI_DEVICE_ID_PROMISE_20262:
+			if (!check_region((bmiba+48), 48))
+				request_region((bmiba+48), 48, "PDC20262");
+			break;
+		case PCI_DEVICE_ID_TTI_HPT343:
+			if(!check_region((bmiba+16), 16))
+				request_region((bmiba+16), 16, "HPT343");
+			break;
+		default:
+			break;
+	}
+}
+
+#define HPT343_PCI_INIT_REG		0x80
+
 /*
  * ide_init_triton() prepares the IDE driver for DMA operation.
  * This routine is called once, from ide.c during driver initialization,
@@ -370,17 +458,20 @@
  */
 void ide_init_triton (byte bus, byte fn)
 {
-	int rc = 0, h;
-	int dma_enabled = 0;
-	unsigned short io[6], count = 0, step_count = 0;
+	byte bridgebus, bridgefn, bridgeset = 0, hpt34x_flag = 0;
+	unsigned char irq = 0;
+	int dma_enabled = 0, rc = 0, h;
+	unsigned short io[6], count = 0, step_count = 0, pass_count = 0;
 	unsigned short pcicmd, vendor, device, class;
 	unsigned int bmiba, timings, reg, tmp;
 	unsigned int addressbios = 0;
+	unsigned long flags;
+	unsigned index;
 
-#ifdef DISPLAY_APOLLO_TIMINGS
+#if defined(DISPLAY_APOLLO_TIMINGS) || defined(DISPLAY_ALI15X3_TIMINGS)
 	bmide_bus = bus;
 	bmide_fn = fn;
-#endif /* DISPLAY_APOLLO_TIMINGS */
+#endif /* DISPLAY_APOLLO_TIMINGS || DISPLAY_ALI15X3_TIMINGS */
 
 /*
  *  We pick up the vendor, device, and class info for selecting the correct
@@ -392,19 +483,61 @@
 	pcibios_read_config_word (bus, fn, PCI_VENDOR_ID, &vendor);
 	pcibios_read_config_word (bus, fn, PCI_DEVICE_ID, &device);
 	pcibios_read_config_word (bus, fn, PCI_CLASS_DEVICE, &class);
+	pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &irq);
 
 	switch(vendor) {
 		case PCI_VENDOR_ID_INTEL:
-                   printk("ide: Intel 82371 (single FIFO) DMA Bus Mastering IDE ");
-                   break;
+			printk("ide: Intel 82371 ");
+			switch(device) {
+				case PCI_DEVICE_ID_INTEL_82371_0:
+					printk("PIIX (single FIFO) ");
+					break;
+				case PCI_DEVICE_ID_INTEL_82371SB_1:
+					printk("PIIX3 (dual FIFO) ");
+					break;
+				case PCI_DEVICE_ID_INTEL_82371AB:
+					printk("PIIX4 (dual FIFO) ");
+					break;
+				default:
+					printk(" (unknown) 0x%04x ", device);
+					break;
+			}
+			printk("DMA Bus Mastering IDE ");
+			break;
 		case PCI_VENDOR_ID_SI:
 			printk("ide: SiS 5513 (dual FIFO) DMA Bus Mastering IDE ");
 			break;
                 case PCI_VENDOR_ID_VIA:
-                   printk("ide: VIA VT82C586B (split FIFO) UDMA Bus Mastering IDE ");
-                   break;
+			printk("ide: VIA VT82C586B (split FIFO) UDMA Bus Mastering IDE ");
+			break;
+		case PCI_VENDOR_ID_TTI:
+			/*PCI_CLASS_STORAGE_UNKNOWN == class */
+			if (device == PCI_DEVICE_ID_TTI_HPT343) {
+				pcibios_write_config_byte(bus, fn, HPT343_PCI_INIT_REG, 0x00);
+				pcibios_read_config_word(bus, fn, PCI_COMMAND, &pcicmd);
+				hpt34x_flag = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
+#if 1
+				if (!hpt34x_flag) {
+					save_flags(flags);
+					cli();
+					pcibios_write_config_word(bus, fn, PCI_COMMAND, pcicmd & ~PCI_COMMAND_IO);
+					pcibios_read_config_dword(bus, fn, PCI_BASE_ADDRESS_4, &bmiba);
+					pcibios_write_config_dword(bus, fn, PCI_BASE_ADDRESS_0, bmiba | 0x20);
+					pcibios_write_config_dword(bus, fn, PCI_BASE_ADDRESS_1, bmiba | 0x34);
+					pcibios_write_config_dword(bus, fn, PCI_BASE_ADDRESS_2, bmiba | 0x28);
+					pcibios_write_config_dword(bus, fn, PCI_BASE_ADDRESS_3, bmiba | 0x3c);
+					pcibios_write_config_word(bus, fn, PCI_COMMAND, pcicmd);
+					bmiba = 0;
+					restore_flags(flags);
+				}
+#endif
+				pcibios_write_config_byte(bus, fn, PCI_LATENCY_TIMER, 0x20); 
+				goto hpt343_jump_in;
+			} else {
+				printk("ide: HPTXXX did == 0x%04X unsupport chipset error.\n", device);
+				return;
+			}
 		case PCI_VENDOR_ID_PROMISE:
-			/*	PCI_CLASS_STORAGE_RAID == class	*/
 			/*
 			 *  I have been able to make my Promise Ultra33 UDMA card change class.
 			 *  It has reported as both PCI_CLASS_STORAGE_RAID and PCI_CLASS_STORAGE_IDE.
@@ -414,15 +547,17 @@
 			 *  correction if needed.
 			 *  PDC20246 (primary) PDC20247 (secondary) IDE hwif's.
 			 *
+			 *  PDC20262 Promise Ultra66 UDMA.
+			 *
 			 *  Note that Promise "stories,fibs,..." about this device not being
 			 *  capable of ATAPI and AT devices.
 			 */
-			if (PCI_CLASS_STORAGE_RAID == class) {
-				unsigned char irq1 = 0, irq2 = 0;
-				pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &irq1);
-				pcibios_read_config_byte (bus, fn, (PCI_INTERRUPT_LINE)|0x80, &irq2);
-				if (irq1 != irq2) {
-					pcibios_write_config_byte(bus, fn, (PCI_INTERRUPT_LINE)|0x80, irq1);
+			if (class != PCI_CLASS_STORAGE_IDE) {
+				unsigned char irq_mirror = 0;
+
+				pcibios_read_config_byte(bus, fn, (PCI_INTERRUPT_LINE)|0x80, &irq_mirror);
+				if (irq != irq_mirror) {
+					pcibios_write_config_byte(bus, fn, (PCI_INTERRUPT_LINE)|0x80, irq);
 				}
 			}
 		case PCI_VENDOR_ID_ARTOP:
@@ -436,8 +571,13 @@
 			 *  0x6000 range.  If they are setup in the 0xef00 range it is reported.
 			 *  WHY??? got me.........
 			 */
+hpt343_jump_in:
 			printk("ide: %s UDMA Bus Mastering ",
-				(vendor == PCI_VENDOR_ID_ARTOP) ? "AEC6210" : "PDC20246");
+				(device == PCI_DEVICE_ID_ARTOP_ATP850UF) 		? "AEC6210" :
+				(device == PCI_DEVICE_ID_PROMISE_20246)  		? "PDC20246" :
+				(device == PCI_DEVICE_ID_PROMISE_20262)  		? "PDC20262" :
+				(hpt34x_flag && (device == PCI_DEVICE_ID_TTI_HPT343))	? "HPT345" :
+				(device == PCI_DEVICE_ID_TTI_HPT343)     		? "HPT343" : "UNKNOWN");
 			pcibios_read_config_dword(bus, fn, PCI_ROM_ADDRESS, &addressbios);
 			if (addressbios) {
 				pcibios_write_config_byte(bus, fn, PCI_ROM_ADDRESS, addressbios | PCI_ROM_ADDRESS_ENABLE);
@@ -460,6 +600,15 @@
 					io[count++] = tmp & PCI_BASE_ADDRESS_IO_MASK;
 			}
 			break;
+		case PCI_VENDOR_ID_AL:
+			save_flags(flags);
+			cli();
+			for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, index, &bridgebus, &bridgefn); ++index) {
+				bridgeset = setup_aladdin(bus, fn);
+			}
+			restore_flags(flags);
+			printk("ide: ALI15X3 (dual FIFO) DMA Bus Mastering IDE ");
+			break;
 		default:
 			return;
 	}
@@ -491,12 +640,20 @@
 				break;
 			} else {
                                 printk("ide: BM-DMA base register is invalid (0x%04x, PnP BIOS problem)\n", bmiba);
-                                if (inb(((vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA : DEFAULT_BMIBA)) != 0xff || !try_again)
+                                if (inb(((vendor == PCI_VENDOR_ID_AL) ? DEFAULT_BMALIBA :
+					 (vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA :
+									DEFAULT_BMIBA)) != 0xff || !try_again)
 					break;
-				printk("ide: setting BM-DMA base register to 0x%04x\n", ((vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA : DEFAULT_BMIBA));
+				printk("ide: setting BM-DMA base register to 0x%04x\n",
+					((vendor == PCI_VENDOR_ID_AL) ? DEFAULT_BMALIBA :
+					 (vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA :
+									DEFAULT_BMIBA));
 				if ((rc = pcibios_write_config_word(bus, fn, PCI_COMMAND, pcicmd&~1)))
 					goto quit;
-				rc = pcibios_write_config_dword(bus, fn, 0x20, ((vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA : DEFAULT_BMIBA)|1);
+				rc = pcibios_write_config_dword(bus, fn, 0x20,
+					((vendor == PCI_VENDOR_ID_AL) ? DEFAULT_BMALIBA :
+					 (vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA :
+									DEFAULT_BMIBA)|1);
 				if (pcibios_write_config_word(bus, fn, PCI_COMMAND, pcicmd|5) || rc)
 					goto quit;
 			}
@@ -509,14 +666,17 @@
 	if ((rc = pcibios_read_config_dword(bus, fn,
 		(vendor == PCI_VENDOR_ID_PROMISE) ? 0x50 : 
 		(vendor == PCI_VENDOR_ID_ARTOP) ? 0x54 :
+		(vendor == PCI_VENDOR_ID_SI) ? 0x48 :
+		(vendor == PCI_VENDOR_ID_AL) ? 0x08 :
 		0x40, &timings)))
 		goto quit;
 	/*
-	 * We do a vendor check since the Ultra33 and AEC6210
+	 * We do a vendor check since the Ultra33/66 and AEC6210
 	 * holds their timings in a different location.
 	 */
+#if 0
 	printk("ide: timings == %08x\n", timings);
-
+#endif
 	/*
 	 *  The switch preserves some stuff that was original.
 	 */
@@ -533,9 +693,39 @@
 				goto quit;
 			}
 			break;
+		case PCI_VENDOR_ID_AL:
+			timings <<= 16;
+			timings >>= 24;
+			if (!(timings & 0x30)) {
+				printk("ide: ALI15X3: neither port is enabled\n");
+				goto quit;
+			}
+			break;
 		case PCI_VENDOR_ID_SI:
+			timings <<= 8;
+			timings >>= 24;
+			if (!(timings & 0x06)) {
+				printk("ide: SIS5513: neither port is enabled\n");
+				goto quit;
+			}
+			break;
 		case PCI_VENDOR_ID_PROMISE:
+			printk("    (U)DMA Burst Bit %sABLED " \
+				"Primary %s Mode " \
+				"Secondary %s Mode.\n",
+				(inb(bmiba + 0x001f) & 1) ? "EN" : "DIS",
+				(inb(bmiba + 0x001a) & 1) ? "MASTER" : "PCI",
+				(inb(bmiba + 0x001b) & 1) ? "MASTER" : "PCI" );
+#if 0
+			if (!(inb(bmiba + 0x001f) & 1)) {
+				outb(inb(bmiba + 0x001f)|0x01, (bmiba + 0x001f));
+				printk("    (U)DMA Burst Bit Forced %sABLED.\n",
+					(inb(bmiba + 0x001f) & 1) ? "EN" : "DIS");
+			}
+#endif
+			break;
 		case PCI_VENDOR_ID_ARTOP:
+		case PCI_VENDOR_ID_TTI:
                 default:
                         break;
         }
@@ -545,15 +735,22 @@
 	 */
 	for (h = 0; h < MAX_HWIFS; ++h) {
 		ide_hwif_t *hwif = &ide_hwifs[h];
+		byte channel = ((h == 1) || (h == 3) || (h == 5)) ? 1 : 0;
 
 		/*
 		 *  This prevents the first contoller from accidentally
 		 *  initalizing the hwif's that it does not use and block
 		 *  an off-board ide-pci from getting in the game.
 		 */
-		if (step_count >= 2) {
+		if ((step_count >= 2) || (pass_count >= 2)) {
 			goto quit;
 		}
+
+#if 0
+		if (hwif->chipset == ide_unknown)
+			printk("ide: index == %d channel(%d)\n", h, channel);
+#endif
+
 #ifdef CONFIG_BLK_DEV_OFFBOARD
 		/*
 		 *  This is a forced override for the onboard ide controller
@@ -562,21 +759,14 @@
 		 *  for offboard UDMA upgrades with hard disks, but saving
 		 *  the onboard DMA2 controllers for CDROMS, TAPES, ZIPS, etc...
 		 */
-		if ((vendor == PCI_VENDOR_ID_INTEL) ||
-		    (vendor == PCI_VENDOR_ID_SI) ||
-		    (vendor == PCI_VENDOR_ID_VIA)) {
-			if (h == 2) {
-				hwif->io_base = 0x1f0;
-				hwif->ctl_port = 0x3f6;
-				hwif->irq = 14;
-				hwif->noprobe = 0;
-			}
-			if (h == 3) {
-				hwif->io_base = 0x170;
-				hwif->ctl_port = 0x376;
-				hwif->irq = 15;
-				hwif->noprobe = 0;
-			}
+		if (((vendor == PCI_VENDOR_ID_INTEL) ||
+		     (vendor == PCI_VENDOR_ID_SI) ||
+		     (vendor == PCI_VENDOR_ID_VIA) ||
+		     (vendor == PCI_VENDOR_ID_AL)) && (h >= 2)) {
+			hwif->io_base	= channel ? 0x170 : 0x1f0;
+			hwif->ctl_port	= channel ? 0x376 : 0x3f6;
+			hwif->irq	= channel ? 15 : 14;
+			hwif->noprobe	= 0;
 		}
 #endif /* CONFIG_BLK_DEV_OFFBOARD */
 		/*
@@ -592,6 +782,7 @@
 			byte s_clks, r_clks;
 			unsigned short devid;
 #endif /* DISPLAY_TRITON_TIMINGS */
+			pass_count++;
 			if (hwif->io_base == 0x1f0) {
 				time = timings & 0xffff;
 				if ((time & 0x8000) == 0)	/* interface enabled? */
@@ -637,12 +828,17 @@
 			print_triton_drive_flags (1, (time >> 4) & 0xf);
 #endif /* DISPLAY_TRITON_TIMINGS */
 		} else if (vendor == PCI_VENDOR_ID_SI) {
+			pass_count++;
 			if (hwif->io_base == 0x1f0) {
+				if ((timings & 0x02) == 0)
+					continue;
 				hwif->chipset = ide_triton;
 				if (dma_enabled)
 					init_triton_dma(hwif, bmiba);
 				step_count++;
 			} else if (hwif->io_base == 0x170) {
+				if ((timings & 0x04) == 0)
+					continue;
 				hwif->chipset = ide_triton;
 				if (dma_enabled)
 					init_triton_dma(hwif, bmiba + 8);
@@ -650,9 +846,10 @@
 			} else {
 				continue;
 			}
-		} else if(vendor == PCI_VENDOR_ID_VIA) {
+		} else if (vendor == PCI_VENDOR_ID_VIA) {
+			pass_count++;
 			if (hwif->io_base == 0x1f0) {
-				if((timings & 0x02) == 0)
+				if ((timings & 0x02) == 0)
 					continue;
 				hwif->chipset = ide_triton;
 				if (dma_enabled)
@@ -664,7 +861,7 @@
 #endif /* DISPLAY_APOLLO_TIMINGS */
 				step_count++;
 			} else if (hwif->io_base == 0x170) {
-				if((timings & 0x01) == 0)
+				if ((timings & 0x01) == 0)
 					continue;
 				hwif->chipset = ide_triton;
 				if (dma_enabled)
@@ -675,41 +872,91 @@
 			} else {
 				continue;
 			}
+		} else if (vendor == PCI_VENDOR_ID_AL) {
+			byte ideic, inmir;
+			byte irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
+						      1, 11, 0, 12, 0, 14, 0, 15 };
+
+			if (bridgeset) {
+				pcibios_read_config_byte(bridgebus, bridgefn, 0x58, &ideic);
+				ideic = ideic & 0x03;
+				if ((channel && ideic == 0x03) || (!channel && !ideic)) {
+					pcibios_read_config_byte(bridgebus, bridgefn, 0x44, &inmir);
+					inmir = inmir & 0x0f;
+					hwif->irq = irq_routing_table[inmir];
+				} else if (channel && !(ideic & 0x01)) {
+					pcibios_read_config_byte(bridgebus, bridgefn, 0x75, &inmir);
+					inmir = inmir & 0x0f;
+					hwif->irq = irq_routing_table[inmir];
+				}
+			}
+			pass_count++;
+			if (hwif->io_base == 0x1f0) {
+				if ((timings & 0x20) == 0)
+					continue;
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba);
+				outb(inb(bmiba+2) & 0x60, bmiba+2);
+				if (inb(bmiba+2) & 0x80)
+					printk("ALI15X3: simplex device: DMA forced\n");
+#ifdef DISPLAY_ALI15X3_TIMINGS
+				proc_register_dynamic(&proc_root, &ali_proc_entry);
+#endif /* DISPLAY_ALI15X3_TIMINGS */
+				step_count++;
+			} else if (hwif->io_base == 0x170) {
+				if ((timings & 0x10) == 0)
+					continue;
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba + 8);
+				outb(inb(bmiba+10) & 0x60, bmiba+10);
+				if (inb(bmiba+10) & 0x80)
+					printk("ALI15X3: simplex device: DMA forced\n");
+				step_count++;
+			} else {
+				continue;
+			}
 		} else if ((vendor == PCI_VENDOR_ID_PROMISE) ||
-			   (vendor == PCI_VENDOR_ID_ARTOP)) {
-	/*
-	 *  This silly tmp = h routine allows an off-board ide-pci card to
-	 *  be booted as primary hwifgroup, provided that the onboard
-	 *  controllers are disabled.  If they are active, then we wait our
-	 *  turn for hwif assignment.
-	 */
-			unsigned char irq = 0;
-			pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &irq);
-			if ((h == 0) || (h == 1)) {
-				tmp = h * 2;
+			   (vendor == PCI_VENDOR_ID_ARTOP) ||
+			   (vendor == PCI_VENDOR_ID_TTI)) {
+			pass_count++;
+			if (vendor == PCI_VENDOR_ID_TTI) {
+				if ((!hpt34x_flag) && (h < 2)) {
+					goto quit;
+				} else if (hpt34x_flag) {
+					hwif->io_base	= channel ? (bmiba + 0x28) : (bmiba + 0x20);
+					hwif->ctl_port	= channel ? (bmiba + 0x3e) : (bmiba + 0x36);
+				} else {
+					goto io_temps;
+				}
 			} else {
-				tmp = (h - 2) * 2;
+io_temps:
+				tmp		= channel ? 2 : 0;
+				hwif->io_base	= io[tmp];
+				hwif->ctl_port	= io[tmp + 1] + 2;
 			}
-			hwif->io_base = io[tmp];
-			hwif->ctl_port = io[tmp + 1] + 2;
 			hwif->irq = irq;
 			hwif->noprobe = 0;
 
-			if (vendor == PCI_VENDOR_ID_ARTOP) {
+			if (device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
 				hwif->serialized = 1;
 			}
 
+			if ((vendor == PCI_VENDOR_ID_PROMISE) ||
+			    (vendor == PCI_VENDOR_ID_TTI)) {
+				set_promise_hpt343_extra(device, bmiba);
+			}
+
 			if (dma_enabled) {
-				if (!check_region(bmiba, 8)) {
-					hwif->chipset = ide_udma;
+				if ((!check_region(bmiba, 8)) && (!channel)) {
+					hwif->chipset = ((vendor == PCI_VENDOR_ID_TTI) && !hpt34x_flag) ? ide_hpt343 :
+							 (device == PCI_DEVICE_ID_PROMISE_20262) ? ide_ultra66 : ide_udma;
 					init_triton_dma(hwif, bmiba);
 					step_count++;
-				} else if (!check_region((bmiba + 0x08), 8)) {
-					if ((vendor == PCI_VENDOR_ID_PROMISE) &&
-					    (!check_region(bmiba+16, 16))) {
-						request_region(bmiba+16, 16, "PDC20246");
-					}
-					hwif->chipset = ide_udma;
+				} else if ((!check_region((bmiba + 0x08), 8)) && (channel)) {
+					hwif->chipset = ((vendor == PCI_VENDOR_ID_TTI) && !hpt34x_flag) ? ide_hpt343 :
+							 (device == PCI_DEVICE_ID_PROMISE_20262) ? ide_ultra66 : ide_udma;
 					init_triton_dma(hwif, bmiba + 8);
 					step_count++;
 				} else {
diff -urN linux-2.0.39-pre4/drivers/char/Config.in linux-2.0.39-pre5/drivers/char/Config.in
--- linux-2.0.39-pre4/drivers/char/Config.in	2003-08-15 15:04:57.000000000 -0700
+++ linux-2.0.39-pre5/drivers/char/Config.in	2003-08-15 15:04:57.000000000 -0700
@@ -12,6 +12,9 @@
 fi
 bool 'Digiboard PC/Xx Support' CONFIG_DIGI
 tristate 'Cyclades async mux support' CONFIG_CYCLADES
+if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then
+   bool '  Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
+fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    dep_tristate 'Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m
 fi
diff -urN linux-2.0.39-pre4/drivers/char/cyclades.c linux-2.0.39-pre5/drivers/char/cyclades.c
--- linux-2.0.39-pre4/drivers/char/cyclades.c	1999-06-13 10:21:00.000000000 -0700
+++ linux-2.0.39-pre5/drivers/char/cyclades.c	2003-08-15 15:04:57.000000000 -0700
@@ -1,7 +1,7 @@
 #define BLOCKMOVE
 #define	Z_WAKE
 static char rcsid[] =
-"$Revision: 2.1.2.1 $$Date: 1999/04/08 16:17:18 $";
+"$Revision: 2.1.2.4 $$Date: 1999/07/12 18:00:24 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -21,7 +21,7 @@
  * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
  * and then fixed as suggested by Michael K. Johnson 12/12/92.
  *
- * This version does not support shared irq's.
+ * This version supports shared IRQ's (only for PCI boards).
  *
  * This module exports the following rs232 io functions:
  *   int cy_init(void);
@@ -31,6 +31,29 @@
  *   void cleanup_module(void);
  *
  * $Log: cyclades.c,v $
+ * Revision 2.1.2.4   1999/07/12 18:00:24 ivan
+ * Fixed bug in cy_set_termios that would prevent XON/XOFF flow control
+ * switching from working properly;
+ * The driver now only prints IRQ info for the Cyclades-Z if it's
+ * configured to work in interrupt mode;
+ *
+ * Revision 2.1.2.3   1999/06/28 11:05:57 ivan
+ * Added support for interrupt mode operation for the Z cards;
+ * Removed the driver inactivity control for the Z;
+ * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when 
+ * the Z firmware is not loaded yet;
+ * Replaced the "manual" Z Tx flush buffer by a call to a FW command of 
+ * same functionality;
+ * Implemented workaround for IRQ setting loss on the PCI configuration 
+ * registers after a PCI bridge EEPROM reload (affects PLX9060 only);
+ *
+ * Revision 2.1.2.2   1999/05/21 17:18:05 ivan
+ * Added support to shared IRQ's (only for PCI boards);
+ * Added support for Cobalt Qube2 systems;
+ * IRQ [de]allocation scheme revisited;
+ * Included a PCI bridge reset and EEPROM reload in the board
+ * initialization code (for both Y and Z series).
+ *
  * Revision 2.1.2.1   1999/04/08 16:17:18 ivan
  * cy_wait_until_sent function revisited;
  * Module usage counter scheme revisited;
@@ -518,7 +541,7 @@
    constant in the definition below. No other change is necessary to
    support more boards/ports. */
 
-#define NR_PORTS        128
+#define NR_PORTS        256
 
 #define ZE_V1_NPORTS	64
 #define ZO_V1	0
@@ -600,6 +623,14 @@
 #include <linux/proc_fs.h>
 #endif
 
+#ifdef CONFIG_COBALT_27
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#define	CACHED_TO_UNCACHED(x)	(((unsigned long)(x) & \
+				  (unsigned long)0x1fffffff) + KSEG1)
+#endif
+
 #define __initfunc(__arginit)	__arginit
 #define copy_from_user		memcpy_fromfs
 #define copy_to_user		memcpy_tofs
@@ -636,6 +667,7 @@
 
 struct tty_driver cy_serial_driver, cy_callout_driver;
 
+#ifndef CONFIG_COBALT_27
 static volatile int cy_irq_triggered;
 static volatile int cy_triggered;
 static int cy_wild_int_mask;
@@ -663,6 +695,8 @@
 };
 #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
 
+#endif /* CONFIG_COBALT_27 */
+
 /* This is the per-card data structure containing address, irq, number of
    channels, etc. This driver supports a maximum of NR_CARDS cards.
 */
@@ -681,12 +715,6 @@
 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 */
-
-static struct cyclades_card     *IRQ_cards[16];
-
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -791,8 +819,9 @@
 
 static void cy_start(struct tty_struct *);
 static void set_line_char(struct cyclades_port *);
+#ifndef CONFIG_COBALT_27
 static void cy_probe(int, void *, struct pt_regs *);
-static void cyz_poll(unsigned long);
+#endif /* CONFIG_COBALT_27 */
 #ifdef CY_SHOW_STATUS
 static void show_status(int);
 #endif
@@ -813,6 +842,9 @@
 };
 #endif
 
+#ifndef CONFIG_CYZ_INTR
+static void cyz_poll(unsigned long);
+
 /* The Cyclades-Z polling cycle is defined by this variable */
 static long cyz_polling_cycle = CZ_DEF_POLL;
 
@@ -821,6 +853,7 @@
 cyz_timerlist = {
     NULL, NULL, 0, 0, cyz_poll
 };
+#endif /* CONFIG_CYZ_INTR */
 
 /**************************************************
 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
@@ -862,7 +895,7 @@
         return 0;
 } /* serial_paranoia_check */
 
-
+#ifndef CONFIG_COBALT_27
 /* The following diagnostic routines allow the driver to spew
    information on the screen, even (especially!) during interrupts.
  */
@@ -895,7 +928,7 @@
 static void CP32(long data)
     { CP16((data>>16) & 0xffff); CP16(data & 0xffff); }/* CP32 */
 #endif
-
+#endif /* CONFIG_COBALT_27 */
 
 /*
  * This routine is used by the interrupt handler to schedule
@@ -1009,6 +1042,8 @@
     return(0);
 } /* cyy_issue_cmd */
 
+#ifndef CONFIG_COBALT_27	/* ISA interrupt detection code */
+
 static int probe_ready;
 
 /*
@@ -1204,6 +1239,8 @@
     return;
 } /* cy_probe */
 
+#endif /* CONFIG_COBALT_27 */
+
 /* The real interrupt service routine is called
    whenever the card wants its hand held--chars
    received, out buffer empty, modem change, etc.
@@ -1227,9 +1264,9 @@
   int mdm_change;
   int mdm_status;
 
-    if((cinfo = IRQ_cards[irq]) == 0){
+    if((cinfo = (struct cyclades_card *)dev_id) == 0){
 #ifdef CY_DEBUG_INTERRUPTS
-printk("cy_interrupt: spurious interrupt %d\n\r", irq);
+	printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
 #endif
         return; /* spurious interrupt */
     }
@@ -1261,7 +1298,7 @@
                 }
                 if (status & CySRReceive) { /* reception interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-printk("cy_interrupt: rcvd intr, chip %d\n\r", chip);
+		    printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip);
 #endif
                     /* determine the channel & change to that context */
                     save_xir = (u_char) cy_readb(base_addr+(CyRIR<<index));
@@ -1319,7 +1356,7 @@
 							    TTY_OVERRUN;
                                         *tty->flip.char_buf_ptr++ = 0;
                                         /* If the flip buffer itself is
-                                           overflowing, we still loose
+                                           overflowing, we still lose
                                            the next incoming character.
                                          */
                                         if(tty->flip.count
@@ -1389,7 +1426,7 @@
                        is empty, we know we can always stuff a dozen
                        characters. */
 #ifdef CY_DEBUG_INTERRUPTS
-printk("cy_interrupt: xmit intr, chip %d\n\r", chip);
+		    printk("cyy_interrupt: xmit intr, chip %d\n\r", chip);
 #endif
 
                     /* determine the channel & change to that context */
@@ -1687,12 +1724,285 @@
 } /* cyz_update_channel */
 #endif
 
-
+#ifdef CONFIG_CYZ_INTR
 static void
 cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+  struct tty_struct *tty;
+  struct cyclades_card *cinfo;
+  struct cyclades_port *info;
+  static volatile struct FIRM_ID *firm_id;
+  static volatile struct ZFW_CTRL *zfw_ctrl;
+  static volatile struct BOARD_CTRL *board_ctrl;
+  static volatile struct CH_CTRL *ch_ctrl;
+  static volatile struct BUF_CTRL *buf_ctrl;
+  uclong channel;
+  ucchar cmd;
+  uclong param;
+  uclong hw_ver, fw_ver;
+  char data;
+  volatile int char_count, special_count;
+#ifdef BLOCKMOVE
+  int small_count;
+#endif
+  volatile uclong tx_put, tx_get, tx_bufsize;
+  volatile uclong rx_put, rx_get, rx_bufsize;
+
+    if((cinfo = (struct cyclades_card *)dev_id) == 0){
+#ifdef CY_DEBUG_INTERRUPTS
+	printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
+#endif
+        return; /* spurious interrupt */
+    }
+
+	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+        if (!ISZLOADED(*cinfo)) {
+#ifdef CY_DEBUG_INTERRUPTS
+	    printk("cyz_interrupt: board not yet loaded (INT %d).\n\r", irq);
+#endif
+	    return;
+	}
+
+	zfw_ctrl = (struct ZFW_CTRL *)
+	           (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
+	board_ctrl = &(zfw_ctrl->board_ctrl);
+	fw_ver = cy_readl(&board_ctrl->fw_version);
+	hw_ver = cy_readl(&((struct RUNTIME_9060 *)
+                            (cinfo->ctl_addr))->mail_box_0);
+
+	while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
+	    special_count = 0;
+	    info = &cy_port[channel + cinfo->first_line];
+            if((tty = info->tty) == 0) continue;
+	    ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+	    buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
+
+	    switch(cmd){
+	    case C_CM_PR_ERROR:
+		tty->flip.count++;
+		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+		*tty->flip.char_buf_ptr++ = 0;
+		special_count++;
+	        break;
+	    case C_CM_FR_ERROR:
+		tty->flip.count++;
+		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+		*tty->flip.char_buf_ptr++ = 0;
+		special_count++;
+	        break;
+	    case C_CM_RXBRK:
+		tty->flip.count++;
+		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+		*tty->flip.char_buf_ptr++ = 0;
+		special_count++;
+	        break;
+	    case C_CM_MDCD:
+		if (info->flags & ASYNC_CHECK_CD){
+		    if ((fw_ver > 241 ? 
+                          ((u_long)param) : 
+                          cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {
+			/* SP("Open Wakeup\n"); */
+			cy_sched_event(info,
+			    Cy_EVENT_OPEN_WAKEUP);
+		    }else if(!((info->flags
+				& ASYNC_CALLOUT_ACTIVE)
+			 &&(info->flags
+			    & ASYNC_CALLOUT_NOHUP))){
+			/* SP("Hangup\n"); */
+			cy_sched_event(info,
+			    Cy_EVENT_HANGUP);
+		    }
+		}
+	        break;
+	    case C_CM_MCTS:
+		if (info->flags & ASYNC_CTS_FLOW) {
+		    if(info->tty->hw_stopped){
+			if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){
+			    /* cy_start isn't used because... 
+			       HW flow is handled by the board */
+			    /* SP("Write Wakeup\n"); */
+			    cy_sched_event(info,
+				Cy_EVENT_WRITE_WAKEUP);
+			}
+		    }else{
+			if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){
+			    /* cy_stop isn't used because 
+			       HW flow is handled by the board */
+			    /* SP("Write stop\n"); */
+			}
+		    }
+		}
+	        break;
+	    case C_CM_MRI:
+	        break;
+	    case C_CM_MDSR:
+	        break;
+#ifdef Z_WAKE
+	    case C_CM_IOCTLW:
+		cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
+	        break;
+#endif
+	    case C_CM_RXHIWM:
+	    case C_CM_RXNNDT:
+		/* Reception Interrupt */
+#ifdef CY_DEBUG_INTERRUPTS
+	    printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", 
+		info->card, channel);
+#endif
+
+	    rx_get = cy_readl(&buf_ctrl->rx_get);
+	    rx_put = cy_readl(&buf_ctrl->rx_put);
+	    rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
+	    if (rx_put >= rx_get)
+	    	char_count = rx_put - rx_get;
+	    else
+	    	char_count = rx_put - rx_get + rx_bufsize;
+
+	    if ( char_count ){
+
+#ifdef CY_ENABLE_MONITORING
+		info->mon.int_count++;
+		info->mon.char_count += char_count;
+		if (char_count > info->mon.char_max)
+		   info->mon.char_max = char_count;
+		info->mon.char_last = char_count;
+#endif
+		info->idle_stats.recv_bytes += char_count;
+		info->idle_stats.recv_idle   = jiffies;
+		if( tty == 0){
+		    /* flush received characters */
+		    rx_get = (rx_get + char_count) & (rx_bufsize - 1);
+		    /* SP("-"); */
+		    info->rflush_count++;
+		}else{
+#ifdef BLOCKMOVE
+		/* we'd like to use memcpy(t, f, n) and memset(s, c, count)
+		   for performance, but because of buffer boundaries, there
+		   may be several steps to the operation */
+		    while(0 < (small_count
+			= cy_min((rx_bufsize - rx_get),
+			         cy_min((TTY_FLIPBUF_SIZE - tty->flip.count),
+				        char_count)))){
+
+			memcpy_fromio(tty->flip.char_buf_ptr,
+			              (char *)(cinfo->base_addr
+				       + cy_readl(&buf_ctrl->rx_bufaddr)
+				       + rx_get),
+			              small_count);
+
+			tty->flip.char_buf_ptr += small_count;
+			memset(tty->flip.flag_buf_ptr,
+			       TTY_NORMAL,
+			       small_count);
+			tty->flip.flag_buf_ptr += small_count;
+			rx_get = (rx_get + small_count) & (rx_bufsize - 1);
+			char_count -= small_count;
+			tty->flip.count += small_count;
+		    }
+#else
+		    while(char_count--){
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE){
+				break;
+			}
+			data = cy_readb(cinfo->base_addr +
+			           cy_readl(&buf_ctrl->rx_bufaddr) + rx_get);
+			rx_get = (rx_get + 1) & (rx_bufsize - 1);
+			tty->flip.count++;
+			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+			*tty->flip.char_buf_ptr++ = data;
+		    }
+#endif
+		    queue_task(&tty->flip.tqueue, &tq_timer);
+		}
+		/* Update rx_get */
+		cy_writel(&buf_ctrl->rx_get, rx_get);
+	    }
+		break;
+	    case C_CM_TXBEMPTY:
+	    case C_CM_TXLOWWM:
+	    case C_CM_INTBACK:
+		/* Transmission Interrupt */
+#ifdef CY_DEBUG_INTERRUPTS
+	    printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", 
+		info->card, channel);
+#endif
+
+	    tx_get = cy_readl(&buf_ctrl->tx_get);
+	    tx_put = cy_readl(&buf_ctrl->tx_put);
+	    tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+	    if (tx_put >= tx_get)
+	    	char_count = tx_get - tx_put - 1 + tx_bufsize;
+	    else
+	    	char_count = tx_get - tx_put - 1;
+
+	    if ( char_count ){
+
+		if( tty == 0 ){
+		    goto ztxdone;
+		}
+
+		if(info->x_char) { /* send special char */
+		    data = info->x_char;
+
+		    cy_writeb((cinfo->base_addr +
+		              cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data);
+		    tx_put = (tx_put + 1) & (tx_bufsize - 1);
+		    info->x_char = 0;
+		    char_count--;
+		}
+#ifdef BLOCKMOVE
+		while(0 < (small_count
+		    = cy_min((tx_bufsize - tx_put),
+			     cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail),
+			             cy_min(info->xmit_cnt, char_count))))){
+
+		    memcpy_toio((char *)(cinfo->base_addr
+			         + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put),
+			        &info->xmit_buf[info->xmit_tail],
+			        small_count);
+
+		    tx_put = (tx_put + small_count) & (tx_bufsize - 1);
+		    char_count -= small_count;
+		    info->xmit_cnt -= small_count;
+		    info->xmit_tail =
+		       (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1);
+		}
+#else
+		while (info->xmit_cnt && char_count){
+		    data = info->xmit_buf[info->xmit_tail];
+		    info->xmit_cnt--;
+		    info->xmit_tail =
+			(info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+
+		    cy_writeb(cinfo->base_addr +
+		              cy_readl(&buf_ctrl->tx_bufaddr) + tx_put, 
+			      data);
+		    tx_put = (tx_put + 1) & (tx_bufsize - 1);
+		    char_count--;
+		}
+
+#endif
+	    ztxdone:
+		if (info->xmit_cnt < WAKEUP_CHARS) {
+		    cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+		}
+		/* Update tx_put */
+		cy_writel(&buf_ctrl->tx_put, tx_put);
+	    }
+		break;
+	    case C_CM_FATAL:
+		/* should do something with this !!! */
+	        break;
+	    }
+	    if(special_count){
+		queue_task(&tty->flip.tqueue, &tq_timer);
+	    }
+	}
+
+    return;
 } /* cyz_interrupt */
 
+#else /* CONFIG_CYZ_INTR */
 
 static void
 cyz_poll(unsigned long arg)
@@ -1726,7 +2036,6 @@
 
 	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
         if (!ISZLOADED(*cinfo)) {
-	    cinfo->inact_ctrl = 0;
 	    continue;
 	}
 
@@ -1737,12 +2046,6 @@
 	hw_ver = cy_readl(&((struct RUNTIME_9060 *)
                             (cinfo->ctl_addr))->mail_box_0);
 
-	/* Enables the firmware inactivity control */
-	if ((fw_ver > 0x00000310L) && (!cinfo->inact_ctrl)) {
-	    param = cyz_issue_cmd( &cy_card[card], 0L, C_CM_TINACT, 0L);
-	    cinfo->inact_ctrl = 1;
-	}
-
 	while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1){
 	    char_count = 0;
 	    info = &cy_port[ channel + cinfo->first_line ];
@@ -1984,17 +2287,13 @@
 	}
 	/* poll every 40 ms */
 	cyz_timerlist.expires = jiffies + cyz_polling_cycle;
-
-	/* refresh inactivity counter */
-	if (cinfo->inact_ctrl) {
-		cy_writel(&board_ctrl->inactivity, (uclong) ZF_TINACT);
-	}
     }
     add_timer(&cyz_timerlist);
 
     return;
 } /* cyz_poll */
 
+#endif /* CONFIG_CYZ_INTR */
 
 /********** End of block of Cyclades-Z specific code *********/
 /***********************************************************/
@@ -2103,12 +2402,27 @@
 
 	cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
 #ifdef Z_WAKE
-	cy_writel(&ch_ctrl[channel].intr_enable, 
-		  C_IN_MDCD|C_IN_MCTS|C_IN_IOCTLW);
+#ifdef CONFIG_CYZ_INTR
+	cy_writel(&ch_ctrl[channel].intr_enable,
+		  C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
+		  C_IN_IOCTLW|
+		  C_IN_MDCD|C_IN_MCTS);
 #else
-	cy_writel(&ch_ctrl[channel].intr_enable, 
+	cy_writel(&ch_ctrl[channel].intr_enable,
+		  C_IN_IOCTLW|
 		  C_IN_MDCD|C_IN_MCTS);
-#endif
+#endif /* CONFIG_CYZ_INTR */
+#else
+#ifdef CONFIG_CYZ_INTR
+	cy_writel(&ch_ctrl[channel].intr_enable,
+		  C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
+		  C_IN_MDCD|C_IN_MCTS);
+#else
+	cy_writel(&ch_ctrl[channel].intr_enable,
+		  C_IN_MDCD|C_IN_MCTS);
+#endif /* CONFIG_CYZ_INTR */
+#endif /* Z_WAKE */
+
 	retval = cyz_issue_cmd( &cy_card[card],
 	    channel, C_CM_IOCTL, 0L);	/* was C_CM_RESET */
 	if (retval != 0){
@@ -2171,11 +2485,21 @@
                cy_readb(base_addr+(CySRER<<index)) | CyTxMpty);
 	restore_flags(flags);
     } else {
+#ifdef CONFIG_CYZ_INTR
+	int retval;
+
+	save_flags(flags); cli();
+	    retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L);
+	    if (retval != 0){
+		printk("cyc:start_xmit retval was %x\n", retval);
+	    }
+	restore_flags(flags);
+#else /* CONFIG_CYZ_INTR */
 	/* Don't have to do anything at this time */
+#endif /* CONFIG_CYZ_INTR */
     }
 } /* start_xmit */
 
-
 /*
  * This routine shuts down a serial port; interrupts are disabled,
  * and DTR is dropped if the hangup on close termio flag is on.
@@ -2557,8 +2881,24 @@
 	    } else {
 		printk("Cyclades-Z firmware not yet loaded\n");
 	    }
+	    MOD_DEC_USE_COUNT;
 	    return -ENODEV;
 	}
+#ifdef CONFIG_CYZ_INTR
+	else {
+	    /* In case this Z board is operating in interrupt mode, its
+	       interrupts should be enabled as soon as the first open happens
+	       to one of its ports. */
+	    if (!cy_card[info->card].intr_enabled) {
+		retval = cyz_issue_cmd(&cy_card[info->card],
+					0, C_CM_IRQ_ENBL, 0L);
+		if (retval != 0){
+		    printk("cyc:IRQ enable retval was %x\n", retval);
+		}
+		cy_card[info->card].intr_enabled = 1;
+	    }
+	}
+#endif /* CONFIG_CYZ_INTR */
     }
 #ifdef CY_DEBUG_OTHER
     printk("cyc:cy_open ttyC%d\n", info->line); /* */
@@ -4139,6 +4479,7 @@
 	case CYGETCD1400VER:
 	    ret_val = info->chip_rev;
 	    break;
+#ifndef CONFIG_CYZ_INTR
 	case CYZSETPOLLCYCLE:
             cyz_polling_cycle = (arg * HZ) / 1000;
 	    ret_val = 0;
@@ -4146,6 +4487,7 @@
 	case CYZGETPOLLCYCLE:
             ret_val = (cyz_polling_cycle * 1000) / HZ;
 	    break;
+#endif /* CONFIG_CYZ_INTR */
 	case CYSETWAIT:
     	    info->closing_wait = (unsigned short)arg * HZ/100;
 	    ret_val = 0;
@@ -4254,7 +4596,8 @@
     printk("cyc:cy_set_termios ttyC%d\n", info->line);
 #endif
 
-    if (tty->termios->c_cflag == old_termios->c_cflag)
+    if ((tty->termios->c_cflag == old_termios->c_cflag) &&
+	((tty->termios->c_iflag & IXON) == (old_termios->c_iflag & IXON)))
         return;
     set_line_char(info);
 
@@ -4272,16 +4615,6 @@
     return;
 } /* cy_set_termios */
 
-
-/*
- * void (*set_ldisc)(struct tty_struct *tty);
- *
- * 	This routine allows the tty driver to be notified when the
- * 	device's termios settings have changed.
- * 
- */
-
-
 /* This routine is called by the upper-layer tty layer to signal
    that incoming characters should be throttled because the input
    buffers are close to full.
@@ -4483,7 +4816,7 @@
 cy_flush_buffer(struct tty_struct *tty)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  int card, channel;
+  int card, channel, retval;
   unsigned long flags;
                                 
 #ifdef CY_DEBUG_IO
@@ -4501,19 +4834,10 @@
 
     if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board 
 				      buffers as well */
-	static volatile struct FIRM_ID *firm_id;
-	static volatile struct ZFW_CTRL *zfw_ctrl;
-	static volatile struct CH_CTRL *ch_ctrl;
-	static volatile struct BUF_CTRL *buf_ctrl;
-
-	firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *) (cy_card[card].base_addr +
-				cy_readl(&firm_id->zfwctrl_addr));
-	ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-	buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
-	while (cy_readl(&buf_ctrl->tx_get) != cy_readl(&buf_ctrl->tx_put))
-		cy_writel(&buf_ctrl->tx_put, cy_readl(&buf_ctrl->tx_get));
+	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
+	if (retval != 0) {
+	    printk("cyc: flush_buffer retval was %x\n", retval);
+	}
     }
     wake_up_interruptible(&tty->write_wait);
     if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
@@ -4639,6 +4963,7 @@
     return chip_number;
 } /* cyy_init_card */
 
+#ifndef CONFIG_COBALT_27
 /*
  * ---------------------------------------------------------------------
  * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
@@ -4699,7 +5024,7 @@
 
                 /* allocate IRQ */
                 if(request_irq(cy_isa_irq, cyy_interrupt,
-				   SA_INTERRUPT, "cyclomY", NULL))
+				   SA_INTERRUPT, "Cyclom-Y", &cy_card[j]))
                 {
                         printk("Cyclom-Y/ISA found at 0x%lx ",
                                 (unsigned long) cy_isa_address);
@@ -4715,7 +5040,6 @@
                 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 */
@@ -4730,6 +5054,20 @@
         return(nboard);
 
 } /* cy_detect_isa */
+#endif /* CONFIG_COBALT_27 */
+
+static void plx_init(uclong addr, uclong initctl)
+{
+    /* Reset PLX */
+    cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
+    udelay(100L);
+    cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000);
+
+    /* Reload Config. Registers from EEPROM */
+    cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000);
+    udelay(100L);
+    cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000);
+}
 
 /*
  * ---------------------------------------------------------------------
@@ -4800,6 +5138,12 @@
 		cy_pci_addr0  &= PCI_BASE_ADDRESS_MEM_MASK;
 		cy_pci_addr2  &= PCI_BASE_ADDRESS_MEM_MASK;
 
+		if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) {
+		    printk("  Warning: PCI I/O bit incorrectly set. "
+			   "Ignoring it...\n");
+		    cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK;
+		}
+
 #if defined(__alpha__)
                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
 		    printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
@@ -4817,7 +5161,9 @@
 		cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0 & PAGE_MASK, 
 					PAGE_ALIGN(CyPCI_Yctl)) 
 				+ (cy_pci_addr0 & (PAGE_SIZE-1));
+#ifndef CONFIG_COBALT_27
                 if ((ulong)cy_pci_addr2 >= 0x100000)  /* above 1M? */
+#endif /* CONFIG_COBALT_27 */
                     cy_pci_addr2 = (ulong) ioremap(cy_pci_addr2, CyPCI_Ywin);
 #endif
 
@@ -4855,7 +5201,7 @@
 
                 /* allocate IRQ */
                 if(request_irq(cy_pci_irq, cyy_interrupt,
-		        SA_INTERRUPT, "cyclomY", NULL))
+		        SA_SHIRQ, "Cyclom-Y", &cy_card[j]))
                 {
                         printk("Cyclom-Y/PCI found at 0x%lx ",
 			    (ulong) cy_pci_addr2);
@@ -4871,13 +5217,14 @@
                 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 */
 		plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
                 switch (plx_ver) {
 		    case PLX_9050:
 
+		    plx_init(cy_pci_addr0, 0x50);
+
 		    cy_writew(cy_pci_addr0+0x4c,
 			cy_readw(cy_pci_addr0+0x4c)|0x0040);
 		    break;
@@ -4886,6 +5233,14 @@
 		    case PLX_9080:
 		    default: /* Old boards, use PLX_9060 */
 
+		    plx_init(cy_pci_addr0, 0x6c);
+		    /* For some yet unknown reason, once the PLX9060 reloads 
+		       the EEPROM, the IRQ is lost and, thus, we have to 
+		       re-write it to the PCI config. registers.
+		       This will remain here until we find a permanent fix. */
+		    pcibios_write_config_byte(cyy_bus, cyy_dev_fn,
+					PCI_INTERRUPT_LINE, cy_pci_irq);
+
 		    cy_writew(cy_pci_addr0+0x68,
 			cy_readw(cy_pci_addr0+0x68)|0x0900);
 		    break;
@@ -4921,15 +5276,31 @@
                 (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
 #endif
                 cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK;
+
 #if !defined(__alpha__)
                 cy_pci_addr0 = (unsigned int) ioremap(
                                cy_pci_addr0 & PAGE_MASK,
                                PAGE_ALIGN(CyPCI_Zctl))
                                + (cy_pci_addr0 & (PAGE_SIZE-1));
 #endif
+
+		plx_init(cy_pci_addr0, 0x6c);
+		/* For some yet unknown reason, once the PLX9060 reloads 
+		   the EEPROM, the IRQ is lost and, thus, we have to 
+		   re-write it to the PCI config. registers.
+		   This will remain here until we find a permanent fix. */
+		pcibios_write_config_byte(cyy_bus, cyy_dev_fn,
+				PCI_INTERRUPT_LINE, cy_pci_irq);
+
 		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
 			   cy_pci_addr0)->mail_box_0);
                 cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+		if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) { 
+		    printk("  Warning: PCI I/O bit incorrectly set. "
+			   "Ignoring it...\n");
+		    cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK;
+		}
 		if (mailbox == ZE_V1) {
 #if !defined(__alpha__)
                	    cy_pci_addr2 = (unsigned int) ioremap(
@@ -5009,10 +5380,11 @@
 		    return(i);
                 }
 
+#ifdef CONFIG_CYZ_INTR
                 /* allocate IRQ only if board has an IRQ */
-		if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) {
-		    if(request_irq(cy_pci_irq,cyz_interrupt,
-			SA_INTERRUPT,"cyclomZ",NULL))
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
+		    if(request_irq(cy_pci_irq, cyz_interrupt,
+			SA_SHIRQ, "Cyclades-Z", &cy_card[j]))
 		    {
 			printk("Could not allocate IRQ%d ",
 			    cy_pci_irq);
@@ -5021,6 +5393,7 @@
 			return(i);
 		    }
 		}
+#endif /* CONFIG_CYZ_INTR */
 
 
                 /* set cy_card */
@@ -5030,22 +5403,28 @@
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
                 cy_card[j].num_chips = -1;
-                IRQ_cards[cy_pci_irq] = &cy_card[j];
 
                 /* print message */
+#ifdef CONFIG_CYZ_INTR
 		/* don't report IRQ if board is no IRQ */
-		if( (cy_pci_irq < 15) && (cy_pci_irq > 1) ) {
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) )
 		    printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
 			j+1,(ulong)cy_pci_addr2,
 			(ulong)(cy_pci_addr2 + CyPCI_Zwin - 1),
 			(int)cy_pci_irq);
-		}else{
+		else
+#endif /* CONFIG_CYZ_INTR */
 		    printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ",
 			j+1,(ulong)cy_pci_addr2,
 			(ulong)(cy_pci_addr2 + CyPCI_Zwin - 1));
-		}
+
                 printk("%d channels starting from port %d.\n",
 		    cy_pci_nchan,cy_next_channel);
+#ifdef CONFIG_CYZ_INTR
+		/* Enable interrupts on the PLX chip */
+		cy_writew(cy_pci_addr0+0x68,
+			cy_readw(cy_pci_addr0+0x68)|0x0900);
+#endif /* CONFIG_CYZ_INTR */
                 cy_next_channel += cy_pci_nchan;
     }
         }
@@ -5065,10 +5444,6 @@
                 (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
 	    printk("Cyclades-Z/PCI: New Cyclades-Z board.  FPGA not loaded\n");
 #endif
-	    /* The following clears the firmware id word.  This ensures
-	       that the driver will not attempt to talk to the board
-	       until it has been properly initialized.
-	     */
 		PAUSE
                 /* This must be the new Cyclades-Ze/PCI. */
                 cy_pci_nchan = ZE_V1_NPORTS;
@@ -5093,10 +5468,11 @@
 		    return(i);
                 }
 
+#ifdef CONFIG_CYZ_INTR
                 /* allocate IRQ only if board has an IRQ */
-		if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) {
-		    if(request_irq(cy_pci_irq,cyz_interrupt,
-			SA_INTERRUPT,"cyclomZ",NULL))
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
+		    if(request_irq(cy_pci_irq, cyz_interrupt,
+			SA_SHIRQ, "Cyclades-Z", &cy_card[j]))
 		    {
 			printk("Could not allocate IRQ%d ",
 			    cy_pci_irq);
@@ -5105,6 +5481,7 @@
 			return(i);
 		    }
 		}
+#endif /* CONFIG_CYZ_INTR */
 
                 /* set cy_card */
                 cy_card[j].base_addr = cy_pci_addr2;
@@ -5113,22 +5490,28 @@
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
                 cy_card[j].num_chips = -1;
-                IRQ_cards[cy_pci_irq] = &cy_card[j];
 
                 /* print message */
+#ifdef CONFIG_CYZ_INTR
 		/* don't report IRQ if board is no IRQ */
-		if( (cy_pci_irq < 15) && (cy_pci_irq > 1) ) {
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) )
 		    printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
 			j+1,(ulong)cy_pci_addr2,
 			(ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1),
 			(int)cy_pci_irq);
-		}else{
+		else
+#endif /* CONFIG_CYZ_INTR */
 		    printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ",
 			j+1,(ulong)cy_pci_addr2,
 			(ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1));
-		}
+
                 printk("%d channels starting from port %d.\n",
 		    cy_pci_nchan,cy_next_channel);
+#ifdef CONFIG_CYZ_INTR
+		/* Enable interrupts on the PLX chip */
+		cy_writew(cy_pci_addr0+0x68,
+			cy_readw(cy_pci_addr0+0x68)|0x0900);
+#endif /* CONFIG_CYZ_INTR */
                 cy_next_channel += cy_pci_nchan;
         }
 	if (ZeIndex != 0) {
@@ -5299,10 +5682,6 @@
 
     init_bh(CYCLADES_BH, do_cyclades_bh);
 
-    for (i = 0; i < 16; i++) {
-            IRQ_cards[i] = 0;
-    }
-
     for (i = 0; i < NR_CARDS; i++) {
             /* base_addr=0 indicates board not found */
             cy_card[i].base_addr = 0;
@@ -5315,8 +5694,10 @@
        availability of cy_card and cy_port data structures and updating
        the cy_next_channel. */
 
+#ifndef CONFIG_COBALT_27
     /* look for isa boards */
     cy_isa_nboard = cy_detect_isa();
+#endif /* CONFIG_COBALT_27 */
     
     /* look for pci boards */
     cy_pci_nboard = cy_detect_pci();
@@ -5348,6 +5729,7 @@
 		mailbox = cy_readl(&((struct RUNTIME_9060 *)
 			     cy_card[board].ctl_addr)->mail_box_0);
 		nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
+		cinfo->intr_enabled = 0;
                 for (port = cinfo->first_line ;
                      port < cinfo->first_line + nports;
                      port++)
@@ -5471,15 +5853,17 @@
                 }
             }
     }
-    
-    if ( number_z_boards && !cyz_timeron){
-        cyz_timeron++;
+
+#ifndef CONFIG_CYZ_INTR
+    if (number_z_boards && !cyz_timeron){
+	cyz_timeron++;
 	cyz_timerlist.expires = jiffies + 1;
 	add_timer(&cyz_timerlist);
 #ifdef CY_PCI_DEBUG
 	printk("Cyclades-Z polling initialized\n");
 #endif
     }
+#endif /* CONFIG_CYZ_INTR */
 
 #if defined(CONFIG_PROC_FS) && !defined(MODULE)
     proc_register_dynamic(&proc_root, &cyclades_proc_entry);
@@ -5504,10 +5888,12 @@
     int i;
     unsigned long flags;
 
+#ifndef CONFIG_CYZ_INTR
     if (cyz_timeron){
 	cyz_timeron = 0;
 	del_timer(&cyz_timerlist);
     }
+#endif /* CONFIG_CYZ_INTR */
 
     save_flags(flags); cli();
 
@@ -5521,9 +5907,12 @@
 
     for (i = 0; i < NR_CARDS; i++) {
         if (cy_card[i].base_addr != 0
+#ifndef CONFIG_CYZ_INTR
+	    && cy_card[i].num_chips != -1 /* not a Z card */
+#endif /* CONFIG_CYZ_INTR */
 	    && cy_card[i].irq)
         {
-            free_irq(cy_card[i].irq,NULL);
+            free_irq(cy_card[i].irq, &cy_card[i]);
         }
     }
 } /* cleanup_module */
@@ -5532,6 +5921,7 @@
 void
 cy_setup(char *str, int *ints)
 {
+#ifndef CONFIG_COBALT_27
   int i, j;
 
     for (i = 0 ; i < NR_ISA_ADDRS ; i++) {
@@ -5542,6 +5932,7 @@
             cy_isa_addresses[i++] = (unsigned char *)(ints[j]);
         }
     }
+#endif /* CONFIG_COBALT_27 */
 
 } /* cy_setup */
 #endif
diff -urN linux-2.0.39-pre4/drivers/net/Config.in linux-2.0.39-pre5/drivers/net/Config.in
--- linux-2.0.39-pre4/drivers/net/Config.in	2003-08-15 15:04:57.000000000 -0700
+++ linux-2.0.39-pre5/drivers/net/Config.in	2003-08-15 15:04:57.000000000 -0700
@@ -54,14 +54,14 @@
 if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
    bool '  3COM ISA, EISA and PCI cards' CONFIG_NET_VENDOR_3COM
    if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
-      tristate '    3c501 support' CONFIG_EL1
-      tristate '    3c503 support' CONFIG_EL2
+      tristate '    3c501 "EtherLink" support' CONFIG_EL1
+      tristate '    3c503 "EtherLink II" support' CONFIG_EL2
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-	 tristate '    3c505 (EXPERIMENTAL) support' CONFIG_ELPLUS
-	 tristate '    3c507 (EXPERIMENTAL) support' CONFIG_EL16
+	 tristate '    3c505 "EtherLink Plus" (EXPERIMENTAL) support' CONFIG_ELPLUS
+	 tristate '    3c507 "EtherLink 16" (EXPERIMENTAL) support' CONFIG_EL16
       fi
-      tristate '    3c509/3c579 support' CONFIG_EL3
-      tristate '    3c515 ISA Fast EtherLink' CONFIG_3C515
+      tristate '    3c509/3c579 "EtherLink III" support' CONFIG_EL3
+      tristate '    3c515 ISA "Fast EtherLink"' CONFIG_3C515
       tristate '    3c590/3c900 series (592/595/597/900/905) "Vortex/Boomerang" support' CONFIG_VORTEX
    fi
    bool '  Western Digital/SMC ISA and EISA cards' CONFIG_NET_VENDOR_SMC
diff -urN linux-2.0.39-pre4/drivers/pci/pci.c linux-2.0.39-pre5/drivers/pci/pci.c
--- linux-2.0.39-pre4/drivers/pci/pci.c	1999-06-13 10:21:02.000000000 -0700
+++ linux-2.0.39-pre5/drivers/pci/pci.c	2003-08-15 15:04:57.000000000 -0700
@@ -210,6 +210,7 @@
 	DEVICE( MOTOROLA,	MOTOROLA_MPC106,"MPC106 Grackle"),
 	DEVICE( MOTOROLA,	MOTOROLA_RAVEN,	"Raven"),
 	DEVICE( PROMISE,	PROMISE_20246,	"IDE UltraDMA/33"),
+	DEVICE(	PROMISE,	PROMISE_20262,	"IDE UltraDMA/66"),
 	DEVICE( PROMISE,	PROMISE_5300,	"DC5030"),
 	DEVICE( N9,		N9_I128,	"Imagine 128"),
 	DEVICE( N9,		N9_I128_2,	"Imagine 128v2"),
@@ -271,8 +272,8 @@
 	DEVICE( WINBOND,	WINBOND_82C105,	"SL82C105"),
 	DEVICE( WINBOND,	WINBOND_83C553,	"W83C553"),
 	DEVICE( DATABOOK,      	DATABOOK_87144,	"DB87144"),
-	DEVICE( PLX,        PLX_SPCOM200, "SPCom 200 PCI serial I/O"),
-	DEVICE( PLX,        PLX_9050,   "PLX9050 PCI <-> IOBus Bridge"),
+	DEVICE( PLX,		PLX_SPCOM200,	"SPCom 200 PCI serial I/O"),
+	DEVICE( PLX,		PLX_9050,	"PLX9050 PCI <-> IOBus Bridge"),
 	DEVICE( PLX,		PLX_9080,	"PCI9080 I2O"),
 	DEVICE( MADGE,		MADGE_MK2,	"Smart 16/4 BM Mk2 Ringnode"),
 	DEVICE( 3COM,		3COM_3C339,	"3C339 TokenRing"),
@@ -297,11 +298,14 @@
 	DEVICE( AL,		AL_M1523,	"M1523"),
 	DEVICE( AL,		AL_M1531,	"M1531 Aladdin IV"),
 	DEVICE( AL,		AL_M1533,	"M1533 Aladdin IV"),
+	DEVICE(	AL,		AL_M1541,	"M1541 Aladdin V"),
+	DEVICE(	AL,		AL_M1543,	"M1543 Aladdin V"),
 	DEVICE( AL,		AL_M3307,	"M3307 MPEG-1 decoder"),
 	DEVICE( AL,		AL_M4803,	"M4803"),
 	DEVICE( AL,		AL_M5219,	"M5219"),
 	DEVICE( AL,		AL_M5229,	"M5229 TXpro"),
 	DEVICE( AL,		AL_M5237,	"M5237 USB"),
+	DEVICE( AL,		AL_M7101,	"M7101 PMU"),
 	DEVICE( SURECOM,	SURECOM_NE34,	"NE-34PCI LAN"),
 	DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070"),
 	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
@@ -489,7 +493,7 @@
 	DEVICE( S3,		S3_ViRGE_MXP,	"ViRGE/MX+"),
 	DEVICE( S3,		S3_ViRGE_MXPMV,	"ViRGE/MX+MV"),
 	DEVICE( S3,		S3_SONICVIBES,	"SonicVibes"),
-	DEVICE( DCI,    DCI_PCCOM4,     "PC COM PCI Bus 4 port serial Adapter"),
+	DEVICE( DCI,		DCI_PCCOM4,	"PC COM PCI Bus 4 port serial Adapter"),
 	DEVICE( INTEL,		INTEL_82375,	"82375EB"),
 	BRIDGE( INTEL,		INTEL_82424,	"82424ZX Saturn",	0x00),
 	DEVICE( INTEL,		INTEL_82378,	"82378IB"),
diff -urN linux-2.0.39-pre4/fs/binfmt_elf.c linux-2.0.39-pre5/fs/binfmt_elf.c
--- linux-2.0.39-pre4/fs/binfmt_elf.c	2003-08-15 15:04:57.000000000 -0700
+++ linux-2.0.39-pre5/fs/binfmt_elf.c	2003-08-15 15:04:57.000000000 -0700
@@ -55,6 +55,19 @@
 #define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_EXEC_PAGESIZE-1))
 #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_EXEC_PAGESIZE-1))
 
+/* Amount to offset dynamic executables, such as glibc 2.x's ld.so when 
+ * used from command line.
+ *   Loading at 0x00000000 is not appropriate since it means 
+ * null-pointer-dereferences are not caught. (and obstructs vm86 use.)
+ *   Loading low in general is bad for ld.so, since it or the heap may 
+ * collide with the second executable it loads.
+ *   Loading near MMAP_SEARCH_START is even worse, since the heap will 
+ * start after the executable, and quickly be occluded by shared 
+ * libraries, etc.
+ *   So we load in the top third of virtual memory.
+ */
+#define DYNAMIC_BIAS  PAGE_ALIGN((TASK_SIZE/3)*2)
+
 static struct linux_binfmt elf_format =
 {
 #ifndef MODULE
@@ -557,7 +570,6 @@
 	current->mm->end_code = 0;
 	current->mm->start_mmap = ELF_START_MMAP;
 	current->mm->mmap = NULL;
-	elf_entry = (unsigned long) elf_ex.e_entry;
 
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
@@ -565,6 +577,19 @@
 	bprm->p = setup_arg_pages(bprm->p, bprm);
 	current->mm->start_stack = bprm->p;
 
+	/* Bias dynamic executables so they are not loaded at 
+         * 0x00000000.  See comment at DYNAMIC_BIAS define.
+         */
+	if (elf_ex.e_type == ET_DYN)
+        {
+		for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
+			elf_ppnt->p_vaddr += DYNAMIC_BIAS;
+		}
+		elf_ex.e_entry += DYNAMIC_BIAS;
+        }
+
+	elf_entry = (unsigned long) elf_ex.e_entry;
+
 	/* Now we do a little grungy work by mmaping the ELF image into
 	   the correct location in memory.  At this point, we assume that
 	   the image should be loaded at fixed address, not at a variable
diff -urN linux-2.0.39-pre4/fs/ext2/balloc.c linux-2.0.39-pre5/fs/ext2/balloc.c
--- linux-2.0.39-pre4/fs/ext2/balloc.c	2003-08-15 15:04:57.000000000 -0700
+++ linux-2.0.39-pre5/fs/ext2/balloc.c	2003-08-15 15:04:57.000000000 -0700
@@ -205,7 +205,7 @@
 	 */
 	if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
 	    sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
-	    sb->u.ext2_sb.s_block_bitmap[block_group]) {
+	    sb->u.ext2_sb.s_block_bitmap[0]) {
 		slot = 0;
 	}
 	/*
diff -urN linux-2.0.39-pre4/fs/smbfs/sock.c linux-2.0.39-pre5/fs/smbfs/sock.c
--- linux-2.0.39-pre4/fs/smbfs/sock.c	1997-09-15 10:02:41.000000000 -0700
+++ linux-2.0.39-pre5/fs/smbfs/sock.c	2003-08-15 15:04:57.000000000 -0700
@@ -64,12 +64,33 @@
 	return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);
 }
 
+struct data_callback {
+	struct tq_struct cb;
+	struct sock *sk;
+};
+/*
+ * N.B. What happens if we're in here when the socket closes??
+ */
 static void
-smb_data_callback(struct sock *sk, int len)
+found_data(struct sock *sk)
 {
-	struct socket *sock = sk->socket;
+	/*
+	 * FIXME: copied from sock_def_readable, it should be a call to
+	 * server->data_ready();
+	 */
+	if (!sk->dead) {
+		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket, 1);
+	}
+}
 
-	if (!sk->dead)
+static void
+smb_data_callback(void *ptr)
+{
+	struct data_callback *job = ptr;
+	struct socket *sock = job->sk->socket;
+
+	if (!job->sk->dead)
 	{
 		unsigned char peek_buf[4];
 		int result;
@@ -101,11 +122,27 @@
 		set_fs(fs);
 
 		if (result != -EAGAIN)
-		{
-			wake_up_interruptible(sk->sleep);
-		}
+			found_data(job->sk);
 	}
+	kfree(ptr);
 }
+static void
+smb_data_ready(struct sock *sk, int len)
+{
+	struct data_callback *job;
+	job = kmalloc(sizeof(struct data_callback), GFP_ATOMIC);
+	if (job == 0) {
+		printk("smb_data_ready(): lost SESSION KEEPALIVE due to OOM.\n");
+		found_data(sk);
+		return;
+	}
+	job->cb.next = NULL;
+	job->cb.sync = 0;
+	job->cb.routine = smb_data_callback;
+	job->cb.data = job;
+	job->sk = sk;
+	queue_task(&job->cb, &tq_scheduler);
+ }
 
 int
 smb_catch_keepalive(struct smb_server *server)
@@ -113,6 +150,7 @@
 	struct file *file;
 	struct inode *inode;
 	struct socket *sock;
+	void *data_ready;
 	struct sock *sk;
 
 	if ((server == NULL)
@@ -143,15 +181,18 @@
 	DDPRINTK("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n",
 		 (unsigned int) (sk->data_ready),
 		 (unsigned int) (server->data_ready));
-
-	if (sk->data_ready == smb_data_callback)
-	{
-		printk("smb_catch_keepalive: already done\n");
+        /*
+         * Install the callback atomically to avoid races ...
+         */
+        data_ready = xchg(&sk->data_ready, smb_data_ready);
+        if (data_ready != smb_data_ready)
+        {
+                server->data_ready = data_ready;
+                return 0;
+        } else {
+                printk("smb_catch_keepalive: already done\n");
 		return -EINVAL;
 	}
-	server->data_ready = sk->data_ready;
-	sk->data_ready = smb_data_callback;
-	return 0;
 }
 
 int
@@ -160,6 +201,7 @@
 	struct file *file;
 	struct inode *inode;
 	struct socket *sock;
+	void *data_ready;
 	struct sock *sk;
 
 	if ((server == NULL)
@@ -191,18 +233,20 @@
 		       "server->data_ready == NULL\n");
 		return -EINVAL;
 	}
-	if (sk->data_ready != smb_data_callback)
+	/*
+ 	 * Restore the original callback atomically to avoid races ...
+	 */
+	data_ready = xchg(&sk->data_ready, server->data_ready);
+	server->data_ready = NULL;
+	if (data_ready != smb_data_ready)
 	{
 		printk("smb_dont_catch_keepalive: "
-		       "sk->data_callback != smb_data_callback\n");
+		"sk->data_ready != smb_data_ready\n");
 		return -EINVAL;
 	}
 	DDPRINTK("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n",
 		 (unsigned int) (sk->data_ready),
 		 (unsigned int) (server->data_ready));
-
-	sk->data_ready = server->data_ready;
-	server->data_ready = NULL;
 	return 0;
 }
 
diff -urN linux-2.0.39-pre4/include/linux/ali_ide_dma.h linux-2.0.39-pre5/include/linux/ali_ide_dma.h
--- linux-2.0.39-pre4/include/linux/ali_ide_dma.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.0.39-pre5/include/linux/ali_ide_dma.h	2003-08-15 15:04:57.000000000 -0700
@@ -0,0 +1,210 @@
+/* Aladdin 5229 timings display header file for triton.c.
+   Copyright (c) 1998-99 Michel Aubry
+   Copyright (c) 1999 Andre Hedrick
+*/
+
+
+static int ali_get_info(char *, char **, off_t, int, int);
+
+static struct proc_dir_entry ali_proc_entry = {
+  0, 3, "ali", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, ali_get_info
+};
+
+/* we save bus, function of chipset here for further debug use */
+static byte bmide_bus, bmide_fn;
+
+static char *fifo[4] = {
+	"FIFO Off",
+	"FIFO On ",
+	"DMA mode",
+	"PIO mode"
+};
+
+static char *udmaT[8] = {
+	"1.5T",
+	"  2T",
+	"2.5T",
+	"  3T",
+	"3.5T",
+	"  4T",
+	"  6T",
+	"  8T"
+};
+
+char *channel_status[8] = {
+	"OK            ",
+	"busy          ",
+	"DRQ           ",
+	"DRQ busy      ",
+	"error         ",
+	"error busy    ",
+	"error DRQ     ",
+	"error DRQ busy"
+};
+
+static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy)
+{
+	byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1;
+	unsigned int bibma;
+	byte c0, c1;
+	byte rev, tmp;
+	char *p = buffer;
+	char *q;
+
+	/* fetch rev. */
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x08, &rev);
+	if (rev >= 0xc1)	/* M1543C or newer */
+		udmaT[7] = " ???";
+	else
+		fifo[3]  = "   ???  ";
+
+	/* first fetch bibma: */
+	pcibios_read_config_dword(bmide_bus, bmide_fn, 0x20, &bibma);
+	bibma = (bibma & 0xfff0) ;
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte
+	 * registers to investigate:
+	 */
+	c0 = inb((unsigned short)bibma + 0x02);
+	c1 = inb((unsigned short)bibma + 0x0a);
+
+	p += sprintf(p,
+		"\n                                Ali M15x3 Chipset.\n");
+	p += sprintf(p,
+		"                                ------------------\n");
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x78, &reg53h);
+	p += sprintf(p, "PCI Clock: %d.\n", reg53h);
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x53, &reg53h);
+	p += sprintf(p,
+		"CD_ROM FIFO:%s, CD_ROM DMA:%s\n",
+		(reg53h & 0x02) ? "Yes" : "No ",
+		(reg53h & 0x01) ? "Yes" : "No " );
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x74, &reg53h);
+	p += sprintf(p,
+		"FIFO Status: contains %d Words, runs%s%s\n\n",
+		(reg53h & 0x3f),
+		(reg53h & 0x40) ? " OVERWR" : "",
+		(reg53h & 0x80) ? " OVERRD." : "." );
+
+	p += sprintf(p,
+		"-------------------primary channel-------------------secondary channel---------\n\n");
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x09, &reg53h);
+	p += sprintf(p,
+		"channel status:       %s                               %s\n",
+		(reg53h & 0x20) ? "On " : "Off",
+		(reg53h & 0x10) ? "On " : "Off" );
+
+	p += sprintf(p,
+		"both channels togth:  %s                               %s\n",
+		(c0&0x80) ? "No " : "Yes",
+		(c1&0x80) ? "No " : "Yes" );
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x76, &reg53h);
+	p += sprintf(p,
+		"Channel state:        %s                    %s\n",
+		channel_status[reg53h & 0x07],
+		channel_status[(reg53h & 0x70) >> 4] );
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x58, &reg5xh);
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x5c, &reg5yh);
+	p += sprintf(p,
+		"Add. Setup Timing:    %dT                                %dT\n",
+		(reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
+		(reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x59, &reg5xh);
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x5d, &reg5yh);
+	p += sprintf(p,
+		"Command Act. Count:   %dT                                %dT\n"
+		"Command Rec. Count:   %dT                               %dT\n\n",
+		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, 
+		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );
+
+	p += sprintf(p,
+		"----------------drive0-----------drive1------------drive0-----------drive1------\n\n");
+	p += sprintf(p,
+		"DMA enabled:      %s              %s               %s              %s\n",
+		(c0&0x20) ? "Yes" : "No ",
+		(c0&0x40) ? "Yes" : "No ",
+		(c1&0x20) ? "Yes" : "No ",
+		(c1&0x40) ? "Yes" : "No " );
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x54, &reg5xh);
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x55, &reg5yh);
+	q = "FIFO threshold:   %2d Words         %2d Words          %2d Words         %2d Words\n";
+	if (rev < 0xc1) {
+		if ((rev == 0x20) && (pcibios_read_config_byte(bmide_bus, bmide_fn, 0x4f, &tmp), (tmp &= 0x20))) {
+			p += sprintf(p, q, 8, 8, 8, 8);
+		} else {
+			p += sprintf(p, q,
+				(reg5xh & 0x03) + 12,
+				((reg5xh & 0x30)>>4) + 12,
+				(reg5yh & 0x03) + 12,
+				((reg5yh & 0x30)>>4) + 12 );
+		}
+	} else {
+		p += sprintf(p, q,
+			(tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4,
+			(tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4,
+			(tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4,
+			(tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4 );
+	}
+
+#if 0
+	p += sprintf(p, 
+		"FIFO threshold:   %2d Words         %2d Words          %2d Words         %2d Words\n",
+		(reg5xh & 0x03) + 12,
+		((reg5xh & 0x30)>>4) + 12,
+		(reg5yh & 0x03) + 12,
+		((reg5yh & 0x30)>>4) + 12 );
+#endif
+
+	p += sprintf(p,
+		"FIFO mode:        %s         %s          %s         %s\n",
+		fifo[((reg5xh & 0x0c) >> 2)],
+		fifo[((reg5xh & 0xc0) >> 6)],
+		fifo[((reg5yh & 0x0c) >> 2)],
+		fifo[((reg5yh & 0xc0) >> 6)] );
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x5a, &reg5xh);
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x5b, &reg5xh1);
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x5e, &reg5yh);
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x5f, &reg5yh1);
+
+	p += sprintf(p,/*
+		"------------------drive0-----------drive1------------drive0-----------drive1------\n")*/
+		"Dt RW act. Cnt    %dT               %dT                %dT               %dT\n"
+		"Dt RW rec. Cnt    %2dT              %2dT               %2dT              %2dT\n\n",
+		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+		(reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
+		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
+		(reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,
+		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+		(reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,
+		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,
+		(reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
+
+	p += sprintf(p,
+		"-----------------------------------UDMA Timings--------------------------------\n\n");
+
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x56, &reg5xh);
+	pcibios_read_config_byte(bmide_bus, bmide_fn, 0x57, &reg5yh);
+	p += sprintf(p,
+		"UDMA:             %s               %s                %s               %s\n"
+		"UDMA timings:     %s             %s              %s             %s\n\n",
+		(reg5xh & 0x08) ? "OK" : "No",
+		(reg5xh & 0x80) ? "OK" : "No",
+		(reg5yh & 0x08) ? "OK" : "No",
+		(reg5yh & 0x80) ? "OK" : "No",
+		udmaT[(reg5xh & 0x07)],
+		udmaT[(reg5xh & 0x70) >> 4],
+		udmaT[reg5yh & 0x07],
+		udmaT[(reg5yh & 0x70) >> 4] );
+
+	return p-buffer; /* => must be less than 4k! */
+}
+
diff -urN linux-2.0.39-pre4/include/linux/cyclades.h linux-2.0.39-pre5/include/linux/cyclades.h
--- linux-2.0.39-pre4/include/linux/cyclades.h	1999-06-13 10:21:04.000000000 -0700
+++ linux-2.0.39-pre5/include/linux/cyclades.h	2003-08-15 15:04:57.000000000 -0700
@@ -490,7 +490,20 @@
 /****************** ****************** *******************/
 #endif
 
+/* Per card data structure */
+struct cyclades_card {
+    long base_addr;
+    long ctl_addr;
+    int irq;
+    int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
+    int first_line;	/* minor number of first channel on card */
+    int bus_index;	/* address shift - 0 for ISA, 1 for PCI */
+    int	intr_enabled;	/* FW Interrupt flag - 0 disabled, 1 enabled */
+};
 
+struct cyclades_chip {
+  int filler;
+};
 
 
 #ifdef __KERNEL__
@@ -508,22 +521,6 @@
 #define cy_readw(port)  readw(port)
 #define cy_readl(port)  readl(port)
 
-/* Per card data structure */
-
-struct cyclades_card {
-    long base_addr;
-    long ctl_addr;
-    int irq;
-    int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
-    int first_line;	/* minor number of first channel on card */
-    int bus_index;	/* address shift - 0 for ISA, 1 for PCI */
-    int	inact_ctrl;	/* FW Inactivity control - 0 disabled, 1 enabled */
-};
-
-struct cyclades_chip {
-  int filler;
-};
-
 /*
  * This is our internal structure for each serial port's state.
  * 
@@ -567,16 +564,16 @@
 	int			xmit_cnt;
         int                     default_threshold;
         int                     default_timeout;
-	struct tq_struct	tqueue;
+	unsigned long		jiffies[3];
+	unsigned long		rflush_count;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
+        struct cyclades_monitor mon;
+	struct cyclades_idle_stats   idle_stats;
+	struct tq_struct	tqueue;
 	struct wait_queue	*open_wait;
 	struct wait_queue	*close_wait;
 	struct wait_queue	*shutdown_wait;
-        struct cyclades_monitor mon;
-	unsigned long		jiffies[3];
-	unsigned long		rflush_count;
-	struct cyclades_idle_stats   idle_stats;
 };
 
 /*
diff -urN linux-2.0.39-pre4/include/linux/major.h linux-2.0.39-pre5/include/linux/major.h
--- linux-2.0.39-pre4/include/linux/major.h	1999-06-13 10:21:04.000000000 -0700
+++ linux-2.0.39-pre5/include/linux/major.h	2003-08-15 15:04:57.000000000 -0700
@@ -68,6 +68,10 @@
 #define DAC960_MAJOR	48	/* 48..55 */
 #define RISCOM8_CALLOUT_MAJOR 49
 #define MKISS_MAJOR	55
+
+#define IDE4_MAJOR	56
+#define IDE5_MAJOR	57
+
 #define APBLOCK_MAJOR   60   /* AP1000 Block device */
 #define DDV_MAJOR       61   /* AP1000 DDV block device */
 
diff -urN linux-2.0.39-pre4/include/linux/pci.h linux-2.0.39-pre5/include/linux/pci.h
--- linux-2.0.39-pre4/include/linux/pci.h	1999-06-13 10:21:04.000000000 -0700
+++ linux-2.0.39-pre5/include/linux/pci.h	2003-08-15 15:04:57.000000000 -0700
@@ -451,6 +451,7 @@
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
 #define PCI_DEVICE_ID_PROMISE_20246	0x4d33
+#define PCI_DEVICE_ID_PROMISE_20262	0x4d38
 #define PCI_DEVICE_ID_PROMISE_5300	0x5300
 
 #define PCI_VENDOR_ID_N9		0x105d
@@ -558,7 +559,7 @@
 #define PCI_DEVICE_ID_DATABOOK_87144	0xb106
 
 #define PCI_VENDOR_ID_PLX		0x10b5
-#define PCI_DEVICE_ID_PLX_9050      0x9050
+#define PCI_DEVICE_ID_PLX_9050		0x9050
 #define PCI_DEVICE_ID_PLX_9080		0x9080
 
 #define PCI_DEVICE_ID_PLX_SPCOM200  0x1103
@@ -593,6 +594,8 @@
 #define PCI_DEVICE_ID_AL_M1523		0x1523
 #define PCI_DEVICE_ID_AL_M1531		0x1531
 #define PCI_DEVICE_ID_AL_M1533		0x1533
+#define PCI_DEVICE_ID_AL_M1541		0x1541
+#define PCI_DEVICE_ID_AL_M1543		0x1543
 #define PCI_DEVICE_ID_AL_M3307		0x3307
 #define PCI_DEVICE_ID_AL_M4803		0x5215
 #define PCI_DEVICE_ID_AL_M5219		0x5219
diff -urN linux-2.0.39-pre4/init/main.c linux-2.0.39-pre5/init/main.c
--- linux-2.0.39-pre4/init/main.c	1999-06-13 10:21:04.000000000 -0700
+++ linux-2.0.39-pre5/init/main.c	2003-08-15 15:04:57.000000000 -0700
@@ -653,6 +653,10 @@
 		{ "hdf",     0x2140 },
 		{ "hdg",     0x2200 },
 		{ "hdh",     0x2240 },
+		{ "hdi",     0x3800 },
+		{ "hdj",     0x3840 },
+		{ "hdk",     0x3900 },
+		{ "hdl",     0x3940 },
 		{ "sda",     0x0800 },
 		{ "sdb",     0x0810 },
 		{ "sdc",     0x0820 },
diff -urN linux-2.0.39-pre4/MAINTAINERS linux-2.0.39-pre5/MAINTAINERS
--- linux-2.0.39-pre4/MAINTAINERS	2003-08-15 15:04:57.000000000 -0700
+++ linux-2.0.39-pre5/MAINTAINERS	2003-08-15 15:04:57.000000000 -0700
@@ -251,14 +251,15 @@
 S:	Maintained
 
 IDE DRIVER [GENERAL]
-P:	Mark Lord
-M:	mlord@pobox.com
+P:	Andre Hedrick
+M:	andre@linux-ide.org
 L:	linux-kernel@vger.rutgers.edu
-S:	Maintained
+W:	http://linux.kernel.org/pub/linux/kernel/people/hedrick/
+S:	Supported
 
 IDE/ATAPI CDROM DRIVER 
 P:	Jens Axboe
-M:	axboe@image.dk
+M:	axboe@suse.de
 L:	linux-kernel@vger.rutgers.edu
 W:	http://www.kernel.dk
 S:	Maintained
