## Automatically generated incremental diff
## From:   linux-2.4.18-pre1
## To:     linux-2.4.18-pre2
## Robot:  $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $

diff -urN linux-2.4.18-pre1/Documentation/sonypi.txt linux/Documentation/sonypi.txt
--- linux-2.4.18-pre1/Documentation/sonypi.txt	Fri Dec 21 09:41:53 2001
+++ linux/Documentation/sonypi.txt	Mon Jan  7 16:42:52 2002
@@ -25,7 +25,8 @@
 can be downloaded at: <http://www.alcove-labs.org/en/software/sonypi/>
 
 This driver supports also some ioctl commands for setting the LCD screen
-brightness (some more commands may be added in the future).
+brightness and querying the batteries charge information (some more 
+commands may be added in the future).
 
 This driver can also be used to set the camera controls on Picturebook series
 (brightness, contrast etc), and is used by the video4linux driver for the 
diff -urN linux-2.4.18-pre1/MAINTAINERS linux/MAINTAINERS
--- linux-2.4.18-pre1/MAINTAINERS	Mon Jan  7 16:42:51 2002
+++ linux/MAINTAINERS	Mon Jan  7 16:42:52 2002
@@ -1150,8 +1150,8 @@
 S:	Maintained
 
 OPL3-SA2, SA3, and SAx DRIVER
-P:	Scott Murray
-M:	scott@spiteful.org
+P:	Zwane Mwaikambo
+M:	zwane@commfireservices.com
 L:	linux-sound@vger.kernel.org
 S:	Maintained
 
@@ -1259,6 +1259,12 @@
 L:	linux-kernel@vger.kernel.org
 W:	http://www.alarsen.net/linux/qnx4fs/
 S:	Maintained
+
+RADEON FRAMEBUFFER DISPLAY DRIVER
+P:	Ani Joshi
+M:	ajoshi@shell.unixbox.com
+L:      linux-fbdev-devel@lists.sourceforge.net
+S:      Maintained
 
 RAGE128 FRAMEBUFFER DISPLAY DRIVER
 P:	Ani Joshi
diff -urN linux-2.4.18-pre1/Makefile linux/Makefile
--- linux-2.4.18-pre1/Makefile	Mon Jan  7 16:42:51 2002
+++ linux/Makefile	Mon Jan  7 16:42:52 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 18
-EXTRAVERSION = pre1
+EXTRAVERSION = pre2
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -204,7 +204,7 @@
 	drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \
 	drivers/scsi/aic7xxx/aicasm/y.tab.h \
 	drivers/scsi/aic7xxx/aicasm/aicasm \
-	drivers/scsi/53c700-mem.c \
+	drivers/scsi/53c700_d.h \
 	net/khttpd/make_times_h \
 	net/khttpd/times.h \
 	submenu*
diff -urN linux-2.4.18-pre1/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- linux-2.4.18-pre1/arch/alpha/kernel/alpha_ksyms.c	Fri Dec 21 09:41:53 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Mon Jan  7 16:42:52 2002
@@ -109,6 +109,7 @@
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(__memsetw);
diff -urN linux-2.4.18-pre1/arch/alpha/kernel/pci-noop.c linux/arch/alpha/kernel/pci-noop.c
--- linux-2.4.18-pre1/arch/alpha/kernel/pci-noop.c	Thu Sep 13 15:21:32 2001
+++ linux/arch/alpha/kernel/pci-noop.c	Mon Jan  7 16:42:52 2002
@@ -104,21 +104,23 @@
 }
 /* stubs for the routines in pci_iommu.c */
 void *
-pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
+pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
 {
+	return (void *)0;
 }
 void
-pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr,
+pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
 		    dma_addr_t dma_addr)
 {
 }
 dma_addr_t
-pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size,
+pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
 	       int direction)
 {
+	return (dma_addr_t)0;
 }
 void
-pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
+pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
 		 int direction)
 {
 }
@@ -126,6 +128,7 @@
 pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
 	   int direction)
 {
+	return 0;
 }
 void
 pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
diff -urN linux-2.4.18-pre1/arch/alpha/kernel/pci_iommu.c linux/arch/alpha/kernel/pci_iommu.c
--- linux-2.4.18-pre1/arch/alpha/kernel/pci_iommu.c	Mon Nov  5 09:47:41 2001
+++ linux/arch/alpha/kernel/pci_iommu.c	Mon Jan  7 16:42:52 2002
@@ -215,12 +215,20 @@
 	/* If the machine doesn't define a pci_tbi routine, we have to
 	   assume it doesn't support sg mapping.  */
 	if (! alpha_mv.mv_pci_tbi) {
-		printk(KERN_WARNING "pci_map_single failed: no hw sg\n");
-		return 0;
+		static int been_here = 0;
+		if (!been_here) {
+		    printk(KERN_WARNING "pci_map_single: no hw sg, using "
+			   "direct map when possible\n");
+		    been_here = 1;
+		}
+		if (paddr + size <= __direct_map_size)
+		    return (paddr + __direct_map_base);
+		else
+		    return 0;
 	}
 		
 	arena = hose->sg_pci;
-	if (!arena || arena->dma_base + arena->size > max_dma)
+	if (!arena || arena->dma_base + arena->size - 1 > max_dma)
 		arena = hose->sg_isa;
 
 	npages = calc_npages((paddr & ~PAGE_MASK) + size);
@@ -247,20 +255,27 @@
 dma_addr_t
 pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
 {
+	int dac_allowed; 
+
 	if (dir == PCI_DMA_NONE)
 		BUG();
-	return pci_map_single_1(pdev, cpu_addr, size,
-				pdev ? (pdev->dma_mask >> 32) != 0 : 0);
+
+	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
+	return pci_map_single_1(pdev, cpu_addr, size, dac_allowed);
 }
 
 dma_addr_t
 pci_map_page(struct pci_dev *pdev, struct page *page, unsigned long offset,
 	     size_t size, int dir)
 {
+	int dac_allowed;
+
 	if (dir == PCI_DMA_NONE)
 		BUG();
-	return pci_map_single_1(pdev, (char *)page_address(page) + offset,
-			        size, pdev ? (pdev->dma_mask >> 32) != 0 : 0);
+
+	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
+	return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
+				size, dac_allowed);
 }
 
 /* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
@@ -558,7 +573,7 @@
 	if (direction == PCI_DMA_NONE)
 		BUG();
 
-	dac_allowed = ((pdev->dma_mask >> 32) != 0);
+	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
 
 	/* Fast path single entry scatterlists.  */
 	if (nents == 1) {
@@ -580,7 +595,7 @@
 		hose = pdev ? pdev->sysdata : pci_isa_hose;
 		max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
 		arena = hose->sg_pci;
-		if (!arena || arena->dma_base + arena->size > max_dma)
+		if (!arena || arena->dma_base + arena->size - 1 > max_dma)
 			arena = hose->sg_isa;
 	} else {
 		max_dma = -1;
@@ -643,7 +658,7 @@
 	hose = pdev ? pdev->sysdata : pci_isa_hose;
 	max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
 	arena = hose->sg_pci;
-	if (!arena || arena->dma_base + arena->size > max_dma)
+	if (!arena || arena->dma_base + arena->size - 1 > max_dma)
 		arena = hose->sg_isa;
 
 	fbeg = -1, fend = 0;
@@ -710,11 +725,10 @@
 	struct pci_iommu_arena *arena;
 
 	/* If there exists a direct map, and the mask fits either
-	   MAX_DMA_ADDRESS defined such that GFP_DMA does something
-	   useful, or the total system memory as shifted by the
-	   map base.  */
+	   the entire direct mapped space or the total system memory as
+	   shifted by the map base */
 	if (__direct_map_size != 0
-	    && (__direct_map_base + MAX_DMA_ADDRESS-IDENT_ADDR-1 <= mask
+	    && (__direct_map_base + __direct_map_size - 1 <= mask
 		|| __direct_map_base + (max_low_pfn<<PAGE_SHIFT)-1 <= mask))
 		return 1;
 
diff -urN linux-2.4.18-pre1/arch/alpha/lib/dec_and_lock.c linux/arch/alpha/lib/dec_and_lock.c
--- linux-2.4.18-pre1/arch/alpha/lib/dec_and_lock.c	Fri Nov  9 13:39:57 2001
+++ linux/arch/alpha/lib/dec_and_lock.c	Mon Jan  7 16:42:52 2002
@@ -27,6 +27,7 @@
 	br	$atomic_dec_and_lock_1..ng	\n\
 	.subsection 2				\n\
 4:	br	1b				\n\
+	.previous				\n\
 	.end atomic_dec_and_lock");
 
 static int __attribute__((unused))
diff -urN linux-2.4.18-pre1/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- linux-2.4.18-pre1/arch/i386/kernel/apic.c	Fri Nov  9 14:12:55 2001
+++ linux/arch/i386/kernel/apic.c	Mon Jan  7 16:42:52 2002
@@ -56,6 +56,14 @@
 	maxlvt = get_maxlvt();
 
 	/*
+	 * Masking an LVT entry on a P6 can trigger a local APIC error
+	 * if the vector is zero. Mask LVTERR first to prevent this.
+	 */
+	if (maxlvt >= 3) {
+		v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
+		apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
+	}
+	/*
 	 * Careful: we have to set masks only first to deassert
 	 * any level-triggered sources.
 	 */
@@ -65,10 +73,6 @@
 	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
 	v = apic_read(APIC_LVT1);
 	apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
-	if (maxlvt >= 3) {
-		v = apic_read(APIC_LVTERR);
-		apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
-	}
 	if (maxlvt >= 4) {
 		v = apic_read(APIC_LVTPC);
 		apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
@@ -84,6 +88,8 @@
 		apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
 	if (maxlvt >= 4)
 		apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
+	apic_write(APIC_ESR, 0);
+	v = apic_read(APIC_ESR);
 }
 
 void __init connect_bsp_APIC(void)
@@ -480,6 +486,7 @@
 	l &= ~MSR_IA32_APICBASE_BASE;
 	l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
 	wrmsr(MSR_IA32_APICBASE, l, h);
+	apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
 	apic_write(APIC_ID, apic_pm_state.apic_id);
 	apic_write(APIC_DFR, apic_pm_state.apic_dfr);
 	apic_write(APIC_LDR, apic_pm_state.apic_ldr);
@@ -487,15 +494,15 @@
 	apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
 	apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
 	apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
+	apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+	apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
+	apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
+	apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
 	apic_write(APIC_ESR, 0);
 	apic_read(APIC_ESR);
 	apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);
 	apic_write(APIC_ESR, 0);
 	apic_read(APIC_ESR);
-	apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
-	apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
-	apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
-	apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
 	__restore_flags(flags);
 	if (apic_pm_state.perfctr_pmdev)
 		pm_send(apic_pm_state.perfctr_pmdev, PM_RESUME, data);
diff -urN linux-2.4.18-pre1/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-2.4.18-pre1/drivers/block/ll_rw_blk.c	Mon Oct 29 12:11:17 2001
+++ linux/drivers/block/ll_rw_blk.c	Mon Jan  7 16:42:53 2002
@@ -694,8 +694,10 @@
 	switch (el_ret) {
 
 		case ELEVATOR_BACK_MERGE:
-			if (!q->back_merge_fn(q, req, bh, max_segments))
+			if (!q->back_merge_fn(q, req, bh, max_segments)) {
+				insert_here = &req->queue;
 				break;
+			}
 			elevator->elevator_merge_cleanup_fn(q, req, count);
 			req->bhtail->b_reqnext = bh;
 			req->bhtail = bh;
@@ -706,8 +708,10 @@
 			goto out;
 
 		case ELEVATOR_FRONT_MERGE:
-			if (!q->front_merge_fn(q, req, bh, max_segments))
+			if (!q->front_merge_fn(q, req, bh, max_segments)) {
+				insert_here = req->queue.prev;
 				break;
+			}
 			elevator->elevator_merge_cleanup_fn(q, req, count);
 			bh->b_reqnext = req->bh;
 			req->bh = bh;
diff -urN linux-2.4.18-pre1/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h
--- linux-2.4.18-pre1/drivers/char/agp/agp.h	Fri Nov  9 14:01:21 2001
+++ linux/drivers/char/agp/agp.h	Mon Jan  7 16:42:53 2002
@@ -179,6 +179,9 @@
 #ifndef PCI_DEVICE_ID_INTEL_820_0
 #define PCI_DEVICE_ID_INTEL_820_0       0x2500
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_820_UP_0
+#define PCI_DEVICE_ID_INTEL_820_UP_0    0x2501
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_840_0
 #define PCI_DEVICE_ID_INTEL_840_0		0x1a21
 #endif
@@ -189,7 +192,7 @@
 #define PCI_DEVICE_ID_INTEL_850_0     0x2530
 #endif
 #ifndef PCI_DEVICE_ID_INTEL_860_0
-#define PCI_DEVICE_ID_INTEL_860_0	0x2532
+#define PCI_DEVICE_ID_INTEL_860_0     0x2531
 #endif
 #ifndef PCI_DEVICE_ID_INTEL_810_DC100_0
 #define PCI_DEVICE_ID_INTEL_810_DC100_0 0x7122
@@ -275,6 +278,9 @@
 #define I830_RDRAM_CHANNEL_TYPE    0x03010
 #define I830_RDRAM_ND(x)           (((x) & 0x20) >> 5)
 #define I830_RDRAM_DDT(x)          (((x) & 0x18) >> 3)
+
+/* This one is for I830MP w. an external graphic card */
+#define INTEL_I830_ERRSTS          0x92
 
 /* intel i820 registers */
 #define INTEL_I820_RDCR     0x51
diff -urN linux-2.4.18-pre1/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c
--- linux-2.4.18-pre1/drivers/char/agp/agpgart_be.c	Fri Dec 21 09:41:53 2001
+++ linux/drivers/char/agp/agpgart_be.c	Mon Jan  7 16:42:53 2002
@@ -1587,6 +1587,40 @@
 	return 0;
 }
 
+static int intel_830mp_configure(void)
+{
+       u32 temp;
+       u16 temp2;
+       aper_size_info_8 *current_size;
+
+       current_size = A_SIZE_8(agp_bridge.current_size);
+
+       /* aperture size */
+       pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+                             current_size->size_value);
+
+       /* address to map to */
+       pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
+       agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+       /* attbase - aperture base */
+       pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE,
+                              agp_bridge.gatt_bus_addr);
+
+       /* agpctrl */
+       pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000);
+
+       /* gmch */
+       pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp2);
+       pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG,
+                             temp2 | (1 << 9));
+       /* clear any possible AGP-related error conditions */
+       pci_write_config_word(agp_bridge.dev, INTEL_I830_ERRSTS, 0x1c);
+       return 0;
+}
+       
+
+
 static int intel_840_configure(void)
 {
 	u32 temp;
@@ -1715,6 +1749,7 @@
 	return 0;
 }
 
+
 static unsigned long intel_mask_memory(unsigned long addr, int type)
 {
 	/* Memory type is ignored */
@@ -1755,6 +1790,14 @@
 	{4, 1024, 0, 63}
 };
 
+static aper_size_info_8 intel_830mp_sizes[4] = 
+{
+  {256, 65536, 6, 0},
+  {128, 32768, 5, 32},
+  {64, 16384, 4, 48},
+  {32, 8192, 3, 56}
+};
+
 static int __init intel_generic_setup (struct pci_dev *pdev)
 {
 	agp_bridge.masks = intel_generic_masks;
@@ -1789,6 +1832,7 @@
 }
 
 
+
 static int __init intel_820_setup (struct pci_dev *pdev)
 {
        agp_bridge.masks = intel_generic_masks;
@@ -1800,7 +1844,7 @@
        agp_bridge.needs_scratch_page = FALSE;
        agp_bridge.configure = intel_820_configure;
        agp_bridge.fetch_size = intel_8xx_fetch_size;
-       agp_bridge.cleanup = intel_cleanup;
+       agp_bridge.cleanup = intel_820_cleanup;
        agp_bridge.tlb_flush = intel_820_tlbflush;
        agp_bridge.mask_memory = intel_mask_memory;
        agp_bridge.agp_enable = agp_generic_agp_enable;
@@ -1819,6 +1863,35 @@
        (void) pdev; /* unused */
 }
 
+static int __init intel_830mp_setup (struct pci_dev *pdev)
+{
+       agp_bridge.masks = intel_generic_masks;
+       agp_bridge.num_of_masks = 1;
+       agp_bridge.aperture_sizes = (void *) intel_830mp_sizes;
+       agp_bridge.size_type = U8_APER_SIZE;
+       agp_bridge.num_aperture_sizes = 4;
+       agp_bridge.dev_private_data = NULL;
+       agp_bridge.needs_scratch_page = FALSE;
+       agp_bridge.configure = intel_830mp_configure;
+       agp_bridge.fetch_size = intel_8xx_fetch_size;
+       agp_bridge.cleanup = intel_8xx_cleanup;
+       agp_bridge.tlb_flush = intel_8xx_tlbflush;
+       agp_bridge.mask_memory = intel_mask_memory;
+       agp_bridge.agp_enable = agp_generic_agp_enable;
+       agp_bridge.cache_flush = global_cache_flush;
+       agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
+       agp_bridge.free_gatt_table = agp_generic_free_gatt_table;
+       agp_bridge.insert_memory = agp_generic_insert_memory;
+       agp_bridge.remove_memory = agp_generic_remove_memory;
+       agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+       agp_bridge.free_by_type = agp_generic_free_by_type;
+       agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+       agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+
+       return 0;
+
+       (void) pdev; /* unused */
+}
 
 static int __init intel_840_setup (struct pci_dev *pdev)
 {
@@ -3572,12 +3645,18 @@
 		"Intel",
 		"i820",
 		intel_820_setup },
+        { PCI_DEVICE_ID_INTEL_820_UP_0,
+                PCI_VENDOR_ID_INTEL,
+                INTEL_I820,
+                "Intel",
+                 "i820",
+                 intel_820_setup },
 	{ PCI_DEVICE_ID_INTEL_830_M_0,
 		PCI_VENDOR_ID_INTEL,
 		INTEL_I830_M,
 		"Intel",
 		"i830M",
-		intel_generic_setup },
+		intel_830mp_setup },
 	{ PCI_DEVICE_ID_INTEL_840_0,
 		PCI_VENDOR_ID_INTEL,
 		INTEL_I840,
@@ -3904,11 +3983,13 @@
 			}
 
 			if (i810_dev == NULL) {
-				printk(KERN_ERR PFX "Detected an "
-					   "Intel 830M, but could not find the"
-					   " secondary device.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return -ENODEV;
+                                /* 
+                                 * We probably have a I830MP chipset
+                                 * with an external graphics
+                                 * card. It will be initialized later 
+                                 */
+				agp_bridge.type = INTEL_I830_M;
+				break;
 			}
 			printk(KERN_INFO PFX "Detected an Intel "
 				   "830M Chipset.\n");
diff -urN linux-2.4.18-pre1/drivers/char/lp.c linux/drivers/char/lp.c
--- linux-2.4.18-pre1/drivers/char/lp.c	Thu Oct 25 00:07:39 2001
+++ linux/drivers/char/lp.c	Mon Jan  7 16:42:53 2002
@@ -650,7 +650,7 @@
 	do {
 		/* Write the data, converting LF->CRLF as we go. */
 		ssize_t canwrite = count;
-		char *lf = strchr (s, '\n');
+		char *lf = memchr (s, '\n', count);
 		if (lf)
 			canwrite = lf - s;
 
diff -urN linux-2.4.18-pre1/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- linux-2.4.18-pre1/drivers/char/ppdev.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/ppdev.c	Mon Jan  7 16:42:53 2002
@@ -324,6 +324,7 @@
 	case PPCLAIM:
 	    {
 		struct ieee1284_info *info;
+		int ret;
 
 		if (pp->flags & PP_CLAIMED) {
 			printk (KERN_DEBUG CHRDEV
@@ -339,7 +340,10 @@
 			}
 		}
 
-		parport_claim_or_block (pp->pdev);
+		ret = parport_claim_or_block (pp->pdev);
+		if (ret < 0)
+			return ret;
+
 		pp->flags |= PP_CLAIMED;
 
 		/* For interrupt-reporting to work, we need to be
diff -urN linux-2.4.18-pre1/drivers/char/sonypi.c linux/drivers/char/sonypi.c
--- linux-2.4.18-pre1/drivers/char/sonypi.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/char/sonypi.c	Mon Jan  7 16:42:53 2002
@@ -109,25 +109,29 @@
         return result;
 }
 
-static void sonypi_ecrset(u16 addr, u16 value) {
+static void sonypi_ecrset(u8 addr, u8 value) {
 
-	wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
-	outw_p(0x81, SONYPI_CST_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(value, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-}
-
-static u16 sonypi_ecrget(u16 addr) {
-
-	wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
-	outw_p(0x80, SONYPI_CST_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	return inw_p(SONYPI_DATA_IOPORT);
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
+	outb_p(0x81, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(value, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+}
+
+static u8 sonypi_ecrget(u8 addr) {
+
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
+	outb_p(0x80, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	return inb_p(SONYPI_DATA_IOPORT);
+}
+
+static u16 sonypi_ecrget16(u8 addr) {
+	return sonypi_ecrget(addr) | (sonypi_ecrget(addr + 1) << 8);
 }
 
 /* Initializes the device - this comes from the AML code in the ACPI bios */
@@ -510,24 +514,60 @@
 static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, 
 			     unsigned int cmd, unsigned long arg) {
 	int ret = 0;
-	u8 val;
+	u8 val8;
+	u16 val16;
 
 	down(&sonypi_device.lock);
 	switch (cmd) {
-		case SONYPI_IOCGBRT:
-			val = sonypi_ecrget(0x96) & 0xff;
-			if (copy_to_user((u8 *)arg, &val, sizeof(val))) {
-				ret = -EFAULT;
-				goto out;
-			}
-			break;
-		case SONYPI_IOCSBRT:
-			if (copy_from_user(&val, (u8 *)arg, sizeof(val))) {
-				ret = -EFAULT;
-				goto out;
-			}
-			sonypi_ecrset(0x96, val);
-			break;
+	case SONYPI_IOCGBRT:
+		val8 = sonypi_ecrget(0x96);
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCSBRT:
+		if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		sonypi_ecrset(0x96, val8);
+		break;
+	case SONYPI_IOCGBAT1CAP:
+		val16 = sonypi_ecrget16(0xb2);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT1REM:
+		val16 = sonypi_ecrget16(0xa2);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT2CAP:
+		val16 = sonypi_ecrget16(0xba);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT2REM:
+		val16 = sonypi_ecrget16(0xaa);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBATFLAGS:
+		val8 = sonypi_ecrget(0x81) & 0x07;
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
 	default:
 		ret = -EINVAL;
 	}
diff -urN linux-2.4.18-pre1/drivers/char/sonypi.h linux/drivers/char/sonypi.h
--- linux-2.4.18-pre1/drivers/char/sonypi.h	Fri Dec 21 09:41:54 2001
+++ linux/drivers/char/sonypi.h	Mon Jan  7 16:42:53 2002
@@ -35,7 +35,7 @@
 #ifdef __KERNEL__
 
 #define SONYPI_DRIVER_MAJORVERSION	1
-#define SONYPI_DRIVER_MINORVERSION	8
+#define SONYPI_DRIVER_MINORVERSION	9
 
 #include <linux/types.h>
 #include <linux/pci.h>
diff -urN linux-2.4.18-pre1/drivers/char/sx.c linux/drivers/char/sx.c
--- linux-2.4.18-pre1/drivers/char/sx.c	Fri Nov  9 14:01:21 2001
+++ linux/drivers/char/sx.c	Mon Jan  7 16:42:53 2002
@@ -1160,7 +1160,8 @@
 				/* DCD went UP */
 				if( (~(port->gs.flags & ASYNC_NORMAL_ACTIVE) || 
 						 ~(port->gs.flags & ASYNC_CALLOUT_ACTIVE)) &&
-						(sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED)) {
+						(sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) &&
+						!(port->gs.tty->termios->c_cflag & CLOCAL) ) {
 					/* Are we blocking in open?*/
 					sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD active, unblocking open\n");
 					wake_up_interruptible(&port->gs.open_wait);
@@ -1170,7 +1171,8 @@
 			} else {
 				/* DCD went down! */
 				if (!((port->gs.flags & ASYNC_CALLOUT_ACTIVE) &&
-				      (port->gs.flags & ASYNC_CALLOUT_NOHUP))) {
+				      (port->gs.flags & ASYNC_CALLOUT_NOHUP)) &&
+				    !(port->gs.tty->termios->c_cflag & CLOCAL) ) {
 					sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. hanging up....\n");
 					tty_hangup (port->gs.tty);
 				} else {
diff -urN linux-2.4.18-pre1/drivers/ieee1394/sbp2.c linux/drivers/ieee1394/sbp2.c
--- linux-2.4.18-pre1/drivers/ieee1394/sbp2.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/ieee1394/sbp2.c	Mon Jan  7 16:42:53 2002
@@ -2773,7 +2773,9 @@
 	/*
 	 * Tell scsi stack that we're done with this command
 	 */
+	spin_lock_irq(&io_request_lock);
 	done (SCpnt);
+	spin_unlock_irq(&io_request_lock);
 
 	return;
 }
diff -urN linux-2.4.18-pre1/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- linux-2.4.18-pre1/drivers/isdn/avmb1/capi.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/isdn/avmb1/capi.c	Mon Jan  7 16:42:53 2002
@@ -87,10 +87,10 @@
 	struct capincci  *nccip;
 	unsigned int      minor;
 
-	__u16		 applid;
-	__u32		 ncci;
-	__u16		 datahandle;
-	__u16		 msgid;
+	u16  		 applid;
+	u32		 ncci;
+	u16		 datahandle;
+	u16		 msgid;
 
 	struct file      *file;
 	struct tty_struct *tty;
@@ -112,7 +112,7 @@
 	/* transmit path */
 	struct datahandle_queue {
 		    struct datahandle_queue *next;
-		    __u16                    datahandle;
+		    u16                      datahandle;
 	} *ackqueue;
 	int nack;
 
@@ -121,7 +121,7 @@
 
 struct capincci {
 	struct capincci *next;
-	__u32		 ncci;
+	u32		 ncci;
 	struct capidev	*cdev;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	struct capiminor *minorp;
@@ -131,8 +131,8 @@
 struct capidev {
 	struct capidev *next;
 	struct file    *file;
-	__u16		applid;
-	__u16		errcode;
+	u16		applid;
+	u16		errcode;
 	unsigned int    minor;
 	unsigned        userflags;
 
@@ -166,7 +166,7 @@
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 /* -------- datahandles --------------------------------------------- */
 
-int capincci_add_ack(struct capiminor *mp, __u16 datahandle)
+static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
 {
 	struct datahandle_queue *n, **pp;
 
@@ -184,7 +184,7 @@
 	return 0;
 }
 
-int capiminor_del_ack(struct capiminor *mp, __u16 datahandle)
+static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
 {
 	struct datahandle_queue **pp, *p;
 
@@ -200,7 +200,7 @@
 	return -1;
 }
 
-void capiminor_del_all_ack(struct capiminor *mp)
+static void capiminor_del_all_ack(struct capiminor *mp)
 {
 	struct datahandle_queue **pp, *p;
 
@@ -216,7 +216,7 @@
 
 /* -------- struct capiminor ---------------------------------------- */
 
-struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci)
+static struct capiminor *capiminor_alloc(u16 applid, u32 ncci)
 {
 	struct capiminor *mp, **pp;
         unsigned int minor = 0;
@@ -257,7 +257,7 @@
 	return mp;
 }
 
-void capiminor_free(struct capiminor *mp)
+static void capiminor_free(struct capiminor *mp)
 {
 	struct capiminor **pp;
 
@@ -283,7 +283,7 @@
 	}
 }
 
-struct capiminor *capiminor_find(unsigned int minor)
+static struct capiminor *capiminor_find(unsigned int minor)
 {
 	struct capiminor *p;
 	for (p = minors; p && p->minor != minor; p = p->next)
@@ -294,7 +294,7 @@
 
 /* -------- struct capincci ----------------------------------------- */
 
-static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci)
+static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
 {
 	struct capincci *np, **pp;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -331,7 +331,7 @@
         return np;
 }
 
-static void capincci_free(struct capidev *cdev, __u32 ncci)
+static void capincci_free(struct capidev *cdev, u32 ncci)
 {
 	struct capincci *np, **pp;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -375,7 +375,7 @@
 	}
 }
 
-struct capincci *capincci_find(struct capidev *cdev, __u32 ncci)
+static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
 {
 	struct capincci *p;
 
@@ -426,7 +426,7 @@
 	kmem_cache_free(capidev_cachep, cdev);
 }
 
-static struct capidev *capidev_find(__u16 applid)
+static struct capidev *capidev_find(u16 applid)
 {
 	struct capidev *p;
 	for (p=capidev_openlist; p; p = p->next) {
@@ -439,13 +439,13 @@
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 /* -------- handle data queue --------------------------------------- */
 
-struct sk_buff *
+static struct sk_buff *
 gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
 {
 	struct sk_buff *nskb;
 	nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC);
 	if (nskb) {
-		__u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
+		u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
 		unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
 		capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
 		capimsg_setu16(s, 2, mp->applid);
@@ -458,11 +458,11 @@
 	return nskb;
 }
 
-int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
+static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
 {
 	struct sk_buff *nskb;
 	unsigned int datalen;
-	__u16 errcode, datahandle;
+	u16 errcode, datahandle;
 
 	datalen = skb->len - CAPIMSG_LEN(skb->data);
 	if (mp->tty) {
@@ -538,7 +538,7 @@
 	return -1;
 }
 
-void handle_minor_recv(struct capiminor *mp)
+static void handle_minor_recv(struct capiminor *mp)
 {
 	struct sk_buff *skb;
 	while ((skb = skb_dequeue(&mp->inqueue)) != 0) {
@@ -552,13 +552,13 @@
 	}
 }
 
-int handle_minor_send(struct capiminor *mp)
+static int handle_minor_send(struct capiminor *mp)
 {
 	struct sk_buff *skb;
-	__u16 len;
+	u16 len;
 	int count = 0;
-	__u16 errcode;
-	__u16 datahandle;
+	u16 errcode;
+	u16 datahandle;
 
 	if (mp->tty && mp->ttyoutstop) {
 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
@@ -569,7 +569,7 @@
 
 	while ((skb = skb_dequeue(&mp->outqueue)) != 0) {
 		datahandle = mp->datahandle;
-		len = (__u16)skb->len;
+		len = (u16)skb->len;
 		skb_push(skb, CAPI_DATA_B3_REQ_LEN);
 		memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
 		capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
@@ -578,7 +578,7 @@
 		capimsg_setu8 (skb->data, 5, CAPI_REQ);
 		capimsg_setu16(skb->data, 6, mp->msgid++);
 		capimsg_setu32(skb->data, 8, mp->ncci);	/* NCCI */
-		capimsg_setu32(skb->data, 12, (__u32) skb->data); /* Data32 */
+		capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
 		capimsg_setu16(skb->data, 16, len);	/* Data length */
 		capimsg_setu16(skb->data, 18, datahandle);
 		capimsg_setu16(skb->data, 20, 0);	/* Flags */
@@ -620,16 +620,16 @@
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 /* -------- function called by lower level -------------------------- */
 
-static void capi_signal(__u16 applid, void *param)
+static void capi_signal(u16 applid, void *param)
 {
 	struct capidev *cdev = (struct capidev *)param;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	struct capiminor *mp;
-	__u16 datahandle;
+	u16 datahandle;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 	struct capincci *np;
 	struct sk_buff *skb = 0;
-	__u32 ncci;
+	u32 ncci;
 
 	(void) (*capifuncs->capi_get_message) (applid, &skb);
 	if (!skb) {
@@ -758,7 +758,7 @@
 	struct capidev *cdev = (struct capidev *)file->private_data;
 	struct sk_buff *skb;
 	int retval;
-	__u16 mlen;
+	u16 mlen;
 
         if (ppos != &file->f_pos)
 		return -ESPIPE;
@@ -998,7 +998,7 @@
 						sizeof(ncci));
 			if (retval)
 				return -EFAULT;
-			nccip = capincci_find(cdev, (__u32) ncci);
+			nccip = capincci_find(cdev, (u32) ncci);
 			if (!nccip)
 				return 0;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -1023,7 +1023,7 @@
 						sizeof(ncci));
 			if (retval)
 				return -EFAULT;
-			nccip = capincci_find(cdev, (__u32) ncci);
+			nccip = capincci_find(cdev, (u32) ncci);
 			if (!nccip || (mp = nccip->minorp) == 0)
 				return -ESRCH;
 			return mp->minor;
@@ -1272,7 +1272,7 @@
 
 /* -------- tty_operations for capincci ----------------------------- */
 
-int capinc_tty_open(struct tty_struct * tty, struct file * file)
+static int capinc_tty_open(struct tty_struct * tty, struct file * file)
 {
 	struct capiminor *mp;
 
@@ -1300,7 +1300,7 @@
 	return 0;
 }
 
-void capinc_tty_close(struct tty_struct * tty, struct file * file)
+static void capinc_tty_close(struct tty_struct * tty, struct file * file)
 {
 	struct capiminor *mp;
 
@@ -1325,8 +1325,8 @@
 #endif
 }
 
-int capinc_tty_write(struct tty_struct * tty, int from_user,
-		      const unsigned char *buf, int count)
+static int capinc_tty_write(struct tty_struct * tty, int from_user,
+			    const unsigned char *buf, int count)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
@@ -1377,7 +1377,7 @@
 	return count;
 }
 
-void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
@@ -1414,7 +1414,7 @@
 	}
 }
 
-void capinc_tty_flush_chars(struct tty_struct *tty)
+static void capinc_tty_flush_chars(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
@@ -1440,7 +1440,7 @@
 	(void)handle_minor_recv(mp);
 }
 
-int capinc_tty_write_room(struct tty_struct *tty)
+static int capinc_tty_write_room(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	int room;
@@ -1458,7 +1458,7 @@
 	return room;
 }
 
-int capinc_tty_chars_in_buffer(struct tty_struct *tty)
+static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	if (!mp || !mp->nccip) {
@@ -1476,7 +1476,7 @@
 	return mp->outbytes;
 }
 
-int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
+static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
 	int error = 0;
@@ -1488,14 +1488,14 @@
 	return error;
 }
 
-void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
+static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_set_termios\n");
 #endif
 }
 
-void capinc_tty_throttle(struct tty_struct * tty)
+static void capinc_tty_throttle(struct tty_struct * tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1505,7 +1505,7 @@
 		mp->ttyinstop = 1;
 }
 
-void capinc_tty_unthrottle(struct tty_struct * tty)
+static void capinc_tty_unthrottle(struct tty_struct * tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1517,7 +1517,7 @@
 	}
 }
 
-void capinc_tty_stop(struct tty_struct *tty)
+static void capinc_tty_stop(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1528,7 +1528,7 @@
 	}
 }
 
-void capinc_tty_start(struct tty_struct *tty)
+static void capinc_tty_start(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1540,49 +1540,43 @@
 	}
 }
 
-void capinc_tty_hangup(struct tty_struct *tty)
+static void capinc_tty_hangup(struct tty_struct *tty)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_hangup\n");
 #endif
 }
 
-void capinc_tty_break_ctl(struct tty_struct *tty, int state)
+static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
 #endif
 }
 
-void capinc_tty_flush_buffer(struct tty_struct *tty)
+static void capinc_tty_flush_buffer(struct tty_struct *tty)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
 #endif
 }
 
-void capinc_tty_set_ldisc(struct tty_struct *tty)
+static void capinc_tty_set_ldisc(struct tty_struct *tty)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
 #endif
 }
 
-void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
+static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
 #endif
 }
 
-int capinc_tty_read_proc(char *page, char **start, off_t off,
-			  int count, int *eof, void *data)
-{
-	return 0;
-}
-
-int capinc_write_proc(struct file *file, const char *buffer,
-			  unsigned long count, void *data)
+static int capinc_tty_read_proc(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
 {
 	return 0;
 }
@@ -1594,7 +1588,7 @@
 static struct termios *capinc_tty_termios[CAPINC_NR_PORTS];
 static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS];
 
-int capinc_tty_init(void)
+static int capinc_tty_init(void)
 {
 	struct tty_driver *drv = &capinc_tty_driver;
 
@@ -1652,7 +1646,7 @@
 	return 0;
 }
 
-void capinc_tty_exit(void)
+static void capinc_tty_exit(void)
 {
 	struct tty_driver *drv = &capinc_tty_driver;
 	int retval;
@@ -1844,7 +1838,7 @@
 	return 0;
 }
 
-static void lower_callback(unsigned int cmd, __u32 contr, void *data)
+static void lower_callback(unsigned int cmd, u32 contr, void *data)
 {
 	struct capi_ncciinfo *np;
 	struct capidev *cdev;
diff -urN linux-2.4.18-pre1/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- linux-2.4.18-pre1/drivers/net/de4x5.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/de4x5.c	Mon Jan  7 16:42:53 2002
@@ -3652,7 +3652,7 @@
     tmp = virt_to_bus(p->data);
     i = ((tmp + ALIGN) & ~ALIGN) - tmp;
     skb_reserve(p, i);
-    lp->rx_ring[index].buf = tmp + i;
+    lp->rx_ring[index].buf = cpu_to_le32(tmp + i);
 
     ret = lp->rx_skb[index];
     lp->rx_skb[index] = p;
@@ -5623,7 +5623,7 @@
 	if (!capable(CAP_NET_ADMIN)) return -EPERM;
 	omr = inl(DE4X5_OMR);
 	omr &= ~OMR_PR;
-	outb(omr, DE4X5_OMR);
+	outl(omr, DE4X5_OMR);
 	dev->flags &= ~IFF_PROMISC;
 	break;
 
diff -urN linux-2.4.18-pre1/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- linux-2.4.18-pre1/drivers/parport/ChangeLog	Fri Dec 21 09:41:55 2001
+++ linux/drivers/parport/ChangeLog	Mon Jan  7 16:42:53 2002
@@ -1,3 +1,51 @@
+2002-01-04  Tim Waugh  <twaugh@redhat.com>
+
+	* share.c (parport_claim_or_block): Sleep interruptibly to prevent
+	a possible deadlock.
+
+2001-12-07  Damian Gruszka  <damian.gruszka@VisionSystems.de>
+
+	* parport_pc.c (ECR_WRITE): Define.  If there are forbidden bits
+	in the ECR register for some chips, this will be a useful place to
+	put that knowledge.
+	(change_mode): Use ECR_WRITE.
+	(parport_pc_restore_state): Likewise.
+	(parport_ECPPS2_supported): Likewise.
+	(parport_ECPEPP_supported): Likewise.
+	(irq_probe_EPP): Likewise.
+	(programmable_irq_support): Likewise.
+	(programmable_dma_support): Likewise.
+	(parport_pc_probe_port): Likewise.
+
+	(frob_set_mode): New function.  Set the mode bits of the ECR.
+	(get_fifo_residue): Use frob_set_mode.
+	(parport_pc_ecpepp_read_data): Likewise.
+	(parport_pc_ecpepp_write_data): Likewise.
+	(parport_pc_ecpepp_read_addr): Likewise.
+	(parport_pc_ecpepp_write_addr): Likewise.
+	(parport_pc_compat_write_block_pio): Likewise.
+	(parport_pc_ecp_write_block_pio): Likewise.
+	(parport_ECR_present): Likewise.
+	(parport_ECP_supported): Likewise.
+	(parport_EPP_supported): Likewise.
+	(parport_ECPEPP_supported): Likewise.
+	(programmable_irq_support): Likewise.
+	(irq_probe_ECP): Likewise.
+	(programmable_dma_support): Likewise.
+
+	(parport_pc_enable_irq): Only enable interrupts if we know which
+	IRQ line they will come from.
+	(parport_pc_init_state): Set nErrIntrEn at initialisation.
+	(parport_pc_restore_state): Only write writable bits of CTR.
+	(parport_irq_probe): If no IRQ is found, take ackIntEn out of the
+	writable bit set.
+
+2001-12-07  Tim Waugh  <twaugh@redhat.com>
+
+	* parport_pc.c (parport_pc_fifo_write_block_pio): Correct typo.
+	(parport_pc_init_state): Only set ackIntEn if we know which IRQ
+	line the interrupts will come from.
+
 2001-12-07  Tim Waugh  <twaugh@redhat.com>
 
 	* ieee1284_ops.c (parport_ieee1284_epp_write_addr,
diff -urN linux-2.4.18-pre1/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- linux-2.4.18-pre1/drivers/parport/parport_pc.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/parport/parport_pc.c	Mon Jan  7 16:42:53 2002
@@ -73,6 +73,8 @@
 #define ECR_VND 05
 #define ECR_TST 06
 #define ECR_CNF 07
+#define ECR_MODE_MASK 0xe0
+#define ECR_WRITE(p,v) frob_econtrol((p),0xff,(v))
 
 #undef DEBUG
 
@@ -100,13 +102,22 @@
 static void frob_econtrol (struct parport *pb, unsigned char m,
 			   unsigned char v)
 {
-	unsigned char ectr = inb (ECONTROL (pb));
+	unsigned char ectr = 0;
+
+	if (m != 0xff)
+		ectr = inb (ECONTROL (pb));
+
 	DPRINTK (KERN_DEBUG "frob_econtrol(%02x,%02x): %02x -> %02x\n",
 		m, v, ectr, (ectr & ~m) ^ v);
 
 	outb ((ectr & ~m) ^ v, ECONTROL (pb));
 }
 
+static void __inline__ frob_set_mode (struct parport *p, int mode)
+{
+	frob_econtrol (p, ECR_MODE_MASK, mode << 5);
+}
+
 #ifdef CONFIG_PARPORT_PC_FIFO
 /* Safely change the mode bits in the ECR 
    Returns:
@@ -166,13 +177,13 @@
 		/* We have to go through mode 001 */
 		oecr &= ~(7 << 5);
 		oecr |= ECR_PS2 << 5;
-		outb (oecr, ecr);
+		ECR_WRITE (p, oecr);
 	}
 
 	/* Set the mode. */
 	oecr &= ~(7 << 5);
 	oecr |= m << 5;
-	outb (oecr, ecr);
+	ECR_WRITE (p, oecr);
 	return 0;
 }
 
@@ -197,10 +208,10 @@
 		residue);
 
 	/* Reset the FIFO. */
-	frob_econtrol (p, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (p, ECR_PS2);
 
 	/* Now change to config mode and clean up. FIXME */
-	frob_econtrol (p, 0xe0, ECR_CNF << 5);
+	frob_set_mode (p, ECR_CNF);
 	cnfga = inb (CONFIGA (p));
 	printk (KERN_DEBUG "%s: cnfgA contains 0x%02x\n", p->name, cnfga);
 
@@ -213,7 +224,7 @@
 	 * PWord != 1 byte. */
 
 	/* Back to PS2 mode. */
-	frob_econtrol (p, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (p, ECR_PS2);
 
 	DPRINTK (KERN_DEBUG "*** get_fifo_residue: done residue collecting (ecr = 0x%2.2x)\n", inb (ECONTROL (p)));
 	return residue;
@@ -331,7 +342,8 @@
 
 void parport_pc_enable_irq(struct parport *p)
 {
-	__parport_pc_frob_control (p, 0x10, 0x10);
+	if (p->irq != PARPORT_IRQ_NONE)
+		__parport_pc_frob_control (p, 0x10, 0x10);
 }
 
 void parport_pc_data_forward (struct parport *p)
@@ -346,8 +358,14 @@
 
 void parport_pc_init_state(struct pardevice *dev, struct parport_state *s)
 {
-	s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
-	s->u.pc.ecr = 0x24;
+	s->u.pc.ctr = 0xc;
+	if (dev->irq_func &&
+	    dev->port->irq != PARPORT_IRQ_NONE)
+		/* Set ackIntEn */
+		s->u.pc.ctr |= 0x10;
+
+	s->u.pc.ecr = 0x34; /* NetMos chip can cause problems 0x24;
+			     * D.Gruszka VScom */
 }
 
 void parport_pc_save_state(struct parport *p, struct parport_state *s)
@@ -361,10 +379,11 @@
 void parport_pc_restore_state(struct parport *p, struct parport_state *s)
 {
 	struct parport_pc_private *priv = p->physport->private_data;
-	outb (s->u.pc.ctr, CONTROL (p));
-	priv->ctr = s->u.pc.ctr;
+	register unsigned char c = s->u.pc.ctr & priv->ctr_writable;
+	outb (c, CONTROL (p));
+	priv->ctr = c;
 	if (priv->ecr)
-		outb (s->u.pc.ecr, ECONTROL (p));
+		ECR_WRITE (p, s->u.pc.ecr);
 }
 
 #ifdef CONFIG_PARPORT_1284
@@ -516,11 +535,11 @@
 {
 	size_t got;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_data_reverse (port);
 	parport_pc_write_control (port, 0x4);
 	got = parport_pc_epp_read_data (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return got;
 }
@@ -531,11 +550,11 @@
 {
 	size_t written;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_write_control (port, 0x4);
 	parport_pc_data_forward (port);
 	written = parport_pc_epp_write_data (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return written;
 }
@@ -545,11 +564,11 @@
 {
 	size_t got;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_data_reverse (port);
 	parport_pc_write_control (port, 0x4);
 	got = parport_pc_epp_read_addr (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return got;
 }
@@ -560,11 +579,11 @@
 {
 	size_t written;
 
-	frob_econtrol (port, 0xe0, ECR_EPP << 5);
+	frob_set_mode (port, ECR_EPP);
 	parport_pc_write_control (port, 0x4);
 	parport_pc_data_forward (port);
 	written = parport_pc_epp_write_addr (port, buf, length, flags);
-	frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+	frob_set_mode (port, ECR_PS2);
 
 	return written;
 }
@@ -663,7 +682,7 @@
 		left--;
         }
 
-dump_parport_state ("leave fifo_write_block_dma", port);
+dump_parport_state ("leave fifo_write_block_pio", port);
 	return length - left;
 }
 
@@ -852,7 +871,7 @@
 		}
 
 		/* Reset the FIFO and return to PS2 mode. */
-		frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+		frob_set_mode (port, ECR_PS2);
 	}
 
 	r = parport_wait_peripheral (port,
@@ -949,7 +968,7 @@
 		}
 
 		/* Reset the FIFO and return to PS2 mode. */
-		frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+		frob_set_mode (port, ECR_PS2);
 
 		/* Host transfer recovery. */
 		parport_pc_data_reverse (port); /* Must be in PS2 mode */
@@ -1727,7 +1746,7 @@
 	outb (0xc, CONTROL (pb));
 	
 	/* Go to mode 000 */
-	frob_econtrol (pb, 0xe0, ECR_SPP << 5);
+	frob_set_mode (pb, ECR_SPP);
 
 	return 1;
 
@@ -1797,8 +1816,8 @@
 		return 0;
 
 	/* Find out FIFO depth */
-	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-	outb (ECR_TST << 5, ECONTROL (pb)); /* TEST FIFO */
+	frob_set_mode (pb, ECR_SPP); /* Reset FIFO */
+	frob_set_mode (pb, ECR_TST); /* TEST FIFO */
 	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++)
 		outb (0xaa, FIFO (pb));
 
@@ -1807,7 +1826,7 @@
 	 * it doesn't support ECP or FIFO MODE
 	 */
 	if (i == 1024) {
-		outb (ECR_SPP << 5, ECONTROL (pb));
+		frob_set_mode (pb, ECR_SPP);
 		return 0;
 	}
 
@@ -1837,9 +1856,9 @@
 	priv->writeIntrThreshold = i;
 
 	/* Find out readIntrThreshold */
-	frob_econtrol (pb, 0xe0, ECR_PS2 << 5); /* Reset FIFO and enable PS2 */
+	frob_set_mode (pb, ECR_PS2); /* Reset FIFO and enable PS2 */
 	parport_pc_data_reverse (pb); /* Must be in PS2 mode */
-	frob_econtrol (pb, 0xe0, ECR_TST << 5); /* Test FIFO */
+	frob_set_mode (pb, ECR_TST); /* Test FIFO */
 	frob_econtrol (pb, 1<<2, 1<<2);
 	frob_econtrol (pb, 1<<2, 0);
 	for (i = 1; i <= priv->fifo_depth; i++) {
@@ -1858,7 +1877,7 @@
 
 	priv->readIntrThreshold = i;
 
-	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
+	frob_set_mode (pb, ECR_SPP); /* Reset FIFO */
 	outb (0xf4, ECONTROL (pb)); /* Configuration mode */
 	config = inb (CONFIGA (pb));
 	pword = (config >> 4) & 0x7;
@@ -1904,7 +1923,7 @@
 	}
 
 	/* Go back to mode 000 */
-	frob_econtrol (pb, 0xe0, ECR_SPP << 5);
+	frob_set_mode (pb, ECR_SPP);
 
 	return 1;
 }
@@ -1920,11 +1939,9 @@
 		return 0;
 
 	oecr = inb (ECONTROL (pb));
-	outb (ECR_PS2 << 5, ECONTROL (pb));
-	
+	frob_set_mode (pb, ECR_PS2);
 	result = parport_PS2_supported(pb);
-
-	outb (oecr, ECONTROL (pb));
+	ECR_WRITE (pb, oecr);
 	return result;
 }
 
@@ -1955,8 +1972,8 @@
 	/* Check for Intel bug. */
 	if (priv->ecr) {
 		unsigned char i;
-		for (i = 0x00; i < 0x80; i += 0x20) {
-			outb (i, ECONTROL (pb));
+		for (i = 0; i < 4; i++) {
+			frob_set_mode (pb, i);
 			if (clear_epp_timeout (pb)) {
 				/* Phony EPP in ECP. */
 				return 0;
@@ -1987,11 +2004,11 @@
 
 	oecr = inb (ECONTROL (pb));
 	/* Search for SMC style EPP+ECP mode */
-	outb (0x80, ECONTROL (pb));
+	frob_set_mode (pb, ECR_EPP);
 	outb (0x04, CONTROL (pb));
 	result = parport_EPP_supported(pb);
 
-	outb (oecr, ECONTROL (pb));
+	ECR_WRITE (pb, oecr);
 
 	if (result) {
 		/* Set up access functions to use ECP+EPP hardware. */
@@ -2028,12 +2045,12 @@
 		PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5
 	};
 
-	outb (ECR_CNF << 5, ECONTROL (pb)); /* Configuration MODE */
+	frob_set_mode (pb, ECR_CNF); /* Configuration MODE */
 
 	intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07;
 	irq = lookup[intrLine];
 
-	outb (oecr, ECONTROL (pb));
+	ECR_WRITE (pb, oecr);
 	return irq;
 }
 
@@ -2045,16 +2062,16 @@
 	sti();
 	irqs = probe_irq_on();
 		
-	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-	outb ((ECR_TST << 5) | 0x04, ECONTROL (pb));
-	outb (ECR_TST << 5, ECONTROL (pb));
+	frob_set_mode (pb, ECR_SPP); /* Reset FIFO */
+	frob_econtrol (pb, ECR_MODE_MASK | 0x04, (ECR_TST << 5) | 0x04);
+	frob_set_mode (pb, ECR_TST);
 
 	/* If Full FIFO sure that writeIntrThreshold is generated */
 	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) 
 		outb (0xaa, FIFO (pb));
 		
 	pb->irq = probe_irq_off(irqs);
-	outb (ECR_SPP << 5, ECONTROL (pb));
+	frob_set_mode (pb, ECR_SPP);
 
 	if (pb->irq <= 0)
 		pb->irq = PARPORT_IRQ_NONE;
@@ -2096,7 +2113,7 @@
 
 	pb->irq = probe_irq_off (irqs);
 	if (pb->modes & PARPORT_MODE_PCECR)
-		outb (oecr, ECONTROL (pb));
+		ECR_WRITE (pb, oecr);
 	parport_pc_write_control(pb, 0xc);
 
 	if (pb->irq <= 0)
@@ -2121,7 +2138,9 @@
  */
 static int __devinit parport_irq_probe(struct parport *pb)
 {
-	const struct parport_pc_private *priv = pb->private_data;
+	struct parport_pc_private *priv = pb->private_data;
+
+	priv->ctr_writable |= 0x10;
 
 	if (priv->ecr) {
 		pb->irq = programmable_irq_support(pb);
@@ -2147,6 +2166,9 @@
 	if (pb->irq == PARPORT_IRQ_NONE)
 		pb->irq = get_superio_irq(pb);
 
+	if (pb->irq == PARPORT_IRQ_NONE)
+		priv->ctr_writable &= ~0x10;
+
 	return pb->irq;
 }
 
@@ -2158,7 +2180,7 @@
 	unsigned char oecr = inb (ECONTROL (p));
 	int dma;
 
-	frob_econtrol (p, 0xe0, ECR_CNF << 5);
+	frob_set_mode (p, ECR_CNF);
 	
 	dma = inb (CONFIGB(p)) & 0x07;
 	/* 000: Indicates jumpered 8-bit DMA if read-only.
@@ -2166,7 +2188,7 @@
 	if ((dma & 0x03) == 0)
 		dma = PARPORT_DMA_NONE;
 
-	outb (oecr, ECONTROL (p));
+	ECR_WRITE (p, oecr);
 	return dma;
 }
 
@@ -2212,7 +2234,7 @@
 	}
 	memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
 	priv->ctr = 0xc;
-	priv->ctr_writable = 0xff;
+	priv->ctr_writable = ~0x10;
 	priv->ecr = 0;
 	priv->fifo_depth = 0;
 	priv->dma_buf = 0;
@@ -2374,7 +2396,7 @@
 		 * Put the ECP detected port in PS2 mode.
 		 * Do this also for ports that have ECR but don't do ECP.
 		 */
-		outb (0x34, ECONTROL (p));
+		ECR_WRITE (p, 0x34);
 
 	parport_pc_write_data(p, 0);
 	parport_pc_data_forward (p);
diff -urN linux-2.4.18-pre1/drivers/parport/share.c linux/drivers/parport/share.c
--- linux-2.4.18-pre1/drivers/parport/share.c	Mon Oct  8 11:54:10 2001
+++ linux/drivers/parport/share.c	Mon Jan  7 16:42:53 2002
@@ -1011,7 +1011,11 @@
 		/* If dev->waiting is clear now, an interrupt
 		   gave us the port and we would deadlock if we slept.  */
 		if (dev->waiting) {
-			sleep_on(&dev->wait_q);
+			interruptible_sleep_on (&dev->wait_q);
+			if (signal_pending (current)) {
+				restore_flags (flags);
+				return -EINTR;
+			}
 			r = 1;
 		} else {
 			r = 0;
@@ -1084,7 +1088,7 @@
 		if (pd->waiting & 2) { /* sleeping in claim_or_block */
 			parport_claim(pd);
 			if (waitqueue_active(&pd->wait_q))
-				wake_up(&pd->wait_q);
+				wake_up_interruptible(&pd->wait_q);
 			return;
 		} else if (pd->wakeup) {
 			pd->wakeup(pd->private);
diff -urN linux-2.4.18-pre1/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c
--- linux-2.4.18-pre1/drivers/scsi/3w-xxxx.c	Fri Nov  9 14:05:02 2001
+++ linux/drivers/scsi/3w-xxxx.c	Mon Jan  7 16:42:53 2002
@@ -6,7 +6,7 @@
    		     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
                      Brad Strand <linux@3ware.com>
 
-   Copyright (C) 1999-2001 3ware Inc.
+   Copyright (C) 1999-2002 3ware Inc.
 
    Kernel compatablity By: 	Andre Hedrick <andre@suse.com>
    Non-Copyright (C) 2000	Andre Hedrick <andre@suse.com>
@@ -106,6 +106,19 @@
                  Add entire aen code string list.
    1.02.00.010 - Cleanup queueing code, fix jbod thoughput.
                  Fix get_param for specific units.
+   1.02.00.011 - Fix bug in tw_aen_complete() where aen's could be lost.
+                 Fix tw_aen_drain_queue() to display useful info at init.
+                 Set tw_host->max_id for 12 port cards.
+                 Add ioctl support for raw command packet post from userspace
+                 with sglist fragments (parameter and io).
+   1.02.00.012 - Fix read capacity to under report by 1 sector to fix get
+                 last sector ioctl.
+   1.02.00.013 - Fix bug where more AEN codes weren't coming out during
+                 driver initialization.
+                 Improved handling of PCI aborts.
+   1.02.00.014 - Fix bug in tw_findcards() where AEN code could be lost.
+                 Increase timeout in tw_aen_drain_queue() to 30 seconds.
+   1.02.00.015 - Re-write raw command post with data ioctl method.
 */
 
 #include <linux/module.h>
@@ -114,7 +127,6 @@
 MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver");
 MODULE_LICENSE("GPL");
 
-
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/time.h>
@@ -149,11 +161,11 @@
 
 /* Notifier block to get a notify on system shutdown/halt/reboot */
 static struct notifier_block tw_notifier = {
-  tw_halt, NULL, 0
+	tw_halt, NULL, 0
 };
 
 /* Globals */
-char *tw_driver_version="1.02.00.010";
+char *tw_driver_version="1.02.00.015";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -164,6 +176,7 @@
 {
 	TW_Param *param;
 	unsigned short aen;
+	int error = 0;
 
 	dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n");
 	if (tw_dev->alignment_virtual_address[request_id] == NULL) {
@@ -182,12 +195,15 @@
 			if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
 				printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
 			} else {
-				printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
+				if (aen != 0x0) 
+					printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
 			}
-		} else
+		} else {
 			printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
+		}
 	}
-	tw_dev->aen_count++;
+	if (aen != 0x0) 
+		tw_dev->aen_count++;
 
 	/* Now queue the code */
 	tw_dev->aen_queue[tw_dev->aen_tail] = aen;
@@ -203,8 +219,18 @@
 			tw_dev->aen_head = tw_dev->aen_head + 1;
 		}
 	}
-	tw_dev->state[request_id] = TW_S_COMPLETED;
-	tw_state_request_finish(tw_dev, request_id);
+
+	if (aen != TW_AEN_QUEUE_EMPTY) {
+		error = tw_aen_read_queue(tw_dev, request_id);
+		if (error) {
+			printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no);
+			tw_dev->state[request_id] = TW_S_COMPLETED;
+			tw_state_request_finish(tw_dev, request_id);
+		}
+	} else {
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		tw_state_request_finish(tw_dev, request_id);
+	}
 
 	return 0;
 } /* End tw_aen_complete() */
@@ -235,10 +261,11 @@
 	status_reg_addr = tw_dev->registers.status_reg_addr;
 	response_que_addr = tw_dev->registers.response_que_addr;
 
-	if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 15)) {
+	if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 30)) {
 		dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
 		return 1;
 	}
+	tw_clear_attention_interrupt(tw_dev);
 
 	/* Initialize command packet */
 	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
@@ -286,7 +313,7 @@
 	do {
 		/* Post command packet */
 		outl(command_que_value, command_que_addr);
-    
+
 		/* Now poll for completion */
 		for (i=0;i<imax;i++) {
 			mdelay(5);
@@ -324,7 +351,7 @@
 				queue = 0;
 				switch (aen_code) {
 					case TW_AEN_QUEUE_EMPTY:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_EMPTY.\n");
+						dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
 						if (first_reset != 1) {
 							continue;
 						} else {
@@ -332,51 +359,28 @@
 						}
 						break;
 					case TW_AEN_SOFT_RESET:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_SOFT_RESET.\n");
 						if (first_reset == 0) {
 							first_reset = 1;
 						} else {
+							printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
+							tw_dev->aen_count++;
 							queue = 1;
 						}
 						break;
-					case TW_AEN_DEGRADED_MIRROR:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_DEGRADED_MIRROR.\n");
-						queue = 1;
-						break;
-					case TW_AEN_CONTROLLER_ERROR:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_CONTROLLER_ERROR.\n");
-						queue = 1;
-						break;
-					case TW_AEN_REBUILD_FAIL:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_FAIL.\n");
-						queue = 1;
-						break;
-					case TW_AEN_REBUILD_DONE:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_DONE.\n");
-						queue = 1;
-						break;
-					case TW_AEN_QUEUE_FULL:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_FULL.\n");
-						queue = 1;
-						break;
-					case TW_AEN_APORT_TIMEOUT:
-						printk(KERN_WARNING "3w-xxxx: Received drive timeout AEN on port %d, check drive and drive cables.\n", aen >> 8);
-						queue = 1;
-						break;
-					case TW_AEN_DRIVE_ERROR:
-						printk(KERN_WARNING "3w-xxxx: Received drive error AEN on port %d, check/replace cabling, or possible bad drive.\n", aen >> 8);
-						queue = 1;
-						break;
-					case TW_AEN_SMART_FAIL:
-						printk(KERN_WARNING "3w-xxxx: Received S.M.A.R.T. threshold AEN on port %d, check drive/cooling, or possible bad drive.\n", aen >> 8);
-						queue = 1;
-						break;
-					case TW_AEN_SBUF_FAIL:
-						printk(KERN_WARNING "3w-xxxx: Received SBUF integrity check failure AEN, reseat card or bad card.\n");
-						queue = 1;
-						break;
 					default:
-						dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unknown AEN code 0x%x.\n", aen_code);
+						if (aen == 0x0ff) {
+							printk(KERN_WARNING "3w-xxxx: AEN: AEN queue overflow.\n");
+						} else {
+							if ((aen & 0x0ff) < TW_AEN_STRING_MAX) {
+								if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
+									printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);
+								} else {
+									printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
+								}
+							} else
+								printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen);
+						}
+						tw_dev->aen_count++;
 						queue = 1;
 				}
 
@@ -619,6 +623,11 @@
 	case TW_STATUS_MICROCONTROLLER_ERROR:
 		printk(KERN_WARNING "3w-xxxx: Microcontroller Error.\n");
 		break;
+	case TW_STATUS_PCI_ABORT:
+		printk(KERN_WARNING "3w-xxxx: PCI Abort: clearing.\n");
+		outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr);
+		pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
+		break;
   }
 } /* End tw_decode_bits() */
 
@@ -689,11 +698,22 @@
 	u32 control_reg_value, control_reg_addr;
 
 	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = (TW_CONTROL_ENABLE_INTERRUPTS |
+			     TW_CONTROL_UNMASK_RESPONSE_INTERRUPT);
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_enable_interrupts() */
+
+/* This function will enable interrupts on the controller */
+void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev)
+{
+	u32 control_reg_value, control_reg_addr;
+
+	control_reg_addr = tw_dev->registers.control_reg_addr;
 	control_reg_value = (TW_CONTROL_CLEAR_ATTENTION_INTERRUPT |
 			     TW_CONTROL_UNMASK_RESPONSE_INTERRUPT |
 			     TW_CONTROL_ENABLE_INTERRUPTS);
 	outl(control_reg_value, control_reg_addr);
-} /* End tw_enable_interrupts() */
+} /* End tw_enable_and_clear_interrupts() */
 
 /* This function will find and initialize all cards */
 int tw_findcards(Scsi_Host_Template *tw_host) 
@@ -761,14 +781,14 @@
 			  
 				error = tw_aen_drain_queue(tw_dev);
 				if (error) {
-					printk(KERN_WARNING "3w-xxxx: tw_findcards(): No attention interrupt for card %d.\n", numcards);
+					printk(KERN_WARNING "3w-xxxx: AEN drain failed for card %d.\n", numcards);
 					tries++;
 					continue;
 				}
 
 				/* Check for controller errors */
 				if (tw_check_errors(tw_dev)) {
-					printk(KERN_WARNING "3w-xxxx: tw_findcards(): Controller errors found, soft resetting card %d.\n", numcards);
+					printk(KERN_WARNING "3w-xxxx: Controller errors found, retrying for card %d.\n", numcards);
 					tries++;
 					continue;
 				}
@@ -776,7 +796,7 @@
 				/* Empty the response queue */
 				error = tw_empty_response_que(tw_dev);
 				if (error) {
-					printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't empty response queue for card %d.\n", numcards);
+					printk(KERN_WARNING "3w-xxxx: Couldn't empty response queue, retrying for card %d.\n", numcards);
 					tries++;
 					continue;
 				}
@@ -786,7 +806,7 @@
 			}
 
 			if (tries >= TW_MAX_RESET_TRIES) {
-				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Controller error or no attention interrupt: giving up for card %d.\n", numcards);
+				printk(KERN_WARNING "3w-xxxx: Controller errors, card not responding, check all cabling for card %d.\n", numcards);
 				tw_free_device_extension(tw_dev);
 				kfree(tw_dev);
 				continue;
@@ -816,7 +836,7 @@
 
 			error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
 			if (error) {
-				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initconnection for card %d.\n", numcards);
+				printk(KERN_WARNING "3w-xxxx: Connection initialization failed for card %d.\n", numcards);
 				release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
 				tw_free_device_extension(tw_dev);
 				kfree(tw_dev);
@@ -841,13 +861,16 @@
 		/* Register the card with the kernel SCSI layer */
 			host = scsi_register(tw_host, sizeof(TW_Device_Extension));
 			if (host == NULL) {
-				printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed for card %d.\n", numcards-1);
+				printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed for card %d.\n", numcards);
 				release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
 				tw_free_device_extension(tw_dev);
 				kfree(tw_dev);
 				continue;
 			}
 
+			/* Set max target id's */
+			host->max_id = TW_MAX_UNITS;
+
 			/* Set max sectors per io */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
 			host->max_sectors = TW_MAX_SECTORS;
@@ -872,7 +895,7 @@
 				tw_device_extension_count = numcards;
 				tw_dev2->host = host;
 			} else { 
-				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", numcards-1);
+				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", numcards);
 				scsi_unregister(host);
 				release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
 				tw_free_device_extension(tw_dev);
@@ -1052,6 +1075,7 @@
 		tw_dev->state[i] = TW_S_INITIAL;
 		tw_dev->ioctl_size[i] = 0;
 		tw_dev->aen_queue[i] = 0;
+		tw_dev->ioctl_data[i] = NULL;
 	}
 
 	for (i=0;i<TW_MAX_UNITS;i++) {
@@ -1330,7 +1354,7 @@
 
 	if (tw_dev->tw_pci_dev->irq == irq) {
 		spin_lock(&tw_dev->tw_lock);
-		dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt()\n");
+		dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n");
 
 		/* Read the registers */
 		status_reg_addr = tw_dev->registers.status_reg_addr;
@@ -1453,18 +1477,21 @@
 						tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
 						tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
 					}
-					if (error) {
+					if (error == 1) {
 						/* Tell scsi layer there was an error */
 						dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Scsi Error.\n");
 						tw_dev->srb[request_id]->result = (DID_RESET << 16);
-					} else {
+					}
+					if (error == 0) {
 						/* Tell scsi layer command was a success */
 						tw_dev->srb[request_id]->result = (DID_OK << 16);
 					}
-					tw_dev->state[request_id] = TW_S_COMPLETED;
-					tw_state_request_finish(tw_dev, request_id);
-					tw_dev->posted_request_count--;
-					tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+					if (error != 2) {
+						tw_dev->state[request_id] = TW_S_COMPLETED;
+						tw_state_request_finish(tw_dev, request_id);
+						tw_dev->posted_request_count--;
+						tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+					}
 					status_reg_value = inl(status_reg_addr);
 					if (tw_check_bits(status_reg_value)) {
 						dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
@@ -1477,19 +1504,21 @@
 	}
 	spin_unlock_irqrestore(&io_request_lock, flags);
 	clear_bit(TW_IN_INTR, &tw_dev->flags);
-}	/* End tw_interrupt() */
+} /* End tw_interrupt() */
 
 /* This function handles ioctls from userspace to the driver */
 int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
 {
 	unsigned char opcode;
-	int bufflen;
+	int bufflen, error = 0;
 	TW_Param *param;
-	TW_Command *command_packet;
+	TW_Command *command_packet, *command_save;
 	u32 param_value;
 	TW_Ioctl *ioctl = NULL;
 	TW_Passthru *passthru = NULL;
-	int tw_aen_code;
+	int tw_aen_code, i, use_sg;
+	char *data_ptr;
+	int total_bytes = 0;
 
 	ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
 	if (ioctl == NULL) {
@@ -1610,6 +1639,159 @@
 				printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
 				return 1;
 			}
+		case TW_CMD_PACKET_WITH_DATA:
+			dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
+			command_save = (TW_Command *)tw_dev->alignment_virtual_address[request_id];
+			if (command_save == NULL) {
+				printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad alignment virtual address.\n", tw_dev->host->host_no);
+				return 1;
+			}
+			if (ioctl->data != NULL) {
+				/* Copy down the command packet */
+				memcpy(command_packet, ioctl->data, sizeof(TW_Command));
+				memcpy(command_save, ioctl->data, sizeof(TW_Command));
+				command_packet->request_id = request_id;
+
+				/* Now deal with the two possible sglists */
+				if (command_packet->byte0.sgl_offset == 2) {
+					use_sg = command_packet->size - 3;
+					for (i=0;i<use_sg;i++)
+						total_bytes+=command_packet->byte8.param.sgl[i].length;
+					tw_dev->ioctl_data[request_id] = kmalloc(total_bytes, GFP_ATOMIC);
+					if (!tw_dev->ioctl_data[request_id]) {
+						printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): kmalloc failed for request_id %d.\n", tw_dev->host->host_no, request_id);
+						return 1;
+					}
+
+					/* Copy param sglist into the kernel */
+					data_ptr = tw_dev->ioctl_data[request_id];
+					for (i=0;i<use_sg;i++) {
+						if ((u32 *)command_packet->byte8.param.sgl[i].address != NULL) {
+							error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length);
+							if (error) {
+								printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no);
+								goto tw_ioctl_bail;
+							}
+						} else {
+							printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
+							tw_dev->srb[request_id]->result = (DID_RESET << 16);
+							goto tw_ioctl_bail;
+						}
+						data_ptr+=command_packet->byte8.param.sgl[i].length;
+					}
+					command_packet->size = 4;
+					command_packet->byte8.param.sgl[0].address = virt_to_bus(tw_dev->ioctl_data[request_id]);
+					command_packet->byte8.param.sgl[0].length = total_bytes;
+				}
+				if (command_packet->byte0.sgl_offset == 3) {
+					use_sg = command_packet->size - 4;
+					for (i=0;i<use_sg;i++)
+						total_bytes+=command_packet->byte8.io.sgl[i].length;
+					tw_dev->ioctl_data[request_id] = kmalloc(total_bytes, GFP_ATOMIC);
+					if (!tw_dev->ioctl_data[request_id]) {
+						printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): kmalloc failed for request_id %d.\n", tw_dev->host->host_no, request_id);
+						return 1;
+					}
+					if (command_packet->byte0.opcode == TW_OP_WRITE) {
+						/* Copy io sglist into the kernel */
+						data_ptr = tw_dev->ioctl_data[request_id];
+						for (i=0;i<use_sg;i++) {
+							if ((u32 *)command_packet->byte8.io.sgl[i].address != NULL) {
+								error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length);
+								if (error) {
+									printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no);
+									goto tw_ioctl_bail;
+								}
+							} else {
+								printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
+								tw_dev->srb[request_id]->result = (DID_RESET << 16);
+								goto tw_ioctl_bail;
+							}
+							data_ptr+=command_packet->byte8.io.sgl[i].length;
+						}
+					}
+					command_packet->size = 5;
+					command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->ioctl_data[request_id]);
+					command_packet->byte8.io.sgl[0].length = total_bytes;
+				}
+
+				spin_unlock_irq(&io_request_lock);
+				spin_unlock_irq(&tw_dev->tw_lock);
+
+				/* Finally post the command packet */
+				tw_post_command_packet(tw_dev, request_id);
+
+				mdelay(TW_IOCTL_WAIT_TIME);
+				spin_lock_irq(&tw_dev->tw_lock);
+				spin_lock_irq(&io_request_lock);
+
+				if (signal_pending(current)) {
+					dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no);
+					tw_dev->srb[request_id]->result = (DID_OK << 16);
+					goto tw_ioctl_bail;
+				}
+
+				tw_dev->srb[request_id]->result = (DID_OK << 16);
+				/* Now copy up the param or io sglist to userspace */
+				if (command_packet->byte0.sgl_offset == 2) {
+					use_sg = command_save->size - 3;
+					data_ptr = phys_to_virt(command_packet->byte8.param.sgl[0].address);
+					for (i=0;i<use_sg;i++) {
+						if ((u32 *)command_save->byte8.param.sgl[i].address != NULL) {
+							error = copy_to_user((u32 *)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length);
+							if (error) {
+								printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no);
+								goto tw_ioctl_bail;
+							}
+							dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.param.sgl[i].length, current->pid);
+							data_ptr+=command_save->byte8.param.sgl[i].length;
+						} else {
+							printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
+							tw_dev->srb[request_id]->result = (DID_RESET << 16);
+							goto tw_ioctl_bail;
+						}
+					}
+				}
+				if (command_packet->byte0.sgl_offset == 3) {
+					use_sg = command_save->size - 4;
+					if (command_packet->byte0.opcode == TW_OP_READ) {
+						data_ptr = phys_to_virt(command_packet->byte8.io.sgl[0].address);
+						for(i=0;i<use_sg;i++) {
+							if ((u32 *)command_save->byte8.io.sgl[i].address != NULL) {
+								error = copy_to_user((u32 *)command_save->byte8.io.sgl[i].address, data_ptr, command_save->byte8.io.sgl[i].length);
+								if (error) {
+									printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no);
+									goto tw_ioctl_bail;
+								}
+								dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.io.sgl[i].length, current->pid);
+								data_ptr+=command_save->byte8.io.sgl[i].length;
+							} else {
+								printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
+								tw_dev->srb[request_id]->result = (DID_RESET << 16);
+								goto tw_ioctl_bail;
+							}
+						}
+					}
+				}
+				
+			tw_ioctl_bail:
+
+				/* Free up sglist memory */
+				if (tw_dev->ioctl_data[request_id])
+					kfree(tw_dev->ioctl_data[request_id]);
+				else
+					printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Error freeing ioctl data.\n", tw_dev->host->host_no);
+				
+				/* Now complete the io */
+				tw_dev->state[request_id] = TW_S_COMPLETED;
+				tw_state_request_finish(tw_dev, request_id);
+				tw_dev->posted_request_count--;
+				tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+				return 0;
+			} else {
+				printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
+				return 1;
+			}
 		default:
 			printk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);
 			tw_dev->state[request_id] = TW_S_COMPLETED;
@@ -1653,6 +1835,7 @@
 	TW_Param *param;
 	TW_Ioctl *ioctl = NULL;
 	TW_Passthru *passthru = NULL;
+	TW_Command *command_packet;
 
 	ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
 	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
@@ -1661,6 +1844,13 @@
 		printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n");
 		return 1;
 	}
+
+	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+	if (command_packet == NULL) {
+		printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl_complete(): Bad command packet virtual address.\n", tw_dev->host->host_no);
+		return 1;
+	}
+
 	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);
 
 	ioctl = (TW_Ioctl *)buff;
@@ -1669,6 +1859,9 @@
 			passthru = (TW_Passthru *)ioctl->data;
 			memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512);
 			break;
+		case TW_CMD_PACKET_WITH_DATA:
+			dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n");
+			return 2; /* Special case for isr to not complete io */
 		default:
 			memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
 			param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
@@ -1819,7 +2012,7 @@
 
 		error = tw_aen_drain_queue(tw_dev);
 		if (error) {
-			printk(KERN_WARNING "3w-xxxx: scsi%d: Card not responding, retrying.\n", tw_dev->host->host_no);
+			printk(KERN_WARNING "3w-xxxx: scsi%d: AEN drain failed, retrying.\n", tw_dev->host->host_no);
 			tries++;
 			continue;
 		}
@@ -1855,7 +2048,7 @@
 	}
 
 	/* Re-enable interrupts */
-	tw_enable_interrupts(tw_dev);
+	tw_enable_and_clear_interrupts(tw_dev);
 
 	return 0;
 } /* End tw_reset_sequence() */
@@ -2381,6 +2574,9 @@
 	capacity = (param_data[3] << 24) | (param_data[2] << 16) | 
 		   (param_data[1] << 8) | param_data[0];
 
+	/* Subtract one sector to fix get last sector ioctl */
+	capacity -= 1;
+
 	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity);
 
 	/* Number of LBA's */
@@ -2671,7 +2867,7 @@
 	}
 
 	/* Re-enable interrupts */
-	tw_enable_interrupts(tw_dev);
+	tw_enable_and_clear_interrupts(tw_dev);
 
 	return 0;
 } /* End tw_shutdown_device() */
@@ -2719,7 +2915,7 @@
 	int id = 0;
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start()\n");
-
+	
 	/* Obtain next free request_id */
 	do {
 		if (tw_dev->free_head == tw_dev->free_wrap) {
@@ -2749,7 +2945,6 @@
 } /* End tw_unmask_command_interrupt() */
 
 /* Now get things going */
-
 static Scsi_Host_Template driver_template = TWXXXX;
 #include "scsi_module.c"
 
diff -urN linux-2.4.18-pre1/drivers/scsi/3w-xxxx.h linux/drivers/scsi/3w-xxxx.h
--- linux-2.4.18-pre1/drivers/scsi/3w-xxxx.h	Fri Nov  9 14:05:02 2001
+++ linux/drivers/scsi/3w-xxxx.h	Mon Jan  7 16:42:53 2002
@@ -6,7 +6,7 @@
    		     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
                      Brad Strand <linux@3ware.com>
 
-   Copyright (C) 1999-2001 3ware Inc.
+   Copyright (C) 1999-2002 3ware Inc.
 
    Kernel compatablity By:	Andre Hedrick <andre@suse.com>
    Non-Copyright (C) 2000	Andre Hedrick <andre@suse.com>
@@ -62,7 +62,7 @@
 static char *tw_aen_string[] = {
 	"AEN queue empty",                      // 0x000
 	"Soft reset occurred",                  // 0x001
-	"Mirorr degraded: Unit #",              // 0x002
+	"Unit degraded: Unit #",                // 0x002
 	"Controller error",                     // 0x003 
 	"Rebuild failed: Unit #",               // 0x004
 	"Rebuild complete: Unit #",             // 0x005
@@ -90,10 +90,12 @@
 	"DCB unsupported version: Port #",      // 0x028
 	"Verify started: Unit #",               // 0x029
 	"Verify failed: Port #",                // 0x02A
-	"Verify complete: Unit #"               // 0x02B
+	"Verify complete: Unit #",              // 0x02B
+	"Overwrote bad sector during rebuild: Port #",  //0x2C
+	"Encountered bad sector during rebuild: Port #" //0x2D
 };
 
-#define TW_AEN_STRING_MAX                      0x02C
+#define TW_AEN_STRING_MAX                      0x02E
 
 /* Control register bit definitions */
 #define TW_CONTROL_CLEAR_HOST_INTERRUPT	       0x00080000
@@ -108,6 +110,7 @@
 #define TW_CONTROL_DISABLE_INTERRUPTS	       0x00000040
 #define TW_CONTROL_ISSUE_HOST_INTERRUPT	       0x00000020
 #define TW_CONTROL_CLEAR_PARITY_ERROR          0x00800000
+#define TW_CONTROL_CLEAR_PCI_ABORT             0x00100000
 
 /* Status register bit definitions */
 #define TW_STATUS_MAJOR_VERSION_MASK	       0xF0000000
@@ -140,6 +143,7 @@
 #define TW_DEVICE_ID2 (0x1001)  /* 7000 series controller */
 #define TW_NUMDEVICES 2
 #define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
+#define TW_PCI_CLEAR_PCI_ABORT     0x2000
 
 /* Command packet opcodes */
 #define TW_OP_NOP	      0x0
@@ -153,6 +157,7 @@
 #define TW_OP_AEN_LISTEN      0x1c
 #define TW_CMD_PACKET         0x1d
 #define TW_ATA_PASSTHRU       0x1e
+#define TW_CMD_PACKET_WITH_DATA 0x1f
 
 /* Asynchronous Event Notification (AEN) Codes */
 #define TW_AEN_QUEUE_EMPTY       0x0000
@@ -197,6 +202,7 @@
 #define TW_MAX_SECTORS                        128
 #endif 
 #define TW_AEN_WAIT_TIME                      1000
+#define TW_IOCTL_WAIT_TIME                    (1 * HZ) /* 1 second */
 
 /* Macros */
 #define TW_STATUS_ERRORS(x) \
@@ -381,6 +387,7 @@
 	unsigned char		aen_head;
 	unsigned char		aen_tail;
 	long			flags; /* long req'd for set_bit --RR */
+	char			*ioctl_data[TW_Q_LENGTH];
 } TW_Device_Extension;
 
 /* Function prototypes */
@@ -397,6 +404,7 @@
 void tw_disable_interrupts(TW_Device_Extension *tw_dev);
 int tw_empty_response_que(TW_Device_Extension *tw_dev);
 void tw_enable_interrupts(TW_Device_Extension *tw_dev);
+void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev);
 int tw_findcards(Scsi_Host_Template *tw_host);
 void tw_free_device_extension(TW_Device_Extension *tw_dev);
 int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits);
diff -urN linux-2.4.18-pre1/drivers/scsi/53c700.c linux/drivers/scsi/53c700.c
--- linux-2.4.18-pre1/drivers/scsi/53c700.c	Thu Oct 11 09:43:29 2001
+++ linux/drivers/scsi/53c700.c	Mon Jan  7 16:42:53 2002
@@ -51,6 +51,14 @@
 
 /* CHANGELOG
  *
+ * Version 2.7
+ *
+ * Fixed scripts problem which caused certain devices (notably CDRWs)
+ * to hang on initial INQUIRY.  Updated NCR_700_readl/writel to use
+ * __raw_readl/writel for parisc compatibility (Thomas
+ * Bogendoerfer). Added missing SCp->request_bufflen initialisation
+ * for sense requests (Ryan Bradetich).
+ *
  * Version 2.6
  *
  * Following test of the 64 bit parisc kernel by Richard Hirst,
@@ -96,7 +104,7 @@
  * Initial modularisation from the D700.  See NCR_D700.c for the rest of
  * the changelog.
  * */
-#define NCR_700_VERSION "2.6"
+#define NCR_700_VERSION "2.7"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -1049,6 +1057,7 @@
 						    slot->pCmd,
 						    SCp->cmd_len,
 						    PCI_DMA_TODEVICE);
+				SCp->request_bufflen = sizeof(SCp->sense_buffer);
 				slot->dma_handle = pci_map_single(hostdata->pci_dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), PCI_DMA_FROMDEVICE);
 				slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer));
 				slot->SG[0].pAddr = bS_to_host(slot->dma_handle);
diff -urN linux-2.4.18-pre1/drivers/scsi/53c700.h linux/drivers/scsi/53c700.h
--- linux-2.4.18-pre1/drivers/scsi/53c700.h	Thu Oct 11 09:43:29 2001
+++ linux/drivers/scsi/53c700.h	Mon Jan  7 16:42:53 2002
@@ -210,7 +210,7 @@
 struct NCR_700_Host_Parameters {
 	/* These must be filled in by the calling driver */
 	int	clock;			/* board clock speed in MHz */
-	__u32	base;			/* the base for the port (copied to host) */
+	unsigned long	base;		/* the base for the port (copied to host) */
 	struct pci_dev	*pci_dev;
 	__u32	dmode_extra;	/* adjustable bus settings */
 	__u32	differential:1;	/* if we are differential */
@@ -503,7 +503,7 @@
 static inline __u32
 NCR_700_readl(struct Scsi_Host *host, __u32 reg)
 {
-	__u32 value = readl(host->base + reg);
+	__u32 value = __raw_readl(host->base + reg);
 	const struct NCR_700_Host_Parameters *hostdata __attribute__((unused))
 		= (struct NCR_700_Host_Parameters *)host->hostdata[0];
 #if 1
@@ -536,7 +536,7 @@
 		BUG();
 #endif
 
-	writel(bS_to_host(value), host->base + reg);
+	__raw_writel(bS_to_host(value), host->base + reg);
 }
 #elif defined(CONFIG_53C700_IO_MAPPED)
 static inline __u8
diff -urN linux-2.4.18-pre1/drivers/scsi/53c700.scr linux/drivers/scsi/53c700.scr
--- linux-2.4.18-pre1/drivers/scsi/53c700.scr	Sun Sep 30 12:26:08 2001
+++ linux/drivers/scsi/53c700.scr	Mon Jan  7 16:42:53 2002
@@ -242,7 +242,7 @@
 
 SendIdentifyMsg:
 	CALL	SendMessage
-	JUMP	SendCommand
+	CLEAR	ATN
 
 IgnoreMsgBeforeCommand:
 	CLEAR	ACK
diff -urN linux-2.4.18-pre1/drivers/scsi/NCR_D700.c linux/drivers/scsi/NCR_D700.c
--- linux-2.4.18-pre1/drivers/scsi/NCR_D700.c	Sun Sep  9 11:58:36 2001
+++ linux/drivers/scsi/NCR_D700.c	Mon Jan  7 16:42:53 2002
@@ -36,6 +36,10 @@
 
 /* CHANGELOG 
  *
+ * Version 2.2
+ *
+ * Added mca_set_adapter_name().
+ *
  * Version 2.1
  *
  * Modularise the driver into a Board piece (this file) and a chip
@@ -86,7 +90,7 @@
  * disconnections and reselections are being processed correctly.
  * */
 
-#define NCR_D700_VERSION "2.1"
+#define NCR_D700_VERSION "2.2"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -299,6 +303,7 @@
 				continue;
 			}
 			found++;
+			mca_set_adapter_name(slot, "NCR D700 SCSI Adapter (version " NCR_D700_VERSION ")");
 		}
 	}
 
diff -urN linux-2.4.18-pre1/drivers/scsi/aic7xxx/aic7xxx_linux.c linux/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- linux-2.4.18-pre1/drivers/scsi/aic7xxx/aic7xxx_linux.c	Wed Nov 21 14:05:29 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux.c	Mon Jan  7 16:42:53 2002
@@ -1703,6 +1703,7 @@
 			       cmd->request_buffer,
 			       cmd->request_bufflen,
 			       scsi_to_pci_dma_dir(cmd->sc_data_direction));
+			scb->sg_count = 0;
 			scb->sg_count = ahc_linux_map_seg(ahc, scb,
 							  sg, addr,
 							  cmd->request_bufflen);
diff -urN linux-2.4.18-pre1/drivers/scsi/lasi700.c linux/drivers/scsi/lasi700.c
--- linux-2.4.18-pre1/drivers/scsi/lasi700.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/scsi/lasi700.c	Mon Jan  7 16:42:53 2002
@@ -136,7 +136,6 @@
 lasi700_driver_callback(struct parisc_device *dev)
 {
 	unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET;
-	int irq = busdevice_alloc_irq(dev);
 	char *driver_name;
 	struct Scsi_Host *host;
 	struct NCR_700_Host_Parameters *hostdata =
@@ -170,14 +169,15 @@
 		hostdata->chip710 = 1;
 		hostdata->dmode_extra = DMODE_FC2;
 	}
+	hostdata->pci_dev = ccio_get_fake(dev);
 	if((host = NCR_700_detect(host_tpnt, hostdata)) == NULL) {
 		kfree(hostdata);
 		release_mem_region(host->base, 64);
 		return 1;
 	}
-	host->irq = irq;
-	if(request_irq(irq, NCR_700_intr, SA_SHIRQ, driver_name, host)) {
-		printk(KERN_ERR "%s: irq problem, detatching\n",
+	host->irq = dev->irq;
+	if(request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, driver_name, host)) {
+		printk(KERN_ERR "%s: irq problem, detaching\n",
 		       driver_name);
 		scsi_unregister(host);
 		NCR_700_release(host);
@@ -197,6 +197,7 @@
 	kfree(hostdata);
 	free_irq(host->irq, host);
 	release_mem_region(host->base, 64);
+	unregister_parisc_driver(&lasi700_driver);
 	return 1;
 }
 
diff -urN linux-2.4.18-pre1/drivers/scsi/mac_scsi.c linux/drivers/scsi/mac_scsi.c
--- linux-2.4.18-pre1/drivers/scsi/mac_scsi.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/mac_scsi.c	Mon Jan  7 16:42:53 2002
@@ -353,7 +353,7 @@
 	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
 	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
 
-	for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+	for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
 		barrier();
 
 	/* switch on SCSI IRQ again */
diff -urN linux-2.4.18-pre1/drivers/scsi/sun3_scsi.c linux/drivers/scsi/sun3_scsi.c
--- linux-2.4.18-pre1/drivers/scsi/sun3_scsi.c	Thu Oct 25 13:53:51 2001
+++ linux/drivers/scsi/sun3_scsi.c	Mon Jan  7 16:42:53 2002
@@ -357,7 +357,7 @@
 	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
 	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
 
-	for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+	for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
 		barrier();
 
 	/* switch on SCSI IRQ again */
diff -urN linux-2.4.18-pre1/drivers/sound/opl3sa2.c linux/drivers/sound/opl3sa2.c
--- linux-2.4.18-pre1/drivers/sound/opl3sa2.c	Thu Oct 11 09:43:30 2001
+++ linux/drivers/sound/opl3sa2.c	Mon Jan  7 16:42:53 2002
@@ -55,6 +55,7 @@
  *                         sb_card.c and awe_wave.c. (Dec 12, 2000)
  * Scott Murray            Some small cleanups to the init code output.
  *                         (Jan 7, 2001)
+ * Zwane Mwaikambo	   Added PM support. (Dec 4 2001)
  *
  */
 
@@ -62,13 +63,16 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/isapnp.h>
-
+#include <linux/pm.h>
 #include "sound_config.h"
 
 #include "ad1848.h"
 #include "mpu401.h"
 
+#define OPL3SA2_MODULE_NAME	"opl3sa2"
+
 /* Useful control port indexes: */
+#define OPL3SA2_PM	     0x01
 #define OPL3SA2_SYS_CTRL     0x02
 #define OPL3SA2_IRQ_CONFIG   0x03
 #define OPL3SA2_DMA_CONFIG   0x06
@@ -86,6 +90,11 @@
 #define DEFAULT_MIC    50
 #define DEFAULT_TIMBRE 0
 
+/* Power saving modes */
+#define OPL3SA2_PM_MODE1	0x05
+#define OPL3SA2_PM_MODE2	0x04
+#define OPL3SA2_PM_MODE3	0x03
+
 /* For checking against what the card returns: */
 #define VERSION_UNKNOWN 0
 #define VERSION_YMF711  1
@@ -121,6 +130,10 @@
 typedef struct opl3sa2_mixerdata_tag {
 	unsigned short cfg_port;
 	unsigned short padding;
+	unsigned char  pm_reg;
+	unsigned int   in_suspend;
+	struct pm_dev  *pmdev;
+	unsigned int   card;
 	unsigned int   volume_l;
 	unsigned int   volume_r;
 	unsigned int   mic;
@@ -328,6 +341,20 @@
 }
 
 
+static void opl3sa2_mixer_restore(opl3sa2_mixerdata* devc, int card)
+{
+	if (devc) {
+		opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
+		opl3sa2_set_mic(devc, devc->mic);
+
+		if (chipset[card] == CHIPSET_OPL3SA3) {
+			opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);
+			opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);
+		}
+	}
+}
+
+
 static inline void arg_to_vol_mono(unsigned int vol, int* value)
 {
 	int left;
@@ -608,9 +635,9 @@
 	char tag;
 
 	/*
-	 * Verify that the I/O port range is free.
+	 * Try and allocate our I/O port range.
 	 */
-	if(check_region(hw_config->io_base, 2)) {
+	if(!request_region(hw_config->io_base, 2, OPL3SA2_MODULE_NAME)) {
 		printk(KERN_ERR "opl3sa2: Control I/O port %#x not free\n",
 		       hw_config->io_base);
 		return 0;
@@ -699,7 +726,6 @@
 
 static void __init attach_opl3sa2(struct address_info* hw_config, int card)
 {
-   	request_region(hw_config->io_base, 2, chipset_name[card]);
 
 	/* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */
 	opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d);
@@ -892,6 +918,81 @@
 
 /* End of component functions */
 
+/* Power Management support functions */
+static int opl3sa2_suspend(struct pm_dev *pdev, unsigned char pm_mode)
+{
+	unsigned long flags;
+	opl3sa2_mixerdata *p;
+
+	if (!pdev)
+		return -EINVAL;
+
+	save_flags(flags);
+	cli();
+
+	p = (opl3sa2_mixerdata *) pdev->data;
+
+	switch (pm_mode) {
+	case 1:
+		pm_mode = OPL3SA2_PM_MODE1;
+		break;
+	case 2:
+		pm_mode = OPL3SA2_PM_MODE2;
+		break;
+	case 3:
+		pm_mode = OPL3SA2_PM_MODE3;
+		break;
+	default:
+		/* we don't know howto handle this... */
+		restore_flags(flags);
+		return -EBUSY;
+	}
+
+	p->in_suspend = 1;
+	/* its supposed to automute before suspending, so we wont bother */
+	opl3sa2_read(p->cfg_port, OPL3SA2_PM, &p->pm_reg);
+	opl3sa2_write(p->cfg_port, OPL3SA2_PM, p->pm_reg | pm_mode);
+	/* wait a while for the clock oscillator to stabilise */
+	mdelay(10);
+
+	restore_flags(flags);
+	return 0;
+}
+
+static int opl3sa2_resume(struct pm_dev *pdev)
+{
+	unsigned long flags;
+	opl3sa2_mixerdata *p;
+
+	if (!pdev)
+		return -EINVAL;
+
+	p = (opl3sa2_mixerdata *) pdev->data;
+	save_flags(flags);
+	cli();
+
+	/* I don't think this is necessary */
+	opl3sa2_write(p->cfg_port, OPL3SA2_PM, p->pm_reg);
+	opl3sa2_mixer_restore(p, p->card);
+	p->in_suspend = 0;
+
+	restore_flags(flags);
+	return 0;
+}
+
+static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
+{
+	unsigned char mode = (unsigned  char)data;
+
+	switch (rqst) {
+		case PM_SUSPEND:
+			return opl3sa2_suspend(pdev, mode);
+
+		case PM_RESUME:
+			return opl3sa2_resume(pdev);
+	}
+	return 0;
+}
 
 /*
  * Install OPL3-SA2 based card(s).
@@ -989,6 +1090,12 @@
 		attach_opl3sa2_mss(&cfg_mss[card]);
 		attach_opl3sa2_mixer(&cfg[card], card);
 
+		opl3sa2_data[card].card = card;
+		/* register our power management capabilities */
+		opl3sa2_data[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback);
+		if (opl3sa2_data[card].pmdev)
+			opl3sa2_data[card].pmdev->data = &opl3sa2_data[card];
+
 		/*
 		 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
 		 * it's supported.
@@ -1033,6 +1140,9 @@
 	int card;
 
 	for(card = 0; card < opl3sa2_cards_num; card++) {
+		if (opl3sa2_data[card].pmdev)
+			pm_unregister(opl3sa2_data[card].pmdev);
+
 	        if(cfg_mpu[card].slots[1] != -1) {
 			unload_opl3sa2_mpu(&cfg_mpu[card]);
 		}
diff -urN linux-2.4.18-pre1/drivers/video/aty128.h linux/drivers/video/aty128.h
--- linux-2.4.18-pre1/drivers/video/aty128.h	Sun Sep 17 09:48:04 2000
+++ linux/drivers/video/aty128.h	Mon Jan  7 16:42:53 2002
@@ -13,6 +13,7 @@
 #define CLOCK_CNTL_DATA				0x000c
 #define BIOS_0_SCRATCH				0x0010
 #define BUS_CNTL				0x0030
+#define BUS_CNTL1				0x0034
 #define GEN_INT_CNTL				0x0040
 #define CRTC_GEN_CNTL				0x0050
 #define CRTC_EXT_CNTL				0x0054
@@ -24,6 +25,7 @@
 #define GEN_RESET_CNTL				0x00f0
 #define CONFIG_MEMSIZE				0x00f8
 #define MEM_CNTL				0x0140
+#define MEM_POWER_MISC				0x015c
 #define AGP_BASE				0x0170
 #define AGP_CNTL				0x0174
 #define AGP_APER_OFFSET				0x0178
@@ -37,6 +39,9 @@
 #define CRTC_H_SYNC_STRT_WID			0x0204
 #define CRTC_V_TOTAL_DISP			0x0208
 #define CRTC_V_SYNC_STRT_WID			0x020c
+#define CRTC_VLINE_CRNT_VLINE			0x0210
+#define CRTC_CRNT_FRAME				0x0214
+#define CRTC_GUI_TRIG_VLINE			0x0218
 #define CRTC_OFFSET				0x0224
 #define CRTC_OFFSET_CNTL			0x0228
 #define CRTC_PITCH				0x022c
@@ -48,6 +53,20 @@
 #define DDA_ON_OFF				0x02e4
 #define VGA_DDA_CONFIG				0x02e8
 #define VGA_DDA_ON_OFF				0x02ec
+#define CRTC2_H_TOTAL_DISP			0x0300
+#define CRTC2_H_SYNC_STRT_WID			0x0304
+#define CRTC2_V_TOTAL_DISP			0x0308
+#define CRTC2_V_SYNC_STRT_WID			0x030c
+#define CRTC2_VLINE_CRNT_VLINE			0x0310
+#define CRTC2_CRNT_FRAME			0x0314
+#define CRTC2_GUI_TRIG_VLINE			0x0318
+#define CRTC2_OFFSET				0x0324
+#define CRTC2_OFFSET_CNTL			0x0328
+#define CRTC2_PITCH				0x032c
+#define DDA2_CONFIG				0x03e0
+#define DDA2_ON_OFF				0x03e4
+#define CRTC2_GEN_CNTL				0x03f8
+#define CRTC2_STATUS				0x03fc
 #define OV0_SCALE_CNTL				0x0420
 #define SUBPIC_CNTL				0x0540
 #define PM4_BUFFER_OFFSET			0x0700
@@ -237,6 +256,10 @@
 #define AGP_PLL_CNTL				0x0010
 #define FCP_CNTL				0x0012
 #define PLL_TEST_CNTL				0x0013
+#define P2PLL_CNTL				0x002a
+#define P2PLL_REF_DIV				0x002b
+#define P2PLL_DIV_0				0x002b
+#define POWER_MANAGEMENT			0x002f
 
 #define PPLL_RESET				0x01
 #define PPLL_ATOMIC_UPDATE_EN			0x10000
@@ -254,6 +277,14 @@
 /* CRTC control values (CRTC_GEN_CNTL) */
 #define CRTC_CSYNC_EN				0x00000010
 
+#define CRTC2_DBL_SCAN_EN			0x00000001
+#define CRTC2_DISPLAY_DIS			0x00800000
+#define CRTC2_FIFO_EXTSENSE			0x00200000
+#define CRTC2_ICON_EN				0x00100000
+#define CRTC2_CUR_EN				0x00010000
+#define CRTC2_EN				0x02000000
+#define CRTC2_DISP_REQ_EN_B			0x04000000
+
 #define CRTC_PIX_WIDTH_MASK			0x00000700
 #define CRTC_PIX_WIDTH_4BPP			0x00000100
 #define CRTC_PIX_WIDTH_8BPP			0x00000200
@@ -267,10 +298,14 @@
 #define DAC_MASK				0xFF000000
 #define DAC_BLANKING				0x00000004
 #define DAC_RANGE_CNTL				0x00000003
-#define DAC_RANGE_CNTL				0x00000003
+#define DAC_CLK_SEL				0x00000010
 #define DAC_PALETTE_ACCESS_CNTL			0x00000020
+#define DAC_PALETTE2_SNOOP_EN			0x00000040
 #define DAC_PDWN				0x00008000
 
+/* CRTC_EXT_CNTL */
+#define CRT_CRTC_ON				0x00008000
+
 /* GEN_RESET_CNTL bit constants */
 #define SOFT_RESET_GUI				0x00000001
 #define SOFT_RESET_VCLK				0x00000100
@@ -348,5 +383,37 @@
 #define LVDS_BL_MOD_EN				0x00010000
 #define LVDS_DIGION				0x00040000
 #define LVDS_BLON				0x00080000
+#define LVDS_ON					0x00000001
+#define LVDS_DISPLAY_DIS			0x00000002
+#define LVDS_PANEL_TYPE_2PIX_PER_CLK		0x00000004
+#define LVDS_PANEL_24BITS_TFT			0x00000008
+#define LVDS_FRAME_MOD_NO			0x00000000
+#define LVDS_FRAME_MOD_2_LEVELS			0x00000010
+#define LVDS_FRAME_MOD_4_LEVELS			0x00000020
+#define LVDS_RST_FM				0x00000040
+#define LVDS_EN					0x00000080
+
+/* CRTC2_GEN_CNTL constants */
+#define CRTC2_EN				0x02000000
+
+/* POWER_MANAGEMENT constants */
+#define	PWR_MGT_ON				0x00000001
+#define PWR_MGT_MODE_MASK			0x00000006
+#define PWR_MGT_MODE_PIN			0x00000000
+#define PWR_MGT_MODE_REGISTER			0x00000002
+#define PWR_MGT_MODE_TIMER			0x00000004
+#define PWR_MGT_MODE_PCI			0x00000006
+#define PWR_MGT_AUTO_PWR_UP_EN			0x00000008
+#define PWR_MGT_ACTIVITY_PIN_ON			0x00000010
+#define PWR_MGT_STANDBY_POL			0x00000020
+#define PWR_MGT_SUSPEND_POL			0x00000040
+#define PWR_MGT_SELF_REFRESH			0x00000080
+#define PWR_MGT_ACTIVITY_PIN_EN			0x00000100
+#define PWR_MGT_KEYBD_SNOOP			0x00000200
+#define PWR_MGT_TRISTATE_MEM_EN			0x00000800
+#define PWR_MGT_SELW4MS				0x00001000
+#define PWR_MGT_SLOWDOWN_MCLK			0x00002000
+
+#define PMI_PMSCR_REG				0x60
 
 #endif /* REG_RAGE128_H */
diff -urN linux-2.4.18-pre1/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c
--- linux-2.4.18-pre1/drivers/video/aty128fb.c	Sun Nov 11 10:09:37 2001
+++ linux/drivers/video/aty128fb.c	Mon Jan  7 16:42:53 2002
@@ -7,13 +7,19 @@
  *                Ani Joshi / Jeff Garzik
  *                      - Code cleanup
  *
+ *                Michel Dänzer <michdaen@iiic.ethz.ch>
+ *                      - 15/16 bit cleanup
+ *                      - fix panning
+ *                      
+ *                Benjamin Herrenschmidt
+ *                      - pmac-specific PM stuff
+ *
  *                Andreas Hundt <andi@convergence.de>
  *                      - FB_ACTIVATE fixes
  *
  *  Based off of Geert's atyfb.c and vfb.c.
  *
  *  TODO:
- *		- panning
  *		- monitor sensing (DDC)
  *              - virtual display
  *		- other platform support (only ppc/x86 supported)
@@ -70,6 +76,9 @@
 #ifdef CONFIG_FB_COMPAT_XPMAC
 #include <asm/vc_ioctl.h>
 #endif
+#ifdef CONFIG_BOOTX_TEXT
+#include <asm/btext.h>
+#endif /* CONFIG_BOOTX_TEXT */
 
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -154,6 +163,7 @@
     {"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL, rage_128},
     {"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF, rage_128_pro},
     {"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR, rage_128_pro},
+    {"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3, rage_128_pro},
     {"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE, rage_M3},
     {"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF, rage_M3},
     {NULL, 0, rage_128}
@@ -227,6 +237,11 @@
 static int default_cmode __initdata = CMODE_8;
 #endif
 
+#ifdef CONFIG_PMAC_PBOOK
+static int default_crt_on __initdata = 0;
+static int default_lcd_on __initdata = 1;
+#endif
+
 #ifdef CONFIG_MTRR
 static int mtrr = 1;
 #endif
@@ -251,7 +266,7 @@
     u32 offset, offset_cntl;
     u32 xoffset, yoffset;
     u32 vxres, vyres;
-    u32 bpp;
+    u32 depth, bpp;
 };
 
 struct aty128_pll {
@@ -307,10 +322,23 @@
     int currcon;
     int blitter_may_be_busy;
     int fifo_slots;                 /* free slots in FIFO (64 max) */
+#ifdef CONFIG_PMAC_PBOOK
+    unsigned char *save_framebuffer;
+    int	pm_reg;
+    int crt_on, lcd_on;
+    u32 save_lcd_gen_cntl;
+#endif
 };
 
 static struct fb_info_aty128 *board_list = NULL;
 
+#ifdef CONFIG_PMAC_PBOOK
+  int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
+  static struct pmu_sleep_notifier aty128_sleep_notifier = {
+  	aty128_sleep_notify, SLEEP_LEVEL_VIDEO,
+  };
+#endif
+
 #define round_div(n, d) ((n+(d/2))/d)
 
     /*
@@ -331,6 +359,8 @@
 			struct fb_info *info);
 static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
 			   struct fb_info *fb);
+static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info);
 static int aty128fb_rasterimg(struct fb_info *info, int start);
 
 
@@ -379,7 +409,7 @@
 static void do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info);
 static void wait_for_fifo(u16 entries, struct fb_info_aty128 *info);
 static void wait_for_idle(struct fb_info_aty128 *info);
-static u32 bpp_to_depth(u32 bpp);
+static u32 depth_to_dst(u32 depth);
 
 #ifdef FBCON_HAS_CFB8
 static struct display_switch fbcon_aty128_8;
@@ -422,6 +452,7 @@
 	fb_get_cmap:	aty128fb_get_cmap,
 	fb_set_cmap:	aty128fb_set_cmap,
 	fb_pan_display:	aty128fb_pan_display,
+	fb_ioctl:	aty128fb_ioctl,
 	fb_rasterimg:	aty128fb_rasterimg,
 };
 
@@ -496,7 +527,7 @@
 _aty_ld_pll(unsigned int pll_index,
 			const struct fb_info_aty128 *info)
 {       
-    aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x1F);
+    aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F);
     return aty_ld_le32(CLOCK_CNTL_DATA);
 }
 
@@ -505,7 +536,7 @@
 _aty_st_pll(unsigned int pll_index, u32 val,
 			const struct fb_info_aty128 *info)
 {
-    aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x1F) | PLL_WR_EN);
+    aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x3F) | PLL_WR_EN);
     aty_st_le32(CLOCK_CNTL_DATA, val);
 }
 
@@ -698,7 +729,7 @@
 		GMC_SRC_CLIP_DEFAULT			|
 		GMC_DST_CLIP_DEFAULT			|
 		GMC_BRUSH_SOLIDCOLOR			|
-		(bpp_to_depth(par->crtc.bpp) << 8)	|
+		(depth_to_dst(par->crtc.depth) << 8)	|
 		GMC_SRC_DSTCOLOR			|
 		GMC_BYTE_ORDER_MSB_TO_LSB		|
 		GMC_DP_CONVERSION_TEMP_6500		|
@@ -731,18 +762,20 @@
 }
 
 
-/* convert bpp values to their register representation */
+/* convert depth values to their register representation */
 static u32
-bpp_to_depth(u32 bpp)
-{
-    if (bpp <= 8)
-	return DST_8BPP;
-    else if (bpp <= 16)
-        return DST_15BPP;
-    else if (bpp <= 24)
-	return DST_24BPP;
-    else if (bpp <= 32)
-	return DST_32BPP;
+depth_to_dst(u32 depth)
+ {
+    if (depth <= 8)
+ 	return DST_8BPP;
+    else if (depth <= 15)
+         return DST_15BPP;
+    else if (depth == 16)
+        return DST_16BPP;
+    else if (depth <= 24)
+ 	return DST_24BPP;
+    else if (depth <= 32)
+ 	return DST_32BPP;
 
     return -EINVAL;
 }
@@ -765,12 +798,8 @@
     aty_st_le32(CRTC_PITCH, crtc->pitch);
     aty_st_le32(CRTC_OFFSET, crtc->offset);
     aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl);
-    /* Disable ATOMIC updating.  Is this the right place?
-     * -- BenH: Breaks on my G4
-     */
-#if 0
-    aty_st_le32(PPLL_CNTL, aty_ld_le32(PPLL_CNTL) & ~(0x00030000));
-#endif
+    /* Disable ATOMIC updating.  Is this the right place? */
+    aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~(0x00030000));
 }
 
 
@@ -779,7 +808,7 @@
 			struct aty128_crtc *crtc,
 			const struct fb_info_aty128 *info)
 {
-    u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
+    u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp, dst;
     u32 left, right, upper, lower, hslen, vslen, sync, vmode;
     u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
     u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
@@ -804,6 +833,11 @@
     sync  = var->sync;
     vmode = var->vmode;
 
+    if (bpp != 16)
+        depth = bpp;
+    else
+        depth = (var->green.length == 6) ? 16 : 15;
+
     /* check for mode eligibility
      * accept only non interlaced modes */
     if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
@@ -819,17 +853,16 @@
     if (vyres < yres + yoffset)
 	vyres = yres + yoffset;
 
-    /* convert bpp into ATI register depth */
-    depth = bpp_to_depth(bpp);
+    /* convert depth into ATI register depth */
+    dst = depth_to_dst(depth);
 
-    /* make sure we didn't get an invalid depth */
-    if (depth == -EINVAL) {
-        printk(KERN_ERR "aty128fb: Invalid depth\n");
+    if (dst == -EINVAL) {
+        printk(KERN_ERR "aty128fb: Invalid depth or RGBA\n");
         return -EINVAL;
     }
 
-    /* convert depth to bpp */
-    bytpp = mode_bytpp[depth];
+    /* convert register depth to bytes per pixel */
+    bytpp = mode_bytpp[dst];
 
     /* make sure there is enough video ram for the mode */
     if ((u32)(vxres * vyres * bytpp) > info->vram_size) {
@@ -870,7 +903,7 @@
     
     c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
 
-    crtc->gen_cntl = 0x3000000L | c_sync | (depth << 8);
+    crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8);
 
     crtc->h_total = h_total | (h_disp << 16);
     crtc->v_total = v_total | (v_disp << 16);
@@ -893,6 +926,7 @@
     crtc->vyres = vyres;
     crtc->xoffset = xoffset;
     crtc->yoffset = yoffset;
+    crtc->depth = depth;
     crtc->bpp = bpp;
 
     return 0;
@@ -900,7 +934,7 @@
 
 
 static int
-aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
+aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
 {
 
     /* fill in pixel info */
@@ -917,7 +951,6 @@
 	var->transp.length = 0;
 	break;
     case CRTC_PIX_WIDTH_15BPP:
-    case CRTC_PIX_WIDTH_16BPP:
 	var->bits_per_pixel = 16;
 	var->red.offset = 10;
 	var->red.length = 5;
@@ -928,6 +961,17 @@
 	var->transp.offset = 0;
 	var->transp.length = 0;
 	break;
+    case CRTC_PIX_WIDTH_16BPP:
+	var->bits_per_pixel = 16;
+	var->red.offset = 11;
+	var->red.length = 5;
+	var->green.offset = 5;
+	var->green.length = 6;
+	var->blue.offset = 0;
+	var->blue.length = 5;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	break;
     case CRTC_PIX_WIDTH_24BPP:
         var->bits_per_pixel = 24;
         var->red.offset = 16;
@@ -996,7 +1040,7 @@
             (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
             (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
 
-    aty128_bpp_to_var(pix_width, var);
+    aty128_pix_width_to_var(pix_width, var);
 
     var->xres = xres;
     var->yres = yres;
@@ -1017,6 +1061,42 @@
 }
 
 static void
+aty128_set_crt_enable(struct fb_info_aty128 *info, int on)
+{
+    if (on) {
+	aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) | CRT_CRTC_ON);
+	aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) | DAC_PALETTE2_SNOOP_EN));
+    } else
+	aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) & ~CRT_CRTC_ON);
+}
+
+static void
+aty128_set_lcd_enable(struct fb_info_aty128 *info, int on)
+{
+    u32 reg;
+    
+    if (on) {
+	reg = aty_ld_le32(LVDS_GEN_CNTL);
+	reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
+	reg &= ~LVDS_DISPLAY_DIS;
+	aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef CONFIG_PMAC_BACKLIGHT
+	aty128_set_backlight_enable(get_backlight_enable(), get_backlight_level(), info);
+#endif	
+    } else {
+#ifdef CONFIG_PMAC_BACKLIGHT
+	aty128_set_backlight_enable(0, 0, info);
+#endif	
+	reg = aty_ld_le32(LVDS_GEN_CNTL);
+	reg |= LVDS_DISPLAY_DIS;
+        aty_st_le32(LVDS_GEN_CNTL, reg);
+        mdelay(100);
+	reg &= ~(LVDS_ON /*| LVDS_EN*/);
+	aty_st_le32(LVDS_GEN_CNTL, reg);
+    }
+}
+
+static void
 aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
 {
     u32 div3;
@@ -1053,6 +1133,23 @@
 
     /* clear the reset, just in case */
     aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
+
+#if 0
+    if (info->chip_gen == rage_M3) {
+	/* XXX energy saving, disable VCLK during blanking */
+	aty_pll_wait_readupdate(info);
+    	aty_st_pll(VCLK_ECP_CNTL, aty_ld_pll(VCLK_ECP_CNTL) | 0xc0);
+		aty_pll_writeupdate(info);
+
+	/* Set PM clocks */
+	aty_pll_wait_readupdate(info);
+	aty_st_pll(XCLK_CNTL, aty_ld_pll(XCLK_CNTL) | 0x00330000);
+	aty_pll_writeupdate(info);
+	aty_pll_wait_readupdate(info);
+	aty_st_pll(MCLK_CNTL, aty_ld_pll(MCLK_CNTL) | 0x00000700);
+	aty_pll_writeupdate(info);
+    }
+#endif    
 }
 
 
@@ -1121,7 +1218,7 @@
 static int
 aty128_ddafifo(struct aty128_ddafifo *dsp,
 		const struct aty128_pll *pll,
-		u32 bpp,
+		u32 depth,
 		const struct fb_info_aty128 *info)
 {
     const struct aty128_meminfo *m = info->mem;
@@ -1129,11 +1226,10 @@
     u32 fifo_width = info->constants.fifo_width;
     u32 fifo_depth = info->constants.fifo_depth;
     s32 x, b, p, ron, roff;
-    u32 n, d;
+    u32 n, d, bpp;
 
-    /* 15bpp is really 16bpp */
-    if (bpp == 15)
-	bpp = 16;
+    /* round up to multiple of 8 */
+    bpp = (depth+7) & ~7;
 
     n = xclk * fifo_width;
     d = pll->vclk * bpp;
@@ -1214,15 +1310,21 @@
     config = aty_ld_le32(CONFIG_CNTL) & ~3;
 
 #if defined(__BIG_ENDIAN)
-    if (par->crtc.bpp >= 24)
-	config |= 2;	/* make aperture do 32 byte swapping */
-    else if (par->crtc.bpp > 8)
-	config |= 1;	/* make aperture do 16 byte swapping */
+    if (par->crtc.bpp == 32)
+	config |= 2;	/* make aperture do 32 bit swapping */
+    else if (par->crtc.bpp == 16)
+	config |= 1;	/* make aperture do 16 bit swapping */
 #endif
 
     aty_st_le32(CONFIG_CNTL, config);
     aty_st_8(CRTC_EXT_CNTL + 1, 0);	/* turn the video back on */
 
+#ifdef CONFIG_PMAC_PBOOK
+    if (info->chip_gen == rage_M3) {
+	aty128_set_crt_enable(info, info->crt_on);
+	aty128_set_lcd_enable(info, info->lcd_on);
+    }
+#endif
     if (par->accel_flags & FB_ACCELF_TEXT)
         aty128_init_engine(par, info);
 
@@ -1247,6 +1349,13 @@
 	display_info.disp_reg_address = info->regbase_phys;
     }
 #endif /* CONFIG_FB_COMPAT_XPMAC */
+#if defined(CONFIG_BOOTX_TEXT)
+    btext_update_display(info->frame_buffer_phys,
+		    (((par->crtc.h_total>>16) & 0xff)+1)*8,
+		    ((par->crtc.v_total>>16) & 0x7ff)+1,
+		    par->crtc.bpp,
+		    par->crtc.vxres*par->crtc.bpp/8);
+#endif /* CONFIG_BOOTX_TEXT */
 }
 
     /*
@@ -1265,7 +1374,7 @@
     if ((err = aty128_var_to_pll(var->pixclock, &par->pll, info)))
 	return err;
 
-    if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info)))
+    if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.depth, info)))
 	return err;
 
     if (var->accel_flags & FB_ACCELF_TEXT)
@@ -1333,7 +1442,7 @@
     struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
     struct aty128fb_par par;
     struct display *display;
-    int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
+    int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldgreen, oldaccel;
     int accel, err;
 
     display = (con >= 0) ? &fb_display[con] : fb->disp;
@@ -1378,11 +1487,13 @@
     oldvxres = display->var.xres_virtual;
     oldvyres = display->var.yres_virtual;
     oldbpp = display->var.bits_per_pixel;
+    oldgreen = display->var.green.length;
     oldaccel = display->var.accel_flags;
     display->var = *var;
     if (oldxres != var->xres || oldyres != var->yres ||
 	oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
-	oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
+	oldgreen != var->green.length || oldbpp != var->bits_per_pixel ||
+	oldaccel != var->accel_flags) {
 
 	struct fb_fix_screeninfo fix;
 
@@ -1412,7 +1523,7 @@
     if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con)
 	aty128_set_par(&par, info);
 
-    if (oldbpp != var->bits_per_pixel) {
+    if (oldbpp != var->bits_per_pixel || oldgreen != var->green.length) {
 	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
 	    return err;
 	do_install_cmap(con, &info->fb_info);
@@ -1433,7 +1544,6 @@
 	break;
 #endif
 #ifdef FBCON_HAS_CFB16
-    case 15:
     case 16:
 	disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
 	disp->dispsw_data = info->fbcon_cmap.cfb16;
@@ -1475,7 +1585,7 @@
     fix->type        = FB_TYPE_PACKED_PIXELS;
     fix->type_aux    = 0;
     fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
-    fix->visual      = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
+    fix->visual      = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR
                                           : FB_VISUAL_DIRECTCOLOR;
     fix->ywrapstep = 0;
     fix->xpanstep  = 8;
@@ -1509,8 +1619,6 @@
 
     /*
      *  Pan or Wrap the Display
-     *
-     *  Not supported (yet!)
      */
 static int
 aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
@@ -1534,7 +1642,10 @@
     par->crtc.xoffset = xoffset;
     par->crtc.yoffset = yoffset;
 
-    offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6;
+    offset = ((yoffset * par->crtc.vxres + xoffset)*(par->crtc.bpp >> 3)) & ~7;
+
+    if (par->crtc.bpp == 24)
+        offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */
 
     aty_st_le32(CRTC_OFFSET, offset);
 
@@ -1550,20 +1661,16 @@
 aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			struct fb_info *info)
 {
-#if 1
-    fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
-#else
-    struct fb_info_aty128 fb = (struct fb_info_aty128 *)info;
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
+    struct display *disp = (con < 0) ? info->disp : (fb_display + con);
 
     if (con == fb->currcon) /* current console? */
-	return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
-    else if (fb_display[con].cmap.len) /* non default colormap? */
-	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-    else {  
-	int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
-	fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
-    }
-#endif
+        return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
+    else if (disp->cmap.len) /* non default colormap? */
+        fb_copy_cmap(&disp->cmap, cmap, kspc ? 0 : 2);
+    else
+        fb_copy_cmap(fb_default_cmap((disp->var.bits_per_pixel==8) ? 256 : 32),
+                     cmap, kspc ? 0 : 2);
 
     return 0;
 }
@@ -1576,19 +1683,19 @@
 aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 			struct fb_info *info)
 {
-    int err;
     struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
-    struct display *disp;  
+    struct display *disp = (con < 0) ? info->disp : (fb_display + con);
+    unsigned int cmap_len = (disp->var.bits_per_pixel==8) ? 256 : 32;
 
-    if (con >= 0)
-	disp = &fb_display[con];
-    else
-	disp = info->disp;
+    if (disp->cmap.len != cmap_len) {
+        int err = fb_alloc_cmap(&disp->cmap, cmap_len, 0);
 
-    if (!disp->cmap.len) {      /* no colormap allocated? */
-        int size = (disp->var.bits_per_pixel <= 8) ? 256 : 32;
-	if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
-	    return err;
+    	if (!disp->cmap.len) {      /* no colormap allocated? */
+        	int size = (disp->var.bits_per_pixel <= 8) ? 256 : 32;
+		if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
+		    return err;
+	}
+        if (err) return err;
     }
 
     if (con == fb->currcon) /* current console? */
@@ -1599,6 +1706,31 @@
     return 0;                
 }
 
+    /*
+     *  Helper function to store a single palette register
+     */
+static __inline__ void
+aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
+	      struct fb_info_aty128 *info)
+{
+    /* Note: For now, on M3, we set palette on both heads, which may
+     * be useless. Can someone with a M3 check this ?
+     * 
+     * This code would still be useful if using the second CRTC to 
+     * do mirroring
+     */
+
+    if (info->chip_gen == rage_M3) {
+#if 0
+        aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
+        aty_st_8(PALETTE_INDEX, regno);
+        aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
+#endif
+        aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
+    }
+    aty_st_8(PALETTE_INDEX, regno);
+    aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
+}
 
 static int
 aty128fb_rasterimg(struct fb_info *info, int start)
@@ -1620,7 +1752,7 @@
     if (!options || !*options)
 	return 0;
 
-    while (this_opt = strsep(&options, ",")) {
+    while ((this_opt = strsep(&options, ",")) != 0) {
 	if (!strncmp(this_opt, "font:", 5)) {
 	    char *p;
 	    int i;
@@ -1633,6 +1765,12 @@
 	    fontname[i] = 0;
 	} else if (!strncmp(this_opt, "noaccel", 7)) {
 	    noaccel = 1;
+#ifdef CONFIG_PMAC_PBOOK
+        } else if (!strncmp(this_opt, "lcd:", 4)) {
+            default_lcd_on = simple_strtoul(this_opt+4, NULL, 0);
+        } else if (!strncmp(this_opt, "crt:", 4)) {
+            default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
+#endif
         }
 #ifdef CONFIG_MTRR
         else if(!strncmp(this_opt, "nomtrr", 6)) {
@@ -1713,7 +1851,11 @@
     info->fb_info.updatevar  = NULL;
     info->fb_info.blank = &aty128fbcon_blank;
     info->fb_info.flags = FBINFO_FLAG_DEFAULT;
-
+#ifdef CONFIG_PMAC_PBOOK
+    info->lcd_on = default_lcd_on;
+    info->crt_on = default_crt_on;
+#endif
+    
     var = default_var;
 #ifdef CONFIG_PPC
     if (_machine == _MACH_Pmac) {
@@ -1724,6 +1866,29 @@
             if (default_vmode <= 0 || default_vmode > VMODE_MAX)
                 default_vmode = VMODE_1024_768_60;
 
+	    /* iMacs need that resolution
+	     * PowerMac2,1 first r128 iMacs
+	     * PowerMac2,2 summer 2000 iMacs
+	     * PowerMac4,1 january 2001 iMacs "flower power"
+	     */
+	    if (machine_is_compatible("PowerMac2,1") ||
+		machine_is_compatible("PowerMac2,2") ||
+		machine_is_compatible("PowerMac4,1"))
+		default_vmode = VMODE_1024_768_75;
+
+	    /* iBook SE */
+	    if (machine_is_compatible("PowerBook2,2"))
+		default_vmode = VMODE_800_600_60;
+ 
+	    /* PowerBook Firewire (Pismo), iBook Dual USB */
+	    if (machine_is_compatible("PowerBook3,1") ||
+	    	machine_is_compatible("PowerBook4,1"))
+		default_vmode = VMODE_1024_768_60;
+
+	    /* PowerBook Titanium */
+	    if (machine_is_compatible("PowerBook3,2"))
+		default_vmode = VMODE_1152_768_60;
+
             if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
                 default_cmode = CMODE_8;
 
@@ -1760,6 +1925,8 @@
     dac = aty_ld_le32(DAC_CNTL);
     dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
     dac |= DAC_MASK;
+    if (info->chip_gen == rage_M3)
+    	dac |= DAC_PALETTE2_SNOOP_EN;
     aty_st_le32(DAC_CNTL, dac);
 
     /* turn off bus mastering, just in case */
@@ -1778,6 +1945,14 @@
     if (info->chip_gen == rage_M3)
     	register_backlight_controller(&aty128_backlight_controller, info, "ati");
 #endif /* CONFIG_PMAC_BACKLIGHT */
+#ifdef CONFIG_PMAC_PBOOK
+    if (!info->pdev)
+    	printk(KERN_WARNING "aty128fb: Not a PCI card, can't enable power management\n");
+    else {
+	    info->pm_reg = pci_find_capability(info->pdev, PCI_CAP_ID_PM);
+	    pmu_register_sleep_notifier(&aty128_sleep_notifier);
+    }
+#endif
 
     printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
 	   GET_FB_IDX(info->fb_info.node), aty128fb_name, name);
@@ -1843,7 +2018,7 @@
 	if ((err = pci_enable_device(pdev))) {
 		printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n",
 				err);
-		goto err_out;
+		return -ENODEV;
 	}
 
 	fb_addr = pci_resource_start(pdev, 0);
@@ -2162,6 +2337,12 @@
 
     aty_st_8(CRTC_EXT_CNTL+1, state);
 
+#ifdef CONFIG_PMAC_PBOOK
+    if (info->chip_gen == rage_M3) {
+	aty128_set_crt_enable(info, info->crt_on && !blank);
+	aty128_set_lcd_enable(info, info->lcd_on && !blank);
+    }
+#endif	
 #ifdef CONFIG_PMAC_BACKLIGHT
     if ((_machine == _MACH_Pmac) && !blank)
     	set_backlight_enable(1);
@@ -2200,7 +2381,7 @@
                          u_int transp, struct fb_info *fb)
 {
     struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
-    u32 col;
+    u32 palreg;
 
     if (regno > 255)
 	return 1;
@@ -2220,65 +2401,47 @@
     if ((info->current_par.crtc.bpp > 8) && (regno == 0)) {
         int i;
 
-        if (info->chip_gen == rage_M3)
-            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
-
-        for (i=16; i<256; i++) {
-            aty_st_8(PALETTE_INDEX, i);
-            col = (i << 16) | (i << 8) | i;
-            aty_st_le32(PALETTE_DATA, col);
-        }
-
-        if (info->chip_gen == rage_M3) {
-            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
-
-            for (i=16; i<256; i++) {
-                aty_st_8(PALETTE_INDEX, i);
-                col = (i << 16) | (i << 8) | i;
-                aty_st_le32(PALETTE_DATA, col);
-            }
-        }
+        for (i=0; i<256; i++)
+            aty128_st_pal(i, i, i, i, info);
     }
 
     /* initialize palette */
 
-    if (info->chip_gen == rage_M3)
-        aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
+    palreg = regno;
 
     if (info->current_par.crtc.bpp == 16)
-        aty_st_8(PALETTE_INDEX, (regno << 3));
-    else
-        aty_st_8(PALETTE_INDEX, regno);
-    col = (red << 16) | (green << 8) | blue;
-    aty_st_le32(PALETTE_DATA, col);
-    if (info->chip_gen == rage_M3) {
-    	aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
-        if (info->current_par.crtc.bpp == 16)
-            aty_st_8(PALETTE_INDEX, (regno << 3));
-        else
-            aty_st_8(PALETTE_INDEX, regno);
-        aty_st_le32(PALETTE_DATA, col);
+        palreg = regno * 8;
+
+    if (info->current_par.crtc.depth == 16) {
+        aty128_st_pal(palreg/2, info->palette[regno/2].red, green,
+                      info->palette[regno/2].blue, info);
+        green = info->palette[regno*2].green;
     }
 
+    if (info->current_par.crtc.bpp == 8 || regno < 32)
+        aty128_st_pal(palreg, red, green, blue, info);
+        
     if (regno < 16)
-	switch (info->current_par.crtc.bpp) {
+	switch (info->current_par.crtc.depth) {
 #ifdef FBCON_HAS_CFB16
-	case 9 ... 16:
+	case 15:
 	    info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
                 regno;
 	    break;
+	case 16:
+	    info->fbcon_cmap.cfb16[regno] = (regno << 11) | (regno << 5) |
+                regno;
+	    break;
 #endif
 #ifdef FBCON_HAS_CFB24
-	case 17 ... 24:
+	case 24:
 	    info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
 		regno;
 	    break;
 #endif
 #ifdef FBCON_HAS_CFB32
-	case 25 ... 32: {
-            u32 i;
-
-            i = (regno << 8) | regno;
+	case 32: {
+            u32 i = (regno << 8) | regno;
             info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
 	    break;
         }
@@ -2291,41 +2454,115 @@
 static void
 do_install_cmap(int con, struct fb_info *info)
 {
-    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
+    struct display *disp = (con < 0) ? info->disp : (fb_display + con);
+
+    if (disp->cmap.len)
+	fb_set_cmap(&disp->cmap, 1, aty128_setcolreg, info);
+    else
+	fb_set_cmap(fb_default_cmap((disp->var.bits_per_pixel==8) ? 256 :32),
+		    1, aty128_setcolreg, info);
+}
 
-    if (con != fb->currcon)
-	return;
+#define ATY_MIRROR_LCD_ON	0x00000001
+#define ATY_MIRROR_CRT_ON	0x00000002
 
-    if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, 1, aty128_setcolreg, info);
-    else {
-	int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
-	fb_set_cmap(fb_default_cmap(size), 1, aty128_setcolreg, info);
+/* out param: u32*	backlight value: 0 to 15 */
+#define FBIO_ATY128_GET_MIRROR	_IOR('@', 1, sizeof(__u32*))
+/* in param: u32*	backlight value: 0 to 15 */
+#define FBIO_ATY128_SET_MIRROR	_IOW('@', 2, sizeof(__u32*))
+
+static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
+    u32 value;
+    int rc;
+    
+    switch (cmd) {
+#ifdef CONFIG_PMAC_PBOOK
+    case FBIO_ATY128_SET_MIRROR:
+    	if (fb->chip_gen != rage_M3)
+    		return -EINVAL;
+    	rc = get_user(value, (__u32*)arg);
+    	if (rc)
+    		return rc;
+    	fb->lcd_on = (value & 0x01) != 0;
+    	fb->crt_on = (value & 0x02) != 0;
+    	if (!fb->crt_on && !fb->lcd_on)
+    		fb->lcd_on = 1;
+    	aty128_set_crt_enable(fb, fb->crt_on);	
+    	aty128_set_lcd_enable(fb, fb->lcd_on);	
+	break;
+    case FBIO_ATY128_GET_MIRROR:
+    	if (fb->chip_gen != rage_M3)
+    		return -EINVAL;
+	value = (fb->crt_on << 1) | fb->lcd_on;
+    	return put_user(value, (__u32*)arg);
+#endif
+    default:
+	return -EINVAL;
     }
+    return 0;
 }
 
-
 #ifdef CONFIG_PMAC_BACKLIGHT
 static int backlight_conv[] = {
 	0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
 	0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
 };
 
+/* We turn off the LCD completely instead of just dimming the backlight.
+ * This provides greater power saving and the display is useless without
+ * backlight anyway
+ */
+#define BACKLIGHT_LVDS_OFF
+/* That one prevents proper CRT output with LCD off */
+#undef BACKLIGHT_DAC_OFF
+
 static int
 aty128_set_backlight_enable(int on, int level, void* data)
 {
 	struct fb_info_aty128 *info = (struct fb_info_aty128 *)data;
 	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
-	
+
+	if (!info->lcd_on)
+		on = 0;
 	reg |= LVDS_BL_MOD_EN | LVDS_BLON;
 	if (on && level > BACKLIGHT_OFF) {
+		reg |= LVDS_DIGION;
+		if (!reg & LVDS_ON) {
+			reg &= ~LVDS_BLON;
+			aty_st_le32(LVDS_GEN_CNTL, reg);
+			(void)aty_ld_le32(LVDS_GEN_CNTL);
+			mdelay(10);
+			reg |= LVDS_BLON;
+			aty_st_le32(LVDS_GEN_CNTL, reg);
+		}
 		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
 		reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+		reg |= LVDS_ON | LVDS_EN;
+		reg &= ~LVDS_DISPLAY_DIS;
+#endif
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
+#endif		
 	} else {
 		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
 		reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+		reg |= LVDS_DISPLAY_DIS;
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+		(void)aty_ld_le32(LVDS_GEN_CNTL);
+		udelay(10);
+		reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
+#endif		
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
+#endif		
 	}
-	aty_st_le32(LVDS_GEN_CNTL, reg);
 
 	return 0;
 }
@@ -2346,18 +2583,18 @@
 		u_int width, u_int height,
 		struct fb_info_aty128 *info)
 {
-    u32 save_dp_datatype, save_dp_cntl, bppval;
+    u32 save_dp_datatype, save_dp_cntl, dstval;
 
     if (!width || !height)
         return;
 
-    bppval = bpp_to_depth(info->current_par.crtc.bpp);
-    if (bppval == DST_24BPP) {
+    dstval = depth_to_dst(info->current_par.crtc.depth);
+    if (dstval == DST_24BPP) {
         srcx *= 3;
         dstx *= 3;
         width *= 3;
-    } else if (bppval == -EINVAL) {
-        printk("aty128fb: invalid depth\n");
+    } else if (dstval == -EINVAL) {
+        printk("aty128fb: invalid depth or RGBA\n");
         return;
     }
 
@@ -2369,7 +2606,7 @@
     aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
     aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
     aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
-    aty_st_le32(DP_DATATYPE, save_dp_datatype | bppval | SRC_DSTCOLOR);
+    aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR);
 
     aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
     aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
@@ -2594,6 +2831,139 @@
     fontwidthmask:	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
+
+#ifdef CONFIG_PMAC_PBOOK
+static void
+aty128_set_suspend(struct fb_info_aty128 *info, int suspend)
+{
+	u32	pmgt;
+	u16	pwr_command;
+
+	if (!info->pm_reg)
+		return;
+		
+	/* Set the chip into the appropriate suspend mode (we use D2,
+	 * D3 would require a complete re-initialisation of the chip,
+	 * including PCI config registers, clocks, AGP configuration, ...)
+	 */
+	if (suspend) {
+		/* Make sure CRTC2 is reset. Remove that the day we decide to
+		 * actually use CRTC2 and replace it with real code for disabling
+		 * the CRTC2 output during sleep
+		 */
+		aty_st_le32(CRTC2_GEN_CNTL, aty_ld_le32(CRTC2_GEN_CNTL) &
+			~(CRTC2_EN));
+
+		/* Set the power management mode to be PCI based */
+		pmgt = aty_ld_pll(POWER_MANAGEMENT);
+#if 0
+		pmgt &= ~PWR_MGT_MODE_MASK;
+		pmgt |= PWR_MGT_MODE_PCI | PWR_MGT_ON | PWR_MGT_TRISTATE_MEM_EN | PWR_MGT_AUTO_PWR_UP_EN;
+#else		/* Use this magic value for now */
+		pmgt = 0x0c005407;
+#endif
+		aty_st_pll(POWER_MANAGEMENT, pmgt);
+		(void)aty_ld_pll(POWER_MANAGEMENT);
+		aty_st_le32(BUS_CNTL1, 0x00000010);
+		aty_st_le32(MEM_POWER_MISC, 0x0c830000);
+		mdelay(100);
+		pci_read_config_word(info->pdev, info->pm_reg+PCI_PM_CTRL, &pwr_command);
+		/* Switch PCI power management to D2 */
+		pci_write_config_word(info->pdev, info->pm_reg+PCI_PM_CTRL,
+			(pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2);
+		pci_read_config_word(info->pdev, info->pm_reg+PCI_PM_CTRL, &pwr_command);
+	} else {
+		/* Switch back PCI power management to D0 */
+		mdelay(100);
+		pci_write_config_word(info->pdev, info->pm_reg+PCI_PM_CTRL, 0);
+		mdelay(100);
+		pci_read_config_word(info->pdev, info->pm_reg+PCI_PM_CTRL, &pwr_command);
+		mdelay(100);
+	}
+}
+
+extern struct display_switch fbcon_dummy;
+
+/*
+ * Save the contents of the frame buffer when we go to sleep,
+ * and restore it when we wake up again.
+ */
+int
+aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+	struct fb_info_aty128 *info;
+ 	int result;
+
+	result = PBOOK_SLEEP_OK;
+
+	for (info = board_list; info != NULL; info = info->next) {
+		struct fb_fix_screeninfo fix;
+		int nb;
+
+		aty128fb_get_fix(&fix, fg_console, (struct fb_info *)info);
+		nb = fb_display[fg_console].var.yres * fix.line_length;
+
+		switch (when) {
+		case PBOOK_SLEEP_REQUEST:
+			info->save_framebuffer = vmalloc(nb);
+			if (info->save_framebuffer == NULL)
+				return PBOOK_SLEEP_REFUSE;
+			break;
+		case PBOOK_SLEEP_REJECT:
+			if (info->save_framebuffer) {
+				vfree(info->save_framebuffer);
+				info->save_framebuffer = 0;
+			}
+			break;
+		case PBOOK_SLEEP_NOW:
+			if (info->currcon >= 0)
+				fb_display[info->currcon].dispsw = &fbcon_dummy;
+			
+			wait_for_idle(info);
+			aty128_reset_engine(info);
+			wait_for_idle(info);
+
+			/* Backup fb content */	
+			if (info->save_framebuffer)
+				memcpy_fromio(info->save_framebuffer,
+				       (void *)info->frame_buffer, nb);
+
+			/* Blank display and LCD */
+			aty128fbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
+			
+			/* Sleep the chip */
+			aty128_set_suspend(info, 1);
+
+			break;
+		case PBOOK_WAKE:
+			/* Wake the chip */
+			aty128_set_suspend(info, 0);
+			
+			aty128_reset_engine(info);
+			wait_for_idle(info);
+
+			/* Restore fb content */			
+			if (info->save_framebuffer) {
+				memcpy_toio((void *)info->frame_buffer,
+				       info->save_framebuffer, nb);
+				vfree(info->save_framebuffer);
+				info->save_framebuffer = 0;
+			}
+
+			if (info->currcon >= 0) {
+				aty128_set_dispsw(
+					&fb_display[info->currcon],
+					info,
+					info->current_par.crtc.bpp,
+					info->current_par.accel_flags & FB_ACCELF_TEXT);
+			}
+			aty128fbcon_blank(0, (struct fb_info *)info);
+			break;
+		}
+	}
+	return result;
+}
+#endif /* CONFIG_PMAC_PBOOK */
 
 #ifdef MODULE
 MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>");
diff -urN linux-2.4.18-pre1/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- linux-2.4.18-pre1/drivers/video/riva/fbdev.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/video/riva/fbdev.c	Mon Jan  7 16:42:53 2002
@@ -136,6 +136,11 @@
 	CH_GEFORCE2_GTS,
 	CH_GEFORCE2_ULTRA,
 	CH_QUADRO2_PRO,
+	CH_GEFORCE2_GO,
+        CH_GEFORCE3,
+        CH_GEFORCE3_1,
+        CH_GEFORCE3_2,
+        CH_QUADRO_DDC
 };
 
 /* directly indexed by riva_chips enum, above */
@@ -158,6 +163,11 @@
 	{ "GeForce2-GTS", NV_ARCH_10},
 	{ "GeForce2-ULTRA", NV_ARCH_10},
 	{ "Quadro2-PRO", NV_ARCH_10},
+        { "GeForce2-Go", NV_ARCH_10},
+        { "GeForce3", NV_ARCH_20}, 
+        { "GeForce3 Ti 200", NV_ARCH_20},
+        { "GeForce3 Ti 500", NV_ARCH_20},
+        { "Quadro DDC", NV_ARCH_20}
 };
 
 static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
@@ -195,6 +205,16 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
+        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
+          PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
+        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
+          PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
+        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
+          PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
+        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
+          PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
+        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
+          PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
@@ -1315,6 +1335,7 @@
 		fix->accel = FB_ACCEL_NV4;
 		break;
 	case NV_ARCH_10:	/* FIXME: ID for GeForce */
+	case NV_ARCH_20:
 		fix->accel = FB_ACCEL_NV4;
 		break;
 
@@ -1930,6 +1951,7 @@
 		break;
 	case NV_ARCH_04:
 	case NV_ARCH_10:
+	case NV_ARCH_20:
 		rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000);
 		rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
 		break;
diff -urN linux-2.4.18-pre1/drivers/video/riva/riva_hw.c linux/drivers/video/riva/riva_hw.c
--- linux-2.4.18-pre1/drivers/video/riva/riva_hw.c	Tue Feb 13 13:15:05 2001
+++ linux/drivers/video/riva/riva_hw.c	Mon Jan  7 16:42:53 2002
@@ -1220,6 +1220,7 @@
             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
             break;
         case NV_ARCH_10:
+	case NV_ARCH_20:
             nv10UpdateArbitrationSettings(VClk, 
                                           pixelDepth * 8, 
                                          &(state->arbitration0),
@@ -1285,6 +1286,7 @@
             chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
             break;
         case NV_ARCH_10:
+	case NV_ARCH_20:
             /*
              * Initialize state for the RivaTriangle3D05 routines.
              */
@@ -1393,6 +1395,7 @@
             chip->PGRAPH[0x0000067C/4] = state->pitch3;
             break;
         case NV_ARCH_10:
+	case NV_ARCH_20:
             LOAD_FIXED_STATE(nv10,PFIFO);
             LOAD_FIXED_STATE(nv10,PRAMIN);
             LOAD_FIXED_STATE(nv10,PGRAPH);
@@ -1421,15 +1424,31 @@
                     chip->Tri03 = 0L;
                     break;
             }
-            chip->PGRAPH[0x00000640/4] = state->offset0;
-            chip->PGRAPH[0x00000644/4] = state->offset1;
-            chip->PGRAPH[0x00000648/4] = state->offset2;
-            chip->PGRAPH[0x0000064C/4] = state->offset3;
-            chip->PGRAPH[0x00000670/4] = state->pitch0;
-            chip->PGRAPH[0x00000674/4] = state->pitch1;
-            chip->PGRAPH[0x00000678/4] = state->pitch2;
-            chip->PGRAPH[0x0000067C/4] = state->pitch3;
-            chip->PGRAPH[0x00000680/4] = state->pitch3;
+
+	    if (chip->Architecture == NV_ARCH_10) {
+            	chip->PGRAPH[0x00000640/4] = state->offset0;
+            	chip->PGRAPH[0x00000644/4] = state->offset1;
+            	chip->PGRAPH[0x00000648/4] = state->offset2;
+            	chip->PGRAPH[0x0000064C/4] = state->offset3;
+            	chip->PGRAPH[0x00000670/4] = state->pitch0;
+            	chip->PGRAPH[0x00000674/4] = state->pitch1;
+            	chip->PGRAPH[0x00000678/4] = state->pitch2;
+            	chip->PGRAPH[0x0000067C/4] = state->pitch3;
+            	chip->PGRAPH[0x00000680/4] = state->pitch3;
+	    } else {
+		chip->PGRAPH[0x00000820/4] = state->offset0;
+		chip->PGRAPH[0x00000824/4] = state->offset1;
+		chip->PGRAPH[0x00000828/4] = state->offset2;
+		chip->PGRAPH[0x0000082C/4] = state->offset3;
+		chip->PGRAPH[0x00000850/4] = state->pitch0;
+		chip->PGRAPH[0x00000854/4] = state->pitch1;
+		chip->PGRAPH[0x00000858/4] = state->pitch2;
+		chip->PGRAPH[0x0000085C/4] = state->pitch3;
+		chip->PGRAPH[0x00000860/4] = state->pitch3;
+		chip->PGRAPH[0x00000864/4] = state->pitch3;
+		chip->PGRAPH[0x000009A4/4] = chip->PFB[0x00000200/4];
+		chip->PGRAPH[0x000009A8/4] = chip->PFB[0x00000204/4];
+	    }
             chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
             chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
             chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
@@ -1607,6 +1626,7 @@
             state->pitch3   = chip->PGRAPH[0x0000067C/4];
             break;
         case NV_ARCH_10:
+	case NV_ARCH_20:
             state->offset0  = chip->PGRAPH[0x00000640/4];
             state->offset1  = chip->PGRAPH[0x00000644/4];
             state->offset2  = chip->PGRAPH[0x00000648/4];
@@ -1970,6 +1990,7 @@
             nv4GetConfig(chip);
             break;
         case NV_ARCH_10:
+	case NV_ARCH_20:
             nv10GetConfig(chip);
             break;
         default:
diff -urN linux-2.4.18-pre1/drivers/video/riva/riva_hw.h linux/drivers/video/riva/riva_hw.h
--- linux-2.4.18-pre1/drivers/video/riva/riva_hw.h	Tue Feb 13 13:15:05 2001
+++ linux/drivers/video/riva/riva_hw.h	Mon Jan  7 16:42:53 2002
@@ -74,6 +74,8 @@
 #define NV_ARCH_03  0x03
 #define NV_ARCH_04  0x04
 #define NV_ARCH_10  0x10
+#define NV_ARCH_20  0x20
+
 /***************************************************************************\
 *                                                                           *
 *                             FIFO registers.                               *
diff -urN linux-2.4.18-pre1/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.18-pre1/fs/binfmt_elf.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/binfmt_elf.c	Mon Jan  7 16:42:53 2002
@@ -517,11 +517,13 @@
 				set_personality(PER_SVR4);
 				interpreter = open_exec(elf_interpreter);
 
+				task_lock(current);
 				new_domain = current->exec_domain;
 				new_fs = current->fs;
 				current->personality = old_pers;
 				current->exec_domain = old_domain;
 				current->fs = old_fs;
+				task_unlock(current);
 				put_exec_domain(new_domain);
 				put_fs_struct(new_fs);
 			} else
@@ -1049,6 +1051,23 @@
 
 	}
 
+	memset(&prstatus, 0, sizeof(prstatus));
+	/*
+	 * This transfers the registers from regs into the standard
+	 * coredump arrangement, whatever that is.
+	 */
+#ifdef ELF_CORE_COPY_REGS
+	ELF_CORE_COPY_REGS(prstatus.pr_reg, regs)
+#else
+	if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
+	{
+		printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",
+			(long)sizeof(elf_gregset_t), (long)sizeof(struct pt_regs));
+	}
+	else
+		*(struct pt_regs *)&prstatus.pr_reg = *regs;
+#endif
+
 	/* now stop all vm operations */
 	down_write(&current->mm->mmap_sem);
 	segs = current->mm->map_count;
@@ -1092,7 +1111,6 @@
 	 * Set up the notes in similar form to SVR4 core dumps made
 	 * with info from their /proc.
 	 */
-	memset(&prstatus, 0, sizeof(prstatus));
 
 	notes[0].name = "CORE";
 	notes[0].type = NT_PRSTATUS;
@@ -1114,22 +1132,6 @@
 	prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime);
 	prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime);
 
-	/*
-	 * This transfers the registers from regs into the standard
-	 * coredump arrangement, whatever that is.
-	 */
-#ifdef ELF_CORE_COPY_REGS
-	ELF_CORE_COPY_REGS(prstatus.pr_reg, regs)
-#else
-	if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
-	{
-		printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",
-			(long)sizeof(elf_gregset_t), (long)sizeof(struct pt_regs));
-	}
-	else
-		*(struct pt_regs *)&prstatus.pr_reg = *regs;
-#endif
-
 #ifdef DEBUG
 	dump_regs("Passed in regs", (elf_greg_t *)regs);
 	dump_regs("prstatus regs", (elf_greg_t *)&prstatus.pr_reg);
@@ -1225,9 +1227,11 @@
 
 		if (!maydump(vma))
 			continue;
+
 #ifdef DEBUG
-		printk("elf_core_dump: writing %08lx %lx\n", addr, len);
+		printk("elf_core_dump: writing %08lx-%08lx\n", vma->vm_start, vma->vm_end);
 #endif
+
 		for (addr = vma->vm_start;
 		     addr < vma->vm_end;
 		     addr += PAGE_SIZE) {
diff -urN linux-2.4.18-pre1/fs/intermezzo/dcache.c linux/fs/intermezzo/dcache.c
--- linux-2.4.18-pre1/fs/intermezzo/dcache.c	Tue Nov 13 09:20:56 2001
+++ linux/fs/intermezzo/dcache.c	Mon Jan  7 16:42:53 2002
@@ -15,7 +15,6 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
-#include <linux/slab.h>
 #include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <linux/string.h>
@@ -23,7 +22,7 @@
 #include <linux/intermezzo_fs.h>
 
 static int presto_dentry_revalidate(struct dentry *de, int );
-static kmem_cache_t * presto_dentry_slab;
+
 
 /* called when a cache lookup succeeds */
 static int presto_dentry_revalidate(struct dentry *de, int flag)
@@ -49,91 +48,15 @@
 	}
 }
 
-static void presto_d_release(struct dentry *dentry)
+static void presto_dentry_iput(struct dentry *dentry, struct inode *inode)
 {
-        if (!presto_d2d(dentry)) {
-                /* This should really only happen in the case of a dentry
-                 * with no inode. */
-                return;
-        }
-
-        presto_d2d(dentry)->dd_count--;
-
-        if (! presto_d2d(dentry)->dd_count) {
-                kmem_cache_free(presto_dentry_slab, presto_d2d(dentry));
-		dentry->d_fsdata = NULL;
-        }
+	dentry->d_time = 0;
+	iput(inode);
 }
 
 struct dentry_operations presto_dentry_ops = 
 {
 	d_revalidate: presto_dentry_revalidate,
-        d_release: presto_d_release
+        d_iput: presto_dentry_iput
 };
 
-
-// XXX THIS DEPENDS ON THE KERNEL LOCK!
-
-void presto_set_dd(struct dentry * dentry)
-{
-        ENTRY;
-        if (dentry == NULL)
-                BUG();
-
-        if (dentry->d_fsdata) {
-                printk("VERY BAD: dentry: %p\n", dentry);
-                if (dentry->d_inode)
-                        printk("    inode: %ld\n", dentry->d_inode->i_ino);
-                EXIT;
-                return;
-        }
-
-        if (dentry->d_inode == NULL) {
-                dentry->d_fsdata = kmem_cache_alloc(presto_dentry_slab,
-                                                    SLAB_KERNEL);
-                memset(dentry->d_fsdata, 0, sizeof(struct presto_dentry_data));
-                presto_d2d(dentry)->dd_count = 1;
-                EXIT;
-                return;
-        }
-
-        /* If there's already a dentry for this inode, share the data */
-        if (dentry->d_alias.next != &dentry->d_inode->i_dentry ||
-            dentry->d_alias.prev != &dentry->d_inode->i_dentry) {
-                struct dentry *de;
-
-                if (dentry->d_alias.next != &dentry->d_inode->i_dentry)
-                        de = list_entry(dentry->d_alias.next, struct dentry,
-                                        d_alias);
-                else
-                        de = list_entry(dentry->d_alias.prev, struct dentry,
-                                        d_alias);
-
-                dentry->d_fsdata = de->d_fsdata;
-                presto_d2d(dentry)->dd_count++;
-                EXIT;
-                return;
-        }
-
-        dentry->d_fsdata = kmem_cache_alloc(presto_dentry_slab, SLAB_KERNEL);
-        memset(dentry->d_fsdata, 0, sizeof(struct presto_dentry_data));
-        presto_d2d(dentry)->dd_count = 1;
-        EXIT;
-        return; 
-}
-
-void presto_init_ddata_cache(void)
-{
-        ENTRY;
-        presto_dentry_slab =
-                kmem_cache_create("presto_cache",
-                                  sizeof(struct presto_dentry_data), 0,
-                                  SLAB_HWCACHE_ALIGN, NULL,
-                                  NULL);
-        EXIT;
-}
-
-void presto_cleanup_ddata_cache(void)
-{
-        kmem_cache_destroy(presto_dentry_slab);
-}
diff -urN linux-2.4.18-pre1/fs/intermezzo/dir.c linux/fs/intermezzo/dir.c
--- linux-2.4.18-pre1/fs/intermezzo/dir.c	Tue Nov 13 09:20:56 2001
+++ linux/fs/intermezzo/dir.c	Mon Jan  7 16:42:53 2002
@@ -163,20 +163,13 @@
                 return ERR_PTR(-EPERM);
         }
         inode = iget(dir->i_sb, ino);
-        if (!inode || is_bad_inode(inode)) {
+        if (!inode || !inode->i_nlink || is_bad_inode(inode)) {
                 CDEBUG(D_PIOCTL, "fatal: invalid inode %ld (%s).\n",
                        ino, inode ? inode->i_nlink ? "bad inode" :
                        "no links" : "NULL");
                 error = -ENOENT;
                 EXIT;
                 goto cleanup_iput;
-        } else if (inode->i_nlink == 0) {
-                /* This is quite evil, but we have little choice.  If we were
-                 * to iput() again with i_nlink == 0, delete_inode would get
-                 * called again, which ext3 really Does Not Like. */
-                atomic_dec(&inode->i_count);
-                EXIT;
-                return ERR_PTR(-ENOENT);
         }
 
         /* We need to make sure we have the right inode (by checking the
@@ -216,7 +209,6 @@
         unsigned int generation;
 
         ENTRY;
-        CDEBUG(D_CACHE, "calling presto_prep on dentry %p\n", dentry);
         error = presto_prep(dentry->d_parent, &cache, &fset);
         if ( error  ) {
                 EXIT;
@@ -245,7 +237,7 @@
                 if (iops && iops->lookup) 
                         de = iops->lookup(dir, dentry);
                 else {
-		        printk("filesystem has no lookup\n");
+                        printk("filesystem has no lookup\n");
                         EXIT;
                         goto exit;
                 }
@@ -261,8 +253,6 @@
                 goto exit;
         }
 
-        presto_set_dd(dentry);
-
         /* some file systems set the methods in lookup, not in
            read_inode, as a result we should set the methods here 
            as well as in read_inode 
@@ -704,7 +694,6 @@
 		double_down(&old_dir->i_zombie, &new_dir->i_zombie);
 }
 
-
 // XXX this can be optimized: renamtes across filesets only require 
 //     multiple KML records, but can locally be executed normally. 
 int presto_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -724,6 +713,7 @@
                 EXIT;
                 return error;
         }
+
         error = presto_prep(new_parent, &new_cache, &new_fset);
         if ( error ) {
                 EXIT;
diff -urN linux-2.4.18-pre1/fs/intermezzo/inode.c linux/fs/intermezzo/inode.c
--- linux-2.4.18-pre1/fs/intermezzo/inode.c	Sun Nov 11 10:20:21 2001
+++ linux/fs/intermezzo/inode.c	Mon Jan  7 16:42:53 2002
@@ -47,6 +47,8 @@
 void presto_set_ops(struct inode *inode, struct  filter_fs *filter)
 {
 	ENTRY; 
+        if (!inode || is_bad_inode(inode))
+                return;
 	if (inode->i_gid == presto_excluded_gid ) { 
 		EXIT;
                 CDEBUG(D_INODE, "excluded methods for %ld at %p, %p\n",
diff -urN linux-2.4.18-pre1/fs/intermezzo/journal.c linux/fs/intermezzo/journal.c
--- linux-2.4.18-pre1/fs/intermezzo/journal.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/intermezzo/journal.c	Mon Jan  7 16:42:53 2002
@@ -301,9 +301,8 @@
 	/* XXX needs to be done after reservation, 
 	   disable ths until version 1.2 */
         if ( dentry ) { 
-                s.prevrec = cpu_to_le32(rec->offset - 
-                                        presto_d2d(dentry)->dd_kml_offset);
-                presto_d2d(dentry)->dd_kml_offset = rec->offset;
+                s.prevrec = cpu_to_le32(rec->offset - dentry->d_time);
+                dentry->d_time = (unsigned long) rec->offset;
         } else { 
                 s.prevrec = -1;
         }
diff -urN linux-2.4.18-pre1/fs/intermezzo/presto.c linux/fs/intermezzo/presto.c
--- linux-2.4.18-pre1/fs/intermezzo/presto.c	Tue Nov 13 09:20:56 2001
+++ linux/fs/intermezzo/presto.c	Mon Jan  7 16:42:53 2002
@@ -50,18 +50,16 @@
         return err;
 }
 
-inline struct presto_dentry_data *presto_d2d(struct dentry *dentry)
+
+static inline int presto_dentry_is_fsetroot(struct dentry *dentry)
 {
-        return (struct presto_dentry_data *)dentry->d_fsdata;
+        return ((long) dentry->d_fsdata) & PRESTO_FSETROOT;
 }
 
 static inline struct presto_file_set *presto_dentry2fset(struct dentry *dentry)
 {
-        if (dentry->d_fsdata == NULL) {
-                printk("fucked dentry: %p\n", dentry);
-                BUG();
-        }
-        return presto_d2d(dentry)->dd_fset;
+        return (struct presto_file_set *)
+                (((long) dentry->d_fsdata) - PRESTO_FSETROOT);
 }
 
 /* find the presto minor device for this inode */
@@ -114,7 +112,7 @@
         ENTRY;
         fsde = de;
         for ( ; ; ) {
-                if ( presto_dentry2fset(fsde) ) {
+                if ( presto_dentry_is_fsetroot(fsde) ) {
                         EXIT;
                         return presto_dentry2fset(fsde);
                 }
@@ -185,21 +183,36 @@
                 return 1;
         }
 
+        /* if it is a fsetroot, it's stored in the fset_flags */
+        if ( fset && presto_dentry_is_fsetroot(dentry) ) {
+                EXIT;
+                return fset->fset_data & flag;
+        }
+
         EXIT;
-        return (presto_d2d(dentry)->dd_flags & flag);
+        return ((int)dentry->d_fsdata & flag);
 }
 
 /* set a bit in the dentry flags */
 void presto_set(struct dentry *dentry, int flag)
 {
 
-        ENTRY;
         if ( dentry->d_inode ) {
                 CDEBUG(D_INODE, "SET ino %ld, flag %x\n",
                        dentry->d_inode->i_ino, flag);
         }
-        presto_d2d(dentry)->dd_flags |= flag;
-        EXIT;
+
+        if ( presto_dentry_is_fsetroot(dentry)) {
+                struct presto_file_set *fset = presto_dentry2fset(dentry);
+                if (fset) {
+                        fset->fset_data |= flag;
+                        CDEBUG(D_INODE, "Setting fset->fset_data: now %x\n",
+                               fset->fset_data);
+                }
+        } else {
+                CDEBUG(D_INODE, "Setting dentry->d_fsdata\n");
+                ((int)dentry->d_fsdata) |= flag;
+        }
 }
 
 /* given a path: complete the closes on the fset */
@@ -451,27 +464,39 @@
         struct dentry *dentry;
         int error;
 
+        CDEBUG(D_INODE, "name: %s, and flag %x, or flag %x\n",
+               name, and_flag, or_flag);
+
         error = presto_walk(name, &nd);
         if (error)
                 return error;
         dentry = nd.dentry;
-
-        CDEBUG(D_INODE, "name: %s, and flag %x, or flag %x, dd_flags %x\n",
-               name, and_flag, or_flag, presto_d2d(dentry)->dd_flags);
-
+        CDEBUG(D_INODE, "dentry at %p, d_fsdata %p\n", dentry, dentry->d_fsdata);
 
         error = -ENXIO;
         if ( !presto_ispresto(dentry->d_inode) )
                 goto out;
 
         error = 0;
+        if ( presto_dentry_is_fsetroot(dentry) ) {
+                struct presto_file_set *fset = presto_dentry2fset(dentry);
+                CDEBUG(D_INODE, "Setting fset fset_data: fset %p\n", fset);
+                if ( fset ) {
+                        fset->fset_data &= and_flag;
+                        fset->fset_data |= or_flag;
+                        if (res) {
+                                *res = fset->fset_data;
+                        }
+                }
+                CDEBUG(D_INODE, "fset %p, flags %x data %x\n", 
+                       fset, fset->fset_flags, fset->fset_data);
+        } else {
+                ((int)dentry->d_fsdata) &= and_flag;
+                ((int)dentry->d_fsdata) |= or_flag;
+                if (res) 
+                        *res = (int)dentry->d_fsdata;
+        }
 
-        presto_d2d(dentry)->dd_flags  &= and_flag;
-        presto_d2d(dentry)->dd_flags  |= or_flag;
-        if (res) 
-                *res = presto_d2d(dentry)->dd_flags;
-
-        // XXX this check makes no sense as d_count can change anytime.
         /* indicate if we were the only users while changing the flag */
         if ( atomic_read(&dentry->d_count) > 1 )
                 error = -EBUSY;
@@ -810,7 +835,6 @@
 
         error = -EEXIST;
         CDEBUG(D_INODE, "\n");
-
         fset2 = presto_fset(dentry);
         if (fset2 && (fset2->fset_mtpt == dentry) ) { 
                 printk(KERN_ERR "Fsetroot already set (path %s)\n", path);
@@ -825,7 +849,7 @@
         fset->fset_flags = flags;
 	fset->fset_file_maxio = FSET_DEFAULT_MAX_FILEIO; 
 
-        presto_d2d(dentry)->dd_fset = fset;
+        dentry->d_fsdata = (void *) ( ((long)fset) + PRESTO_FSETROOT );
         list_add(&fset->fset_list, &cache->cache_fset_list);
 
         error = presto_init_kml_file(fset);
@@ -869,15 +893,15 @@
                 cache->cache_flags |= CACHE_FSETROOT_SET;
         }
 
-        CDEBUG(D_PIOCTL, "-------> fset at %p, dentry at %p, mtpt %p, fset %s, cache %p, presto_d2d(dentry)->dd_fset %p\n",
-               fset, dentry, fset->fset_mtpt, fset->fset_name, cache, presto_d2d(dentry)->dd_fset);
+        CDEBUG(D_PIOCTL, "-------> fset at %p, dentry at %p, mtpt %p, fset %s, cache %p, d_fsdata %p\n",
+               fset, dentry, fset->fset_mtpt, fset->fset_name, cache, dentry->d_fsdata);
 
         EXIT;
         return 0;
 
  out_list_del:
         list_del(&fset->fset_list);
-        presto_d2d(dentry)->dd_fset = NULL;
+        dentry->d_fsdata = 0;
  out_dput:
         path_release(&fset->fset_nd); 
  out_free:
@@ -907,7 +931,7 @@
         }
 
         error = -EINVAL;
-        if ( ! presto_dentry2fset(dentry)) {
+        if ( ! presto_dentry_is_fsetroot(dentry)) {
                 EXIT;
                 goto kml_out;
         }
@@ -925,44 +949,12 @@
         return error;
 }
 
-static void presto_cleanup_fset(struct presto_file_set *fset)
-{
-	int error;
-	struct presto_cache *cache;
-
-	ENTRY;
-#ifdef  CONFIG_KREINT
-        error = kml_cleanup (fset);
-        if ( error ) {
-                printk("InterMezzo: Closing kml for fset %s: %d\n",
-                       fset->fset_name, error);
-        }
-#endif
-
-        error = presto_close_journal_file(fset);
-        if ( error ) {
-                printk("InterMezzo: Closing journal for fset %s: %d\n",
-                       fset->fset_name, error);
-        }
-        cache = fset->fset_cache;
-        cache->cache_flags &= ~CACHE_FSETROOT_SET;
-
-        list_del(&fset->fset_list);
-
-	presto_d2d(fset->fset_mtpt)->dd_fset = NULL;
-        path_release(&fset->fset_nd);
-
-        fset->fset_mtpt = NULL;
-        PRESTO_FREE(fset->fset_name, strlen(fset->fset_name) + 1);
-        PRESTO_FREE(fset, sizeof(*fset));
-        EXIT;
-}
-
 int presto_clear_fsetroot(char *path)
 {
         struct nameidata nd;
         struct presto_file_set *fset;
         struct dentry *dentry;
+        struct presto_cache *cache;
         int error;
 
         ENTRY;
@@ -980,7 +972,7 @@
         }
 
         error = -EINVAL;
-        if ( ! presto_dentry2fset(dentry)) {
+        if ( ! presto_dentry_is_fsetroot(dentry)) {
                 EXIT;
                 goto put_out;
         }
@@ -991,7 +983,28 @@
                 goto put_out;
         }
 
-	presto_cleanup_fset(fset);
+#ifdef  CONFIG_KREINT
+        error = kml_cleanup (fset);
+        if ( error ) {
+                printk("InterMezzo: Closing kml for fset %s: %d\n",
+                       fset->fset_name, error);
+        }
+#endif
+
+        error = presto_close_journal_file(fset);
+        if ( error ) {
+                printk("InterMezzo: Closing journal for fset %s: %d\n",
+                       fset->fset_name, error);
+        }
+        cache = fset->fset_cache;
+        cache->cache_flags &= ~CACHE_FSETROOT_SET;
+
+        list_del(&fset->fset_list);
+        dentry->d_fsdata = 0;
+        path_release(&fset->fset_nd);
+        fset->fset_mtpt = NULL;
+        PRESTO_FREE(fset->fset_name, strlen(fset->fset_name) + 1);
+        PRESTO_FREE(fset, sizeof(*fset));
         EXIT;
 
 put_out:
@@ -1024,7 +1037,7 @@
         }
 
         error = -EINVAL;
-        if ( ! presto_dentry2fset(dentry)) {
+        if ( ! presto_dentry_is_fsetroot(dentry)) {
                 EXIT;
                 goto put_out;
         }
@@ -1035,18 +1048,29 @@
                 goto put_out;
         }
 
-	error = 0;
+        cache = fset->fset_cache;
         cache = fset->fset_cache;
         cache->cache_flags &= ~CACHE_FSETROOT_SET;
 
         tmp = &cache->cache_fset_list;
         tmpnext = tmp->next;
         while ( tmpnext != &cache->cache_fset_list) {
-		tmp = tmpnext;
-                tmpnext = tmp->next;
+		tmp=tmpnext;
+                tmpnext=tmp->next;
                 fset = list_entry(tmp, struct presto_file_set, fset_list);
 
-		presto_cleanup_fset(fset);
+                
+                error = presto_close_journal_file(fset);
+                if ( error ) {
+                        printk("InterMezzo: Closing journal for fset %s: %d\n",
+                               fset->fset_name, error);
+                }
+                list_del(&fset->fset_list);
+                fset->fset_mtpt->d_fsdata = 0;
+                path_release(&fset->fset_nd);
+                fset->fset_mtpt = NULL;
+                PRESTO_FREE(fset->fset_name, strlen(fset->fset_name) +1);
+                PRESTO_FREE(fset, sizeof(*fset));
         }
 
         EXIT;
@@ -1079,7 +1103,7 @@
         }
 
         error = -EINVAL;
-        if ( ! presto_dentry2fset(dentry)) {
+        if ( ! presto_dentry_is_fsetroot(dentry)) {
                 EXIT;
                 goto kml_out;
         }
diff -urN linux-2.4.18-pre1/fs/intermezzo/psdev.c linux/fs/intermezzo/psdev.c
--- linux-2.4.18-pre1/fs/intermezzo/psdev.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/intermezzo/psdev.c	Mon Jan  7 16:42:53 2002
@@ -1465,8 +1465,8 @@
                                 break;
                         /* signal is present: after timeout always return
                            really smart idea, probably useless ... */
-                        if ( jiffies > req->rq_posttime +
-                             upc_comms[minor].uc_timeout * HZ )
+                        if ( time_after(jiffies, req->rq_posttime +
+                             upc_comms[minor].uc_timeout * HZ) )
                                 break;
                 }
                 schedule();
diff -urN linux-2.4.18-pre1/fs/intermezzo/super.c linux/fs/intermezzo/super.c
--- linux-2.4.18-pre1/fs/intermezzo/super.c	Sun Nov 11 10:20:21 2001
+++ linux/fs/intermezzo/super.c	Mon Jan  7 16:42:53 2002
@@ -319,6 +319,7 @@
                 goto out_err;
         }
 
+	
 	cache->cache_sb = mysb;
         ops = filter_get_filter_fs(cache_type);
 
@@ -347,7 +348,6 @@
                                         &presto_dentry_ops);
                 presto_sb->s_root->d_op = filter_c2udops(cache->cache_filter);
                 cache->cache_mtde = mysb->s_root;
-                presto_set_dd(mysb->s_root);
         }
 
         CDEBUG(D_MALLOC, "after mounting: kmem %ld, vmem %ld\n",
@@ -481,7 +481,6 @@
         }
 
         presto_init_cache_hash();
-        presto_init_ddata_cache();
 
         status = register_filesystem(&presto_fs_type);
         if (status) {
@@ -513,7 +512,7 @@
 
         presto_psdev_cleanup();
         cleanup_intermezzo_sysctl();
-        presto_cleanup_ddata_cache();
+
 
 #ifdef PRESTO_DEVEL
         unregister_chrdev(PRESTO_PSDEV_MAJOR, "intermezzo_psdev_devel");
diff -urN linux-2.4.18-pre1/fs/intermezzo/vfs.c linux/fs/intermezzo/vfs.c
--- linux-2.4.18-pre1/fs/intermezzo/vfs.c	Tue Nov 13 09:20:56 2001
+++ linux/fs/intermezzo/vfs.c	Mon Jan  7 16:42:53 2002
@@ -197,7 +197,7 @@
 
         error = -EPERM;
         iops = filter_c2cdiops(fset->fset_cache->cache_filter); 
-        if (!iops) { 
+        if (!iops) {
                 EXIT;
                 return error;
         }
@@ -449,8 +449,17 @@
             dentry->d_inode->i_gid != presto_excluded_gid) {
                 struct presto_cache *cache = fset->fset_cache;
                 /* was this already done? */
-                presto_set_ops(dentry->d_inode, cache->cache_filter);
-
+                if ( !filter_c2cfiops(cache->cache_filter) )
+                        filter_setup_file_ops(cache->cache_filter, 
+                                              dentry->d_inode,
+                                              &presto_file_iops,
+                                              &presto_file_fops);
+
+                /* make the new inode ours */
+                dentry->d_inode->i_op = 
+                        filter_c2ufiops(cache->cache_filter);
+                dentry->d_inode->i_fop = 
+                        filter_c2uffops(cache->cache_filter);
                 filter_setup_dentry_ops(cache->cache_filter, 
                                         dentry->d_op, 
                                         &presto_dentry_ops);
@@ -480,8 +489,8 @@
         presto_getversion(&new_file_ver, dentry->d_inode);
         if ( presto_do_kml(info, dentry->d_inode) )
                 error = presto_journal_create(&rec, fset, dentry, &tgt_dir_ver,
-                                              &new_file_ver, 
-					      dentry->d_inode->i_mode);
+                                              &new_file_ver,
+                                              dentry->d_inode->i_mode);
 
         presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x20);
         if ( presto_do_expect(info, dentry->d_inode) )
@@ -936,8 +945,15 @@
             dentry->d_inode->i_gid != presto_excluded_gid) {
                 struct presto_cache *cache = fset->fset_cache;
                 
-                presto_set_ops(dentry->d_inode, cache->cache_filter);
+                /* was this already done? */
+                if ( !filter_c2csiops(cache->cache_filter) )
+                        filter_setup_symlink_ops(cache->cache_filter, 
+                                                 dentry->d_inode,
+                                                 &presto_sym_iops,
+                                                 NULL);
 
+                /* make the new inode ours */
+                dentry->d_inode->i_op = filter_c2usiops(cache->cache_filter);
                 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op, 
                                         &presto_dentry_ops);
                 dentry->d_op = filter_c2udops(cache->cache_filter);
@@ -1098,9 +1114,8 @@
         if ( dentry->d_inode && !error && 
              dentry->d_inode->i_gid != presto_excluded_gid) {
                 struct presto_cache *cache = fset->fset_cache;
-
-                presto_set_ops(dentry->d_inode, cache->cache_filter);
-
+                /* make it ours */
+                dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
                 filter_setup_dentry_ops(cache->cache_filter, 
                                         dentry->d_op, 
                                         &presto_dentry_ops);
@@ -1128,8 +1143,8 @@
         presto_getversion(&new_dir_ver, dentry->d_inode);
         if ( presto_do_kml(info, dentry->d_inode) )
                 error = presto_journal_mkdir(&rec, fset, dentry, &tgt_dir_ver,
-                                             &new_dir_ver, 
-					     dentry->d_inode->i_mode);
+                                             &new_dir_ver,
+                                             dentry->d_inode->i_mode);
 
         presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x20);
         if ( presto_do_expect(info, dentry->d_inode) )
@@ -1398,12 +1413,15 @@
         }
 
         error = iops->mknod(dir->d_inode, dentry, mode, dev);
+        if (error) {
+                EXIT;
+                goto exit_commit;
+        }
         if ( dentry->d_inode &&
              dentry->d_inode->i_gid != presto_excluded_gid) {
                 struct presto_cache *cache = fset->fset_cache;
-
-                presto_set_ops(dentry->d_inode, cache->cache_filter);
-
+                /* make it ours */
+                dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
                 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op, 
                                         &presto_dentry_ops);
                 dentry->d_op = filter_c2udops(cache->cache_filter);
@@ -1429,8 +1447,8 @@
         presto_getversion(&new_node_ver, dentry->d_inode);
         if ( presto_do_kml(info, dentry->d_inode) )
                 error = presto_journal_mknod(&rec, fset, dentry, &tgt_dir_ver,
-                                             &new_node_ver, 
-					     dentry->d_inode->i_mode,
+                                             &new_node_ver,
+                                             dentry->d_inode->i_mode,
                                              MAJOR(dev), MINOR(dev) );
 
         presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x20);
@@ -1439,6 +1457,7 @@
 
         presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x30);
         EXIT;
+ exit_commit:
         presto_trans_commit(fset, handle);
  exit_lock2:
         unlock_kernel();
diff -urN linux-2.4.18-pre1/fs/jffs2/dir.c linux/fs/jffs2/dir.c
--- linux-2.4.18-pre1/fs/jffs2/dir.c	Fri Sep 14 14:04:07 2001
+++ linux/fs/jffs2/dir.c	Mon Jan  7 16:42:53 2002
@@ -31,13 +31,14 @@
  * provisions above, a recipient may use your version of this file
  * under either the RHEPL or the GPL.
  *
- * $Id: dir.c,v 1.42 2001/05/24 22:24:39 dwmw2 Exp $
+ * $Id: dir.c,v 1.45 2001/12/27 22:43:20 dwmw2 Exp $
  *
  */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/mtd/compatmac.h> /* For completion */
 #include <linux/jffs2.h>
 #include <linux/jffs2_fs_i.h>
 #include <linux/jffs2_fs_sb.h>
@@ -541,7 +542,7 @@
 
 	f = JFFS2_INODE_INFO(inode);
 
-	ri->dsize = ri->csize = strlen(target);
+	inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target);
 	ri->totlen = sizeof(*ri) + ri->dsize;
 	ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4);
 
@@ -931,20 +932,16 @@
 	ret = jffs2_do_unlink(old_dir_i, old_dentry, 1);
 	
 	if (ret) {
-		/* Try to delete the _new_ link to return a clean failure */
-		int ret2 = jffs2_do_unlink(new_dir_i, new_dentry, 1);
-		if (ret2) {
-			struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
-			down(&f->sem);
-			old_dentry->d_inode->i_nlink = f->inocache->nlink++;
-			up(&f->sem);
+		/* Oh shit. We really ought to make a single node which can do both atomically */
+		struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
+		down(&f->sem);
+		old_dentry->d_inode->i_nlink = f->inocache->nlink++;
+		up(&f->sem);
 		       
-			printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (old err %d, new err %d). You now have a hard link\n", ret, ret2);
-			/* Might as well let the VFS know */
-			d_instantiate(new_dentry, old_dentry->d_inode);
-			atomic_inc(&old_dentry->d_inode->i_count);
-		}
-		
+		printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
+		/* Might as well let the VFS know */
+		d_instantiate(new_dentry, old_dentry->d_inode);
+		atomic_inc(&old_dentry->d_inode->i_count);
 	}
 	return ret;
 }
diff -urN linux-2.4.18-pre1/fs/jffs2/readinode.c linux/fs/jffs2/readinode.c
--- linux-2.4.18-pre1/fs/jffs2/readinode.c	Fri Sep 14 14:04:07 2001
+++ linux/fs/jffs2/readinode.c	Mon Jan  7 16:42:53 2002
@@ -31,7 +31,7 @@
  * provisions above, a recipient may use your version of this file
  * under either the RHEPL or the GPL.
  *
- * $Id: readinode.c,v 1.56 2001/07/26 20:32:39 dwmw2 Exp $
+ * $Id: readinode.c,v 1.57 2001/12/27 22:49:46 dwmw2 Exp $
  *
  */
 
@@ -408,6 +408,12 @@
 
 	case S_IFLNK:
 		inode->i_op = &jffs2_symlink_inode_operations;
+		/* Hack to work around broken isize in old symlink code.
+		   Remove this when dwmw2 comes to his senses and stops
+		   symlinks from being an entirely gratuitous special
+		   case. */
+		if (!inode->i_size)
+			inode->i_size = latest_node.dsize;
 		break;
 		
 	case S_IFDIR:
diff -urN linux-2.4.18-pre1/fs/jffs2/write.c linux/fs/jffs2/write.c
--- linux-2.4.18-pre1/fs/jffs2/write.c	Thu Oct  4 15:13:18 2001
+++ linux/fs/jffs2/write.c	Mon Jan  7 16:42:53 2002
@@ -31,7 +31,7 @@
  * provisions above, a recipient may use your version of this file
  * under either the RHEPL or the GPL.
  *
- * $Id: write.c,v 1.28 2001/05/01 16:25:25 dwmw2 Exp $
+ * $Id: write.c,v 1.30 2001/12/30 16:01:11 dwmw2 Exp $
  *
  */
 
@@ -207,8 +207,6 @@
 	}
 	raw->flash_offset = flash_ofs;
 	raw->totlen = PAD(ri->totlen);
-	raw->next_in_ino = f->inocache->nodes;
-	f->inocache->nodes = raw;
 	raw->next_phys = NULL;
 
 	fn->ofs = ri->offset;
@@ -222,6 +220,14 @@
 		       sizeof(*ri)+datalen, flash_ofs, ret, retlen);
 		/* Mark the space as dirtied */
 		if (retlen) {
+			/* Doesn't belong to any inode */
+			raw->next_in_ino = NULL;
+
+			/* Don't change raw->size to match retlen. We may have 
+			   written the node header already, and only the data will
+			   seem corrupted, in which case the scan would skip over
+			   any node we write before the original intended end of 
+			   this node */
 			jffs2_add_physical_node_ref(c, raw, sizeof(*ri)+datalen, 1);
 			jffs2_mark_node_obsolete(c, raw);
 		} else {
@@ -237,6 +243,11 @@
 	}
 	/* Mark the space used */
 	jffs2_add_physical_node_ref(c, raw, retlen, 0);
+
+	/* Link into per-inode list */
+	raw->next_in_ino = f->inocache->nodes;
+	f->inocache->nodes = raw;
+
 	D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", flash_ofs, ri->dsize, ri->csize, ri->node_crc, ri->data_crc, ri->totlen));
 	if (writelen)
 		*writelen = retlen;
diff -urN linux-2.4.18-pre1/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c
--- linux-2.4.18-pre1/fs/reiserfs/inode.c	Mon Jan  7 16:42:52 2002
+++ linux/fs/reiserfs/inode.c	Mon Jan  7 16:42:53 2002
@@ -325,6 +325,16 @@
     */
     if (buffer_uptodate(bh_result)) {
         goto finished ;
+    } else 
+	/*
+	** grab_tail_page can trigger calls to reiserfs_get_block on up to date
+	** pages without any buffers.  If the page is up to date, we don't want
+	** read old data off disk.  Set the up to date bit on the buffer instead
+	** and jump to the end
+	*/
+	    if (Page_Uptodate(bh_result->b_page)) {
+		mark_buffer_uptodate(bh_result, 1);
+		goto finished ;
     }
 
     // read file tail into part of page
@@ -833,7 +843,7 @@
 	}
 	if (retval == POSITION_FOUND) {
 	    reiserfs_warning ("vs-825: reiserfs_get_block: "
-			      "%k should not be found\n", &key);
+			      "%K should not be found\n", &key);
 	    retval = -EEXIST;
 	    if (allocated_block_nr)
 	        reiserfs_free_block (&th, allocated_block_nr);
diff -urN linux-2.4.18-pre1/fs/reiserfs/journal.c linux/fs/reiserfs/journal.c
--- linux-2.4.18-pre1/fs/reiserfs/journal.c	Fri Dec 21 09:42:03 2001
+++ linux/fs/reiserfs/journal.c	Mon Jan  7 16:42:53 2002
@@ -1851,7 +1851,7 @@
       break ;
     }
     wake_up(&reiserfs_commit_thread_done) ;
-    interruptible_sleep_on_timeout(&reiserfs_commit_thread_wait, 5) ;
+    interruptible_sleep_on_timeout(&reiserfs_commit_thread_wait, 5 * HZ) ;
   }
   unlock_kernel() ;
   wake_up(&reiserfs_commit_thread_done) ;
diff -urN linux-2.4.18-pre1/fs/reiserfs/namei.c linux/fs/reiserfs/namei.c
--- linux-2.4.18-pre1/fs/reiserfs/namei.c	Fri Dec 21 09:42:03 2001
+++ linux/fs/reiserfs/namei.c	Mon Jan  7 16:42:53 2002
@@ -309,9 +309,10 @@
 
     while (1) {
 	retval = search_by_entry_key (dir->i_sb, &key_to_search, path_to_entry, de);
-	if (retval == IO_ERROR)
-	    // FIXME: still has to be dealt with
-	    reiserfs_panic (dir->i_sb, "zam-7001: io error in " __FUNCTION__ "\n");
+	if (retval == IO_ERROR) {
+	    reiserfs_warning ("zam-7001: io error in " __FUNCTION__ "\n");
+	    return IO_ERROR;
+	}
 
 	/* compare names for all entries having given hash value */
 	retval = linear_search_in_dir_item (&key_to_search, de, name, namelen);
diff -urN linux-2.4.18-pre1/include/linux/intermezzo_fs.h linux/include/linux/intermezzo_fs.h
--- linux-2.4.18-pre1/include/linux/intermezzo_fs.h	Tue Nov 13 09:20:56 2001
+++ linux/include/linux/intermezzo_fs.h	Mon Jan  7 16:42:53 2002
@@ -135,6 +135,7 @@
         int fset_permit_count;
         int fset_permit_cookie;
         int fset_chunkbits; 
+        int fset_data; /* replaces the dentry d_data field for fsetroots */
 	struct  kml_fsdata *fset_kmldata;
 	loff_t  fset_file_maxio;  /* writing more than this causes a close */ 
 };
@@ -201,9 +202,6 @@
 void presto_frob_dop(struct dentry *de) ;
 char * presto_path(struct dentry *dentry, struct dentry *root,
                    char *buffer, int buflen);
-void presto_set_dd(struct dentry *);
-void presto_init_ddata_cache(void);
-void presto_cleanup_ddata_cache(void);
 extern struct dentry_operations presto_dentry_ops;
 
 
@@ -231,14 +229,6 @@
 };
 
 
-struct presto_dentry_data { 
-        int dd_count; /* how mnay dentries are using this dentry */
-        struct presto_file_set *dd_fset;
-        loff_t dd_kml_offset;
-        int dd_flags;
-
-}; 
-
 struct presto_file_data { 
         int fd_do_lml;
         loff_t fd_lml_offset;
@@ -259,7 +249,6 @@
         __u64 pv_ctime;
         __u64 pv_size;
 };
-inline struct presto_dentry_data *presto_d2d(struct dentry *);
 int presto_walk(const char *name, struct nameidata *nd);
 int presto_clear_fsetroot(char *path);
 int presto_clear_all_fsetroots(char *path);
diff -urN linux-2.4.18-pre1/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- linux-2.4.18-pre1/include/linux/pci_ids.h	Mon Jan  7 16:42:52 2002
+++ linux/include/linux/pci_ids.h	Mon Jan  7 16:42:53 2002
@@ -862,11 +862,17 @@
 #define PCI_DEVICE_ID_NVIDIA_QUADRO		0x0103
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX	0x0110
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2	0x0111
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO	0x0112
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR	0x0113
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS	0x0150
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2	0x0151
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA	0x0152
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
+#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3		0x0200
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1		0x0201
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2		0x0202
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC		0x0203
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
diff -urN linux-2.4.18-pre1/include/linux/reiserfs_fs_sb.h linux/include/linux/reiserfs_fs_sb.h
--- linux-2.4.18-pre1/include/linux/reiserfs_fs_sb.h	Fri Dec 21 09:42:03 2001
+++ linux/include/linux/reiserfs_fs_sb.h	Mon Jan  7 16:42:53 2002
@@ -407,7 +407,7 @@
 				/* To be obsoleted soon by per buffer seals.. -Hans */
     atomic_t s_generation_counter; // increased by one every time the
     // tree gets re-balanced
-    unsigned int s_properties;    /* File system properties. Currently holds
+    unsigned long s_properties;    /* File system properties. Currently holds
 				     on-disk FS format */
     
     /* session statistics */
diff -urN linux-2.4.18-pre1/include/linux/sonypi.h linux/include/linux/sonypi.h
--- linux-2.4.18-pre1/include/linux/sonypi.h	Thu Oct 11 11:17:22 2001
+++ linux/include/linux/sonypi.h	Mon Jan  7 16:42:53 2002
@@ -75,9 +75,21 @@
 #define SONYPI_EVENT_LID_OPENED			37
 
 
-/* brightness etc. ioctls */
-#define SONYPI_IOCGBRT	_IOR('v', 0, __u8)
-#define SONYPI_IOCSBRT	_IOW('v', 0, __u8)
+/* get/set brightness */
+#define SONYPI_IOCGBRT		_IOR('v', 0, __u8)
+#define SONYPI_IOCSBRT		_IOW('v', 0, __u8)
+
+/* get battery full capacity/remaining capacity */
+#define SONYPI_IOCGBAT1CAP	_IOR('v', 2, __u16)
+#define SONYPI_IOCGBAT1REM	_IOR('v', 3, __u16)
+#define SONYPI_IOCGBAT2CAP	_IOR('v', 4, __u16)
+#define SONYPI_IOCGBAT2REM	_IOR('v', 5, __u16)
+
+/* get battery flags: battery1/battery2/ac adapter present */
+#define SONYPI_BFLAGS_B1	0x01
+#define SONYPI_BFLAGS_B2	0x02
+#define SONYPI_BFLAGS_AC	0x04
+#define SONYPI_IOCGBATFLAGS	_IOR('v', 7, __u8)
 
 #ifdef __KERNEL__
 
diff -urN linux-2.4.18-pre1/include/linux/sunrpc/clnt.h linux/include/linux/sunrpc/clnt.h
--- linux-2.4.18-pre1/include/linux/sunrpc/clnt.h	Thu Nov 22 11:47:20 2001
+++ linux/include/linux/sunrpc/clnt.h	Mon Jan  7 16:42:53 2002
@@ -136,7 +136,6 @@
 	xprt_set_timeout(&clnt->cl_timeout, retr, incr);
 }
 
-extern void rpciod_tcp_dispatcher(void);
 extern void rpciod_wake_up(void);
 
 /*
diff -urN linux-2.4.18-pre1/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.18-pre1/mm/vmscan.c	Fri Dec 21 09:42:05 2001
+++ linux/mm/vmscan.c	Mon Jan  7 16:42:53 2002
@@ -537,7 +537,7 @@
 
 	spin_lock(&pagemap_lru_lock);
 	entry = active_list.prev;
-	while (nr_pages-- && entry != &active_list) {
+	while (nr_pages && entry != &active_list) {
 		struct page * page;
 
 		page = list_entry(entry, struct page, lru);
@@ -547,6 +547,8 @@
 			list_add(&page->lru, &active_list);
 			continue;
 		}
+
+		nr_pages--;
 
 		del_page_from_active_list(page);
 		add_page_to_inactive_list(page);
