## Automatically generated incremental diff
## From:   linux-2.4.10-pre2
## To:     linux-2.4.10-pre3
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.10-pre2/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.10-pre2/Documentation/Configure.help	Mon Dec  3 23:05:11 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 23:05:27 2001
@@ -11690,19 +11690,6 @@
   The module will be called usbnet.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
-PLUSB driver
-CONFIG_USB_PLUSB
-  A driver for the Prolific PL-2302 USB-to-USB network device. This
-  'USB cable' connects two hosts via a point-to-point network with
-  bandwidth of 5 Mbit/s. Configure this driver after connecting the
-  USB cable via ifconfig plusb0 10.0.0.1 pointopoint 10.0.0.2 (and
-  vice versa on the other host).
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called plusb.o. If you want to compile it as a
-  module, say M here and read Documentation/modules.txt.
-
 USB Diamond Rio500 support
 CONFIG_USB_RIO500
   Say Y here if you want to connect a USB Rio500 mp3 player to your
diff -urN linux-2.4.10-pre2/Makefile linux/Makefile
--- linux-2.4.10-pre2/Makefile	Mon Dec  3 23:05:11 2001
+++ linux/Makefile	Mon Dec  3 23:05:27 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 10
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.10-pre2/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.4.10-pre2/arch/i386/defconfig	Mon Dec  3 23:05:11 2001
+++ linux/arch/i386/defconfig	Mon Dec  3 23:05:27 2001
@@ -742,7 +742,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
-# CONFIG_USB_NET1080 is not set
+# CONFIG_USB_USBNET is not set
 
 #
 # USB port drivers
diff -urN linux-2.4.10-pre2/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- linux-2.4.10-pre2/arch/i386/kernel/bluesmoke.c	Sun Jul  1 19:52:45 2001
+++ linux/arch/i386/kernel/bluesmoke.c	Mon Dec  3 23:05:27 2001
@@ -19,7 +19,7 @@
 	u32 mcgstl, mcgsth;
 	int i;
 	
-	rdmsr(0x17a, mcgstl, mcgsth);
+	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 	if(mcgstl&(1<<0))	/* Recoverable ? */
 		recover=0;
 
@@ -27,7 +27,7 @@
 	
 	for(i=0;i<banks;i++)
 	{
-		rdmsr(0x401+i*4,low, high);
+		rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
 		if(high&(1<<31))
 		{
 			if(high&(1<<29))
@@ -38,18 +38,18 @@
 			high&=~(1<<31);
 			if(high&(1<<27))
 			{
-				rdmsr(0x402+i*4, alow, ahigh);
+				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
 				printk("[%08x%08x]", alow, ahigh);
 			}
 			if(high&(1<<26))
 			{
-				rdmsr(0x402+i*4, alow, ahigh);
+				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
 				printk(" at %08x%08x", 
 					high, low);
 			}
 			printk("\n");
 			/* Clear it */
-			wrmsr(0x401+i*4, 0UL, 0UL);
+			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
 			/* Serialize */
 			wmb();
 		}
@@ -61,7 +61,7 @@
 		panic("Unable to continue");
 	printk(KERN_EMERG "Attempting to continue.\n");
 	mcgstl&=~(1<<2);
-	wrmsr(0x17a,mcgstl, mcgsth);
+	wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
 }
 
 /*
@@ -71,8 +71,8 @@
 static void pentium_machine_check(struct pt_regs * regs, long error_code)
 {
 	u32 loaddr, hi, lotype;
-	rdmsr(0x0, loaddr, hi);
-	rdmsr(0x1, lotype, hi);
+	rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
+	rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
 	printk(KERN_EMERG "CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
 	if(lotype&(1<<5))
 		printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
@@ -133,8 +133,8 @@
 		machine_check_vector = pentium_machine_check;
 		wmb();
 		/* Read registers before enabling */
-		rdmsr(0x0, l, h);
-		rdmsr(0x1, l, h);
+		rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
+		rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
 		if(done==0)
 			printk(KERN_INFO "Intel old style machine check architecture supported.\n");
 		/* Enable MCE */		
@@ -161,17 +161,17 @@
 	
 	if(done==0)
 		printk(KERN_INFO "Intel machine check architecture supported.\n");
-	rdmsr(0x179, l, h);
+	rdmsr(MSR_IA32_MCG_CAP, l, h);
 	if(l&(1<<8))
-		wrmsr(0x17b, 0xffffffff, 0xffffffff);
+		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 	banks = l&0xff;
 	for(i=1;i<banks;i++)
 	{
-		wrmsr(0x400+4*i, 0xffffffff, 0xffffffff); 
+		wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
 	}
 	for(i=0;i<banks;i++)
 	{
-		wrmsr(0x401+4*i, 0x0, 0x0); 
+		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
 	}
 	set_in_cr4(X86_CR4_MCE);
 	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
@@ -191,10 +191,10 @@
 	/* Winchip C6 */
 	machine_check_vector = winchip_machine_check;
 	wmb();
-	rdmsr(0x107, lo, hi);
+	rdmsr(MSR_IDT_FCR1, lo, hi);
 	lo|= (1<<2);	/* Enable EIERRINT (int 18 MCE) */
 	lo&= ~(1<<4);	/* Enable MCE */
-	wrmsr(0x107, lo, hi);
+	wrmsr(MSR_IDT_FCR1, lo, hi);
 	__asm__ __volatile__ (
 		"movl %%cr4, %%eax\n\t"
 		"orl $0x40, %%eax\n\t"
@@ -236,6 +236,6 @@
 static int __init mcheck_disable(char *str)
 {
 	mce_disabled = 1;
-	return 1;
+	return 0;
 }
 __setup("nomce", mcheck_disable);
diff -urN linux-2.4.10-pre2/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- linux-2.4.10-pre2/arch/i386/kernel/mtrr.c	Thu May 24 15:14:08 2001
+++ linux/arch/i386/kernel/mtrr.c	Mon Dec  3 23:05:27 2001
@@ -389,21 +389,19 @@
 	 return;
 
     /*  Save value of CR4 and clear Page Global Enable (bit 7)  */
-    if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
-	asm volatile ("movl  %%cr4, %0\n\t"
-		      "movl  %0, %1\n\t"
-		      "andb  $0x7f, %b1\n\t"
-		      "movl  %1, %%cr4\n\t"
-		      : "=r" (ctxt->cr4val), "=q" (tmp) : : "memory");
+    if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) {
+	ctxt->cr4val = read_cr4();
+	write_cr4(ctxt->cr4val & (unsigned char) ~(1<<7));
+    }
 
     /*  Disable and flush caches. Note that wbinvd flushes the TLBs as
 	a side-effect  */
-    asm volatile ("movl  %%cr0, %0\n\t"
-		  "orl   $0x40000000, %0\n\t"
-		  "wbinvd\n\t"
-		  "movl  %0, %%cr0\n\t"
-		  "wbinvd\n\t"
-		  : "=r" (tmp) : : "memory");
+    {
+	unsigned int cr0 = read_cr0() | 0x40000000;
+	wbinvd();
+	write_cr0( cr0 );
+	wbinvd();
+    }
 
     if ( mtrr_if == MTRR_IF_INTEL ) {
 	/*  Disable MTRRs, and set the default type to uncached  */
@@ -420,15 +418,13 @@
 /*  Restore the processor after a set_mtrr_prepare  */
 static void set_mtrr_done (struct set_mtrr_context *ctxt)
 {
-    unsigned long tmp;
-
     if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) {
 	 __restore_flags (ctxt->flags);
 	 return;
     }
 
     /*  Flush caches and TLBs  */
-    asm volatile ("wbinvd" : : : "memory" );
+    wbinvd();
 
     /*  Restore MTRRdefType  */
     if ( mtrr_if == MTRR_IF_INTEL ) {
@@ -440,15 +436,11 @@
     }
 
     /*  Enable caches  */
-    asm volatile ("movl  %%cr0, %0\n\t"
-		  "andl  $0xbfffffff, %0\n\t"
-		  "movl  %0, %%cr0\n\t"
-		  : "=r" (tmp) : : "memory");
+    write_cr0( read_cr0() & 0xbfffffff );
 
     /*  Restore value of CR4  */
     if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
-	asm volatile ("movl  %0, %%cr4"
-		      : : "r" (ctxt->cr4val) : "memory");
+	write_cr4(ctxt->cr4val);
 
     /*  Re-enable interrupts locally (if enabled previously)  */
     __restore_flags (ctxt->flags);
@@ -607,7 +599,7 @@
 {
     unsigned long low, high;
 
-    rdmsr (0xC0000085, low, high);
+    rdmsr (MSR_K6_UWCCR, low, high);
     /*  Upper dword is region 1, lower is region 0  */
     if (reg == 1) low = high;
     /*  The base masks off on the right alignment  */
@@ -771,7 +763,7 @@
     /*
      *	Low is MTRR0 , High MTRR 1
      */
-    rdmsr (0xC0000085, regs[0], regs[1]);
+    rdmsr (MSR_K6_UWCCR, regs[0], regs[1]);
     /*
      *	Blank to disable
      */
@@ -792,8 +784,8 @@
      *	The writeback rule is quite specific. See the manual. Its
      *	disable local interrupts, write back the cache, set the mtrr
      */
-    __asm__ __volatile__ ("wbinvd" : : : "memory");
-    wrmsr (0xC0000085, regs[0], regs[1]);
+	wbinvd();
+	wrmsr (MSR_K6_UWCCR, regs[0], regs[1]);
     if (do_safe) set_mtrr_done (&ctxt);
 }   /*  End Function amd_set_mtrr_up  */
 
@@ -826,7 +818,7 @@
     }
     centaur_mcr[reg].high = high;
     centaur_mcr[reg].low = low;
-    wrmsr (0x110 + reg, low, high);
+    wrmsr (MSR_IDT_MCR0 + reg, low, high);
     if (do_safe) set_mtrr_done( &ctxt );
 }   /*  End Function centaur_set_mtrr_up  */
 
@@ -2012,12 +2004,12 @@
      * find out what the bios might have done.
      */
      
-    rdmsr(0x120, lo, hi);
+    rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
     if(((lo>>17)&7)==1)		/* Type 1 Winchip2 MCR */
     {
     	lo&= ~0x1C0;		/* clear key */
     	lo|= 0x040;		/* set key to 1 */
-	wrmsr(0x120, lo, hi);	/* unlock MCR */
+	wrmsr(MSR_IDT_MCR_CTRL, lo, hi);	/* unlock MCR */
     }    
     
     centaur_mcr_type = 1;
@@ -2031,7 +2023,7 @@
     	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
     	{
     		if(!(lo & (1<<(9+i))))
-			wrmsr (0x110 + i , 0, 0);
+			wrmsr (MSR_IDT_MCR0 + i , 0, 0);
 		else
 			/*
 			 *	If the BIOS set up an MCR we cannot see it
@@ -2047,7 +2039,7 @@
      */
 
     lo |= 15;			/* Write combine enables */
-    wrmsr(0x120, lo, hi);
+    wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
 }   /*  End Function centaur_mcr1_init  */
 
 /*
@@ -2071,10 +2063,10 @@
     for (i = 0; i < 8; ++i)
     {
     	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
-		wrmsr (0x110 + i , 0, 0);
+		wrmsr (MSR_IDT_MCR0 + i , 0, 0);
     }
 
-    wrmsr(0x120, 0x01F0001F, 0);	/* Write only */
+    wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);	/* Write only */
 }   /*  End Function centaur_mcr0_init  */
 
 /*
@@ -2230,6 +2222,8 @@
 	 *  :-)
 	 */
 	cyrix_arr_init_secondary ();
+	break;
+    case MTRR_IF_NONE:
 	break;
     default:
 	/* I see no MTRRs I can support in SMP mode... */
diff -urN linux-2.4.10-pre2/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- linux-2.4.10-pre2/arch/i386/kernel/pci-pc.c	Sun Aug 12 10:54:07 2001
+++ linux/arch/i386/kernel/pci-pc.c	Mon Dec  3 23:05:27 2001
@@ -20,65 +20,145 @@
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
 
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus;
-struct pci_ops *pci_root_ops;
+struct pci_bus *pci_root_bus = NULL;
+struct pci_ops *pci_root_ops = NULL;
+
+int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
+int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
 
 /*
- * Direct access to PCI hardware...
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
  */
+spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
 
-#ifdef CONFIG_PCI_DIRECT
 
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
  */
 
-#define CONFIG_CMD(dev, where)   (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
+#ifdef CONFIG_PCI_DIRECT
+
+#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
+	(0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+{
+	unsigned long flags;
+
+	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+
+	switch (len) {
+	case 1:
+		*value = inb(0xCFC + (reg & 3));
+		break;
+	case 2:
+		*value = inw(0xCFC + (reg & 2));
+		break;
+	case 4:
+		*value = inl(0xCFC);
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+	unsigned long flags;
+
+	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+
+	switch (len) {
+	case 1:
+		outb((u8)value, 0xCFC + (reg & 3));
+		break;
+	case 2:
+		outw((u16)value, 0xCFC + (reg & 2));
+		break;
+	case 4:
+		outl((u32)value, 0xCFC);
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+#undef PCI_CONF1_ADDRESS
 
 static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	*value = inb(0xCFC + (where&3));
-	return PCIBIOS_SUCCESSFUL;
+	int result; 
+	u32 data;
+
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, &data);
+
+	*value = (u8)data;
+
+	return result;
 }
 
 static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);    
-	*value = inw(0xCFC + (where&2));
-	return PCIBIOS_SUCCESSFUL;    
+	int result; 
+	u32 data;
+
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, &data);
+
+	*value = (u16)data;
+
+	return result;
 }
 
 static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	*value = inl(0xCFC);
-	return PCIBIOS_SUCCESSFUL;    
+	if (!value) 
+		return -EINVAL;
+
+	return pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
 static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);    
-	outb(value, 0xCFC + (where&3));
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, value);
 }
 
 static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	outw(value, 0xCFC + (where&2));
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, value);
 }
 
 static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
-	outl(CONFIG_CMD(dev,where), 0xCF8);
-	outl(value, 0xCFC);
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
-#undef CONFIG_CMD
-
 static struct pci_ops pci_direct_conf1 = {
 	pci_conf1_read_config_byte,
 	pci_conf1_read_config_word,
@@ -88,68 +168,131 @@
 	pci_conf1_write_config_dword
 };
 
+
 /*
  * Functions for accessing PCI configuration space with type 2 accesses
  */
 
-#define IOADDR(devfn, where)	((0xC000 | ((devfn & 0x78) << 5)) + where)
-#define FUNC(devfn)		(((devfn & 7) << 1) | 0xf0)
-#define SET(dev)		if (dev->devfn & 0x80) return PCIBIOS_DEVICE_NOT_FOUND;		\
-				outb(FUNC(dev->devfn), 0xCF8);					\
-				outb(dev->bus->number, 0xCFA);
+#define PCI_CONF2_ADDRESS(dev, reg)	(u16)(0xC000 | (dev << 8) | reg)
 
-static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+static int pci_conf2_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
 {
-	SET(dev);
-	*value = inb(IOADDR(dev->devfn,where));
+	unsigned long flags;
+
+	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	if (dev & 0x10) 
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+	outb((u8)bus, 0xCFA);
+
+	switch (len) {
+	case 1:
+		*value = inb(PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 2:
+		*value = inw(PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 4:
+		*value = inl(PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	}
+
 	outb (0, 0xCF8);
-	return PCIBIOS_SUCCESSFUL;
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+static int pci_conf2_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+	unsigned long flags;
+
+	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
+		return -EINVAL;
+
+	if (dev & 0x10) 
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+	outb((u8)bus, 0xCFA);
+
+	switch (len) {
+	case 1:
+		outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 2:
+		outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	case 4:
+		outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg));
+		break;
+	}
+
+	outb (0, 0xCF8);    
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return 0;
+}
+
+#undef PCI_CONF2_ADDRESS
+
+static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	int result; 
+	u32 data;
+	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, &data);
+	*value = (u8)data;
+	return result;
 }
 
 static int pci_conf2_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	SET(dev);
-	*value = inw(IOADDR(dev->devfn,where));
-	outb (0, 0xCF8);
-	return PCIBIOS_SUCCESSFUL;
+	int result; 
+	u32 data;
+	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, &data);
+	*value = (u8)data;
+	return result;
 }
 
 static int pci_conf2_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	SET(dev);
-	*value = inl (IOADDR(dev->devfn,where));    
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	int result; 
+	u32 data;
+	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, &data);
+	*value = (u8)data;
+	return result;
 }
 
 static int pci_conf2_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	SET(dev);
-	outb (value, IOADDR(dev->devfn,where));
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, value);
 }
 
 static int pci_conf2_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	SET(dev);
-	outw (value, IOADDR(dev->devfn,where));
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, value);
 }
 
 static int pci_conf2_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
-	SET(dev);
-	outl (value, IOADDR(dev->devfn,where));    
-	outb (0, 0xCF8);    
-	return PCIBIOS_SUCCESSFUL;
+	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
-#undef SET
-#undef IOADDR
-#undef FUNC
-
 static struct pci_ops pci_direct_conf2 = {
 	pci_conf2_read_config_byte,
 	pci_conf2_read_config_word,
@@ -159,6 +302,7 @@
 	pci_conf2_write_config_dword
 };
 
+
 /*
  * Before we decide to use direct hardware access mechanisms, we try to do some
  * trivial checks to ensure it at least _seems_ to be working -- we just test
@@ -420,114 +564,176 @@
 	return (int) (ret & 0xff00) >> 8;
 }
 
+static int pci_bios_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+{
+	unsigned long result = 0;
+	unsigned long flags;
+	unsigned long bx = ((bus << 8) | (dev << 3) | fn);
+
+	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	switch (len) {
+	case 1:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=c" (*value),
+			  "=a" (result)
+			: "1" (PCIBIOS_READ_CONFIG_BYTE),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 2:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=c" (*value),
+			  "=a" (result)
+			: "1" (PCIBIOS_READ_CONFIG_WORD),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 4:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=c" (*value),
+			  "=a" (result)
+			: "1" (PCIBIOS_READ_CONFIG_DWORD),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return (int)((result & 0xff00) >> 8);
+}
+
+static int pci_bios_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+	unsigned long result = 0;
+	unsigned long flags;
+	unsigned long bx = ((bus << 8) | (dev << 3) | fn);
+
+	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
+		return -EINVAL;
+
+	spin_lock_irqsave(&pci_config_lock, flags);
+
+	switch (len) {
+	case 1:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=a" (result)
+			: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
+			  "c" (value),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 2:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=a" (result)
+			: "0" (PCIBIOS_WRITE_CONFIG_WORD),
+			  "c" (value),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	case 4:
+		__asm__("lcall (%%esi); cld\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:"
+			: "=a" (result)
+			: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
+			  "c" (value),
+			  "b" (bx),
+			  "D" ((long)reg),
+			  "S" (&pci_indirect));
+		break;
+	}
+
+	spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	return (int)((result & 0xff00) >> 8);
+}
+
 static int pci_bios_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
+	int result; 
+	u32 data;
 
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_BYTE),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, &data);
+
+	*value = (u8)data;
+
+	return result;
 }
 
 static int pci_bios_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
+	int result; 
+	u32 data;
 
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_WORD),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	if (!value) 
+		return -EINVAL;
+
+	result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, &data);
+
+	*value = (u16)data;
+
+	return result;
 }
 
 static int pci_bios_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_DWORD),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	if (!value) 
+		return -EINVAL;
+	
+	return pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
 static int pci_bios_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 1, value);
 }
 
 static int pci_bios_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_WORD),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 2, value);
 }
 
 static int pci_bios_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
-	unsigned long ret;
-	unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
-	__asm__("lcall (%%esi); cld\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	return (int) (ret & 0xff00) >> 8;
+	return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
+		PCI_FUNC(dev->devfn), where, 4, value);
 }
 
+
 /*
  * Function table for BIOS32 access
  */
@@ -981,34 +1187,47 @@
 	pci_read_bridge_bases(b);
 }
 
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space, but we still keep BIOS order of cards to be
- * compatible with 2.0.X. This should go away some day.
- */
 
-void __init pcibios_init(void)
+void __init pcibios_config_init(void)
 {
-	struct pci_ops *bios = NULL;
-	struct pci_ops *dir = NULL;
+	/*
+	 * Try all known PCI access methods. Note that we support using 
+	 * both PCI BIOS and direct access, with a preference for direct.
+	 */
 
 #ifdef CONFIG_PCI_BIOS
-	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
+	if ((pci_probe & PCI_PROBE_BIOS) 
+		&& ((pci_root_ops = pci_find_bios()))) {
 		pci_probe |= PCI_BIOS_SORT;
 		pci_bios_present = 1;
+		pci_config_read = pci_bios_read;
+		pci_config_write = pci_bios_write;
 	}
 #endif
+
 #ifdef CONFIG_PCI_DIRECT
-	if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
-		dir = pci_check_direct();
+	if ((pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)) 
+		&& (pci_root_ops = pci_check_direct())) {
+		if (pci_root_ops == &pci_direct_conf1) {
+			pci_config_read = pci_conf1_read;
+			pci_config_write = pci_conf1_write;
+		}
+		else {
+			pci_config_read = pci_conf2_read;
+			pci_config_write = pci_conf2_write;
+		}
+	}
 #endif
-	if (dir)
-		pci_root_ops = dir;
-	else if (bios)
-		pci_root_ops = bios;
-	else {
-		printk("PCI: No PCI bus detected\n");
+
+	return;
+}
+
+void __init pcibios_init(void)
+{
+	if (!pci_root_ops)
+		pcibios_config_init();
+	if (!pci_root_ops) {
+		printk("PCI: System does not support PCI\n");
 		return;
 	}
 
diff -urN linux-2.4.10-pre2/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.4.10-pre2/arch/i386/kernel/setup.c	Wed Jul 11 09:31:44 2001
+++ linux/arch/i386/kernel/setup.c	Mon Dec  3 23:05:27 2001
@@ -64,6 +64,9 @@
  *
  *  VIA C3 Support.
  *  Dave Jones <davej@suse.de>, March 2001
+ *
+ *  AMD Athlon/Duron/Thunderbird bluesmoke support.
+ *  Dave Jones <davej@suse.de>, April 2001.
  */
 
 /*
@@ -93,6 +96,7 @@
 #include <linux/bootmem.h>
 #include <asm/processor.h>
 #include <linux/console.h>
+#include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -145,9 +149,9 @@
 
 unsigned char aux_device_present;
 
+extern void mcheck_init(struct cpuinfo_x86 *c);
 extern int root_mountflags;
 extern char _text, _etext, _edata, _end;
-extern unsigned long cpu_khz;
 
 static int disable_x86_serial_nr __initdata = 1;
 static int disable_x86_fxsr __initdata = 0;
@@ -1088,11 +1092,18 @@
 	l2size = ecx >> 16;
 
 	/* AMD errata T13 (order #21922) */
-	if (c->x86_vendor == X86_VENDOR_AMD &&
-	    c->x86 == 6 &&
-	    c->x86_model == 3 &&
-	    c->x86_mask == 0) {
-		l2size = 64;
+	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+		if (c->x86_model == 3 && c->x86_mask == 0)	/* Duron Rev A0 */
+			l2size = 64;
+		if (c->x86_model == 4 &&
+			(c->x86_mask==0 || c->x86_mask==1))	/* Tbird rev A1/A2 */
+			l2size = 256;
+	}
+
+	/* VIA C3 CPUs (670-68F) need further shifting. */
+	if (c->x86_vendor == X86_VENDOR_CENTAUR && (c->x86 == 6) &&
+		((c->x86_model == 7) || (c->x86_model == 8))) {
+		l2size = l2size >> 8;
 	}
 
 	if ( l2size == 0 )
@@ -1109,7 +1120,7 @@
  *	misexecution of code under Linux. Owners of such processors should
  *	contact AMD for precise details and a CPU swap.
  *
- *	See	http://www.mygale.com/~poulot/k6bug.html
+ *	See	http://www.multimania.com/poulot/k6bug.html
  *		http://www.amd.com/K6/k6docs/revgd.html
  *
  *	The following test is erm.. interesting. AMD neglected to up
@@ -1126,6 +1137,12 @@
 	int mbytes = max_mapnr >> (20-PAGE_SHIFT);
 	int r;
 
+	/*
+	 *	FIXME: We should handle the K5 here. Set up the write
+	 *	range and also turn on MSR 83 bits 4 and 31 (write alloc,
+	 *	no bus pipeline)
+	 */
+
 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
 	clear_bit(0*32+31, &c->x86_capability);
@@ -1185,13 +1202,13 @@
 				if(mbytes>508)
 					mbytes=508;
 					
-				rdmsr(0xC0000082, l, h);
+				rdmsr(MSR_K6_WHCR, l, h);
 				if ((l&0x0000FFFF)==0) {
 					unsigned long flags;
 					l=(1<<0)|((mbytes/4)<<1);
 					local_irq_save(flags);
-					__asm__ __volatile__ ("wbinvd": : :"memory");
-					wrmsr(0xC0000082, l, h);
+					wbinvd();
+					wrmsr(MSR_K6_WHCR, l, h);
 					local_irq_restore(flags);
 					printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
 						mbytes);
@@ -1206,13 +1223,13 @@
 				if(mbytes>4092)
 					mbytes=4092;
 
-				rdmsr(0xC0000082, l, h);
+				rdmsr(MSR_K6_WHCR, l, h);
 				if ((l&0xFFFF0000)==0) {
 					unsigned long flags;
 					l=((mbytes>>2)<<22)|(1<<16);
 					local_irq_save(flags);
-					__asm__ __volatile__ ("wbinvd": : :"memory");
-					wrmsr(0xC0000082, l, h);
+					wbinvd();
+					wrmsr(MSR_K6_WHCR, l, h);
 					local_irq_restore(flags);
 					printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n",
 						mbytes);
@@ -1226,10 +1243,10 @@
 					set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability);
 				break;
 			}
-
 			break;
 
 		case 6:	/* An Athlon/Duron. We can trust the BIOS probably */
+			mcheck_init(c);
 			break;		
 	}
 
@@ -1312,9 +1329,10 @@
 
 static void __init check_cx686_slop(struct cpuinfo_x86 *c)
 {
+	unsigned long flags;
+
 	if (Cx86_dir0_msb == 3) {
 		unsigned char ccr3, ccr5;
-		unsigned long flags;
 
 		local_irq_save(flags);
 		ccr3 = getCx86(CX86_CCR3);
@@ -1551,14 +1569,12 @@
 				name="??";
 			}
 
-			/* get FCR  */
-			rdmsr(0x107, lo, hi);
-
+			rdmsr(MSR_IDT_FCR1, lo, hi);
 			newlo=(lo|fcr_set) & (~fcr_clr);
 
 			if (newlo!=lo) {
 				printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
-				wrmsr(0x107, newlo, hi );
+				wrmsr(MSR_IDT_FCR1, newlo, hi );
 			} else {
 				printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
 			}
@@ -1577,14 +1593,15 @@
 				c->x86_cache_size = (cc>>24)+(dd>>24);
 			}
 			sprintf( c->x86_model_id, "WinChip %s", name );
+			mcheck_init(c);
 			break;
 
 		case 6:
 			switch (c->x86_model) {
 				case 6 ... 7:		/* Cyrix III or C3 */
-					rdmsr (0x1107, lo, hi);
+					rdmsr (MSR_VIA_FCR, lo, hi);
 					lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
-					wrmsr (0x1107, lo, hi);
+					wrmsr (MSR_VIA_FCR, lo, hi);
 
 					set_bit(X86_FEATURE_CX8, &c->x86_capability);
 					set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
@@ -1595,7 +1612,6 @@
 			}
 			break;
 	}
-
 }
 
 
@@ -1668,7 +1684,6 @@
 	if (c->x86_model > 2)
 		printk(" II");
 	printk("\n");
-	printk("If you have one of these please email davej@suse.de\n");
 
 	/* Unhide possibly hidden capability flags
 	   The mp6 iDragon family don't have MSRs.
@@ -1694,7 +1709,6 @@
 #ifndef CONFIG_M686
 	static int f00f_workaround_enabled = 0;
 #endif
-	extern void mcheck_init(struct cpuinfo_x86 *c);
 	char *p = NULL;
 	unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
 
@@ -1989,9 +2003,9 @@
 	    disable_x86_serial_nr ) {
 		/* Disable processor serial number */
 		unsigned long lo,hi;
-		rdmsr(0x119,lo,hi);
+		rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
 		lo |= 0x200000;
-		wrmsr(0x119,lo,hi);
+		wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
 		printk(KERN_NOTICE "CPU serial number disabled.\n");
 		clear_bit(X86_FEATURE_PN, &c->x86_capability);
 
diff -urN linux-2.4.10-pre2/arch/mips64/kernel/ioctl32.c linux/arch/mips64/kernel/ioctl32.c
--- linux-2.4.10-pre2/arch/mips64/kernel/ioctl32.c	Wed Jul  4 11:50:39 2001
+++ linux/arch/mips64/kernel/ioctl32.c	Mon Dec  3 23:05:27 2001
@@ -770,6 +770,8 @@
 	IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans),
 	IOCTL32_DEFAULT(BLKELVGET),
 	IOCTL32_DEFAULT(BLKELVSET),
+	IOCTL32_DEFAULT(BLKBSZGET),
+	IOCTL32_DEFAULT(BLKBSZSET),
 
 #ifdef CONFIG_MD
 	/* status */
diff -urN linux-2.4.10-pre2/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- linux-2.4.10-pre2/arch/ppc/kernel/chrp_setup.c	Mon Dec  3 23:05:12 2001
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon Dec  3 23:05:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.chrp_setup.c 1.32 08/20/01 22:58:32 paulus
+ * BK Id: SCCS/s.chrp_setup.c 1.34 08/29/01 10:07:29 paulus
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -78,7 +78,6 @@
 			   char raw_mode);
 extern char pckbd_unexpected_up(unsigned char keycode);
 extern void pckbd_leds(unsigned char leds);
-extern int pckbd_rate(struct kbd_repeat *rep);
 extern void pckbd_init_hw(void);
 extern unsigned char pckbd_sysrq_xlate[128];
 extern void select_adb_keyboard(void);
@@ -546,7 +545,6 @@
 	ppc_md.kbd_translate     = pckbd_translate;
 	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
 	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_rate_fn	 = pckbd_rate;
 	ppc_md.kbd_init_hw       = pckbd_init_hw;
 #ifdef CONFIG_MAGIC_SYSRQ
 	ppc_md.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
diff -urN linux-2.4.10-pre2/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- linux-2.4.10-pre2/arch/ppc/kernel/head_8xx.S	Mon Dec  3 23:05:12 2001
+++ linux/arch/ppc/kernel/head_8xx.S	Mon Dec  3 23:05:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.head_8xx.S 1.19 08/16/01 23:00:17 paulus
+ * BK Id: SCCS/s.head_8xx.S 1.21 08/28/01 16:27:27 trini
  */
 /*
  *  arch/ppc/kernel/except_8xx.S
@@ -823,8 +823,8 @@
 	mtspr	DC_CST, r8
 	lis	r8, IDC_ENABLE@h
 	mtspr	DC_CST, r8
-	blr
 #endif
+	blr
 
 
 /*
diff -urN linux-2.4.10-pre2/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- linux-2.4.10-pre2/arch/ppc/kernel/pmac_setup.c	Mon Dec  3 23:05:12 2001
+++ linux/arch/ppc/kernel/pmac_setup.c	Mon Dec  3 23:05:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pmac_setup.c 1.35 08/20/01 22:37:37 paulus
+ * BK Id: SCCS/s.pmac_setup.c 1.37 08/29/01 10:07:29 paulus
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -728,7 +728,6 @@
 	ppc_md.kbd_setkeycode    = 0;
 	ppc_md.kbd_getkeycode    = 0;
 	ppc_md.kbd_leds		 = 0;
-	ppc_md.kbd_rate_fn	 = 0;
 #ifdef CONFIG_MAGIC_SYSRQ
 #ifdef CONFIG_MAC_ADBKEYCODES
 	if (!keyboard_sends_linux_keycodes) {
@@ -747,7 +746,6 @@
 	ppc_md.kbd_translate        = mackbd_translate;
 	ppc_md.kbd_unexpected_up    = mackbd_unexpected_up;
 	ppc_md.kbd_leds             = mackbd_leds;
-	ppc_md.kbd_rate_fn	    = NULL;
 	ppc_md.kbd_init_hw          = mackbd_init_hw;
 #ifdef CONFIG_MAGIC_SYSRQ
 	ppc_md.ppc_kbd_sysrq_xlate  = mackbd_sysrq_xlate;
diff -urN linux-2.4.10-pre2/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- linux-2.4.10-pre2/arch/ppc/kernel/prep_setup.c	Mon Dec  3 23:05:12 2001
+++ linux/arch/ppc/kernel/prep_setup.c	Mon Dec  3 23:05:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.prep_setup.c 1.32 08/20/01 15:06:15 paulus
+ * BK Id: SCCS/s.prep_setup.c 1.34 08/29/01 10:07:29 paulus
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -89,7 +89,6 @@
 			   char raw_mode);
 extern char pckbd_unexpected_up(unsigned char keycode);
 extern void pckbd_leds(unsigned char leds);
-extern int pckbd_rate(struct kbd_repeat *rep);
 extern void pckbd_init_hw(void);
 extern unsigned char pckbd_sysrq_xlate[128];
 
@@ -955,7 +954,6 @@
 	ppc_md.kbd_translate     = pckbd_translate;
 	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
 	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_rate_fn	 = pckbd_rate;
 	ppc_md.kbd_init_hw       = pckbd_init_hw;
 #ifdef CONFIG_MAGIC_SYSRQ
 	ppc_md.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
diff -urN linux-2.4.10-pre2/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.10-pre2/arch/sparc64/kernel/ioctl32.c	Tue Aug  7 08:30:50 2001
+++ linux/arch/sparc64/kernel/ioctl32.c	Mon Dec  3 23:05:27 2001
@@ -3691,6 +3691,8 @@
 COMPATIBLE_IOCTL(BLKFRASET)
 COMPATIBLE_IOCTL(BLKSECTSET)
 COMPATIBLE_IOCTL(BLKSSZGET)
+COMPATIBLE_IOCTL(BLKBSZGET)
+COMPATIBLE_IOCTL(BLKBSZSET)
 
 /* RAID */
 COMPATIBLE_IOCTL(RAID_VERSION)
diff -urN linux-2.4.10-pre2/drivers/acpi/include/platform/acgcc.h linux/drivers/acpi/include/platform/acgcc.h
--- linux-2.4.10-pre2/drivers/acpi/include/platform/acgcc.h	Wed Jun 20 17:47:40 2001
+++ linux/drivers/acpi/include/platform/acgcc.h	Mon Dec  3 23:05:27 2001
@@ -39,7 +39,6 @@
 #define BREAKPOINT3
 #define disable() __cli()
 #define enable()  __sti()
-#define wbinvd()
 
 /*! [Begin] no source code translation */
 
@@ -101,7 +100,6 @@
 #define disable() __cli()
 #define enable()  __sti()
 #define halt()    __asm__ __volatile__ ("sti; hlt":::"memory")
-#define wbinvd()
 
 /*! [Begin] no source code translation
  *
diff -urN linux-2.4.10-pre2/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- linux-2.4.10-pre2/drivers/block/DAC960.c	Mon Aug  6 10:34:38 2001
+++ linux/drivers/block/DAC960.c	Mon Dec  3 23:05:27 2001
@@ -31,6 +31,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/hdreg.h>
+#include <linux/blkpg.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/locks.h>
@@ -5094,21 +5095,12 @@
 						 .nr_sects,
 		      (long *) Argument);
     case BLKRAGET:
-      /* Get Read-Ahead. */
-      if ((long *) Argument == NULL) return -EINVAL;
-      return put_user(read_ahead[MAJOR(Inode->i_rdev)], (long *) Argument);
     case BLKRASET:
-      /* Set Read-Ahead. */
-      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-      if (Argument > 256) return -EINVAL;
-      read_ahead[MAJOR(Inode->i_rdev)] = Argument;
-      return 0;
     case BLKFLSBUF:
-      /* Flush Buffers. */
-      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-      fsync_dev(Inode->i_rdev);
-      invalidate_buffers(Inode->i_rdev);
-      return 0;
+    case BLKBSZGET:
+    case BLKBSZSET:
+      return blk_ioctl (Inode->i_rdev, Request, Argument);
+
     case BLKRRPART:
       /* Re-Read Partition Table. */
       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
diff -urN linux-2.4.10-pre2/drivers/block/blkpg.c linux/drivers/block/blkpg.c
--- linux-2.4.10-pre2/drivers/block/blkpg.c	Sun May 20 11:34:05 2001
+++ linux/drivers/block/blkpg.c	Mon Dec  3 23:05:27 2001
@@ -274,6 +274,29 @@
 			return blkelvset_ioctl(&blk_get_queue(dev)->elevator,
 					       (blkelv_ioctl_arg_t *) arg);
 
+		case BLKBSZGET:
+			/* get the logical block size (cf. BLKSSZGET) */
+			intval = BLOCK_SIZE;
+			if (blksize_size[MAJOR(dev)])
+				intval = blksize_size[MAJOR(dev)][MINOR(dev)];
+			return put_user (intval, (int *) arg);
+
+		case BLKBSZSET:
+			/* set the logical block size */
+			if (!capable (CAP_SYS_ADMIN))
+				return -EACCES;
+			if (!dev || !arg)
+				return -EINVAL;
+			if (get_user (intval, (int *) arg))
+				return -EFAULT;
+			if (intval > PAGE_SIZE || intval < 512 ||
+			    (intval & (intval - 1)))
+				return -EINVAL;
+			if (is_mounted (dev) || is_swap_partition (dev))
+				return -EBUSY;
+			set_blocksize (dev, intval);
+			return 0;
+
 		default:
 			return -EINVAL;
 	}
diff -urN linux-2.4.10-pre2/drivers/block/cciss.c linux/drivers/block/cciss.c
--- linux-2.4.10-pre2/drivers/block/cciss.c	Mon Jul  2 13:56:40 2001
+++ linux/drivers/block/cciss.c	Mon Dec  3 23:05:27 2001
@@ -406,6 +406,8 @@
 	case BLKRRPART:
 		return revalidate_logvol(inode->i_rdev, 1);
 	case BLKFLSBUF:
+	case BLKBSZSET:
+	case BLKBSZGET:
 	case BLKROSET:
 	case BLKROGET:
 	case BLKRASET:
diff -urN linux-2.4.10-pre2/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- linux-2.4.10-pre2/drivers/block/cpqarray.c	Wed Jul 25 14:12:01 2001
+++ linux/drivers/block/cpqarray.c	Mon Dec  3 23:05:27 2001
@@ -1266,6 +1266,8 @@
 	}	
 
 	case BLKFLSBUF:
+	case BLKBSZSET:
+	case BLKBSZGET:
 	case BLKROSET:
 	case BLKROGET:
 	case BLKRASET:
diff -urN linux-2.4.10-pre2/drivers/block/loop.c linux/drivers/block/loop.c
--- linux-2.4.10-pre2/drivers/block/loop.c	Fri Jun 29 16:16:56 2001
+++ linux/drivers/block/loop.c	Mon Dec  3 23:05:27 2001
@@ -62,6 +62,7 @@
 #include <linux/major.h>
 #include <linux/wait.h>
 #include <linux/blk.h>
+#include <linux/blkpg.h>
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
@@ -853,6 +854,10 @@
 			break;
 		}
 		err = put_user(loop_sizes[lo->lo_number] << 1, (long *) arg);
+		break;
+	case BLKBSZGET:
+	case BLKBSZSET:
+		err = blk_ioctl(inode->i_rdev, cmd, arg);
 		break;
 	default:
 		err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
diff -urN linux-2.4.10-pre2/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- linux-2.4.10-pre2/drivers/block/ps2esdi.c	Tue Jul 10 16:18:51 2001
+++ linux/drivers/block/ps2esdi.c	Mon Dec  3 23:05:27 2001
@@ -1127,6 +1127,8 @@
 		case BLKRASET:
 		case BLKRAGET:
 		case BLKFLSBUF:
+		case BLKBSZGET:
+		case BLKBSZSET:
 		case BLKPG:
 			return blk_ioctl(inode->i_rdev, cmd, arg);
 		}
diff -urN linux-2.4.10-pre2/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.4.10-pre2/drivers/ide/ide.c	Mon Aug 13 14:56:19 2001
+++ linux/drivers/ide/ide.c	Mon Dec  3 23:05:27 2001
@@ -2788,6 +2788,8 @@
 		case BLKPG:
 		case BLKELVGET:
 		case BLKELVSET:
+		case BLKBSZGET:
+		case BLKBSZSET:
 			return blk_ioctl(inode->i_rdev, cmd, arg);
 
 		case HDIO_GET_BUSSTATE:
diff -urN linux-2.4.10-pre2/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile
--- linux-2.4.10-pre2/drivers/macintosh/Makefile	Sun Feb  4 10:21:25 2001
+++ linux/drivers/macintosh/Makefile	Mon Dec  3 23:05:27 2001
@@ -15,7 +15,7 @@
 
 # Objects that export symbols.
 
-export-objs	:= adb.o rtc.o mac_hid.o
+export-objs	:= adb.o rtc.o mac_hid.o via-pmu.o
 
 # Object file lists.
 
diff -urN linux-2.4.10-pre2/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- linux-2.4.10-pre2/drivers/macintosh/via-pmu.c	Mon Jul  2 14:34:57 2001
+++ linux/drivers/macintosh/via-pmu.c	Mon Dec  3 23:05:27 2001
@@ -32,24 +32,29 @@
 #include <linux/pmu.h>
 #include <linux/cuda.h>
 #include <linux/smp_lock.h>
+#include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
-#include <asm/init.h>
 #include <asm/irq.h>
 #include <asm/hardirq.h>
 #include <asm/feature.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/cputable.h>
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
 
 /* Some compile options */
 #undef SUSPEND_USES_PMU
+#define DEBUG_SLEEP
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR	154
@@ -102,13 +107,11 @@
 static struct adb_request *current_req;
 static struct adb_request *last_req;
 static struct adb_request *req_awaiting_reply;
-static unsigned char interrupt_data[256]; /* Made bigger: I've been told that might happen */
+static unsigned char interrupt_data[32];
 static unsigned char *reply_ptr;
 static int data_index;
 static int data_len;
 static volatile int adb_int_pending;
-static int pmu_adb_flags;
-static int adb_dev_map = 0;
 static struct adb_request bright_req_1, bright_req_2, bright_req_3;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
@@ -118,11 +121,20 @@
 static int gpio_irq = -1;
 static volatile int pmu_suspended = 0;
 static spinlock_t pmu_lock;
+static u8 pmu_intr_mask;
+static int pmu_version;
+static int drop_interrupts;
+#ifdef CONFIG_PMAC_PBOOK
+static int sleep_in_progress;
+#endif /* CONFIG_PMAC_PBOOK */
 
 int asleep;
 struct notifier_block *sleep_notifier_list;
 
 #ifdef CONFIG_ADB
+static int adb_dev_map = 0;
+static int pmu_adb_flags;
+
 static int pmu_probe(void);
 static int pmu_init(void);
 static int pmu_send_request(struct adb_request *req, int sync);
@@ -163,8 +175,25 @@
 #endif /* CONFIG_ADB */
 
 extern void low_sleep_handler(void);
-extern void sleep_save_intrs(int);
-extern void sleep_restore_intrs(void);
+extern void pmac_sleep_save_intrs(int);
+extern void pmac_sleep_restore_intrs(void);
+extern void openpic_sleep_save_intrs(void);
+extern void openpic_sleep_restore_intrs(void);
+extern void enable_kernel_altivec(void);
+extern void enable_kernel_fp(void);
+
+#ifdef DEBUG_SLEEP
+int pmu_polled_request(struct adb_request *req);
+int pmu_wink(struct adb_request *req);
+#endif
+
+#if defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM)
+static int generic_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static struct pmu_sleep_notifier generic_sleep_notifier = {
+	generic_notify_sleep,
+	SLEEP_LEVEL_MISC,
+};
+#endif /* defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM) */
 
 /*
  * This table indicates for each PMU opcode:
@@ -246,6 +275,11 @@
 
 	pmu_has_adb = 1;
 
+	pmu_intr_mask =	PMU_INT_PCEJECT |
+			PMU_INT_SNDBRT |
+			PMU_INT_ADB |
+			PMU_INT_TICK;
+	
 	if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
 	    || device_is_compatible(vias->parent, "ohare")))
 		pmu_kind = PMU_OHARE_BASED;
@@ -258,7 +292,12 @@
 
 		pmu_kind = PMU_KEYLARGO_BASED;
 		pmu_has_adb = (find_type_devices("adb") != NULL);
-
+		pmu_intr_mask =	PMU_INT_PCEJECT |
+				PMU_INT_SNDBRT |
+				PMU_INT_ADB |
+				PMU_INT_TICK |
+				PMU_INT_ENVIRONMENT;
+		
 		gpiop = find_devices("gpio");
 		if (gpiop && gpiop->n_addrs) {
 			gpio_reg = ioremap(gpiop->addrs->address, 0x10);
@@ -281,11 +320,16 @@
 		return 0;
 	}
 
-	printk(KERN_INFO "PMU driver initialized for %s\n",
-	       pbook_type[pmu_kind]);
+	printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n",
+	       PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
 	       
 	sys_ctrler = SYS_CTRLER_PMU;
 	
+#if defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM)
+	pmu_register_sleep_notifier(&generic_sleep_notifier);
+	pm_active = 1;
+#endif	
+
 	return 1;
 }
 
@@ -367,7 +411,7 @@
 	out_8(&via[B], via[B] | TREQ);			/* negate TREQ */
 	out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK);	/* TACK in, TREQ out */
 
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
 	timeout =  100000;
 	while (!req.complete) {
 		if (--timeout < 0) {
@@ -392,13 +436,20 @@
 		udelay(10);
 	}
 
-	/* Tell PMU we are ready. Which PMU support this ? */
+	/* Tell PMU we are ready.  */
 	if (pmu_kind == PMU_KEYLARGO_BASED) {
 		pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
 		while (!req.complete)
 			pmu_poll();
 	}
-		
+
+	/* Read PMU version */
+	pmu_request(&req, NULL, 1, PMU_GET_VERSION);
+	while (!req.complete)
+		pmu_poll();
+	if (req.reply_len > 1)
+		pmu_version = req.reply[1];
+
 	return 1;
 }
 
@@ -529,7 +580,7 @@
 	req.done = NULL;
 	req.data[0] = PMU_ADB_CMD;
 	req.data[1] = 0;
-	req.data[2] = ADB_BUSRESET; /* 3 ??? */
+	req.data[2] = ADB_BUSRESET;
 	req.data[3] = 0;
 	req.data[4] = 0;
 	req.reply_len = 0;
@@ -759,7 +810,7 @@
 	}
 	adb_int_pending = 1;
 #ifdef SUSPEND_USES_PMU
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
 	spin_unlock_irqrestore(&pmu_lock, flags);
 	while(!req.complete)
 		pmu_poll();
@@ -789,16 +840,11 @@
 			       "intr=%x pmu_state=%d\n", intr, pmu_state);
 			break;
 		}
+		out_8(&via[IFR], intr);
 		if (intr & SR_INT)
 			pmu_sr_intr(regs);
-		else if (intr & CB1_INT) {
+		else if (intr & CB1_INT)
 			adb_int_pending = 1;
-			out_8(&via[IFR], CB1_INT);
-		}
-		intr &= ~(SR_INT | CB1_INT);
-		if (intr != 0) {
-			out_8(&via[IFR], intr);
-		}
 	}
 	/* This is not necessary except if synchronous ADB requests are done
 	 * with interrupts off, which should not happen. Since I'm not sure
@@ -846,23 +892,17 @@
 		out_8(&via[IFR], SR_INT);
 		return;
 	}
-	/* This one seems to appear with PMU99. According to OF methods,
-	 * the protocol didn't change...
-	 */
-	if (via[B] & TACK) {
-		while ((in_8(&via[B]) & TACK) != 0)
+	/* The ack may not yet be low when we get the interrupt */
+	while ((in_8(&via[B]) & TACK) != 0)
 			;
-	}
-
-	/* reset TREQ and wait for TACK to go high */
-	out_8(&via[B], in_8(&via[B]) | TREQ);
-	wait_for_ack();
 
 	/* if reading grab the byte, and reset the interrupt */
 	if (pmu_state == reading || pmu_state == reading_intr)
 		bite = in_8(&via[SR]);
 
-	out_8(&via[IFR], SR_INT);
+	/* reset TREQ and wait for TACK to go high */
+	out_8(&via[B], in_8(&via[B]) | TREQ);
+	wait_for_ack();
 
 	switch (pmu_state) {
 	case sending:
@@ -909,9 +949,8 @@
 		if (data_len == -1) {
 			data_len = bite;
 			if (bite > 32)
-				printk(KERN_ERR "PMU: bad reply len %d\n",
-				       bite);
-		} else {
+				printk(KERN_ERR "PMU: bad reply len %d\n", bite);
+		} else if (data_index < 32) {
 			reply_ptr[data_index++] = bite;
 		}
 		if (data_index < data_len) {
@@ -954,11 +993,14 @@
 pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
 {
 	asleep = 0;
-	if (len < 1) {
-//		xmon_printk("empty ADB\n");
+	if (drop_interrupts || len < 1) {
 		adb_int_pending = 0;
 		return;
 	}
+	/* Note: for some reason, we get an interrupt with len=1,
+	 * data[0]==0 after each normal ADB interrupt, at least
+	 * on the Pismo. Still investigating...  --BenH
+	 */
 	if (data[0] & PMU_INT_ADB) {
 		if ((data[0] & PMU_INT_ADB_AUTO) == 0) {
 			struct adb_request *req = req_awaiting_reply;
@@ -1085,10 +1127,14 @@
 
 	cli();
 
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
-					PMU_INT_TICK );
-	while(!req.complete)
-		pmu_poll();
+	drop_interrupts = 1;
+	
+	if (pmu_kind != PMU_KEYLARGO_BASED) {
+		pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+						PMU_INT_TICK );
+		while(!req.complete)
+			pmu_poll();
+	}
 
 	pmu_request(&req, NULL, 1, PMU_RESET);
 	while(!req.complete || (pmu_state != idle))
@@ -1104,10 +1150,14 @@
 
 	cli();
 
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
-					PMU_INT_TICK );
-	while(!req.complete)
-		pmu_poll();
+	drop_interrupts = 1;
+
+	if (pmu_kind != PMU_KEYLARGO_BASED) {
+		pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+						PMU_INT_TICK );
+		while(!req.complete)
+			pmu_poll();
+	}
 
 	pmu_request(&req, NULL, 5, PMU_SHUTDOWN,
 		    'M', 'A', 'T', 'T');
@@ -1127,6 +1177,22 @@
 
 static LIST_HEAD(sleep_notifiers);
 
+#ifdef CONFIG_PM
+static int
+generic_notify_sleep(struct pmu_sleep_notifier *self, int when)
+{
+	switch (when) {
+		case PBOOK_SLEEP_NOW:
+			if (pm_send_all(PM_SUSPEND, (void *)3))
+				return PBOOK_SLEEP_REJECT;
+			break;
+		case PBOOK_WAKE:
+			(void) pm_send_all(PM_RESUME, (void *)0);
+	}
+	return PBOOK_SLEEP_OK;
+}
+#endif /* CONFIG_PM */
+
 int
 pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
 {
@@ -1268,23 +1334,42 @@
 	}
 }
 
-#if 0
+#ifdef DEBUG_SLEEP
 /* N.B. This doesn't work on the 3400 */
-void pmu_blink(int n)
+void
+pmu_blink(int n)
 {
 	struct adb_request req;
 
+	memset(&req, 0, sizeof(req));
+
 	for (; n > 0; --n) {
-		pmu_request(&req, NULL, 4, 0xee, 4, 0, 1);
-		while (!req.complete) pmu_poll();
-		udelay(50000);
-		pmu_request(&req, NULL, 4, 0xee, 4, 0, 0);
-		while (!req.complete) pmu_poll();
-		udelay(50000);
+		req.nbytes = 4;
+		req.done = NULL;
+		req.data[0] = 0xee;
+		req.data[1] = 4;
+		req.data[2] = 0;
+		req.data[3] = 1;
+		req.reply[0] = ADB_RET_OK;
+		req.reply_len = 1;
+		req.reply_expected = 0;
+		pmu_polled_request(&req);
+		mdelay(50);
+		req.nbytes = 4;
+		req.done = NULL;
+		req.data[0] = 0xee;
+		req.data[1] = 4;
+		req.data[2] = 0;
+		req.data[3] = 0;
+		req.reply[0] = ADB_RET_OK;
+		req.reply_len = 1;
+		req.reply_expected = 0;
+		pmu_polled_request(&req);
+		mdelay(50);
 	}
-	udelay(150000);
+	mdelay(50);
 }
-#endif
+#endif /* DEBUG_SLEEP */
 
 /*
  * Put the powerbook to sleep.
@@ -1317,7 +1402,6 @@
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 }
 
-#define FEATURE_CTRL(base)	((unsigned int *)(base + 0x38))
 #define	GRACKLE_PM	(1<<7)
 #define GRACKLE_DOZE	(1<<5)
 #define	GRACKLE_NAP	(1<<4)
@@ -1363,7 +1447,8 @@
 		mb();
 
 	/* Wait for completion of async backlight requests */
-	while (!bright_req_1.complete || !bright_req_2.complete || !bright_req_3.complete)
+	while (!bright_req_1.complete || !bright_req_2.complete ||
+		!bright_req_3.complete)
 		pmu_poll();
 	
 	/* Turn off various things. Darwin does some retry tests here... */
@@ -1375,8 +1460,8 @@
 	while (!req.complete)
 		pmu_poll();
 
-	/* Disable all interrupts except pmu */
-	sleep_save_intrs(vias->intrs[0].line);
+	/* Disable all interrupts */
+	pmac_sleep_save_intrs(-1);
 
 	/* Make sure the PMU is idle */
 	while (pmu_state != idle)
@@ -1393,6 +1478,9 @@
 	if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
 		giveup_fpu(current);
 
+	/* We can now disable MSR_EE */
+	cli();
+
 	/* For 750, save backside cache setting and disable it */
 	save_l2cr = _get_L2CR();	/* (returns 0 if not 750) */
 	if (save_l2cr)
@@ -1431,7 +1519,7 @@
  		_set_L2CR(save_l2cr);
 	
 	/* Restore userland MMU context */
-	set_context(current->mm->context);
+	set_context(current->active_mm->context, current->active_mm->pgd);
 
 	/* Re-enable DEC interrupts and kick DEC */
 	asm volatile("mtdec %0" : : "r" (0x7fffffff));
@@ -1464,26 +1552,29 @@
 	}
 
 	/* reenable interrupt controller */
-	sleep_restore_intrs();
+	pmac_sleep_restore_intrs();
 
 	/* Leave some time for HW to settle down */
 	mdelay(100);
 
 	/* Notify drivers */
-	mdelay(10);
 	broadcast_wake();
 
 	return 0;
 }
 
-/* Not finished yet */
 int __openfirmware powerbook_sleep_Core99(void)
 {
-	int ret;
 	unsigned long save_l2cr;
 	unsigned long wait;
 	struct adb_request req;
-
+	int ret, timeout;
+	
+	if (!feature_can_sleep()) {
+		printk(KERN_ERR "Sleep mode not supported on this machine\n");
+		return -ENOSYS;
+	}
+	
 	/* Notify device drivers */
 	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
 	if (ret != PBOOK_SLEEP_OK) {
@@ -1507,81 +1598,140 @@
 	}
 
 	/* Give the disks a little time to actually finish writing */
-	for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
+	for (wait = jiffies + HZ; time_before(jiffies, wait); )
 		mb();
 
+	/* Wait for completion of async backlight requests */
+	while (!bright_req_1.complete || !bright_req_2.complete ||
+		!bright_req_3.complete)
+		pmu_poll();
+
 	/* Tell PMU what events will wake us up */
 	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
 		0xff, 0xff);
 	while (!req.complete)
 		pmu_poll();
+
 	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
 		0, PMU_PWR_WAKEUP_KEY | PMU_PWR_WAKEUP_LID_OPEN);
 	while (!req.complete)
 		pmu_poll();
 		
-	/* Disable all interrupts except pmu */
-	sleep_save_intrs(vias->intrs[0].line);
+	/* Save & disable all interrupts */
+	openpic_sleep_save_intrs();
+
+	/* Make sure the PMU is idle */
+	while (pmu_state != idle)
+		pmu_poll();
 
 	/* Make sure the decrementer won't interrupt us */
 	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	/* Make sure any pending DEC interrupt occuring while we did
+	 * the above didn't re-enable the DEC */
+	mb();
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
 
-	/* Save the state of PCI config space for some slots */
-	pbook_pci_save();
+	/* Giveup the FPU & vec */
+	enable_kernel_fp();
 
-	feature_prepare_for_sleep();
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	/* We can now disable MSR_EE */
+	cli();
 
 	/* For 750, save backside cache setting and disable it */
 	save_l2cr = _get_L2CR();	/* (returns 0 if not 750) */
 	if (save_l2cr)
-		_set_L2CR(0);
+		_set_L2CR(save_l2cr & 0x7fffffff);
 
-	if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
-		giveup_fpu(current);
+	/* Save the state of PCI config space for some slots */
+	//pbook_pci_save();
 
 	/* Ask the PMU to put us to sleep */
 	pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-	while (!req.complete)
-		mb();
-
-	cli();
-	while (pmu_state != idle)
+	while (!req.complete && pmu_state != idle)
 		pmu_poll();
 
-	/* Call low-level ASM sleep handler */
-	low_sleep_handler();
+	out_8(&via[B], in_8(&via[B]) | TREQ);
+	wait_for_ack();
 
-	/* Make sure the PMU is idle */
-	while (pmu_state != idle)
-		pmu_poll();
+	/* The VIA is supposed not to be restored correctly*/
+	save_via_state();
 
-	sti();
+	/* Shut down various ASICs. There's a chance that we can no longer
+	 * talk to the PMU after this, so I moved it to _after_ sending the
+	 * sleep command to it. Still need to be checked.
+	 */
+	feature_prepare_for_sleep();
 
+	/* Call low-level ASM sleep handler */
+	low_sleep_handler();
+
+	/* Restore Apple core ASICs state */
 	feature_wake_up();
-	pbook_pci_restore();
 
-	set_context(current->mm->context);
+	/* Restore VIA */
+	restore_via_state();
+
+	/* Restore PCI config space. This should be overridable by PCI device
+	 * drivers as some of them may need special restore code. That's yet
+	 * another issue that should be handled by the common code properly,
+	 * maybe one day ?
+	 */
+	/* Don't restore PCI for now, it crashes. Maybe unnecessary on pbook */
+	//pbook_pci_restore();
 
+	pmu_blink(2);
+		
 	/* Restore L2 cache */
 	if (save_l2cr)
- 		_set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */
+ 		_set_L2CR(save_l2cr);
+	
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
 
-	/* reenable interrupts */
-	sleep_restore_intrs();
+	/* Re-enable DEC interrupts and kick DEC */
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	sti();
+	asm volatile("mtdec %0" : : "r" (0x10000000));
 
 	/* Tell PMU we are ready */
 	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
 	while (!req.complete)
 		pmu_poll();
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+	while (!req.complete)
+		pmu_poll();
 		
+	/* ack all pending interrupts */
+	timeout = 100000;
+	interrupt_data[0] = 1;
+	while (interrupt_data[0] || pmu_state != idle) {
+		if (--timeout < 0)
+			break;
+		if (pmu_state == idle)
+			adb_int_pending = 1;
+		via_pmu_interrupt(0, 0, 0);
+		udelay(10);
+	}
+
+	/* reenable interrupt controller */
+	openpic_sleep_restore_intrs();
+
+	/* Leave some time for HW to settle down */
+	mdelay(100);
+
 	/* Notify drivers */
-	mdelay(10);
 	broadcast_wake();
 
 	return 0;
 }
 
-#define PB3400_MEM_CTRL		((unsigned int *)0xf8000070)
+#define PB3400_MEM_CTRL		0xf8000000
+#define PB3400_MEM_CTRL_SLEEP	0x70
 
 int __openfirmware powerbook_sleep_3400(void)
 {
@@ -1590,6 +1740,16 @@
 	unsigned int hid0;
 	unsigned long p, wait;
 	struct adb_request sleep_req;
+	char *mem_ctrl;
+	unsigned int *mem_ctrl_sleep;
+
+	/* first map in the memory controller registers */
+	mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
+	if (mem_ctrl == NULL) {
+		printk("powerbook_sleep_3400: ioremap failed\n");
+		return -ENOMEM;
+	}
+	mem_ctrl_sleep = (unsigned int *) (mem_ctrl + PB3400_MEM_CTRL_SLEEP);
 
 	/* Notify device drivers */
 	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
@@ -1617,11 +1777,20 @@
 	for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
 		mb();
 
+	/* Wait for completion of async backlight requests */
+	while (!bright_req_1.complete || !bright_req_2.complete ||
+		!bright_req_3.complete)
+		pmu_poll();
+
 	/* Disable all interrupts except pmu */
-	sleep_save_intrs(vias->intrs[0].line);
+	pmac_sleep_save_intrs(vias->intrs[0].line);
 
 	/* Make sure the decrementer won't interrupt us */
 	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	/* Make sure any pending DEC interrupt occuring while we did
+	 * the above didn't re-enable the DEC */
+	mb();
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
 
 	/* Save the state of PCI config space for some slots */
 	pbook_pci_save();
@@ -1629,9 +1798,9 @@
 	/* Set the memory controller to keep the memory refreshed
 	   while we're asleep */
 	for (i = 0x403f; i >= 0x4000; --i) {
-		out_be32(PB3400_MEM_CTRL, i);
+		out_be32(mem_ctrl_sleep, i);
 		do {
-			x = (in_be32(PB3400_MEM_CTRL) >> 16) & 0x3ff;
+			x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;
 		} while (x == 0);
 		if (x >= 0x100)
 			break;
@@ -1651,32 +1820,36 @@
 	asm volatile("mfspr %0,1008" : "=r" (hid0) :);
 	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
 	asm volatile("mtspr 1008,%0" : : "r" (hid0));
-	save_flags(msr);
-	msr |= MSR_POW | MSR_EE;
-	restore_flags(msr);
+	_nmask_and_or_msr(0, MSR_POW | MSR_EE);
 	udelay(10);
 
 	/* OK, we're awake again, start restoring things */
-	out_be32(PB3400_MEM_CTRL, 0x3f);
+	out_be32(mem_ctrl_sleep, 0x3f);
 	pbook_pci_restore();
 
 	/* wait for the PMU interrupt sequence to complete */
 	while (asleep)
 		mb();
 
+	/* Re-enable DEC interrupts and kick DEC */
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	sti();
+	asm volatile("mtdec %0" : : "r" (0x10000000));
+
 	/* reenable interrupts */
-	sleep_restore_intrs();
+	pmac_sleep_restore_intrs();
 
 	/* Notify drivers */
 	broadcast_wake();
 
+	iounmap(mem_ctrl);
 	return 0;
 }
 
 /*
  * Support for /dev/pmu device
  */
-#define RB_SIZE		10
+#define RB_SIZE		0x10
 struct pmu_private {
 	struct list_head list;
 	int	rb_get;
@@ -1830,6 +2003,11 @@
 
 	switch (cmd) {
 	case PMU_IOC_SLEEP:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EACCES;
+		if (sleep_in_progress)
+			return -EBUSY;
+		sleep_in_progress = 1;
 		switch (pmu_kind) {
 		case PMU_OHARE_BASED:
 			error = powerbook_sleep_3400();
@@ -1838,20 +2016,24 @@
 		case PMU_PADDINGTON_BASED:
 			error = powerbook_sleep_G3();
 			break;
-#if 0 /* Not ready yet */
 		case PMU_KEYLARGO_BASED:
 			error = powerbook_sleep_Core99();
 			break;
-#endif			
 		default:
 			error = -ENOSYS;
 		}
+		sleep_in_progress = 0;
 		return error;
+	case PMU_IOC_CAN_SLEEP:
+		return put_user(feature_can_sleep(), (__u32 *)arg);
+
 #ifdef CONFIG_PMAC_BACKLIGHT
 	/* Backlight should have its own device or go via
 	 * the fbdev
 	 */
 	case PMU_IOC_GET_BACKLIGHT:
+		if (sleep_in_progress)
+			return -EBUSY;
 		error = get_backlight_level();
 		if (error < 0)
 			return error;
@@ -1859,6 +2041,8 @@
 	case PMU_IOC_SET_BACKLIGHT:
 	{
 		__u32 value;
+		if (sleep_in_progress)
+			return -EBUSY;
 		error = get_user(value, (__u32 *)arg);
 		if (!error)
 			error = set_backlight_level(value);
@@ -1893,7 +2077,7 @@
 }
 #endif /* CONFIG_PMAC_PBOOK */
 
-#if 0
+#ifdef DEBUG_SLEEP
 static inline void polled_handshake(volatile unsigned char *via)
 {
 	via[B] &= ~TREQ; eieio();
@@ -1939,6 +2123,8 @@
 	while (pmu_state != idle)
 		pmu_poll();
 
+	while ((via[B] & TACK) == 0)
+		;
 	polled_send_byte(v, c);
 	if (l < 0) {
 		l = req->nbytes - 1;
@@ -1959,4 +2145,15 @@
 	restore_flags(flags);
 	return 0;
 }
-#endif /* 0 */
+#endif /* DEBUG_SLEEP */
+
+EXPORT_SYMBOL(pmu_request);
+EXPORT_SYMBOL(pmu_poll);
+EXPORT_SYMBOL(pmu_suspend);
+EXPORT_SYMBOL(pmu_resume);
+#ifdef CONFIG_PMAC_PBOOK
+EXPORT_SYMBOL(pmu_register_sleep_notifier);
+EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
+EXPORT_SYMBOL(pmu_enable_irled);
+#endif /* CONFIG_PMAC_PBOOK */
+
diff -urN linux-2.4.10-pre2/drivers/md/md.c linux/drivers/md/md.c
--- linux-2.4.10-pre2/drivers/md/md.c	Sun Aug 12 12:39:02 2001
+++ linux/drivers/md/md.c	Mon Dec  3 23:05:27 2001
@@ -921,17 +921,19 @@
 	dev = rdev->dev;
 	sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1);
 	if (rdev->sb_offset != sb_offset) {
-		printk("%s's sb offset has changed from %ld to %ld, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset);
+		printk("%s's sb offset has changed from %ld to %ld, skipping\n",
+		       partition_name(dev), rdev->sb_offset, sb_offset);
 		goto skip;
 	}
 	/*
 	 * If the disk went offline meanwhile and it's just a spare, then
-	 * it's size has changed to zero silently, and the MD code does
+	 * its size has changed to zero silently, and the MD code does
 	 * not yet know that it's faulty.
 	 */
 	size = calc_dev_size(dev, rdev->mddev, 1);
 	if (size != rdev->size) {
-		printk("%s's size has changed from %ld to %ld since import, skipping\n", partition_name(dev), rdev->size, size);
+		printk("%s's size has changed from %ld to %ld since import, skipping\n",
+		       partition_name(dev), rdev->size, size);
 		goto skip;
 	}
 
@@ -2488,27 +2490,14 @@
 						(long *) arg);
 			goto done;
 
-		case BLKFLSBUF:
-			fsync_dev(dev);
-			invalidate_buffers(dev);
-			goto done;
-
+		case BLKRAGET:
 		case BLKRASET:
-			if (arg > 0xff) {
-				err = -EINVAL;
-				goto abort;
-			}
-			read_ahead[MAJOR(dev)] = arg;
-			goto done;
+		case BLKFLSBUF:
+		case BLKBSZGET:
+		case BLKBSZSET:
+			err = blk_ioctl (dev, cmd, arg);
+			goto abort;
 
-		case BLKRAGET:
-			if (!arg) {
-				err = -EINVAL;
-				goto abort;
-			}
-			err = md_put_user (read_ahead[
-				MAJOR(dev)], (long *) arg);
-			goto done;
 		default:;
 	}
 
diff -urN linux-2.4.10-pre2/drivers/md/raid1.c linux/drivers/md/raid1.c
--- linux-2.4.10-pre2/drivers/md/raid1.c	Sun Aug 12 12:39:02 2001
+++ linux/drivers/md/raid1.c	Mon Dec  3 23:05:27 2001
@@ -162,7 +162,7 @@
 			conf->freer1 = r1_bh->next_r1;
 			conf->freer1_cnt--;
 			r1_bh->next_r1 = NULL;
-			r1_bh->state = 0;
+			r1_bh->state = (1 << R1BH_PreAlloc);
 			r1_bh->bh_req.b_state = 0;
 		}
 		md_spin_unlock_irq(&conf->device_lock);
diff -urN linux-2.4.10-pre2/drivers/net/macsonic.c linux/drivers/net/macsonic.c
--- linux-2.4.10-pre2/drivers/net/macsonic.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/macsonic.c	Mon Dec  3 23:05:27 2001
@@ -135,8 +135,9 @@
 		unsigned long desc_base, desc_top;
 		if ((lp->sonic_desc = 
 		     kmalloc(SIZEOF_SONIC_DESC
-			     * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_DMA)) == NULL) {
+			     * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_KERNEL | GFP_DMA)) == NULL) {
 			printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
+			return -ENOMEM;
 		}
 		desc_base = (unsigned long) lp->sonic_desc;
 		desc_top = desc_base + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode);
@@ -165,7 +166,7 @@
 
 	/* FIXME, maybe we should use skbs */
 	if ((lp->rba = (char *)
-	     kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_DMA)) == NULL) {
+	     kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
 		printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
 		return -ENOMEM;
 	}
diff -urN linux-2.4.10-pre2/drivers/net/wan/dscc4.c linux/drivers/net/wan/dscc4.c
--- linux-2.4.10-pre2/drivers/net/wan/dscc4.c	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/wan/dscc4.c	Mon Dec  3 23:05:27 2001
@@ -348,7 +348,7 @@
 {
 	struct sk_buff *skb;
 
-	skb = dev_alloc_skb(RX_MAX(dev->mtu+2));
+	skb = dev_alloc_skb(RX_MAX(HDLC_MAX_MRU+2));
 	priv->rx_skbuff[cur] = skb;
 	if (!skb) {
 		priv->rx_fd[cur--].data = (u32) NULL;
@@ -428,9 +428,9 @@
 	int pkt_len;
 
 	skb = dpriv->rx_skbuff[cur];
-	pkt_len = TO_SIZE(rx_fd->state2);
-	pci_dma_sync_single(pdev, rx_fd->data, pkt_len, PCI_DMA_FROMDEVICE);
-	if((skb->data[pkt_len - 1] & FrameOk) == FrameOk) {
+	pkt_len = TO_SIZE(rx_fd->state2) - 1;
+	pci_dma_sync_single(pdev, rx_fd->data, pkt_len + 1, PCI_DMA_FROMDEVICE);
+	if((skb->data[pkt_len] & FrameOk) == FrameOk) {
 		pci_unmap_single(pdev, rx_fd->data, skb->len, PCI_DMA_FROMDEVICE);
 		dpriv->stats.rx_packets++;
 		dpriv->stats.rx_bytes += pkt_len;
@@ -442,11 +442,11 @@
 			netif_rx(skb);
 		try_get_rx_skb(dpriv, cur, dev);
 	} else {
-		if(skb->data[pkt_len - 1] & FrameRdo)
+		if(skb->data[pkt_len] & FrameRdo)
 			dpriv->stats.rx_fifo_errors++;
-		else if(!(skb->data[pkt_len - 1] | ~FrameCrc))
+		else if(!(skb->data[pkt_len] | ~FrameCrc))
 			dpriv->stats.rx_crc_errors++;
-		else if(!(skb->data[pkt_len - 1] | ~FrameVfr))
+		else if(!(skb->data[pkt_len] | ~FrameVfr))
 			dpriv->stats.rx_length_errors++;
 		else
 			dpriv->stats.rx_errors++;
@@ -760,7 +760,7 @@
 	/* FIXME: VIS */
 	writel(readl(ioaddr + CCR0) | 0x80001000, ioaddr + CCR0);
 
-	writel(LengthCheck | (dev->mtu >> 5), ioaddr + RLCR);
+	writel(LengthCheck | (HDLC_MAX_MRU >> 5), ioaddr + RLCR);
 
 	/* no address recognition/crc-CCITT/cts enabled */
 	writel(readl(ioaddr + CCR1) | 0x021c8000, ioaddr + CCR1);
@@ -1224,7 +1224,7 @@
 		       dev->name, SOURCE_ID(state), state );
 		return;
 	}
-	if (state & 0x0df80c01) {
+	if (state & 0x0df80c00) {
 		printk(KERN_DEBUG "%s (Tx): state=%08x (UFO alert)\n",
 		       dev->name, state);
 		return;
@@ -1377,7 +1377,7 @@
 		       dev->name, SOURCE_ID(state), state);
 		goto try;
 	}
-	if (state & 0x0df80c01) {
+	if (state & 0x0df80c00) {
 		printk(KERN_DEBUG "%s (Rx): state=%08x (UFO alert)\n",
 		       dev->name, state);
 		goto try;
@@ -1609,7 +1609,7 @@
 	        rx_fd->state1 = HiDesc; /* Hi, no Hold */
 	        rx_fd->state2 = 0x00000000;
 	        rx_fd->end = 0xbabeface;
-	        rx_fd->state1 |= ((u32)(dev->mtu & RxSizeMax)) << 16;
+	        rx_fd->state1 |= ((u32)(HDLC_MAX_MRU & RxSizeMax)) << 16;
 		try_get_rx_skb(dpriv, i, dev);
 		i++;
 		rx_fd->next = (u32)(dpriv->rx_fd_dma + i*sizeof(struct RxFD));
@@ -1720,7 +1720,7 @@
 	hdlc = &dpriv->hdlc;
 	/* XXX: Don't look at the next line */
 	hdlc->netdev.base_addr = (unsigned long)dev;
-	// FIXME: set hdlc->set_mode ?
+	hdlc->set_mode = NULL;
 	hdlc->open = dscc4_hdlc_open;
 	hdlc->close = dscc4_hdlc_close;
 	hdlc->ioctl = dscc4_hdlc_ioctl;
diff -urN linux-2.4.10-pre2/drivers/pci/pci.c linux/drivers/pci/pci.c
--- linux-2.4.10-pre2/drivers/pci/pci.c	Mon Aug 13 14:49:21 2001
+++ linux/drivers/pci/pci.c	Mon Dec  3 23:05:27 2001
@@ -307,8 +307,8 @@
 
 /**
  * pci_save_state - save the PCI configuration space of a device before suspending
- * @dev - PCI device that we're dealing with
- * @buffer - buffer to hold config space context
+ * @dev: - PCI device that we're dealing with
+ * @buffer: - buffer to hold config space context
  *
  * @buffer must be large enough to hold the entire PCI 2.2 config space 
  * (>= 64 bytes).
@@ -327,8 +327,8 @@
 
 /** 
  * pci_restore_state - Restore the saved state of a PCI device
- * @dev - PCI device that we're dealing with
- * @buffer - saved PCI config space
+ * @dev: - PCI device that we're dealing with
+ * @buffer: - saved PCI config space
  *
  */
 int 
@@ -489,6 +489,7 @@
 /**
  *	pci_request_regions - Reserved PCI I/O and memory resources
  *	@pdev: PCI device whose resources are to be reserved
+ *	@res_name: Name to be associated with resource.
  *
  *	Mark all PCI regions associated with PCI device @pdev as
  *	being reserved by owner @res_name.  Do not access any
diff -urN linux-2.4.10-pre2/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- linux-2.4.10-pre2/drivers/pcmcia/yenta.c	Mon Dec  3 23:05:12 2001
+++ linux/drivers/pcmcia/yenta.c	Mon Dec  3 23:05:27 2001
@@ -702,6 +702,12 @@
 	u32 start, end;
 	u32 align, size, min, max;
 	unsigned offset;
+	unsigned mask;
+
+	/* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
+	mask = ~0xfff;
+	if (type & IORESOURCE_IO)
+		mask = ~3;
 
 	offset = 0x1c + 8*nr;
 	bus = socket->dev->subordinate;
@@ -715,8 +721,8 @@
 	if (!root)
 		return;
 
-	start = config_readl(socket, offset);
-	end = config_readl(socket, offset+4) | 0xfff;
+	start = config_readl(socket, offset) & mask;
+	end = config_readl(socket, offset+4) | ~mask;
 	if (start && end > start) {
 		res->start = start;
 		res->end = end;
diff -urN linux-2.4.10-pre2/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- linux-2.4.10-pre2/drivers/scsi/sd.c	Sun Aug  5 13:12:41 2001
+++ linux/drivers/scsi/sd.c	Mon Dec  3 23:05:27 2001
@@ -238,8 +238,10 @@
 		case BLKFLSBUF:
 		case BLKSSZGET:
 		case BLKPG:
-                case BLKELVGET:
-                case BLKELVSET:
+		case BLKELVGET:
+		case BLKELVSET:
+		case BLKBSZGET:
+		case BLKBSZSET:
 			return blk_ioctl(inode->i_rdev, cmd, arg);
 
 		case BLKRRPART: /* Re-read partition tables */
diff -urN linux-2.4.10-pre2/drivers/usb/Config.in linux/drivers/usb/Config.in
--- linux-2.4.10-pre2/drivers/usb/Config.in	Mon Dec  3 23:05:12 2001
+++ linux/drivers/usb/Config.in	Mon Dec  3 23:05:27 2001
@@ -64,7 +64,6 @@
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
 
    comment 'USB Network adaptors'
-   dep_tristate '  PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
    dep_tristate '  USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
    dep_tristate '  USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
    dep_tristate '  USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.10-pre2/drivers/usb/Makefile linux/drivers/usb/Makefile
--- linux-2.4.10-pre2/drivers/usb/Makefile	Mon Dec  3 23:05:12 2001
+++ linux/drivers/usb/Makefile	Mon Dec  3 23:05:27 2001
@@ -60,7 +60,6 @@
 obj-$(CONFIG_USB_MDC800)	+= mdc800.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
 obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
-obj-$(CONFIG_USB_PLUSB)		+= plusb.o
 obj-$(CONFIG_USB_OV511)		+= ov511.o
 obj-$(CONFIG_USB_SE401)		+= se401.o
 obj-$(CONFIG_USB_PEGASUS)	+= pegasus.o
diff -urN linux-2.4.10-pre2/drivers/usb/plusb.c linux/drivers/usb/plusb.c
--- linux-2.4.10-pre2/drivers/usb/plusb.c	Tue Jun 12 15:53:37 2001
+++ linux/drivers/usb/plusb.c	Wed Dec 31 16:00:00 1969
@@ -1,1060 +0,0 @@
-/*****************************************************************************/
-
-/*
- *      plusb.c  --  prolific pl-2301/pl-2302 driver.
- *
- *      Copyright (C) 2000  Deti Fliegl (deti@fliegl.de)
- *      Copyright (C) 2000  Pavel Machek (pavel@suse.cz)
- *      Copyright (C) 2000  Eric Z. Ayers (eric@compgen.com)
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *  This driver creates a network interface (plusb0, plusb1, ...) that will
- *  send messages over a USB host-host cable based on the Prolific ASIC.
- *  It works a lot like plip or PP over an RS-232C null modem cable.
- *
- *  Expect speeds of around 330Kbytes/second over a UHCI host controller.
- *  OHCI should be faster.  Increase the MTU for faster transfers of large
- *  files (up-to 800Kbytes/second).  (16384 is a good size)
- *
- *  $Id: plusb.c,v 1.18 2000/02/14 10:38:58 fliegl Exp $
- *
- *  Changelog:
- *
- *    v0.1                deti
- *        Original Version of driver.
- *    v0.2     15 Sep 2000  pavel
- *        Patches to decrease latency by rescheduling the bottom half of
- *          interrupt code.
- *    v0.3     10 Oct 2000  eric
- *        Patches to work in v2.2 backport (v2.4 changes the way net_dev.name
- *          is allocated)
- *    v0.4     19 Oct 2000  eric
- *        Some more performance fixes.  Lock re-submitting urbs.
- *          Lower the number of sk_buff's to queue.
- *    v0.5     25 Oct 2000 eric
- *        Removed use of usb_bulk_msg() all together.  This caused
- *          the driver to block in an interrupt context.
- *        Consolidate read urb submission into read_urb_submit().
- *        Performance is the same as v0.4.
- *    v0.5.1   27 Oct 2000 eric
- *        Extra debugging messages to help diagnose problem with uchi.o stack.
- *    v0.5.2   27 Oct 2000 eric
- *        Set the 'start' flag for the network device in plusb_net_start()
- *         and plusb_net_stop() (doesn't help)
- *    v0.5.3   27 Oct 2000 pavel
- *        Commented out handlers when -EPIPE is received,
- *         (remove calls to usb_clear_halt()) Since the callback is in
- *         an interrupt context, it doesn't help, it just panics
- *         the kernel. (what do we do?)
- *        Under high load, dev_alloc_skb() fails, the read URB must
- *         be re-submitted.
- *        Added plusb_change_mtu() and increased the size of _BULK_DATA_LEN
- *    v0.5.4   31 Oct 2000 eric
- *        Fix race between plusb_net_xmit() and plusb_bulk_write_complete()
- *    v0.5.5    1 Nov 2000 eric
- *        Remove dev->start field, otherwise, it won't compile in 2.4
- *        Use dev_kfree_skb_any(). (important in 2.4 kernel)
- *    v0.5.6   2 Nov 2000 pavel,eric
- *        Add calls to netif_stop_queue() and netif_start_queue()
- *        Drop packets that come in while the free list is empty.
- *        (This version is being submitted after the release of 2.4-test10)
- *    v0.5.7   6 Nov 2000
- *        Fix to not re-submit the urb on error to help when cables
- *          are yanked (not tested)
- *
- *
- * KNOWN PROBLEMS: (Any suggestions greatfully accepted!)
- *
- *     2 Nov 2000
- *      - The shutdown for this may not be entirely clean.  Sometimes, the
- *         kernel will Oops when the cable is unplugged, or
- *         if the plusb module is removed.
- *      - If you ifdown a device and then ifup it again, the link will not
- *         always work.  You have to 'rmmod plusb ; modprobe plusb' on
- *         both machines to get it to work again.  Something must be wrong with
- *         plusb_net_open() and plusb_net_start() ?  Maybe
- *         the 'suspend' and 'resume' entry points need to be
- *         implemented?
- *      - Needs to handle -EPIPE correctly in bulk complete handlers.
- *         (replace usb_clear_halt() function with async urbs?)
- *      - I think this code relies too much on one spinlock and does
- *         too much in the interrupt handler.  The net1080 code is
- *         much more elegant, and should work for this chip.  Its
- *         only drawback is that it is going to be tough to backport
- *         it to v2.2.
- *      - Occasionally the device will hang under the 'uhci.o'
- *         driver.   The workaround is to ifdown the device and
- *         remove the modules, then re-insert them.  You may have
- *         better luck with the 'usb-uhci.o' driver.
- *      - After using ifconfig down ; ifconfig up, sometimes packets
- *         continue to be received, but there is a framing problem.
- *
- * FUTURE DIRECTIONS:
- *
- *     - Fix the known problems.
- *     - There isn't much functional difference between the net1080
- *        driver and this one.  It would be neat if the same driver
- *        could handle both types of chips.  Or if both drivers
- *        could handle both types of chips - this one is easier to
- *        backport to the 2.2 kernel.
- *     - Get rid of plusb_add_buf_tail and the single spinlock.
- *        Use a separate spinlock for the 2 lists, and use atomic
- *        operators for writeurb_submitted and readurb_submitted members.
- *
- *
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/miscdevice.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-//#define DEBUG 1
-#include <linux/usb.h>
-
-#if (LINUX_VERSION_CODE < 0x020300)
-#define dev_kfree_skb_any dev_kfree_skb
-#endif
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.5.7"
-#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
-#define DRIVER_DESC "PL-2302 USB Interface Driver for Linux (c)2000"
-
-/* Definitions formerly in plusb.h relocated. No need to export them -EZA */
-
-#define _PLUSB_INTPIPE		0x1
-#define _PLUSB_BULKOUTPIPE	0x2
-#define _PLUSB_BULKINPIPE	0x3
-
-#define _SKB_NUM		32
-
-/* increase size of BULK_DATA_LEN so we can use bigger MTU's*/
-#define _BULK_DATA_LEN		32768
-
-
-typedef struct
-{
-	int connected;   /* indicates if this structure is active */
-	struct usb_device *usbdev;
-					 /* keep track of USB structure */
-	int status;      /* Prolific status byte returned from interrupt */
-	int in_bh;       /* flag to indicate that we are in the bulk handler */
-	int opened;      /* flag to indicate that network dev is open    */
-
-	spinlock_t lock; /* Lock for the buffer list. re-used for
-						locking around submitting the readurb member.
-					 */
-	urb_t *inturb;   /* Read buffer for the interrupt callback */
-	unsigned char *		interrupt_in_buffer;
-			 /* holds data for the inturb*/
-	urb_t *readurb;  /* Read buffer for the bulk data callback */
-	unsigned char *		bulk_in_buffer;
-					 /* kmalloc'ed data for the readurb */
-	int readurb_submitted;
-					 /* Flag to indicate that readurb already sent */
-	urb_t *writeurb; /* Write buffer for the bulk data callback */
-	int writeurb_submitted;
-					 /* Flag to indicate that writeurb already sent */
-	
-	struct list_head tx_skb_list;
-		 			 /* sk_buff's read from net device */
-	struct list_head free_skb_list;
-					/* free sk_buff list */
-	struct net_device net_dev;
-					/* handle to linux network device */
-	struct net_device_stats net_stats;
-					/* stats to return for ifconfig output */
-} plusb_t,*pplusb_t;
-
-/*
- * skb_list - queue of packets from the network driver to be delivered to USB
- */
-typedef struct
-{
-	struct list_head skb_list;
-	struct sk_buff *skb;
-	int state;
-	plusb_t *s;
-} skb_list_t,*pskb_list_t;
-
-
-/* --------------------------------------------------------------------- */
-
-#define NRPLUSB 4
-
-/*
- * Interrupt endpoint status byte, from Prolific PL-2301 docs
- * Check the 'download' link at www.prolifictech.com
- */
-#define _PL_INT_RES1    0x80 /* reserved              */
-#define _PL_INT_RES2    0x40 /* reserved              */
-#define _PL_INT_RXD	_PL_INT_RES2  /* Read data ready - Not documented by Prolific, but seems to work! */
-#define _PL_INT_TX_RDY	0x20 /* OK to transmit data   */
-#define _PL_INT_RESET_O	0x10 /* reset output pipe     */
-#define _PL_INT_RESET_I 0x08 /* reset input pipe      */
-#define _PL_INT_TX_C    0x04 /* transmission complete */
-#define _PL_INT_TX_REQ  0x02 /* transmission received */
-#define _PL_INT_PEER_E  0x01 /* peer exists           */
-
-/*-------------------------------------------------------------------*/
-
-static plusb_t plusb[NRPLUSB];
-
-static void plusb_write_bulk_complete(urb_t *purb);
-static void plusb_read_bulk_complete(urb_t *purb);
-static void plusb_int_complete(urb_t *purb);
-
-/* --------------------------------------------------------------------- */
-
-/*
- * plusb_add_buf_tail - Take the head of the src list and append it to
- *                      the tail of the dest list
- */
-static int plusb_add_buf_tail (plusb_t *s, struct list_head *dst, struct list_head *src)
-{
-	unsigned long flags = 0;
-	struct list_head *tmp;
-	int ret = 0;
-
-	spin_lock_irqsave (&s->lock, flags);
-
-	if (list_empty (src)) {
-		// no elements in source buffer
-		ret = -1;
-		goto err;
-	}
-	tmp = src->next;
-	list_del (tmp);
-	list_add_tail (tmp, dst);
-
-  err:	spin_unlock_irqrestore (&s->lock, flags);
-	return ret;
-}
-/*-------------------------------------------------------------------*/
-
-/*
- * dequeue_next_skb - submit the first thing on the tx_skb_list to the
- * USB stack.  This function should be called each time we get a new
- * message to send to the other host, or each time a message is successfully
- * sent.
- */
-static void dequeue_next_skb(char * func, plusb_t * s)
-{
-	skb_list_t * skb_list;
-	unsigned long flags = 0;
-
-	if (!s->connected)
-		return;
-	
-	spin_lock_irqsave (&s->lock, flags);
-	
-	if (!list_empty (&s->tx_skb_list) && !s->writeurb_submitted) {
-		int submit_ret;
-		skb_list = list_entry (s->tx_skb_list.next, skb_list_t, skb_list);
-
-		if (skb_list->skb) {
-			s->writeurb_submitted = 1;
-		
-			/* Use the buffer inside the sk_buff directly. why copy? */
-			FILL_BULK_URB_TO(s->writeurb, s->usbdev,
-							 usb_sndbulkpipe(s->usbdev, _PLUSB_BULKOUTPIPE),
-							 skb_list->skb->data, skb_list->skb->len,
-							 plusb_write_bulk_complete, skb_list, 500);
-			
-			dbg ("%s: %s: submitting urb. skb_list %p", s->net_dev.name, func, skb_list);
-		
-			submit_ret = usb_submit_urb(s->writeurb);
-			if (submit_ret) {
-				s->writeurb_submitted = 0;
-				printk (KERN_CRIT "%s: %s: can't submit writeurb: %d\n",
-						s->net_dev.name, func, submit_ret);
-			}
-		} /* end if the skb value has been filled in */
-	}
-	
-	spin_unlock_irqrestore (&s->lock, flags);	
-}
-
-/*
- * submit_read_urb - re-submit the read URB to the stack
- */
-void submit_read_urb(char * func, plusb_t * s)
-{
-	unsigned long flags=0;
-
-	if (!s->connected)
-		return;
-	
-	spin_lock_irqsave (&s->lock, flags);
-	
-	if (!s->readurb_submitted) {
-		int ret;
-		s->readurb_submitted=1;
-		s->readurb->dev=s->usbdev;
-		ret = usb_submit_urb(s->readurb);
-		if (ret) {
-			printk (KERN_CRIT "%s: %s: error %d submitting read URB\n",
-				   s->net_dev.name, func, ret);
-			s->readurb_submitted=0;
-		}
-	}
-
-	spin_unlock_irqrestore (&s->lock, flags);
-	
-}
-/* --------------------------------------------------------------------- */
-
-/*
- * plusb_net_xmit - callback from the network device driver for outgoing data
- *
- * Data has arrived to the network device from the local machine and needs
- * to be sent over the USB cable.  This is in an interrupt, so we don't
- * want to spend too much time in this function.
- *
- */
-static int plusb_net_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	plusb_t *s=dev->priv;
-	skb_list_t *skb_list;
-	unsigned int flags;
-
-	dbg("plusb_net_xmit: len:%d i:%d",skb->len,in_interrupt());
-
-	if(!s->connected || !s->opened) {
-		/*
-		  NOTE: If we get to this point, you'll return the error
-		  kernel: virtual device plusb0 asks to queue packet
-
-		  Other things we could do:
-		  1) just drop this packet
-		  2) drop other packets in the queue
-		*/
-		return 1;
-	}
-
-	spin_lock_irqsave (&s->lock, flags);
-
-	if  (list_empty(&s->free_skb_list)
-	|| plusb_add_buf_tail (s, &s->tx_skb_list, &s->free_skb_list)) {
-		/* The buffers on this side are full. DROP the packet
-		   I think that this shouldn't happen with the correct
-		   use of the netif_XXX functions -EZA
-		 */
-		dbg ("plusb: Free list is empty.");
-		kfree_skb(skb);
-		s->net_stats.tx_dropped++;
-		spin_unlock_irqrestore (&s->lock, flags);
-		return 0;
-	}
-	
-	skb_list = list_entry (s->tx_skb_list.prev, skb_list_t, skb_list);
-	skb_list->skb=skb;
-	skb_list->state=1;
-	skb_list->s=s;
-
-	if (list_empty(&s->free_skb_list)) {
-		/* apply "backpressure". Tell the net layer to stop sending
-		   the driver packets.
-		*/
-		netif_stop_queue(dev);
-	}
-	
-	spin_unlock_irqrestore (&s->lock, flags);
-	
-	/* If there is no write urb outstanding, pull the first thing
-	   off of the list and submit it to the USB stack
-	*/
-	dequeue_next_skb("plusb_net_xmit", s);
-	
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * plusb_write_bulk_complete () - callback after the data has been
- *   sent to the USB device, or a timeout occurred.
- */
-static void plusb_write_bulk_complete(urb_t *purb)
-{
-	skb_list_t * skb_list=purb->context;
-	plusb_t *s=skb_list->s;
-
-	dbg ("%s: plusb_write_bulk_complete: status:%d skb_list:%p\n",
-		 s->net_dev.name, purb->status, skb_list);
-
-	skb_list->state=0;
-
-	if( purb->status == -EPIPE )
-		printk(KERN_CRIT "%s: plusb_write_bulk_complete: got -EPIPE and don't know what to do!\n",
-		     s->net_dev.name);
-		
-	if(!purb->status) {
-		s->net_stats.tx_packets++;
-		s->net_stats.tx_bytes+=skb_list->skb->len;
-	}
-	else {
-		err ("%s: plusb_write_bulk_complete: returned ERROR status:%d\n",
-			 s->net_dev.name, purb->status);
-
-		s->net_stats.tx_errors++;
-		s->net_stats.tx_aborted_errors++;
-	}
-	
-	dbg("plusb_bh: dev_kfree_skb");
-
-	/* NOTE: In 2.4 it's a problem to call dev_kfree_skb() in a hard IRQ:
-	   Oct 28 23:42:14 bug kernel: Warning: kfree_skb on hard IRQ c023329a
-	*/
-	dev_kfree_skb_any(skb_list->skb);
-	
-	skb_list->skb = NULL;
-	if (plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list)) {
-		err ("plusb: tx list empty. This shouldn't happen.");
-	}
-
-	purb->status = 0;
-	s->writeurb_submitted = 0;
-	
-    netif_wake_queue((&s->net_dev));
-	
-	dequeue_next_skb("plusb_write_bulk_complete", s);
-
-	
-}
-
-/*
- * plusb_read_bulk_complete - Callback for data arriving from the USB device
- *
- * This gets called back when a full 'urb' is received from the remote system.
- * This urb was allocated by this driver and is kept in the member: s->readurb
- *
- */
-static void plusb_read_bulk_complete(urb_t *purb)
-{
-	
-	plusb_t *s=purb->context;
-
-	dbg("plusb_read_bulk_complete: status:%d length:%d", purb->status,purb->actual_length);
-	
-	if(!s->connected)
-		return;
-
-	if( purb->status == -EPIPE )
-		printk(KERN_CRIT "%s: plusb_read_bulk_complete: got -EPIPE and I don't know what to do!\n",
-		     s->net_dev.name);
-	else if (!purb->status) {
-		struct sk_buff *skb;
-		unsigned char *dst;
-		int len=purb->transfer_buffer_length;
-		struct net_device_stats *stats=&s->net_stats;
-
-		skb=dev_alloc_skb(len);
-
-		if(!skb) {
-			printk (KERN_CRIT "%s: plusb_read_bulk_complete: dev_alloc_skb(%d)=NULL, dropping frame\n", s->net_dev.name, len);
-			stats->rx_dropped++;
-		} else {
-			dst=(char *)skb_put(skb, len);
-			memcpy( dst, purb->transfer_buffer, len);
-			
-			skb->dev=&s->net_dev;
-			skb->protocol=eth_type_trans(skb, skb->dev);
-			stats->rx_packets++;
-			stats->rx_bytes+=len;
-			netif_rx(skb);
-		}
-		
-	}
-	
-	s->readurb_submitted = 0;
-	
-	if (purb->status) {
-		/* Give the system a chance to "catch its breath". Shortcut
-		   re-submitting the read URB>  It will be re-submitted if
-		   another interrupt comes back.  The problem scenario is that
-		   the plub is pulled and the read returns an error.
-		   You don't want to resumbit in this case.
-		*/
-		err ("%s: plusb_read_bulk_complete: returned status %d\n",
-			 s->net_dev.name, purb->status);
-		return;
-	}
-
-
-	purb->status=0;
-
-	/* Keep it coming! resubmit the URB for reading.. Make sure
-	   we aren't in contention with the interrupt callback.
-	*/
-	submit_read_urb("plusb_read_bulk_complete", s);
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * plusb_int_complete - USB driver callback for interrupt msg from the device
- *
- * Interrupts are scheduled to go off on a periodic basis (see FILL_INT_URB)
- * For the prolific device, this is basically just returning a register
- * filled with bits.  See the macro definitions for _PL_INT_XXX above.
- * Most of these bits are for implementing a machine-machine protocol
- * and can be set with a special message (described as the "Quicklink"
- * feature in the prolific documentation.)
- *
- * I don't think we need any of that to work as a network device. If a
- * message is lost, big deal - that's what UNIX networking expects from
- * the physical layer.
- *
- */
-static void plusb_int_complete(urb_t *purb)
-{
-	plusb_t *s=purb->context;
-	s->status=((unsigned char*)purb->transfer_buffer)[0]&255;
-	
-#if 0
-	/* This isn't right because 0x20 is TX_RDY and
-	   sometimes will not be set
-	*/
-	if((s->status&0x3f)!=0x20) {
-		warn("invalid device status %02X", s->status);
-		return;
-	}
-#endif	
-	if(!s->connected)
-		return;
-
-	/* Don't turn this on unless you want to see the log flooded. */
-#if 0
-	printk("plusb_int_complete: PEER_E:%d TX_REQ:%d TX_C:%d RESET_IN:%d RESET_O: %d TX_RDY:%d RES1:%d RES2:%d\n",
-	    s->status & _PL_INT_PEER_E  ? 1 : 0,
-	    s->status & _PL_INT_TX_REQ  ? 1 : 0,
-	    s->status & _PL_INT_TX_C    ? 1 : 0,
-	    s->status & _PL_INT_RESET_I ? 1 : 0,
-	    s->status & _PL_INT_RESET_O ? 1 : 0,
-	    s->status & _PL_INT_TX_RDY  ? 1 : 0,
-	    s->status & _PL_INT_RES1    ? 1 : 0,
-	    s->status & _PL_INT_RES2    ? 1 : 0);
-#endif
-
-#if 1
-	/* At first glance, this logic appears to not really be needed, but
-	   it can help recover from intermittent problems where the
-	   usb_submit_urb() fails in the read callback. -EZA
-	*/
-	
-	/* Try to submit the read URB again. Make sure
-	   we aren't in contention with the bulk read callback
-	*/
-	submit_read_urb ("plusb_int_complete", s);
-	
-	/* While we are at it, why not check to see if the
-	   write urb should be re-submitted?
-	*/
-	dequeue_next_skb("plusb_int_complete", s);	
-	
-#endif
-
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * plusb_free_all - deallocate all memory kept for an instance of the device.
- */
-static void plusb_free_all(plusb_t *s)
-{
-	struct list_head *skb;
-	skb_list_t *skb_list;
-	
-	dbg("plusb_free_all");
-	
-	/* set a flag to tell all callbacks to cease and desist */
-	s->connected = 0;
-
-	/* If the interrupt handler is about to fire, let it finish up */
-	run_task_queue(&tq_immediate);	
-
-	if(s->inturb) {
-		dbg("unlink inturb");
-		usb_unlink_urb(s->inturb);
-		dbg("free_urb inturb");
-		usb_free_urb(s->inturb);
-		s->inturb=NULL;
-	}
-	
-	if(s->interrupt_in_buffer) {
-		dbg("kfree s->interrupt_in_buffer");
-		kfree(s->interrupt_in_buffer);
-		s->interrupt_in_buffer=NULL;
-	}
-
-	if(s->readurb) {
-		dbg("unlink readurb");
-		usb_unlink_urb(s->readurb);
-		dbg("free_urb readurb:");
-		usb_free_urb(s->readurb);
-		s->readurb=NULL;
-	}
-
-	if(s->bulk_in_buffer) {
-		dbg("kfree s->bulk_in_buffer");
-		kfree(s->bulk_in_buffer);
-		s->bulk_in_buffer=NULL;
-	}
-	
-	s->readurb_submitted = 0;
-	
-	if(s->writeurb) {
-		dbg("unlink writeurb");
-		usb_unlink_urb(s->writeurb);
-		dbg("free_urb writeurb:");
-		usb_free_urb(s->writeurb);
-		s->writeurb=NULL;
-	}
-
-	s->writeurb_submitted = 0;
-	
-	while(!list_empty(&s->free_skb_list)) {
-		skb=s->free_skb_list.next;
-		list_del(skb);
-		skb_list = list_entry (skb, skb_list_t, skb_list);
-		kfree(skb_list);
-	}
-
-	while(!list_empty(&s->tx_skb_list)) {
-		skb=s->tx_skb_list.next;
-		list_del(skb);
-		skb_list = list_entry (skb, skb_list_t, skb_list);
-		if (skb_list->skb) {
-			dbg ("Freeing SKB in queue");
-			dev_kfree_skb_any(skb_list->skb);
-			skb_list->skb = NULL;
-		}
-		kfree(skb_list);
-	}
-	
-	s->in_bh=0;
-	
-	dbg("plusb_free_all: finished");	
-}
-
-/*-------------------------------------------------------------------*/
-/*
- * plusb_alloc - allocate memory associated with one instance of the device
- */
-static int plusb_alloc(plusb_t *s)
-{
-	int i;
-	skb_list_t *skb;
-
-	dbg("plusb_alloc");
-
-	for(i=0 ; i < _SKB_NUM ; i++) {
-		skb=kmalloc(sizeof(skb_list_t), GFP_KERNEL);
-		if(!skb) {
-			err("kmalloc for skb_list failed");
-			goto reject;
-		}
-		memset(skb, 0, sizeof(skb_list_t));
-		list_add(&skb->skb_list, &s->free_skb_list);
-	}
-
-	dbg("inturb allocation:");
-	s->inturb=usb_alloc_urb(0);
-	if(!s->inturb) {
-		err("alloc_urb failed");
-		goto reject;
-	}
-
-	dbg("bulk read urb allocation:");
-	s->readurb=usb_alloc_urb(0);
-	if(!s->readurb) {
-		err("alloc_urb failed");
-		goto reject;
-	}
-	
-	dbg("bulk write urb allocation:");
-	s->writeurb=usb_alloc_urb(0);
-	if(!s->writeurb) {
-		err("alloc_urb for writeurb failed");
-		goto reject;
-	}
-	
-	dbg("readurb/inturb init:");
-	s->interrupt_in_buffer=kmalloc(64, GFP_KERNEL);
-	if(!s->interrupt_in_buffer) {
-		err("kmalloc failed");
-		goto reject;
-	}
-
-	/* The original value of '10' makes this interrupt fire off a LOT.
-	   It was set so low because the callback determined when to
-	   sumbit the buld read URB. I've lowered it to 100 - the driver
-	   doesn't depend on that logic anymore. -EZA
-	*/
-	FILL_INT_URB(s->inturb, s->usbdev,
-		     usb_rcvintpipe (s->usbdev, _PLUSB_INTPIPE),
-		     s->interrupt_in_buffer, 1,
-		     plusb_int_complete, s, HZ);
-
-	dbg("inturb submission:");
-	if(usb_submit_urb(s->inturb)<0) {
-		err("usb_submit_urb failed");
-		goto reject;
-	}
-	
-	dbg("readurb init:");
-	s->bulk_in_buffer = kmalloc(_BULK_DATA_LEN, GFP_KERNEL);
-	if (!s->bulk_in_buffer) {
-		err("kmalloc %d bytes for bulk in buffer failed", _BULK_DATA_LEN);
-	}
-
-	FILL_BULK_URB(s->readurb, s->usbdev,
-		      usb_rcvbulkpipe(s->usbdev, _PLUSB_BULKINPIPE),
-		      s->bulk_in_buffer, _BULK_DATA_LEN,
-		      plusb_read_bulk_complete, s);
-
-	/* The write urb will be initialized inside the network
-	   interrupt.
-	*/
-
-	/* get the bulk read going */
-	submit_read_urb("plusb_alloc", s);
-
-	dbg ("plusb_alloc: finished. readurb=%p writeurb=%p inturb=%p",
-		s->readurb, s->writeurb, s->inturb);
-	
-	return 0;
-
-  reject:
-  	dbg("plusb_alloc: failed");
-	
-	plusb_free_all(s);
-	return -ENOMEM;
-}
-
-/*-------------------------------------------------------------------*/
-
-static int plusb_net_open(struct net_device *dev)
-{
-	plusb_t *s=dev->priv;
-	
-	dbg("plusb_net_open");
-	
-	if(plusb_alloc(s))
-		return -ENOMEM;
-
-	s->opened=1;
-	
-	MOD_INC_USE_COUNT;
-
-	netif_start_queue(dev);
-
-	dbg("plusb_net_open: success");
-	
-	return 0;
-	
-}
-
-/* --------------------------------------------------------------------- */
-
-static int plusb_net_stop(struct net_device *dev)
-{
-	plusb_t *s=dev->priv;
-
-	netif_stop_queue(dev);
-	
-	dbg("plusb_net_stop");	
-	
-	s->opened=0;
-	plusb_free_all(s);
-
-	MOD_DEC_USE_COUNT;
-	dbg("plusb_net_stop:finished");
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static struct net_device_stats *plusb_net_get_stats(struct net_device *dev)
-{
-	plusb_t *s=dev->priv;
-	
-	dbg("net_device_stats");
-	
-	return &s->net_stats;
-}
-
-/* --------------------------------------------------------------------- */
-
-static plusb_t *plusb_find_struct (void)
-{
-	int u;
-
-	for (u = 0; u < NRPLUSB; u++) {
-		plusb_t *s = &plusb[u];
-		if (!s->connected)
-			return s;
-	}
-	return NULL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void plusb_disconnect (struct usb_device *usbdev, void *ptr)
-{
-	plusb_t *s = ptr;
-
-	dbg("plusb_disconnect");
-	
-	plusb_free_all(s);
-
-	if(!s->opened && s->net_dev.name) {
-		dbg("unregistering netdev: %s",s->net_dev.name);
-		unregister_netdev(&s->net_dev);
-		s->net_dev.name[0] = '\0';
-#if (LINUX_VERSION_CODE < 0x020300)
-		dbg("plusb_disconnect: About to free name");
- 		kfree (s->net_dev.name);
- 		s->net_dev.name = NULL;
-#endif	
-	}
-	
-	dbg("plusb_disconnect: finished");
-	MOD_DEC_USE_COUNT;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int plusb_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if ((new_mtu < 68) || (new_mtu > _BULK_DATA_LEN))
-		return -EINVAL;
-
-	printk("plusb: changing mtu to %d\n", new_mtu);
-	dev->mtu = new_mtu;
-	
-	/* NOTE: Could we change the size of the READ URB here dynamically
-	   to save kernel memory?
-	*/
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-int plusb_net_init(struct net_device *dev)
-{
-	dbg("plusb_net_init");
-	
-	dev->open=plusb_net_open;
-	dev->stop=plusb_net_stop;
-	dev->hard_start_xmit=plusb_net_xmit;
-	dev->get_stats	= plusb_net_get_stats;
-	ether_setup(dev);
-	dev->change_mtu = plusb_change_mtu;
-	/* Setting the default MTU to 16K gives good performance for
-	   me, and keeps the ping latency low too.  Setting it up
-	   to 32K made performance go down. -EZA
-	   Pavel says it would be best not to do this...
-	*/
-	/*dev->mtu=16384; */
-	dev->tx_queue_len = 0;	
-	dev->flags = IFF_POINTOPOINT|IFF_NOARP;
-
-	
-	dbg("plusb_net_init: finished");
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void *plusb_probe (struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id)
-{
-	plusb_t *s;
-
-	dbg("plusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
-	  usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
-
-	if (usbdev->descriptor.idVendor != 0x067b || usbdev->descriptor.idProduct > 0x1)
-		return NULL;
-
-	/* We don't handle multiple configurations */
-	if (usbdev->descriptor.bNumConfigurations != 1)
-		return NULL;
-
-	s = plusb_find_struct ();
-	if (!s)
-		return NULL;
-
-	s->usbdev = usbdev;
-
-	if (usb_set_configuration (s->usbdev, usbdev->config[0].bConfigurationValue) < 0) {
-		err("set_configuration failed");
-		return NULL;
-	}
-
-	if (usb_set_interface (s->usbdev, 0, 0) < 0) {
-		err("set_interface failed");
-		return NULL;
-	}
-
-#if (LINUX_VERSION_CODE < 0x020300)
- 	{
- 		int i;
-		
- 		/* For Kernel version 2.2, the driver is responsible for
- 		   allocating this memory. For version 2.4, the rules
- 		   have apparently changed, but there is a nifty function
- 		   'init_netdev' that might make this easier...  It's in 
- 		   ../net/net_init.c - but can we get there from here?  (no)
-		   -EZA
- 		*/
- 		
- 		/* Find the device number... we seem to have lost it... -EZA */
- 		for (i=0; i<NRPLUSB; i++) {
- 			if (&plusb[i] == s)
- 				break;
- 		}
- 	
- 		if(!s->net_dev.name) {
- 			s->net_dev.name = kmalloc(strlen("plusbXXXX"), GFP_KERNEL);
- 			sprintf (s->net_dev.name, "plusb%d", i);
- 			s->net_dev.init=plusb_net_init;
- 			s->net_dev.priv=s;
- 			
- 			printk ("plusb_probe: Registering Device\n");	
- 			if(!register_netdev(&s->net_dev))
- 				info("registered: %s", s->net_dev.name);
- 			else {
- 				err("register_netdev failed");
- 				s->net_dev.name[0] = '\0';
- 			}
- 			dbg ("plusb_probe: Connected!");
- 		}
- 	}
-#else
- 	/* Kernel version 2.3+ works a little bit differently than 2.2 */
-	if(!s->net_dev.name[0]) {
-		strcpy(s->net_dev.name, "plusb%d");
-		s->net_dev.init=plusb_net_init;
-		s->net_dev.priv=s;
-		if(!register_netdev(&s->net_dev))
-			info("registered: %s", s->net_dev.name);
-		else {
-			err("register_netdev failed");
-			s->net_dev.name[0] = '\0';
-		}
-	}
-#endif
-	
-	s->connected = 1;
-
-	if(s->opened) {
-		dbg("net device already allocated, restarting USB transfers");
-		plusb_alloc(s);
-	}
-
-	info("bound to interface: %d dev: %p", ifnum, usbdev);
-	MOD_INC_USE_COUNT;
-	return s;
-}
-/* --------------------------------------------------------------------- */
-
-static struct usb_driver plusb_driver =
-{
-	name: "plusb",
-	probe: plusb_probe,
-	disconnect: plusb_disconnect,
-};
-
-/* --------------------------------------------------------------------- */
-
-static int __init plusb_init (void)
-{
-	unsigned u;
-	dbg("plusb_init");
-	
-	/* initialize struct */
-	for (u = 0; u < NRPLUSB; u++) {
-		plusb_t *s = &plusb[u];
-		memset (s, 0, sizeof (plusb_t));
-		INIT_LIST_HEAD (&s->tx_skb_list);
-		INIT_LIST_HEAD (&s->free_skb_list);
-		spin_lock_init (&s->lock);
-	}
-
-	/* register misc device */
-	usb_register (&plusb_driver);
-
-	dbg("plusb_init: driver registered");
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void __exit plusb_cleanup (void)
-{
-	unsigned u;
-
-	dbg("plusb_cleanup");
-	for (u = 0; u < NRPLUSB; u++) {
-		plusb_t *s = &plusb[u];
-#if (LINUX_VERSION_CODE < 0x020300)
-		if(s->net_dev.name) {
-			dbg("unregistering netdev: %s",s->net_dev.name);
-			unregister_netdev(&s->net_dev);
-			s->net_dev.name[0] = '\0';
-			kfree (s->net_dev.name);
-			s->net_dev.name = NULL;		
-		}		
-#else
-		if(s->net_dev.name[0]) {
-			dbg("unregistering netdev: %s",s->net_dev.name);
-			unregister_netdev(&s->net_dev);
-			s->net_dev.name[0] = '\0';
-		}
-#endif
-	}
-	usb_deregister (&plusb_driver);
-	dbg("plusb_cleanup: finished");
-}
-
-/* --------------------------------------------------------------------- */
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-
-
-module_init (plusb_init);
-module_exit (plusb_cleanup);
-
-/* --------------------------------------------------------------------- */
diff -urN linux-2.4.10-pre2/drivers/usb/printer.c linux/drivers/usb/printer.c
--- linux-2.4.10-pre2/drivers/usb/printer.c	Mon Dec  3 23:05:12 2001
+++ linux/drivers/usb/printer.c	Mon Dec  3 23:05:27 2001
@@ -269,6 +269,7 @@
 	struct usblp *usblp = file->private_data;
 
 	down (&usblp->sem);
+	lock_kernel();
 	usblp->used = 0;
 	if (usblp->dev) {
 		if (usblp->bidir)
@@ -277,6 +278,7 @@
 		up(&usblp->sem);
 	} else 		/* finish cleanup from disconnect */
 		usblp_cleanup (usblp);
+	unlock_kernel();
 	return 0;
 }
 
@@ -685,11 +687,9 @@
 		BUG ();
 	}
 
-
 	down (&usblp->sem);
 	lock_kernel();
 	usblp->dev = NULL;
-	unlock_kernel();
 
 	usb_unlink_urb(&usblp->writeurb);
 	if (usblp->bidir)
@@ -699,6 +699,7 @@
 		usblp_cleanup (usblp);
 	else 	/* cleanup later, on close */
 		up (&usblp->sem);
+	unlock_kernel();
 }
 
 static struct usb_device_id usblp_ids [] = {
diff -urN linux-2.4.10-pre2/drivers/usb/storage/unusual_devs.h linux/drivers/usb/storage/unusual_devs.h
--- linux-2.4.10-pre2/drivers/usb/storage/unusual_devs.h	Wed Aug 15 14:23:40 2001
+++ linux/drivers/usb/storage/unusual_devs.h	Mon Dec  3 23:05:27 2001
@@ -96,7 +96,7 @@
 #endif
 
 /* This entry is from Andries.Brouwer@cwi.nl */
-UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0205, 
+UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB SmartMedia / CompactFlash Adapter",
 		US_SC_SCSI, US_PR_DPCM_USB, NULL, 
diff -urN linux-2.4.10-pre2/drivers/video/vga16fb.c linux/drivers/video/vga16fb.c
--- linux-2.4.10-pre2/drivers/video/vga16fb.c	Wed Apr 18 11:49:12 2001
+++ linux/drivers/video/vga16fb.c	Mon Dec  3 23:05:27 2001
@@ -33,7 +33,7 @@
 #define dac_val	(0x3c9)
 
 #define VGA_FB_PHYS 0xA0000
-#define VGA_FB_PHYS_LEN 65535
+#define VGA_FB_PHYS_LEN 65536
 
 /* --------------------------------------------------------------------- */
 
diff -urN linux-2.4.10-pre2/fs/Makefile linux/fs/Makefile
--- linux-2.4.10-pre2/fs/Makefile	Mon Aug 13 12:02:01 2001
+++ linux/fs/Makefile	Mon Dec  3 23:05:27 2001
@@ -32,6 +32,7 @@
 subdir-$(CONFIG_CODA_FS)	+= coda
 subdir-$(CONFIG_MINIX_FS)	+= minix
 subdir-$(CONFIG_FAT_FS)		+= fat
+subdir-$(CONFIG_UMSDOS_FS)	+= umsdos
 subdir-$(CONFIG_MSDOS_FS)	+= msdos
 subdir-$(CONFIG_VFAT_FS)	+= vfat
 subdir-$(CONFIG_BFS_FS)		+= bfs
@@ -43,7 +44,6 @@
 subdir-$(CONFIG_NFSD)		+= nfsd
 subdir-$(CONFIG_LOCKD)		+= lockd
 subdir-$(CONFIG_NLS)		+= nls
-subdir-$(CONFIG_UMSDOS_FS)	+= umsdos
 subdir-$(CONFIG_SYSV_FS)	+= sysv
 subdir-$(CONFIG_SMB_FS)		+= smbfs
 subdir-$(CONFIG_NCP_FS)		+= ncpfs
diff -urN linux-2.4.10-pre2/fs/umsdos/README-WIP.txt linux/fs/umsdos/README-WIP.txt
--- linux-2.4.10-pre2/fs/umsdos/README-WIP.txt	Thu Dec  9 13:22:21 1999
+++ linux/fs/umsdos/README-WIP.txt	Mon Dec  3 23:05:27 2001
@@ -5,18 +5,11 @@
 There is no warning any more.
 Both read-only and read-write stuff is fixed, both in
 msdos-compatibile mode, and in umsdos EMD mode, and it seems stable.
-There are still few hardlink nuisances, but those are not fatal.
-
-I'd call it pre-release, and ask for as many people as possible to
-come and test it! See notes below for some more information, or if
-you are trying to use UMSDOS as root partition.
 
 Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that
-will compile and work on 2.2.x kernels and glibc based systems may be found
-at http://cvs.linux.hr/
-
-Also look at the quick-hack "homepage" for umsdos filesystem at 
-http://www.voyager.hr/~mnalis/umsdos
+will compile and work on 2.2.x+ kernels and glibc based systems, as well as
+kernel patches and other umsdos related information may be found at
+http://linux.voyager.hr/umsdos/
 
 Information below is getting outdated slowly -- I'll fix it one day when I
 get enough time - there are more important things to fix right now.
@@ -24,7 +17,7 @@
 Legend: those lines marked with '+' on the beggining of line indicates it
 passed all of my tests, and performed perfect in all of them.
 
-Current status (990202) - UMSDOS 0.85:
+Current status (010125) - UMSDOS 0.86j:
 
 (1) pure MSDOS (no --linux-.--- EMD file):
 
@@ -35,7 +28,7 @@
 
 WRITE:
 + creat file			- works
-+ delete file			- works
++ unlink file			- works
 + write file			- works
 + rename file (same dir)	- works
 + rename file (dif. dir)	- works
@@ -66,21 +59,22 @@
 
 WRITE:
 + create symlink		- works
-- create hardlink		- works
++ create hardlink		- works
 + create file			- works
 + create special file		- works
 + write to file			- works
 + rename file (same dir)	- works
 + rename file (dif. dir)	- works
-- rename hardlink (same dir)	-
-- rename hardlink (dif. dir)	-
++ rename hardlink (same dir)	- works
+- rename hardlink (dif. dir)	- works, but see notes below.
 + rename symlink (same dir)	- works
 + rename symlink (dif. dir)	- works
 + rename dir (same dir)		- works
 + rename dir (dif. dir)		- works
-+ delete file			- works
++ unlink file			- works
 + notify_change (chown,perms)	- works
-+ delete hardlink		- works
++ notify_change for hardlinks	- works
++ unlink hardlink		- works
 + mkdir				- works
 + rmdir 			- works
 + umssyncing (many ioctls)	- works
@@ -99,24 +93,11 @@
 example is specs file about it. Specifically, moving directory which
 contains hardlinks will break them.
 
-Note: (about pseudoroot) If you are currently trying to use UMSDOS as root
-partition (with linux installed in c:\linux) it will boot, but there may be
-some problems. Volunteers ready to test pseudoroot are needed (preferably
-ones with working backups or unimportant data).  For example, '/DOS' pseudo
-directory is only partially re-implemented and buggy. It works most of the
-time, though. Update: should work ok in 0.84, although it still does not
-work correctly in combination with initrd featere. Working on this!
-
 Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in
 pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice
 versa. Thanks to Sorin Iordachescu <sorin@rodae.ro> for providing fix.
-
-Warning: (about hardlinks) - modifying hardlinks (esp. if they are in
-different directories) are currently somewhat broken, I'm working on it.
-Problem seems to be that code uses and updates EMD of directory where 'real
-hardlink' is stored, not EMD of directory where our pseudo-hardlink is
-located! I'm looking for ideas how to work around this in clean way, since
-without it modifying hardlinks in any but most simple ways is broken!
+See http://linux.voyager.hr/umsdos/hlbug.html for more info and upgrade
+procedure if you used broken versions...
 
 ------------------------------------------------------------------------------
 
@@ -130,6 +111,4 @@
 I'm unfortunately somewhat out of time to read linux-kernel@vger, but I do
 check for messages having "UMSDOS" in the subject, and read them.  I might
 miss some in all that volume, though.  I should reply to any direct e-mail
-in few days.  If I don't, probably I never got your message.  You can try
-mnalis-umsdos@voyager.hr; however mnalis@jagor.srce.hr is preferable.
-
+in few days.  If I don't, probably I never got your message.
diff -urN linux-2.4.10-pre2/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- linux-2.4.10-pre2/fs/umsdos/dir.c	Mon Dec  3 23:05:12 2001
+++ linux/fs/umsdos/dir.c	Mon Dec  3 23:05:27 2001
@@ -651,13 +651,13 @@
 	old_root = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
 	spin_lock(&dcache_lock);
-	path = __d_path(dentry, NULL, dentry->d_sb->s_root, NULL, buffer, len);
+	path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */
 	spin_unlock(&dcache_lock);
 
 	if (*path == '/')
 		path++; /* skip leading '/' */
 
-	if (old_root->d_inode == pseudo_root)
+	if (current->fs->root->d_inode == pseudo_root)
 	{
 		*(path-1) = '/';
 		path -= (UMSDOS_PSDROOT_LEN+1);
diff -urN linux-2.4.10-pre2/fs/umsdos/emd.c linux/fs/umsdos/emd.c
--- linux-2.4.10-pre2/fs/umsdos/emd.c	Mon Dec  3 23:05:12 2001
+++ linux/fs/umsdos/emd.c	Mon Dec  3 23:05:27 2001
@@ -18,7 +18,21 @@
 #include <linux/pagemap.h>
 #include <linux/delay.h>
 
-static void copy_entry(struct umsdos_dirent *p, struct umsdos_dirent *q)
+void put_entry (struct umsdos_dirent *p, struct umsdos_dirent *q)
+{
+	p->name_len = q->name_len;
+	p->flags = q->flags;
+	p->nlink = cpu_to_le16(q->nlink);
+	p->uid = cpu_to_le16(q->uid);
+	p->gid = cpu_to_le16(q->gid);
+	p->atime = cpu_to_le32(q->atime);
+	p->mtime = cpu_to_le32(q->mtime);
+	p->ctime = cpu_to_le32(q->ctime);
+	p->rdev = cpu_to_le16(q->rdev);
+	p->mode = cpu_to_le16(q->mode);
+}
+
+static void get_entry(struct umsdos_dirent *p, struct umsdos_dirent *q)
 {
 	p->name_len = q->name_len;
 	p->name[p->name_len]='\0';
@@ -136,6 +150,7 @@
 		printk (KERN_WARNING "Ignoring invalid EMD entry with size %d\n", entry->name_len);
 		p->name_len = 0; 
 		ret = -ENAMETOOLONG; /* notify umssync(8) code that something is wrong */
+		/* FIXME: does not work if we did 'ls -l' before 'udosctl uls' ?! */
 	}
 
 	recsize = umsdos_evalrecsize(p->name_len);
@@ -163,7 +178,7 @@
 		page_cache_release(page2);
 	} else
 		memcpy(entry->spare,p->spare,((char*)p+recsize)-p->spare);
-	copy_entry(entry, p);
+	get_entry(entry, p);
 	kunmap(page);
 	page_cache_release(page);
 	*pos += recsize;
@@ -249,16 +264,7 @@
 					offs+info->recsize-PAGE_CACHE_SIZE);
 		if (ret)
 			goto out_unlock3;
-		p->name_len = entry->name_len;
-		p->flags = entry->flags;
-		p->nlink = cpu_to_le16(entry->nlink);
-		p->uid = cpu_to_le16(entry->uid);
-		p->gid = cpu_to_le16(entry->gid);
-		p->atime = cpu_to_le32(entry->atime);
-		p->mtime = cpu_to_le32(entry->mtime);
-		p->ctime = cpu_to_le32(entry->ctime);
-		p->rdev = cpu_to_le16(entry->rdev);
-		p->mode = cpu_to_le16(entry->mode);
+		put_entry (p, entry);
 		memcpy(p->spare,entry->spare,
 			(char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare);
 		memcpy(page_address(page2),
@@ -279,16 +285,7 @@
 					offs + info->recsize);
 		if (ret)
 			goto out_unlock;
-		p->name_len = entry->name_len;
-		p->flags = entry->flags;
-		p->nlink = cpu_to_le16(entry->nlink);
-		p->uid = cpu_to_le16(entry->uid);
-		p->gid = cpu_to_le16(entry->gid);
-		p->atime = cpu_to_le32(entry->atime);
-		p->mtime = cpu_to_le32(entry->mtime);
-		p->ctime = cpu_to_le32(entry->ctime);
-		p->rdev = cpu_to_le16(entry->rdev);
-		p->mode = cpu_to_le16(entry->mode);
+		put_entry (p, entry);
 		memcpy(p->spare,entry->spare,((char*)p+info->recsize)-p->spare);
 		ret = mapping->a_ops->commit_write(NULL,page,offs,
 					offs + info->recsize);
@@ -463,7 +460,7 @@
 			goto skip_it;
 
 		info->f_pos = pos;
-		copy_entry(entry, rentry);
+		get_entry(entry, rentry);
 		ret = 0;
 		break;
 skip_it:
diff -urN linux-2.4.10-pre2/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- linux-2.4.10-pre2/fs/umsdos/inode.c	Sat May 19 18:02:45 2001
+++ linux/fs/umsdos/inode.c	Mon Dec  3 23:05:27 2001
@@ -38,7 +38,7 @@
 		 ,atomic_read(&inode->i_count)));
 
 	if (inode == pseudo_root) {
-		printk (KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count));
+		Printk ((KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count)));
 	}
 
 	if (atomic_read(&inode->i_count) == 1)
@@ -49,7 +49,7 @@
 void UMSDOS_put_super (struct super_block *sb)
 {
 	Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
-	if (saved_root) {
+	if (saved_root && pseudo_root && sb->s_dev == ROOT_DEV) {
 		shrink_dcache_parent(saved_root);
 		dput(saved_root);
 		saved_root = NULL;
@@ -153,16 +153,56 @@
 }
 
 
-int umsdos_notify_change_locked(struct dentry *, struct iattr *);
 /*
  * lock the parent dir before starting ...
+ * also handles hardlink converting
  */
 int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
 {
-	struct inode *dir = dentry->d_parent->d_inode;
-	struct inode *inode = dentry->d_inode;
+	struct inode *dir, *inode;
+	struct umsdos_info info;
+	struct dentry *temp, *old_dentry = NULL;
 	int ret;
 
+	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len,
+				&info);
+	if (ret)
+		goto out;
+	ret = umsdos_findentry (dentry->d_parent, &info, 0);
+	if (ret) {
+printk("UMSDOS_notify_change: %s/%s not in EMD, ret=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, ret);
+		goto out;
+	}
+
+	if (info.entry.flags & UMSDOS_HLINK) {
+		/*
+		 * In order to get the correct (real) inode, we just drop
+		 * the original dentry.
+		 */ 
+		d_drop(dentry);
+Printk(("UMSDOS_notify_change: hard link %s/%s, fake=%s\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname));
+	
+		/* Do a real lookup to get the short name dentry */
+		temp = umsdos_covered(dentry->d_parent, info.fake.fname,
+						info.fake.len);
+		ret = PTR_ERR(temp);
+		if (IS_ERR(temp))
+			goto out;
+	
+		/* now resolve the link ... */
+		temp = umsdos_solve_hlink(temp);
+		ret = PTR_ERR(temp);
+		if (IS_ERR(temp))
+			goto out;
+		old_dentry = dentry;
+		dentry = temp;	/* so umsdos_notify_change_locked will operate on that */
+	}
+
+	dir = dentry->d_parent->d_inode;
+	inode = dentry->d_inode;
+
 	ret = inode_change_ok (inode, attr);
 	if (ret)
 		goto out;
@@ -173,9 +213,12 @@
 	if (ret == 0)
 		inode_setattr (inode, attr);
 out:
+	if (old_dentry)
+		dput (dentry);	/* if we had to use fake dentry for hardlinks, dput() it now */
 	return ret;
 }
 
+
 /*
  * Must be called with the parent lock held.
  */
@@ -316,16 +359,16 @@
 	struct super_block *res;
 	struct dentry *new_root;
 
-	MSDOS_SB(sb)->options.isvfat = 0;
 	/*
 	 * Call msdos-fs to mount the disk.
 	 * Note: this returns res == sb or NULL
 	 */
 	res = msdos_read_super (sb, data, silent);
+
 	if (!res)
 		goto out_fail;
 
-	printk (KERN_INFO "UMSDOS 0.86i "
+	printk (KERN_INFO "UMSDOS 0.86k "
 		"(compatibility level %d.%d, fast msdos)\n", 
 		UMSDOS_VERSION, UMSDOS_RELEASE);
 
@@ -334,6 +377,7 @@
 
 	/* install our dentry operations ... */
 	sb->s_root->d_op = &umsdos_dentry_operations;
+
 	umsdos_patch_dentry_inode(sb->s_root, 0);
 
 	/* Check whether to change to the /linux root */
@@ -345,10 +389,9 @@
 			printk("umsdos_read_super: pseudo-root wrong ops!\n");
 
 		pseudo_root = new_root->d_inode;
-
 		saved_root = sb->s_root;
-		sb->s_root = new_root;
 		printk(KERN_INFO "UMSDOS: changed to alternate root\n");
+		dget (sb->s_root); sb->s_root = dget(new_root);
 	}
 	return sb;
 
@@ -381,10 +424,12 @@
 	root = lookup_one_len(UMSDOS_PSDROOT_NAME, sb->s_root,UMSDOS_PSDROOT_LEN); 
 	if (IS_ERR(root))
 		goto out_noroot;
+		
 	if (!root->d_inode || !S_ISDIR(root->d_inode->i_mode))
 		goto out_dput;
 
-	printk(KERN_INFO "check_pseudo_root: found %s/%s\n", root->d_parent->d_name.name, root->d_name.name);
+printk(KERN_INFO "check_pseudo_root: found %s/%s\n",
+root->d_parent->d_name.name, root->d_name.name);
 
 	/* look for /sbin/init */
 	sbin = lookup_one_len("sbin", root, 4);
diff -urN linux-2.4.10-pre2/fs/umsdos/namei.c linux/fs/umsdos/namei.c
--- linux-2.4.10-pre2/fs/umsdos/namei.c	Sun Aug 12 11:13:59 2001
+++ linux/fs/umsdos/namei.c	Mon Dec  3 23:05:27 2001
@@ -405,8 +405,15 @@
 		goto out_unlock;
 	/* make sure it's the same inode! */
 	ret = -ENOENT;
-	if (old->d_inode != old_inode)
-		goto out_dput;
+	/*
+	 * note: for hardlinks they will be different!
+	 *  old_inode will contain inode of .LINKxxx file containing data, and
+	 *  old->d_inode will contain inode of file containing path to .LINKxxx file
+	 */
+	if (!(old_info.entry.flags & UMSDOS_HLINK)) {
+	 	if (old->d_inode != old_inode)
+ 			goto out_dput;
+	}
 
 	new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname, 
 					new_info.fake.len);
@@ -531,7 +538,7 @@
 	struct umsdos_info hid_info;
 
 #ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_link: new %s%s -> %s/%s\n",
+printk("umsdos_link: new %s/%s -> %s/%s\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, 
 olddentry->d_parent->d_name.name, olddentry->d_name.name);
 #endif
@@ -698,17 +705,36 @@
 	if (ret == 0) {
 		struct iattr newattrs;
 
+		/* Do a real lookup to get the short name dentry */
+		temp = umsdos_covered(olddentry->d_parent,
+					old_info.fake.fname,
+					old_info.fake.len);
+		ret = PTR_ERR(temp);
+		if (IS_ERR(temp))
+			goto out_unlock2;
+
+		/* now resolve the link ... */
+		temp = umsdos_solve_hlink(temp);
+		ret = PTR_ERR(temp);
+		if (IS_ERR(temp))
+			goto out_unlock2;
+
+
 #ifdef UMSDOS_PARANOIA
 if (!oldinode->u.umsdos_i.i_is_hlink)
 printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n",
 olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino);
 #endif
-		oldinode->i_nlink++;
+		temp->d_inode->i_nlink++;
 Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n",
 olddentry->d_parent->d_name.name, olddentry->d_name.name,
 oldinode->i_ino, oldinode->i_nlink));
 		newattrs.ia_valid = 0;
-		ret = umsdos_notify_change_locked(olddentry, &newattrs);
+		ret = umsdos_notify_change_locked(temp, &newattrs);
+ 		if (ret == 0)
+			mark_inode_dirty(temp->d_inode);
+		dput(temp);
+out_unlock2:	
 		if (ret == 0)
 			mark_inode_dirty(olddentry->d_inode);
 	}
diff -urN linux-2.4.10-pre2/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- linux-2.4.10-pre2/fs/umsdos/rdir.c	Mon Dec  3 23:05:12 2001
+++ linux/fs/umsdos/rdir.c	Mon Dec  3 23:05:27 2001
@@ -111,6 +111,9 @@
 		 */
 Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n",
 dentry->d_parent->d_name.name, dentry->d_name.name));
+/* only patch if needed (because we get called even for lookup
+   (not only rlookup) stuff sometimes, like in umsdos_covered() */
+		if (dentry->d_inode->u.umsdos_i.i_patched == 0)	
 		umsdos_patch_dentry_inode(dentry, 0);
 
 	}
diff -urN linux-2.4.10-pre2/include/asm-i386/hw_irq.h linux/include/asm-i386/hw_irq.h
--- linux-2.4.10-pre2/include/asm-i386/hw_irq.h	Wed Aug 15 14:21:11 2001
+++ linux/include/asm-i386/hw_irq.h	Mon Dec  3 23:05:27 2001
@@ -130,7 +130,7 @@
 __asm__( \
 "\n"__ALIGN_STR"\n" \
 SYMBOL_NAME_STR(x) ":\n\t" \
-	"pushl $"#v"\n\t" \
+	"pushl $"#v"-256\n\t" \
 	SAVE_ALL \
 	SYMBOL_NAME_STR(call_##x)":\n\t" \
 	"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
@@ -143,7 +143,7 @@
 __asm__( \
 "\n"__ALIGN_STR"\n" \
 SYMBOL_NAME_STR(x) ":\n\t" \
-	"pushl $"#v"\n\t" \
+	"pushl $"#v"-256\n\t" \
 	SAVE_ALL \
 	"movl %esp,%eax\n\t" \
 	"pushl %eax\n\t" \
diff -urN linux-2.4.10-pre2/include/asm-i386/msr.h linux/include/asm-i386/msr.h
--- linux-2.4.10-pre2/include/asm-i386/msr.h	Mon Dec 11 13:42:08 2000
+++ linux/include/asm-i386/msr.h	Mon Dec  3 23:05:27 2001
@@ -1,3 +1,6 @@
+#ifndef __ASM_MSR_H
+#define __ASM_MSR_H
+
 /*
  * Access to machine-specific registers (available on 586 and better only)
  * Note: the rd* operations modify the parameters directly (without using
@@ -5,9 +8,9 @@
  */
 
 #define rdmsr(msr,val1,val2) \
-       __asm__ __volatile__("rdmsr" \
-			    : "=a" (val1), "=d" (val2) \
-			    : "c" (msr))
+     __asm__ __volatile__("rdmsr" \
+			  : "=a" (val1), "=d" (val2) \
+			  : "c" (msr))
 
 #define wrmsr(msr,val1,val2) \
      __asm__ __volatile__("wrmsr" \
@@ -18,10 +21,10 @@
      __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
 
 #define rdtscl(low) \
-     __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
+     __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
 
 #define rdtscll(val) \
-     __asm__ __volatile__ ("rdtsc" : "=A" (val))
+     __asm__ __volatile__("rdtsc" : "=A" (val))
 
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
@@ -31,6 +34,71 @@
 			  : "c" (counter))
 
 /* symbolic names for some interesting MSRs */
-#define MSR_IA32_PLATFORM_ID	0x17
-#define MSR_IA32_UCODE_WRITE	0x79
-#define MSR_IA32_UCODE_REV	0x8B
+/* Intel defined MSRs. */
+#define MSR_IA32_P5_MC_ADDR		0
+#define MSR_IA32_P5_MC_TYPE		1
+#define MSR_IA32_PLATFORM_ID		0x17
+#define MSR_IA32_EBL_CR_POWERON		0x2a
+
+#define MSR_IA32_APICBASE		0x1b
+#define MSR_IA32_APICBASE_BSP		(1<<8)
+#define MSR_IA32_APICBASE_ENABLE	(1<<11)
+#define MSR_IA32_APICBASE_BASE		(0xfffff<<12)
+
+#define MSR_IA32_UCODE_WRITE		0x79
+#define MSR_IA32_UCODE_REV		0x8b
+
+#define MSR_IA32_PERFCTR0		0xc1
+#define MSR_IA32_PERFCTR1		0xc2
+
+#define MSR_IA32_BBL_CR_CTL		0x119
+
+#define MSR_IA32_MCG_CAP		0x179
+#define MSR_IA32_MCG_STATUS		0x17a
+#define MSR_IA32_MCG_CTL		0x17b
+
+#define MSR_IA32_EVNTSEL0		0x186
+#define MSR_IA32_EVNTSEL1		0x187
+
+#define MSR_IA32_DEBUGCTLMSR		0x1d9
+#define MSR_IA32_LASTBRANCHFROMIP	0x1db
+#define MSR_IA32_LASTBRANCHTOIP		0x1dc
+#define MSR_IA32_LASTINTFROMIP		0x1dd
+#define MSR_IA32_LASTINTTOIP		0x1de
+
+#define MSR_IA32_MC0_CTL		0x400
+#define MSR_IA32_MC0_STATUS		0x401
+#define MSR_IA32_MC0_ADDR		0x402
+#define MSR_IA32_MC0_MISC		0x403
+
+/* AMD Defined MSRs */
+#define MSR_K6_EFER			0xC0000080
+#define MSR_K6_STAR			0xC0000081
+#define MSR_K6_WHCR			0xC0000082
+#define MSR_K6_UWCCR			0xC0000085
+#define MSR_K6_PSOR			0xC0000087
+#define MSR_K6_PFIR			0xC0000088
+
+#define MSR_K7_EVNTSEL0			0xC0010000
+#define MSR_K7_PERFCTR0			0xC0010004
+
+/* Centaur-Hauls/IDT defined MSRs. */
+#define MSR_IDT_FCR1			0x107
+#define MSR_IDT_FCR2			0x108
+#define MSR_IDT_FCR3			0x109
+#define MSR_IDT_FCR4			0x10a
+
+#define MSR_IDT_MCR0			0x110
+#define MSR_IDT_MCR1			0x111
+#define MSR_IDT_MCR2			0x112
+#define MSR_IDT_MCR3			0x113
+#define MSR_IDT_MCR4			0x114
+#define MSR_IDT_MCR5			0x115
+#define MSR_IDT_MCR6			0x116
+#define MSR_IDT_MCR7			0x117
+#define MSR_IDT_MCR_CTRL		0x120
+
+/* VIA Cyrix defined MSRs*/
+#define MSR_VIA_FCR			0x1107
+
+#endif /* __ASM_MSR_H */
diff -urN linux-2.4.10-pre2/include/asm-i386/system.h linux/include/asm-i386/system.h
--- linux-2.4.10-pre2/include/asm-i386/system.h	Wed Aug 15 14:21:11 2001
+++ linux/include/asm-i386/system.h	Mon Dec  3 23:05:27 2001
@@ -110,9 +110,22 @@
 })
 #define write_cr0(x) \
 	__asm__("movl %0,%%cr0": :"r" (x));
+
+#define read_cr4() ({ \
+	unsigned int __dummy; \
+	__asm__( \
+		"movl %%cr4,%0\n\t" \
+		:"=r" (__dummy)); \
+	__dummy; \
+})
+#define write_cr4(x) \
+	__asm__("movl %0,%%cr4": :"r" (x));
 #define stts() write_cr0(8 | read_cr0())
 
 #endif	/* __KERNEL__ */
+
+#define wbinvd() \
+	__asm__ __volatile__ ("wbinvd": : :"memory");
 
 static inline unsigned long get_limit(unsigned long segment)
 {
diff -urN linux-2.4.10-pre2/include/asm-i386/timex.h linux/include/asm-i386/timex.h
--- linux-2.4.10-pre2/include/asm-i386/timex.h	Wed Aug 15 14:21:11 2001
+++ linux/include/asm-i386/timex.h	Mon Dec  3 23:05:27 2001
@@ -45,4 +45,6 @@
 #endif
 }
 
+extern unsigned long cpu_khz;
+
 #endif
diff -urN linux-2.4.10-pre2/include/asm-ppc/keyboard.h linux/include/asm-ppc/keyboard.h
--- linux-2.4.10-pre2/include/asm-ppc/keyboard.h	Mon Dec  3 23:05:12 2001
+++ linux/include/asm-ppc/keyboard.h	Mon Dec  3 23:05:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: %F% %I% %G% %U% %#%
+ * BK Id: SCCS/s.keyboard.h 1.11 08/29/01 10:07:29 paulus
  */
 /*
  *  linux/include/asm-ppc/keyboard.h
@@ -75,7 +75,6 @@
 		ppc_md.kbd_init_hw();
 }
 
-#define kbd_rate	(ppc_md.kbd_rate_fn)
 #define kbd_sysrq_xlate	(ppc_md.ppc_kbd_sysrq_xlate)
 
 extern unsigned long SYSRQ_KEY;
diff -urN linux-2.4.10-pre2/include/asm-ppc/kmap_types.h linux/include/asm-ppc/kmap_types.h
--- linux-2.4.10-pre2/include/asm-ppc/kmap_types.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/kmap_types.h	Mon Dec  3 23:05:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.kmap_types.h 1.6 05/17/01 18:14:24 cort
+ * BK Id: SCCS/s.kmap_types.h 1.9 08/29/01 14:03:05 paulus
  */
 #ifdef __KERNEL__
 #ifndef _ASM_KMAP_TYPES_H
@@ -10,6 +10,8 @@
 	KM_BOUNCE_WRITE,
 	KM_SKB_DATA,
 	KM_SKB_DATA_SOFTIRQ,
+	KM_USER0,
+	KM_USER1,
 	KM_TYPE_NR
 };
 
diff -urN linux-2.4.10-pre2/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h
--- linux-2.4.10-pre2/include/asm-ppc/machdep.h	Mon Dec  3 23:05:12 2001
+++ linux/include/asm-ppc/machdep.h	Mon Dec  3 23:05:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.machdep.h 1.19 08/18/01 18:16:33 paulus
+ * BK Id: SCCS/s.machdep.h 1.21 08/29/01 10:07:29 paulus
  */
 #ifdef __KERNEL__
 #ifndef _PPC_MACHDEP_H
@@ -14,7 +14,6 @@
 struct pt_regs;
 struct pci_bus;	
 struct pci_dev;
-struct kbd_repeat;
 
 struct machdep_calls {
 	void		(*setup_arch)(void);
@@ -61,7 +60,6 @@
 				char raw_mode);
 	char		(*kbd_unexpected_up)(unsigned char keycode);
 	void		(*kbd_leds)(unsigned char leds);
-	int		(*kbd_rate_fn)(struct kbd_repeat *rep);
 	void		(*kbd_init_hw)(void);
 #ifdef CONFIG_MAGIC_SYSRQ
 	unsigned char 	*ppc_kbd_sysrq_xlate;
@@ -74,6 +72,10 @@
 	/* Called after scanning the bus, before allocating resources */
 	void (*pcibios_fixup)(void);
 
+	/* Called after PPC generic resource fixup to perform
+	   machine specific fixups */
+	void (*pcibios_fixup_resources)(struct pci_dev *);
+
 	/* Called for each PCI bus in the system when it's probed */
 	void (*pcibios_fixup_bus)(struct pci_bus *);
 
@@ -81,6 +83,13 @@
 	 * when a device with no assigned resource is found (initial=1).
 	 * Returns 0 to allow assignment/enabling of the device. */
 	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
+
+	/* For interrupt routing */
+	unsigned char (*pci_swizzle)(struct pci_dev *, unsigned char *);
+	int (*pci_map_irq)(struct pci_dev *, unsigned char, unsigned char);
+
+	/* Called in indirect_* to avoid touching devices */
+	int (*pci_exclude_device)(unsigned char, unsigned char);
 
 	/* Called at then very end of pcibios_init() */
 	void (*pcibios_after_init)(void);
diff -urN linux-2.4.10-pre2/include/asm-sparc/kmap_types.h linux/include/asm-sparc/kmap_types.h
--- linux-2.4.10-pre2/include/asm-sparc/kmap_types.h	Thu Apr 12 12:11:39 2001
+++ linux/include/asm-sparc/kmap_types.h	Mon Dec  3 23:05:27 2001
@@ -6,6 +6,8 @@
 	KM_BOUNCE_WRITE,
 	KM_SKB_DATA,
 	KM_SKB_DATA_SOFTIRQ,
+	KM_USER0,
+	KM_USER1,
 	KM_TYPE_NR
 };
 
diff -urN linux-2.4.10-pre2/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.10-pre2/include/linux/fs.h	Mon Dec  3 23:05:12 2001
+++ linux/include/linux/fs.h	Mon Dec  3 23:05:27 2001
@@ -182,7 +182,9 @@
 /* This was here just to show that the number is taken -
    probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
 #endif
-
+/* A jump here: 108-111 have been used for various private purposes. */
+#define BLKBSZGET  _IOR(0x12,112,sizeof(int))
+#define BLKBSZSET  _IOW(0x12,113,sizeof(int))
 
 #define BMAP_IOCTL 1		/* obsolete - kept for compatibility */
 #define FIBMAP	   _IO(0x00,1)	/* bmap access */
diff -urN linux-2.4.10-pre2/include/linux/pmu.h linux/include/linux/pmu.h
--- linux-2.4.10-pre2/include/linux/pmu.h	Sun Sep 17 09:48:05 2000
+++ linux/include/linux/pmu.h	Mon Dec  3 23:05:27 2001
@@ -7,6 +7,9 @@
  */
 
 #include <linux/config.h>
+
+#define PMU_DRIVER_VERSION	2
+
 /*
  * PMU commands
  */
@@ -23,6 +26,7 @@
 #define PMU_GET_VOLBUTTON	0x48	/* get volume up/down position */
 #define PMU_PCEJECT		0x4c	/* eject PC-card from slot */
 #define PMU_BATTERY_STATE	0x6b	/* report battery state etc. */
+#define PMU_SMART_BATTERY_STATE	0x6f	/* report battery state (new way) */
 #define PMU_SET_INTR_MASK	0x70	/* set PMU interrupt mask */
 #define PMU_INT_ACK		0x78	/* read interrupt bits */
 #define PMU_SHUTDOWN		0x7e	/* turn power off */
@@ -32,6 +36,7 @@
 #define PMU_GET_BRIGHTBUTTON	0xd9	/* report brightness up/down pos */
 #define PMU_GET_COVER		0xdc	/* report cover open/closed */
 #define PMU_SYSTEM_READY	0xdf	/* tell PMU we are awake */
+#define PMU_GET_VERSION		0xea	/* read the PMU version */
 
 /* Bits to use with the PMU_POWER_CTRL0 command */
 #define PMU_POW0_ON		0x80	/* OR this to power ON the device */
@@ -46,16 +51,23 @@
 #define PMU_POW_IRLED		0x04	/* IR led power (on wallstreet) */
 #define PMU_POW_MEDIABAY	0x08	/* media bay power (wallstreet/lombard ?) */
 
-
 /* Bits in PMU interrupt and interrupt mask bytes */
-#define PMU_INT_ADB_AUTO	0x04	/* ADB autopoll, when PMU_INT_ADB */
 #define PMU_INT_PCEJECT		0x04	/* PC-card eject buttons */
 #define PMU_INT_SNDBRT		0x08	/* sound/brightness up/down buttons */
 #define PMU_INT_ADB		0x10	/* ADB autopoll or reply data */
-#define PMU_INT_BATTERY		0x20
-#define PMU_INT_WAKEUP		0x40
+#define PMU_INT_BATTERY		0x20	/* Battery state change */
+#define PMU_INT_ENVIRONMENT	0x40	/* Environment interrupts */
 #define PMU_INT_TICK		0x80	/* 1-second tick interrupt */
 
+/* Other bits in PMU interrupt valid when PMU_INT_ADB is set */
+#define PMU_INT_ADB_AUTO	0x04	/* ADB autopoll, when PMU_INT_ADB */
+#define PMU_INT_WAITING_CHARGER	0x01	/* ??? */
+#define PMU_INT_AUTO_SRQ_POLL	0x02	/* ??? */
+
+/* Bits in the environement message (either obtained via PMU_GET_COVER,
+ * or via PMU_INT_ENVIRONMENT on core99 */
+#define PMU_ENV_LID_CLOSED	0x01	/* The lid is closed */
+
 /* Kind of PMU (model) */
 enum {
 	PMU_UNKNOWN,
@@ -99,6 +111,8 @@
 #define PMU_IOC_GET_MODEL	_IOR('B', 3, sizeof(__u32*))
 /* out param: u32*	has_adb: 0 or 1 */
 #define PMU_IOC_HAS_ADB		_IOR('B', 4, sizeof(__u32*)) 
+/* out param: u32*	can_sleep: 0 or 1 */
+#define PMU_IOC_CAN_SLEEP	_IOR('B', 5, sizeof(__u32*)) 
 
 #ifdef __KERNEL__
 
@@ -160,7 +174,7 @@
 #define SLEEP_LEVEL_NET		60	/* bmac */
 #define SLEEP_LEVEL_ADB		50	/* ADB */
 #define SLEEP_LEVEL_MISC	30	/* Anything */
-#define SLEEP_LEVEL_LAST	0	/* Anything */
+#define SLEEP_LEVEL_LAST	0	/* Reserved for apm_emu */
 
 /* special register notifier functions */
 int pmu_register_sleep_notifier(struct pmu_sleep_notifier* notifier);
diff -urN linux-2.4.10-pre2/include/linux/skbuff.h linux/include/linux/skbuff.h
--- linux-2.4.10-pre2/include/linux/skbuff.h	Wed Aug 15 14:21:30 2001
+++ linux/include/linux/skbuff.h	Mon Dec  3 23:05:27 2001
@@ -1082,7 +1082,7 @@
 /**
  *	skb_linearize - convert paged skb to linear one
  *	@skb: buffer to linarize
- *	@gfp_mask: allocation mode
+ *	@gfp: allocation mode
  *
  *	If there is no free memory -ENOMEM is returned, otherwise zero
  *	is returned and the old skb data released.  */
diff -urN linux-2.4.10-pre2/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.10-pre2/mm/vmscan.c	Wed Aug 15 02:37:07 2001
+++ linux/mm/vmscan.c	Mon Dec  3 23:05:27 2001
@@ -818,10 +818,12 @@
 #define GENERAL_SHORTAGE 4
 static int do_try_to_free_pages(unsigned int gfp_mask, int user)
 {
-	/* Always walk at least the active queue when called */
-	int shortage = INACTIVE_SHORTAGE;
+	int shortage = 0;
 	int maxtry;
 
+	/* Always walk at least the active queue when called */
+	refill_inactive_scan(DEF_PRIORITY);
+
 	maxtry = 1 << DEF_PRIORITY;
 	do {
 		/*
@@ -872,7 +874,8 @@
 			break;
 	} while (shortage);
 
-	return !shortage;
+	/* Return success if we're not "totally short" */
+	return shortage != (FREE_SHORTAGE | INACTIVE_SHORTAGE | GENERAL_SHORTAGE);
 }
 
 DECLARE_WAIT_QUEUE_HEAD(kswapd_wait);
diff -urN linux-2.4.10-pre2/scripts/ver_linux linux/scripts/ver_linux
--- linux-2.4.10-pre2/scripts/ver_linux	Thu Apr 12 12:16:36 2001
+++ linux/scripts/ver_linux	Mon Dec  3 23:05:27 2001
@@ -26,7 +26,7 @@
 
 insmod -V  2>&1 | awk 'NR==1 {print "modutils              ",$NF}'
 
-tune2fs 2>&1 | grep tune2fs | sed 's/,//' |  awk \
+tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' |  awk \
 'NR==1 {print "e2fsprogs             ", $2}'
 
 reiserfsck 2>&1 | grep reiserfsprogs | awk \
