]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.4.0-test7-pre5 2.4.0-test7pre5
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:07 +0000 (15:38 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:07 +0000 (15:38 -0500)
    - i2c-old compile fix.
    - sparc updates (pte_pagenr cleanups)
    - make ipv6 loadable as a module together with CONFIG_INET_ECN
    - get rid of bdf_prm.b_un.age_super - it just confused the buffer aging
    - smbfs knows about nls and ascii mount options
    - small joystick driver updates
    - make sure to mark inode dirty after having changed the size!
    - hgafb documentation update

40 files changed:
Documentation/Configure.help
MAINTAINERS
arch/arm/kernel/semaphore.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
drivers/char/i2c-old.c
drivers/char/joystick/amijoy.c
drivers/char/joystick/db9.c
drivers/char/joystick/gamecon.c
drivers/char/joystick/sidewinder.c
drivers/char/joystick/spaceball.c
drivers/isdn/eicon/Divas_mod.c
drivers/video/hgafb.c
fs/Config.in
fs/buffer.c
fs/inode.c
fs/nls/Config.in
fs/smbfs/ChangeLog
fs/smbfs/Makefile
fs/smbfs/dir.c
fs/smbfs/getopt.c [new file with mode: 0644]
fs/smbfs/getopt.h [new file with mode: 0644]
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/smbfs/sock.c
include/asm-arm/arch-arc/irq.h
include/asm-arm/arch-arc/system.h
include/asm-sparc/pgtable.h
include/asm-sparc/spinlock.h
include/asm-sparc/unistd.h
include/asm-sparc64/spinlock.h
include/asm-sparc64/unistd.h
include/linux/smb.h
include/linux/smb_fs.h
include/linux/smb_fs_sb.h
include/linux/smb_mount.h
kernel/ksyms.c
mm/filemap.c
mm/highmem.c
net/netsyms.c

index 12f162feb13d78ee1f466bd7c47f7eb5a2edf711..58c7f23db97ed91850c5db067aa4c058a3c70aaa 100644 (file)
@@ -11305,6 +11305,21 @@ CONFIG_SMB_FS
   want), say M here and read Documentation/modules.txt. The module
   will be called smbfs.o. Most people say N, however.
 
+nls support setting
+CONFIG_SMB_NLS_REMOTE
+  This setting allows you to specify a default value for which
+  codepage the server uses. If this field is left blank no
+  translations will be done by default. The local codepage/charset
+  default to CONFIG_NLS_DEFAULT.
+
+  The nls settings can be changed at mount time, if your smbmount
+  supports that, using the codepage and iocharset parameters.
+
+  Currently no smbmount distributed with samba supports this, it is
+  assumed future versions will. In the meantime you can get an
+  unofficial patch for samba 2.0.7 from:
+  http://www.hojdpunkten.ac.se/054/samba/index.html
+
 Coda file system support (advanced network fs)
 CONFIG_CODA_FS
   Coda is an advanced network file system, similar to NFS in that it
index d74d1596e37d542756f40f0058eaf3d708d83893..faac0cebc29f05a366f50a02c769994e113bff9a 100644 (file)
@@ -450,6 +450,13 @@ M:      asun@cobaltnet.com
 L:      linux-kernel@vger.rutgers.edu
 S:      Maintained
 
+HGA FRAMEBUFFER DRIVER
+P:     Ferenc Bakonyi
+M:     fero@drama.obuda.kando.hu
+L:     linux-nvidia@lists.surfsouth.com
+W:     http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
+S:     Maintained
+
 HIGH-SPEED SCC DRIVER FOR AX.25
 P:     Klaus Kudielka
 M:     klaus.kudielka@ieee.org
index ab2e095afecfed632579f8f8f5c608cf2d1d4cd4..d29f8cf1ff8c776133fc2ab3b3ecc8da86272a62 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Modified for ARM by Russell King
  */
+#include <linux/config.h>
 #include <linux/sched.h>
 
 #include <asm/semaphore.h>
index 96fbf1b889a8fecbe7e6f59f38e8dcc995d86de0..4f5bd16c5b31d0ee0453cbfd120f40063c9ed18c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.220 2000/08/09 00:00:15 davem Exp $
+/* $Id: srmmu.c,v 1.221 2000/08/14 00:46:13 anton Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -137,8 +137,8 @@ static inline unsigned long srmmu_pgd_page(pgd_t pgd)
 static inline unsigned long srmmu_pmd_page(pmd_t pmd)
 { return srmmu_device_memory(pmd_val(pmd))?~0:(unsigned long)__nocache_va((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); }
 
-static inline unsigned long srmmu_pte_pagenr(pte_t pte)
-{ return srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT); }
+static inline struct page *srmmu_pte_page(pte_t pte)
+{ return (mem_map + (unsigned long)(srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT))); }
 
 static inline int srmmu_pte_none(pte_t pte)
 { return !(pte_val(pte) & 0xFFFFFFF); }
@@ -2153,7 +2153,7 @@ void __init ld_mmu_srmmu(void)
        BTFIXUPSET_CALL(set_pte, srmmu_set_pte, BTFIXUPCALL_SWAPO0O1);
        BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM);
 
-       BTFIXUPSET_CALL(sparc_pte_pagenr, srmmu_pte_pagenr, BTFIXUPCALL_NORM);
+       BTFIXUPSET_CALL(pte_page, srmmu_pte_page, BTFIXUPCALL_NORM);
        BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
        BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM);
 
index 0ce0ca1e82368899df6596beb2ecbae162d317b9..66bc3af7b811a7b027b9e7af94a367b8de38e78f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.197 2000/08/09 00:00:15 davem Exp $
+/* $Id: sun4c.c,v 1.198 2000/08/14 00:46:13 anton Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -2156,9 +2156,9 @@ static pte_t sun4c_mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
        return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
 }
 
-static unsigned long sun4c_pte_pagenr(pte_t pte)
+static struct page *sun4c_pte_page(pte_t pte)
 {
-       return (pte_val(pte) & SUN4C_PFN_MASK);
+       return (mem_map + (unsigned long)(pte_val(pte) & SUN4C_PFN_MASK));
 }
 
 static inline unsigned long sun4c_pmd_page(pmd_t pmd)
@@ -2650,7 +2650,7 @@ void __init ld_mmu_sun4c(void)
 
        BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0);
 
-       BTFIXUPSET_CALL(sparc_pte_pagenr, sun4c_pte_pagenr, BTFIXUPCALL_NORM);
+       BTFIXUPSET_CALL(pte_page, sun4c_pte_page, BTFIXUPCALL_NORM);
 #if PAGE_SHIFT <= 12   
        BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1));
 #else
index bd9750fc33642e2d96740579255cbcd825728f8e..c896057cd56e01ca5f022f39bf36158f6796e201 100644 (file)
@@ -36,10 +36,6 @@ static struct i2c_bus    *busses[I2C_BUS_MAX];
 static struct i2c_driver *drivers[I2C_DRIVER_MAX];
 static int bus_count = 0, driver_count = 0;
 
-#ifdef CONFIG_VIDEO_BT848
-extern int i2c_tuner_init(void);
-extern int msp3400c_init(void);
-#endif
 #ifdef CONFIG_VIDEO_BUZ
 extern int saa7111_init(void);
 extern int saa7185_init(void);
@@ -54,10 +50,6 @@ int i2c_init(void)
        printk(KERN_INFO "i2c: initialized%s\n",
                scan ? " (i2c bus scan enabled)" : "");
        /* anything to do here ? */
-#ifdef CONFIG_VIDEO_BT848
-       i2c_tuner_init();
-       msp3400c_init();
-#endif 
 #ifdef CONFIG_VIDEO_BUZ
        saa7111_init();
        saa7185_init();
index f17aeda24478d07e8ada638ce8affe8b35d39559..452d173d78be3f3b96dc892cd7cead180cc1ece9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: amijoy.c,v 1.4 2000/05/29 10:39:54 vojtech Exp $
+ * $Id: amijoy.c,v 1.5 2000/07/21 22:52:24 vojtech Exp $
  *
  *  Copyright (c) 1998-2000 Vojtech Pavlik
  *
@@ -77,7 +77,7 @@ static int amijoy_open(struct input_dev *dev)
                return 0;
        
        if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", NULL)) {
-               amijoy_used--;
+               (*used)--;
                printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", amijoy_irq);
                return -EBUSY;
        }
@@ -89,7 +89,7 @@ static void amijoy_close(struct input_dev *dev)
 {
        int *used = dev->private;
 
-       if (!--(*port->used))
+       if (!--(*used))
                free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
 }
 
@@ -112,13 +112,21 @@ static int __init amijoy_init(void)
 
        for (i = 0; i < 2; i++)
                if (amijoy[i]) {
+                       if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
+                                               amijoy [Denise]")) {
+                               if (i == 1 && amijoy[0]) {
+                                       input_unregister_device(amijoy_dev);
+                                       release_mem_region(CUSTOM_PHYSADDR+10, 2);
+                               }
+                               return -EBUSY;
+                       }
 
                        amijoy_dev[i].open = amijoy_open;
                        amijoy_dev[i].close = amijoy_close;
                        amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
                        amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
                        amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-                       for (j = 0; j < 2; j++)
+                       for (j = 0; j < 2; j++) {
                                amijoy_dev[i].absmin[ABS_X + j] = -1;
                                amijoy_dev[i].absmax[ABS_X + j] = 1;
                        }
@@ -134,6 +142,7 @@ static int __init amijoy_init(void)
                        input_register_device(amijoy_dev + i);
                        printk(KERN_INFO "input%d: %s at joy%ddat\n", amijoy_dev[i].number, amijoy_name, i);
                }
+       return 0;
 }
 
 static void _exit amijoy_exit(void)
@@ -141,8 +150,10 @@ static void _exit amijoy_exit(void)
        int i;
 
        for (i = 0; i < 2; i++)
-               if (amijoy[i])
+               if (amijoy[i]) {
                        input_unregister_device(amijoy_dev + i);
+                       release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
+               }
 }
 
 module_init(amijoy_init);
index f9edd0755fc5ef29b1a4d77e2505f85b0ddd86c2..4277e7f3de2874170f1460ba447436aade38ceb5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: db9.c,v 1.5 2000/05/29 20:39:38 vojtech Exp $
+ * $Id: db9.c,v 1.6 2000/06/25 10:57:50 vojtech Exp $
  *
  *  Copyright (c) 1999 Vojtech Pavlik
  *
@@ -95,7 +95,7 @@ static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y,
 static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
 
 static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 8, 1, 1, 7 };
-static short *db9_btn[DB9_MAX_PAD] = { db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
+static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
                                        db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn };
 static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
                                      NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
@@ -113,36 +113,36 @@ static void db9_timer(unsigned long private)
 
                        data = parport_read_data(port) >> 3;
 
-                       input_report_abs(dev + 1, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev + 1, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
-                       input_report_key(dev + 1, BTN_TRIGGER, ~data&DB9_FIRE1);
+                       input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+                       input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
 
                case DB9_MULTI_0802:
 
                        data = parport_read_status(port) >> 3;
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
-                       input_report_key(dev, BTN_TRIGGER, data&DB9_FIRE1);
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+                       input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
                        break;
 
                case DB9_MULTI_STICK:
 
                        data = parport_read_data(port);
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
-                       input_report_key(dev, BTN_TRIGGER, ~data&DB9_FIRE1);
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+                       input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
                        break;
 
                case DB9_MULTI2_STICK:
 
                        data = parport_read_data(port);
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
-                       input_report_key(dev, BTN_TRIGGER, ~data&DB9_FIRE1);
-                       input_report_key(dev, BTN_THUMB,   ~data&DB9_FIRE2);
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+                       input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
+                       input_report_key(dev, BTN_THUMB,   ~data & DB9_FIRE2);
                        break;
 
                case DB9_GENESIS_PAD:
@@ -150,16 +150,16 @@ static void db9_timer(unsigned long private)
                        parport_write_control(port, DB9_NOSELECT);
                        data = parport_read_data(port);
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
-                       input_report_key(dev, BTN_B, ~data&DB9_FIRE1);
-                       input_report_key(dev, BTN_C, ~data&DB9_FIRE2);
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+                       input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
+                       input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
 
                        parport_write_control(port, DB9_NORMAL);
                        data=parport_read_data(port);
 
-                       input_report_key(dev, BTN_A,     ~data&DB9_FIRE1);
-                       input_report_key(dev, BTN_START, ~data&DB9_FIRE2);
+                       input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
+                       input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
                        break;
 
                case DB9_GENESIS5_PAD:
@@ -167,18 +167,18 @@ static void db9_timer(unsigned long private)
                        parport_write_control(port, DB9_NOSELECT);
                        data=parport_read_data(port);
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
-                       input_report_key(dev, BTN_B, ~data&DB9_FIRE1);
-                       input_report_key(dev, BTN_C, ~data&DB9_FIRE2);
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+                       input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
+                       input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
 
                        parport_write_control(port, DB9_NORMAL);
                        data=parport_read_data(port);
 
-                       input_report_key(dev, BTN_A,     ~data&DB9_FIRE1);
-                       input_report_key(dev, BTN_X,     ~data&DB9_FIRE2);
-                       input_report_key(dev, BTN_Y,     ~data&DB9_LEFT);
-                       input_report_key(dev, BTN_START, ~data&DB9_RIGHT);
+                       input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
+                       input_report_key(dev, BTN_X,     ~data & DB9_FIRE2);
+                       input_report_key(dev, BTN_Y,     ~data & DB9_LEFT);
+                       input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
                        break;
 
                case DB9_GENESIS6_PAD:
@@ -187,17 +187,17 @@ static void db9_timer(unsigned long private)
                        udelay(DB9_GENESIS6_DELAY);
                        data=parport_read_data(port);
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
-                       input_report_key(dev, BTN_B, ~data&DB9_FIRE1);
-                       input_report_key(dev, BTN_C, ~data&DB9_FIRE2);
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+                       input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
+                       input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
 
                        parport_write_control(port, DB9_NORMAL);
                        udelay(DB9_GENESIS6_DELAY);
                        data=parport_read_data(port);
 
-                       input_report_key(dev, BTN_A, ~data&DB9_FIRE1);
-                       input_report_key(dev, BTN_X, ~data&DB9_FIRE2);
+                       input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
+                       input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
 
                        parport_write_control(port, DB9_NOSELECT); /* 2 */
                        udelay(DB9_GENESIS6_DELAY);
@@ -207,10 +207,10 @@ static void db9_timer(unsigned long private)
                        udelay(DB9_GENESIS6_DELAY);
                        data=parport_read_data(port);
 
-                       input_report_key(dev, BTN_Y,     ~data&DB9_LEFT);
-                       input_report_key(dev, BTN_Z,     ~data&DB9_DOWN);
-                       input_report_key(dev, BTN_MODE,  ~data&DB9_UP);
-                       input_report_key(dev, BTN_START, ~data&DB9_RIGHT);
+                       input_report_key(dev, BTN_Y,     ~data & DB9_LEFT);
+                       input_report_key(dev, BTN_Z,     ~data & DB9_DOWN);
+                       input_report_key(dev, BTN_MODE,  ~data & DB9_UP);
+                       input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
 
                        parport_write_control(port, DB9_NORMAL);
                        udelay(DB9_GENESIS6_DELAY);
@@ -224,32 +224,32 @@ static void db9_timer(unsigned long private)
                        parport_write_control(port, DB9_SATURN0);
                        data = parport_read_data(port);
 
-                       input_report_key(dev, BTN_Y, ~data&DB9_LEFT);
-                       input_report_key(dev, BTN_Z, ~data&DB9_DOWN);
-                       input_report_key(dev, BTN_TL,~data&DB9_UP);
-                       input_report_key(dev, BTN_TR,~data&DB9_RIGHT);
+                       input_report_key(dev, BTN_Y,  ~data & DB9_LEFT);
+                       input_report_key(dev, BTN_Z,  ~data & DB9_DOWN);
+                       input_report_key(dev, BTN_TL, ~data & DB9_UP);
+                       input_report_key(dev, BTN_TR, ~data & DB9_RIGHT);
 
                        parport_write_control(port, DB9_SATURN2);
                        data = parport_read_data(port);
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
                        
                        parport_write_control(port, DB9_NORMAL);
                        data = parport_read_data(port);
 
-                       input_report_key(dev, BTN_A, ~data&DB9_LEFT);
-                       input_report_key(dev, BTN_B, ~data&DB9_UP);
-                       input_report_key(dev, BTN_C, ~data&DB9_DOWN);
-                       input_report_key(dev, BTN_X, ~data&DB9_RIGHT);
+                       input_report_key(dev, BTN_A, ~data & DB9_LEFT);
+                       input_report_key(dev, BTN_B, ~data & DB9_UP);
+                       input_report_key(dev, BTN_C, ~data & DB9_DOWN);
+                       input_report_key(dev, BTN_X, ~data & DB9_RIGHT);
                        break;
 
                case DB9_CD32_PAD:
 
                        data=parport_read_data(port);
 
-                       input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP  ?0:1));
-                       input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1));
+                       input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+                       input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
 
                        parport_write_control(port, 0x0a); 
 
@@ -257,7 +257,7 @@ static void db9_timer(unsigned long private)
                                data = parport_read_data(port);
                                parport_write_control(port, 0x02); 
                                parport_write_control(port, 0x0a); 
-                               input_report_key(dev, db9_cd32_btn[i], ~data&DB9_FIRE2);
+                               input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
                                }
 
                        parport_write_control(port, 0x00); 
index a92ef58a997b22e1e31f40957c6dd0e7b6e1ff03..c1d37248f099ae8e3c747727c459e5e569d00619 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: gamecon.c,v 1.4 2000/05/29 21:08:45 vojtech Exp $
+ * $Id: gamecon.c,v 1.5 2000/06/25 09:56:58 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -157,7 +157,7 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
 
 static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 };
 static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 };
-static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_START, BTN_SELECT, BTN_X, BTN_Y, BTN_TL, BTN_TR };
+static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR };
 
 /*
  * gc_nes_read_packet() reads a NES/SNES packet.
@@ -515,7 +515,7 @@ static struct gc __init *gc_probe(int *config)
 
                        case GC_N64:
                                for (j = 0; j < 10; j++)
-                                       set_bit(gc_n64_btn[j], gc->dev[j].keybit);
+                                       set_bit(gc_n64_btn[j], gc->dev[i].keybit);
 
                                for (j = 0; j < 2; j++) {
                                        set_bit(ABS_X + j, gc->dev[i].absbit);
@@ -530,18 +530,15 @@ static struct gc __init *gc_probe(int *config)
                                break;
 
                        case GC_SNES:
-                               for (j = 0; j < 8; j++)
-                                       set_bit(gc_snes_btn[j], gc->dev[j].keybit);
-                               break;
-
+                               for (j = 4; j < 8; j++)
+                                       set_bit(gc_snes_btn[j], gc->dev[i].keybit);
                        case GC_NES:
                                for (j = 0; j < 4; j++)
-                                       set_bit(gc_snes_btn[j], gc->dev[j].keybit);
+                                       set_bit(gc_snes_btn[j], gc->dev[i].keybit);
                                break;
 
                        case GC_MULTI2:
                                set_bit(BTN_THUMB, gc->dev[i].keybit);
-
                        case GC_MULTI:
                                set_bit(BTN_TRIGGER, gc->dev[i].keybit);
                                break;
@@ -656,12 +653,13 @@ void __exit gc_exit(void)
 {
        int i, j;
 
-       for (i = 0; i < 3; i++)  {
-               for (j = 0; j < 5; j++) 
-                       if (gc_base[i]->pads[0] & gc_status_bit[j])
-                               input_unregister_device(gc_base[i]->dev + j);
-               parport_unregister_device(gc_base[i]->pd);
-       }
+       for (i = 0; i < 3; i++)
+               if (gc_base[i]) {
+                       for (j = 0; j < 5; j++)
+                               if (gc_base[i]->pads[0] & gc_status_bit[j])
+                                       input_unregister_device(gc_base[i]->dev + j); 
+                       parport_unregister_device(gc_base[i]->pd);
+               }
 }
 
 module_init(gc_init);
index 861966b4e08c0138fffa4d1a2ae5a67e1ec5d5b8..85be9f8b11de266f83d7104f35e468880d677371 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: sidewinder.c,v 1.14 2000/05/29 11:27:55 vojtech Exp $
+ * $Id: sidewinder.c,v 1.16 2000/07/14 09:02:41 vojtech Exp $
  *
  *  Copyright (c) 1998-2000 Vojtech Pavlik
  *
@@ -330,8 +330,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
 
                                if (sw_parity(GB(i*15,15))) return -1;
 
-                               input_report_key(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
-                               input_report_key(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
+                               input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
+                               input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
 
                                for (j = 0; j < 10; j++)
                                        input_report_key(dev, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
index 4f5059330c93590a81d74165c20bb578e319d045..8e2936f73e349e92e7f4617bf1541b6ddd400624 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: spaceball.c,v 1.6 2000/05/29 11:19:51 vojtech Exp $
+ * $Id: spaceball.c,v 1.7 2000/06/24 11:55:40 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -46,7 +46,7 @@
  */
 
 #define JS_SBALL_MAX_LENGTH    128
-static int spaceball_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
+static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
 static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX"; 
 
 /*
@@ -70,10 +70,12 @@ static void spaceball_process_packet(struct spaceball* spaceball)
 {
        struct input_dev *dev = &spaceball->dev;
        unsigned char *data = spaceball->data;
-       int i, d;
+       int i;
 
        if (spaceball->idx < 2) return;
 
+       printk("%c %d\n", spaceball->data[0], spaceball->idx);
+
        switch (spaceball->data[0]) {
 
                case '@':                                       /* Reset packet */
@@ -84,17 +86,17 @@ static void spaceball_process_packet(struct spaceball* spaceball)
                        break;
 
                case 'D':                                       /* Ball data */
-                       if (spaceball->idx != 16) return;
+                       if (spaceball->idx != 15) return;
                        for (i = 0; i < 6; i++) {
-                               d = ((data[2 * i + 3] << 8) | data[2 * i + 2]);
-                               input_report_abs(dev, spaceball_axes[i], d - ((d & 0x8000) ? 0x10000 : 0));
+                               input_report_abs(dev, spaceball_axes[i], 
+                                       (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
                        }
                        break;
 
                case '.':                               /* Button data, part2 */
-                       if (spaceball->idx != 4) return;
-                       input_report_key(dev, BTN_LEFT,  data[2] & 1);
-                       input_report_key(dev, BTN_RIGHT, data[2] & 2);
+                       if (spaceball->idx != 3) return;
+                       input_report_key(dev, BTN_0,  data[2] & 1);
+                       input_report_key(dev, BTN_1, data[2] & 2);
                        break;
 
                case '?':                               /* Error packet */
@@ -118,22 +120,27 @@ static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigne
 
        switch (data) {
                case 0xd:
-                       if (spaceball->idx)
-                               spaceball_process_packet(spaceball);
+                       spaceball_process_packet(spaceball);
                        spaceball->idx = 0;
                        spaceball->escape = 0;
                        return;
+               case '^':
+                       if (!spaceball->escape) {
+                               spaceball->escape ^= 1;
+                               return;
+                       }
+                       spaceball->escape = 0;
                case 'M':
                case 'Q':
                case 'S':
-                       if (spaceball->escape)
+                       if (spaceball->escape) {
+                               spaceball->escape = 0;
                                data = 0xd;
-               case '^':
-                       spaceball->escape ^= 1;
+                       }
                default:
                        if (spaceball->escape) {
-                               printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x\n", data);
                                spaceball->escape = 0;
+                               printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data);
                        }
                        if (spaceball->idx < JS_SBALL_MAX_LENGTH)
                                spaceball->data[spaceball->idx++] = data;
@@ -172,15 +179,15 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
        memset(spaceball, 0, sizeof(struct spaceball));
 
        spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);    
-       spaceball->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+       spaceball->dev.keybit[LONG(BTN_0)] = BIT(BTN_0) | BIT(BTN_1);
 
        for (i = 0; i < 6; i++) {
                t = spaceball_axes[i];
                set_bit(t, spaceball->dev.absbit);
-               spaceball->dev.absmin[t] = i < 3 ? -10000 : -2000;
-               spaceball->dev.absmax[t] = i < 3 ?  10000 :  2000;
-               spaceball->dev.absflat[t] = i < 3 ? 50 : 10;
-               spaceball->dev.absfuzz[t] = i < 3 ? 12 : 2;
+               spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
+               spaceball->dev.absmax[t] = i < 3 ?  8000 :  1600;
+               spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
+               spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
        }
 
        spaceball->serio = serio;
index 752255682d2a2efd0cf65c000a1d1693ced2afd5..8cb2a0409f52cdf1b90b4d2d4b319b448d9a5ecb 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 
+#include <linux/config.h>
 #include <linux/fs.h>
 #undef N_DATA
 
index d2b09416b4b881bf1b5000fb345c66cc6e8f4714..8b389f84688c6c0e428b36337a983854913d0fe7 100644 (file)
@@ -7,6 +7,8 @@
  *
  * History:
  *
+ * - Revision 0.1.6 (17 Aug 2000): new style structs
+ *                                 documentation
  * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
  *                                 minor fixes
  * - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for 
@@ -107,19 +109,23 @@ spinlock_t hga_reg_lock = SPIN_LOCK_UNLOCKED;
 /* Framebuffer driver structures */
 
 static struct fb_var_screeninfo hga_default_var = {
-       720, 348,                       /* xres, yres */
-       720, 348,                       /* xres_virtual, yres_virtual */
-       0, 0,                           /* xoffset, yoffset */
-       1,                              /* bits_per_pixel */
-       0,                              /* grayscale */
-       {0, 1, 0},                      /* red */
-       {0, 1, 0},                      /* green */
-       {0, 1, 0},                      /* blue */
-       {0, 0, 0},                      /* transp */ 
-       0,                              /* nonstd (FB_NONSTD_HGA ?) */
-       0,                              /* activate */
-       -1, -1,                         /* height, width */
-       0,                              /* accel_flags */
+       xres:           720,
+       yres:           348,
+       xres_virtual:   720,
+       yres_virtual:   348,
+       xoffset:        0,
+       yoffset:        0,
+       bits_per_pixel: 1,
+       grayscale:      0,
+       red:            {0, 1, 0},
+       green:          {0, 1, 0},
+       blue:           {0, 1, 0},
+       transp:         {0, 0, 0},
+       nonstd:         0,                      /* (FB_NONSTD_HGA ?) */
+       activate:       0,
+       height:         -1,
+       width:          -1,
+       accel_flags:    0,
        /* pixclock */
        /* left_margin, right_margin */
        /* upper_margin, lower_margin */
@@ -129,19 +135,19 @@ static struct fb_var_screeninfo hga_default_var = {
 };
 
 static struct fb_fix_screeninfo hga_fix = {
-       "HGA",                          /* id */
-       (unsigned long) NULL,           /* smem_start */
-       0,                              /* smem_len */
-       FB_TYPE_PACKED_PIXELS,          /* type (not sure) */
-       0,                              /* type_aux (not sure) */
-       FB_VISUAL_MONO10,               /* visual */
-       8,                              /* xpanstep */
-       8,                              /* ypanstep */
-       0,                              /* ywrapstep */
-       90,                             /* line_length */
-       0,                              /* mmio_start */
-       0,                              /* mmio_len */
-       FB_ACCEL_NONE                   /* accel */
+       id:             "HGA",
+       smem_start:     (unsigned long) NULL,
+       smem_len:       0,
+       type:           FB_TYPE_PACKED_PIXELS,  /* (not sure) */
+       type_aux:       0,                      /* (not sure) */
+       visual:         FB_VISUAL_MONO10,
+       xpanstep:       8,
+       ypanstep:       8,
+       ywrapstep:      0,
+       line_length:    90,
+       mmio_start:     0,
+       mmio_len:       0,
+       accel:          FB_ACCEL_NONE
 };
 
 static struct fb_info fb_info;
@@ -377,9 +383,15 @@ static int __init hga_card_detect(void)
  *
  * ------------------------------------------------------------------------- */
 
-       /*
-        * Get the Fixed Part of the Display
-        */
+/**
+ *     hga_get_fix - get the fixed part of the display
+ *     @fix:struct fb_fix_screeninfo to fill in
+ *     @con:unused
+ *     @info:pointer to fb_info object containing info for current hga board
+ *
+ *     This wrapper function copies @info->fix to @fix.
+ *     A zero is returned on success and %-EINVAL for failure.
+ */
 
 int hga_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 {
@@ -390,10 +402,15 @@ int hga_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
        return 0;
 }
 
-
-       /*
-        *  Get the User Defined Part of the Display
-        */
+/**
+ *     hga_get_var - get the user defined part of the display
+ *     @var:struct fb_var_screeninfo to fill in
+ *     @con:unused
+ *     @info:pointer to fb_info object containing info for current hga board
+ *
+ *     This wrapper function copies @info->var to @var.
+ *     A zero is returned on success and %-EINVAL for failure.
+ */
 
 int hga_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
@@ -404,13 +421,23 @@ int hga_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
        return 0;
 }
 
-       /*
-        * Set the User Defined Part of the Display
-        * This is the most mystical function (at least for me).
-        * What is the exact specification of xxx_set_var?
-        * Should it handle xoffset, yoffset? Should it do pannig?
-        * What does vmode mean?
-        */
+/**
+ *     hga_set_var - set the user defined part of the display
+ *     @var:new video mode
+ *     @con:unused
+ *     @info:pointer to fb_info object containing info for current hga board
+ *     
+ *     This function is called for changing video modes. Since HGA cards have
+ *     only one fixed mode we have not much to do. After checking input 
+ *     parameters @var is copied to @info->var and @info->changevar is called.
+ *     A zero is returned on success and %-EINVAL for failure.
+ *     
+ *     FIXME:
+ *     This is the most mystical function (at least for me).
+ *     What is the exact specification of xxx_set_var()?
+ *     Should it handle xoffset, yoffset? Should it do panning?
+ *     What does vmode mean?
+ */
 
 int hga_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
@@ -431,10 +458,20 @@ int hga_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
        return 0;
 }
 
-
-       /*
-        *  Get the Colormap
-        */
+/**
+ *     hga_getcolreg - read color registers
+ *     @regno:register index to read out
+ *     @red:red value
+ *     @green:green value
+ *     @blue:blue value
+ *     @transp:transparency value
+ *     @info:unused
+ *
+ *     This callback function is used to read the color registers of a HGA
+ *     board. Since we have only two fixed colors, RGB values are 0x0000 
+ *     for register0 and 0xaaaa for register1.
+ *     A zero is returned on success and 1 for failure.
+ */
 
 static int hga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
                         u_int *transp, struct fb_info *info)
@@ -450,6 +487,17 @@ static int hga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
        return 0;
 }
 
+/**
+ *     hga_get_cmap - get the colormap
+ *     @cmap:struct fb_cmap to fill in
+ *     @kspc:called from kernel space?
+ *     @con:unused
+ *     @info:pointer to fb_info object containing info for current hga board
+ *
+ *     This wrapper function passes it's input parameters to fb_get_cmap().
+ *     Callback function hga_getcolreg() is used to read the color registers.
+ */
+
 int hga_get_cmap(struct fb_cmap *cmap, int kspc, int con,
                  struct fb_info *info)
 {
@@ -458,9 +506,19 @@ int hga_get_cmap(struct fb_cmap *cmap, int kspc, int con,
        return fb_get_cmap(cmap, kspc, hga_getcolreg, info);
 }
        
-       /*
-        * Set the Colormap
-        */
+/**
+ *     hga_setcolreg - set color registers
+ *     @regno:register index to set
+ *     @red:red value, unused
+ *     @green:green value, unused
+ *     @blue:blue value, unused
+ *     @transp:transparency value, unused
+ *     @info:unused
+ *
+ *     This callback function is used to set the color registers of a HGA
+ *     board. Since we have only two fixed colors only @regno is checked.
+ *     A zero is returned on success and 1 for failure.
+ */
 
 static int hga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                         u_int transp, struct fb_info *info)
@@ -470,6 +528,17 @@ static int hga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
        return 0;
 }
 
+/**
+ *     hga_set_cmap - set the colormap
+ *     @cmap:struct fb_cmap to set
+ *     @kspc:called from kernel space?
+ *     @con:unused
+ *     @info:pointer to fb_info object containing info for current hga board
+ *
+ *     This wrapper function passes it's input parameters to fb_set_cmap().
+ *     Callback function hga_setcolreg() is used to set the color registers.
+ */
+
 int hga_set_cmap(struct fb_cmap *cmap, int kspc, int con,
                  struct fb_info *info)
 {
@@ -478,11 +547,17 @@ int hga_set_cmap(struct fb_cmap *cmap, int kspc, int con,
        return fb_set_cmap(cmap, kspc, hga_setcolreg, info);
 }
 
-       /*
-        *  Pan or Wrap the Display
-        *
-        *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-        */
+/**
+ *     hga_pan_display - pan or wrap the display
+ *     @var:contains new xoffset, yoffset and vmode values
+ *     @con:unused
+ *     @info:pointer to fb_info object containing info for current hga board
+ *
+ *     This function looks only at xoffset, yoffset and the %FB_VMODE_YWRAP
+ *     flag in @var. If input parameters are correct it calls hga_pan() to 
+ *     program the hardware. @info->var is updated to the new values.
+ *     A zero is returned on success and %-EINVAL for failure.
+ */
 
 int hga_pan_display(struct fb_var_screeninfo *var, int con,
                     struct fb_info *info)
@@ -531,6 +606,18 @@ static struct fb_ops hgafb_ops = {
  * 
  * ------------------------------------------------------------------------- */
 
+/**
+ *     hgafbcon_switch - switch console
+ *     @con:new console to switch to
+ *     @info:pointer to fb_info object containing info for current hga board
+ *
+ *     This function should install a new colormap and change the video mode.
+ *     Since we have fixed colors and only one video mode we have nothing to 
+ *     do.
+ *     Only console administration is done but it should go to fbcon.c IMHO.
+ *     A zero is returned on success and %-EINVAL for failure.
+ */
+
 static int hgafbcon_switch(int con, struct fb_info *info)
 {
        CHKINFO(-EINVAL);
@@ -564,6 +651,17 @@ static int hgafbcon_switch(int con, struct fb_info *info)
        return 0;
 }
 
+/**
+ *     hgafbcon_updatevar - update the user defined part of the display
+ *     @con:console to update or -1 when no consoles defined on this fb
+ *     @info:pointer to fb_info object containing info for current hga board
+ *
+ *     This function is called when @var is changed by fbcon.c without calling 
+ *     hga_set_var(). It usually means scrolling.  hga_pan_display() is called
+ *     to update the hardware and @info->var.
+ *     A zero is returned on success and %-EINVAL for failure.
+ */
+
 static int hgafbcon_updatevar(int con, struct fb_info *info)
 {
        CHKINFO(-EINVAL);
@@ -571,17 +669,21 @@ static int hgafbcon_updatevar(int con, struct fb_info *info)
        return (con < 0) ? -EINVAL : hga_pan_display(&fb_display[con].var, con, info);
 }
 
+/**
+ *     hgafbcon_blank - (un)blank the screen
+ *     @blank_mode:blanking method to use
+ *     @info:unused
+ *     
+ *     Blank the screen if blank_mode != 0, else unblank. 
+ *     Implements VESA suspend and powerdown modes on hardware that supports 
+ *     disabling hsync/vsync:
+ *             @blank_mode == 2 means suspend vsync,
+ *             @blank_mode == 3 means suspend hsync,
+ *             @blank_mode == 4 means powerdown.
+ */
+
 static void hgafbcon_blank(int blank_mode, struct fb_info *info)
 {
-       /*
-        *  Blank the screen if blank_mode != 0, else unblank. 
-        *  Implements VESA suspend and powerdown modes on hardware 
-        *  that supports disabling hsync/vsync:
-        *    blank_mode == 2: suspend vsync
-        *    blank_mode == 3: suspend hsync
-        *    blank_mode == 4: powerdown
-        */
-
        CHKINFO( );
        DPRINTK("hga_blank: blank_mode:%d, info:%x, fb_info:%x\n", blank_mode, (unsigned)info, (unsigned)&fb_info);
 
index e48f7549692104c39364321deb4b9377bea1a700..183aab8f89748ae2852014fed83ebc15b253f059 100644 (file)
@@ -99,7 +99,9 @@ if [ "$CONFIG_NET" = "y" ]; then
    fi
 
    dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
-
+   if [ "$CONFIG_SMB_FS" != "n" ]; then
+      string 'Default Remote NLS Option' CONFIG_SMB_NLS_REMOTE ""
+   fi   
    if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then
       tristate 'NCP file system support (to mount NetWare volumes)' CONFIG_NCP_FS
       source fs/ncpfs/Config.in
index 8c731615669a56f2fe446191fbb67ae2e9523ac0..ca6e2f919882642e16a54e41c51132d712311f7b 100644 (file)
@@ -119,7 +119,7 @@ union bdflush_param {
                                  when trying to refill buffers. */
                int interval; /* jiffies delay between kupdate flushes */
                int age_buffer;  /* Time for normal buffer to age before we flush it */
-               int age_super;  /* Time for superblock to age before we flush it */
+               int dummy1;    /* unused, was age_super */
                int dummy2;    /* unused */
                int dummy3;    /* unused */
        } b_un;
@@ -894,7 +894,7 @@ void balance_dirty(kdev_t dev)
 
 static __inline__ void __mark_dirty(struct buffer_head *bh, int flag)
 {
-       bh->b_flushtime = jiffies + (flag ? bdf_prm.b_un.age_super : bdf_prm.b_un.age_buffer);
+       bh->b_flushtime = jiffies + bdf_prm.b_un.age_buffer;
        refile_buffer(bh);
 }
 
@@ -1714,8 +1714,10 @@ int generic_commit_write(struct file *file, struct page *page,
        loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
        __block_commit_write(inode,page,from,to);
        kunmap(page);
-       if (pos > inode->i_size)
+       if (pos > inode->i_size) {
                inode->i_size = pos;
+               mark_inode_dirty(inode);
+       }
        return 0;
 }
 
@@ -1837,6 +1839,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
        int             pageind;
        int             bhind;
        int             offset;
+       int             sectors = size>>9;
        unsigned long   blocknr;
        struct kiobuf * iobuf = NULL;
        struct page *   map;
@@ -1888,9 +1891,10 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
                                tmp->b_this_page = tmp;
 
                                init_buffer(tmp, end_buffer_io_kiobuf, iobuf);
-                               tmp->b_dev = dev;
+                               tmp->b_rdev = tmp->b_dev = dev;
                                tmp->b_blocknr = blocknr;
-                               tmp->b_state = 1 << BH_Mapped;
+                               tmp->b_rsector = blocknr*sectors;
+                               tmp->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | (1 << BH_Req);
 
                                if (rw == WRITE) {
                                        set_bit(BH_Uptodate, &tmp->b_state);
index 455c4af6e6594c6e290e030dc6b395da7266d14e..2199d68884e77f7be5c1bceebc24452d5d9833c4 100644 (file)
@@ -771,6 +771,7 @@ void iput(struct inode *inode)
                        list_del(&inode->i_list);
                        INIT_LIST_HEAD(&inode->i_list);
                        inode->i_state|=I_FREEING;
+                       inodes_stat.nr_inodes--;
                        spin_unlock(&inode_lock);
 
                        if (inode->i_data.nrpages)
@@ -799,11 +800,11 @@ void iput(struct inode *inode)
                                list_del(&inode->i_list);
                                INIT_LIST_HEAD(&inode->i_list);
                                inode->i_state|=I_FREEING;
+                               inodes_stat.nr_inodes--;
                                spin_unlock(&inode_lock);
                                clear_inode(inode);
                        }
                }
-               inodes_stat.nr_inodes--;
                destroy_inode(inode);
        }
 }
index c33e9d6b8fef8a8ea10e99246f2eaeb151146aba..5c9754acac5252167e907411c63d8c6fe5ae85bd 100644 (file)
@@ -4,7 +4,8 @@
 
 # msdos and Joliet want NLS
 if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
-       -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" ]; then
+       -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
+       -o "$CONFIG_SMB_FS" != "n" ]; then
   define_bool CONFIG_NLS y
 else
   define_bool CONFIG_NLS n
index 89389033483d94dea6bc4fafc3276f8c38389b94..a57b1cc6714f55772120f0b1609fab4377331ea6 100644 (file)
@@ -1,5 +1,16 @@
 ChangeLog for smbfs.
 
+2000-08-14 Urban Widmark <urban@svenskatest.se>
+
+       * dir.c: support case sensitive shares
+       * inode.c: ascii mount options
+       * proc.c: check length of paths to avoid buffer overflow
+       * proc.c: don't do interruptable_sleep in smb_retry to avoid signal
+         problem/race.
+       * proc.c: O_RDONLY & smb_revalidate_inode fix (tail -f)
+       * proc.c: add nls support
+       * sock.c: attempt to fix smb_data_callback (avoid infinite loop)
+
 2000-07-25 Urban Widmark <urban@svenskatest.se>
 
        * proc.c: fix 3 places where bad server responses could cause an Oops.
index 3ea59f6cc178fa3bcd649e44b178644d9e73bb64..825b0156a44165c1714b5c36f8c5eb04470e51a9 100644 (file)
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := smbfs.o
-O_OBJS   := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o 
+O_OBJS   := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o
 M_OBJS   := $(O_TARGET)
 
 # If you want debugging output, you may add these flags to the EXTRA_CFLAGS
index 9598ab82c92938849292874893651273ea5e15f4..b2d5c40998f4dc422b822c5e49f098d909d47617 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/ctype.h>
 
 #include <linux/smb_fs.h>
+#include <linux/smb_mount.h>
 #include <linux/smbno.h>
 
 #include "smb_debug.h"
@@ -142,7 +143,7 @@ out:
 }
 
 /*
- * Note: in order to allow the smbclient process to open the
+ * Note: in order to allow the smbmount process to open the
  * mount point, we don't revalidate if conn_pid is NULL.
  */
 static int
@@ -190,6 +191,13 @@ static struct dentry_operations smbfs_dentry_operations =
        d_delete:       smb_delete_dentry,
 };
 
+static struct dentry_operations smbfs_dentry_operations_case =
+{
+       d_revalidate:   smb_lookup_validate,
+       d_delete:       smb_delete_dentry,
+};
+
+
 /*
  * This is the callback when the dcache has a lookup hit.
  */
@@ -249,8 +257,7 @@ smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
 
        if (a->len != b->len)
                goto out;
-       for (i=0; i < a->len; i++)
-       {
+       for (i=0; i < a->len; i++) {
                if (tolower(a->name[i]) != tolower(b->name[i]))
                        goto out;
        }
@@ -300,6 +307,7 @@ smb_lookup(struct inode *dir, struct dentry *dentry)
        struct smb_fattr finfo;
        struct inode *inode;
        int error;
+       struct smb_sb_info *server;
 
        error = -ENAMETOOLONG;
        if (dentry->d_name.len > SMB_MAXNAMELEN)
@@ -315,15 +323,18 @@ smb_lookup(struct inode *dir, struct dentry *dentry)
        inode = NULL;
        if (error == -ENOENT)
                goto add_entry;
-       if (!error)
-       {
+       if (!error) {
                error = -EACCES;
                finfo.f_ino = smb_invent_inos(1);
                inode = smb_iget(dir->i_sb, &finfo);
-               if (inode)
-               {
+               if (inode) {
        add_entry:
-                       dentry->d_op = &smbfs_dentry_operations;
+                       server = server_from_dentry(dentry);
+                       if (server->mnt->flags & SMB_MOUNT_CASE)
+                               dentry->d_op = &smbfs_dentry_operations_case;
+                       else
+                               dentry->d_op = &smbfs_dentry_operations;
+
                        d_add(dentry, inode);
                        smb_renew_times(dentry);
                        error = 0;
diff --git a/fs/smbfs/getopt.c b/fs/smbfs/getopt.c
new file mode 100644 (file)
index 0000000..0c5d111
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * getopt.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include "getopt.h"
+
+/**
+ *     smb_getopt - option parser
+ *     @caller: name of the caller, for error messages
+ *     @options: the options string
+ *     @opts: an array of &struct option entries controlling parser operations
+ *     @optopt: output; will contain the current option
+ *     @optarg: output; will contain the value (if one exists)
+ *     @flag: output; may be NULL; should point to a long for or'ing flags
+ *     @value: output; may be NULL; will be overwritten with the integer value
+ *             of the current argument.
+ *
+ *     Helper to parse options on the format used by mount ("a=b,c=d,e,f").
+ *     Returns opts->val if a matching entry in the 'opts' array is found,
+ *     0 when no more tokens are found, -1 if an error is encountered.
+ */
+int smb_getopt(char *caller, char **options, struct option *opts,
+              char **optopt, char **optarg, unsigned long *flag,
+              unsigned long *value)
+{
+       char *token;
+       char *val;
+       int i;
+
+       if ( (token = strsep(options, ",")) == NULL)
+               return 0;
+       *optopt = token;
+
+       *optarg = NULL;
+       if ((val = strchr (token, '=')) != NULL) {
+               *val++ = 0;
+               if (value)
+                       *value = simple_strtoul(val, NULL, 0);
+               *optarg = val;
+       }
+
+       for (i = 0; opts[i].name != NULL; i++) {
+               if (!strcmp(opts[i].name, token)) {
+                       if (opts[i].has_arg && (!val || !*val)) {
+                               printk("%s: the %s option requires an argument\n",
+                                      caller, token);
+                               return -1;
+                       }
+
+                       if (flag && opts[i].flag)
+                               *flag |= opts[i].flag;
+
+                       return opts[i].val;
+               }
+       }
+       printk("%s: Unrecognized mount option %s\n", caller, token);
+       return -1;
+}
diff --git a/fs/smbfs/getopt.h b/fs/smbfs/getopt.h
new file mode 100644 (file)
index 0000000..691f211
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _LINUX_GETOPT_H
+#define _LINUX_GETOPT_H
+
+struct option {
+       const char *name;
+       int has_arg;
+       unsigned long flag;
+       int val;
+};
+
+extern int smb_getopt(char *caller, char **options, struct option *opts,
+                     char **optopt, char **optarg, unsigned long *flag,
+                     unsigned long *value);
+
+#endif /* _LINUX_GETOPT_H */
index d7cb992b88471d0a85e9635d07e49081a9b58e49..d26f079ff7e3695f8ceb1bc87c0d479460b09061 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/file.h>
 #include <linux/dcache.h>
 #include <linux/smp_lock.h>
+#include <linux/nls.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
@@ -29,6 +30,7 @@
 #include <asm/uaccess.h>
 
 #include "smb_debug.h"
+#include "getopt.h"
 
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
@@ -282,6 +284,82 @@ smb_delete_inode(struct inode *ino)
        clear_inode(ino);
 }
 
+/* FIXME: flags and has_arg could probably be merged. */
+struct option opts[] = {
+       { "version",    1, 0, 'v' },
+       { "win95",      0, SMB_MOUNT_WIN95, 1 },
+       { "oldattr",    0, SMB_MOUNT_OLDATTR, 1 },
+       { "dirattr",    0, SMB_MOUNT_DIRATTR, 1 },
+       { "case",       0, SMB_MOUNT_CASE, 1 },
+       { "uid",        1, 0, 'u' },
+       { "gid",        1, 0, 'g' },
+       { "file_mode",  1, 0, 'f' },
+       { "dir_mode",   1, 0, 'd' },
+       { "iocharset",  1, 0, 'i' },
+       { "codepage",   1, 0, 'c' },
+       { NULL,         0, 0, 0}
+};
+
+static int
+parse_options(struct smb_mount_data_kernel *mnt, char *options)
+{
+       int c;
+       unsigned long flags;
+       unsigned long value;
+       char *optarg;
+       char *optopt;
+
+       flags = 0;
+       while ( (c = smb_getopt("smbfs", &options, opts,
+                               &optopt, &optarg, &flags, &value)) > 0) {
+
+               VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");
+
+               switch (c) {
+               case 1:
+                       /* got a "flag" option */
+                       break;
+               case 'v':
+                       if (value != SMB_MOUNT_VERSION) {
+                       printk ("smbfs: Bad mount version %ld, expected %d\n",
+                               value, SMB_MOUNT_VERSION);
+                               return 0;
+                       }
+                       mnt->version = value;
+                       break;
+               case 'u':
+                       mnt->uid = value;
+                       break;
+               case 'g':
+                       mnt->gid = value;
+                       break;
+               case 'f':
+                       mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
+                       mnt->file_mode |= S_IFREG;
+                       break;
+               case 'd':
+                       mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
+                       mnt->dir_mode |= S_IFDIR;
+                       break;
+               case 'i':
+                       strncpy(mnt->codepage.local_name, optarg, 
+                               SMB_NLS_MAXNAMELEN);
+                       break;
+               case 'c':
+                       strncpy(mnt->codepage.remote_name, optarg,
+                               SMB_NLS_MAXNAMELEN);
+                       break;
+               default:
+                       printk ("smbfs: Unrecognized mount option %s\n",
+                               optopt);
+                       return -1;
+               }
+       }
+       mnt->flags = flags;
+       return c;
+}
+
+
 static void
 smb_put_super(struct super_block *sb)
 {
@@ -300,18 +378,32 @@ smb_put_super(struct super_block *sb)
        kfree(sb->u.smbfs_sb.temp_buf);
        if (server->packet)
                smb_vfree(server->packet);
+
+       if(sb->u.smbfs_sb.remote_nls) {
+               unload_nls(sb->u.smbfs_sb.remote_nls);
+               sb->u.smbfs_sb.remote_nls = NULL;
+       }
+       if(sb->u.smbfs_sb.local_nls) {
+               unload_nls(sb->u.smbfs_sb.local_nls);
+               sb->u.smbfs_sb.local_nls = NULL;
+       }
 }
 
 struct super_block *
 smb_read_super(struct super_block *sb, void *raw_data, int silent)
 {
-       struct smb_mount_data *mnt;
+       struct smb_mount_data_kernel *mnt;
+       struct smb_mount_data *oldmnt;
        struct inode *root_inode;
        struct smb_fattr root;
+       int ver;
 
        if (!raw_data)
                goto out_no_data;
-       if (((struct smb_mount_data *) raw_data)->version != SMB_MOUNT_VERSION)
+
+       oldmnt = (struct smb_mount_data *) raw_data;
+       ver = oldmnt->version;
+       if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII)
                goto out_wrong_data;
 
        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
@@ -320,6 +412,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        sb->s_flags = 0;
        sb->s_op = &smb_sops;
 
+       sb->u.smbfs_sb.mnt = NULL;
        sb->u.smbfs_sb.sock_file = NULL;
        init_MUTEX(&sb->u.smbfs_sb.sem);
        init_waitqueue_head(&sb->u.smbfs_sb.wait);
@@ -332,30 +425,61 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
                goto out_no_mem;
 
        /* Allocate the global temp buffer */
-       sb->u.smbfs_sb.temp_buf = kmalloc(SMB_MAXPATHLEN + 20, GFP_KERNEL);
+       sb->u.smbfs_sb.temp_buf = kmalloc(2*SMB_MAXPATHLEN + 20, GFP_KERNEL);
        if (!sb->u.smbfs_sb.temp_buf)
                goto out_no_temp;
 
+       /* Setup NLS stuff */
+       sb->u.smbfs_sb.remote_nls = NULL;
+       sb->u.smbfs_sb.local_nls = NULL;
+       sb->u.smbfs_sb.name_buf = sb->u.smbfs_sb.temp_buf + SMB_MAXPATHLEN + 20;
+
        /* Allocate the mount data structure */
-       mnt = kmalloc(sizeof(struct smb_mount_data), GFP_KERNEL);
+       /* FIXME: merge this with the other malloc and get a whole page? */
+       mnt = kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
        if (!mnt)
                goto out_no_mount;
-       *mnt = *((struct smb_mount_data *) raw_data);
-       /* FIXME: passes config flags in high bits of file mode. Should be a
-          separate flags field. (but smbmount includes kernel headers ...) */
-       mnt->version = (mnt->file_mode >> 9);
-       mnt->file_mode &= (S_IRWXU | S_IRWXG | S_IRWXO);
-       mnt->file_mode |= S_IFREG;
-       mnt->dir_mode  &= (S_IRWXU | S_IRWXG | S_IRWXO);
-       mnt->dir_mode  |= S_IFDIR;
        sb->u.smbfs_sb.mnt = mnt;
+
+       memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
+       strncpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
+               SMB_NLS_MAXNAMELEN);
+       strncpy(mnt->codepage.local_name, CONFIG_SMB_NLS_REMOTE,
+               SMB_NLS_MAXNAMELEN);
+
+       if (ver == SMB_MOUNT_OLDVERSION) {
+               mnt->version = oldmnt->version;
+
+               /* FIXME: is this enough to convert uid/gid's ? */
+               mnt->mounted_uid = oldmnt->mounted_uid;
+               mnt->uid = oldmnt->uid;
+               mnt->gid = oldmnt->gid;
+
+               mnt->file_mode =
+                       oldmnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+               mnt->dir_mode =
+                       oldmnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+               mnt->file_mode |= S_IFREG;
+               mnt->dir_mode  |= S_IFDIR;
+
+               mnt->flags = (oldmnt->file_mode >> 9);
+       } else {
+               if (parse_options(mnt, raw_data))
+                       goto out_bad_option;
+
+               mnt->mounted_uid = current->uid;
+       }
+       smb_setcodepage(&sb->u.smbfs_sb, &mnt->codepage);
+       if (!sb->u.smbfs_sb.convert)
+               PARANOIA("convert funcptr was NULL!\n");
+
        /*
         * Display the enabled options
         * Note: smb_proc_getattr uses these in 2.4 (but was changed in 2.2)
         */
-       if (mnt->version & SMB_FIX_OLDATTR)
+       if (mnt->flags & SMB_MOUNT_OLDATTR)
                printk("SMBFS: Using core getattr (Win 95 speedup)\n");
-       else if (mnt->version & SMB_FIX_DIRATTR)
+       else if (mnt->flags & SMB_MOUNT_DIRATTR)
                printk("SMBFS: Using dir ff getattr\n");
 
        /*
@@ -374,16 +498,18 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
 
 out_no_root:
        iput(root_inode);
+out_bad_option:
        kfree(sb->u.smbfs_sb.mnt);
 out_no_mount:
        kfree(sb->u.smbfs_sb.temp_buf);
 out_no_temp:
        smb_vfree(sb->u.smbfs_sb.packet);
 out_no_mem:
-       printk(KERN_ERR "smb_read_super: allocation failure\n");
+       if (!sb->u.smbfs_sb.mnt)
+               printk(KERN_ERR "smb_read_super: allocation failure\n");
        goto out_fail;
 out_wrong_data:
-       printk(KERN_ERR "SMBFS: need mount version %d\n", SMB_MOUNT_VERSION);
+       printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
        goto out_fail;
 out_no_data:
        printk(KERN_ERR "smb_read_super: missing data argument\n");
index e969320b798ada3b507792333497cc28eb22cd61..7863cd2da6201291042d57f28e0fca6b40c0336b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/fcntl.h>
 #include <linux/dcache.h>
 #include <linux/dirent.h>
+#include <linux/nls.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
 
 #include "smb_debug.h"
 
+
 /* Features. Undefine if they cause problems, this should perhaps be a
    config option. */
 #define SMBFS_POSIX_UNLINK 1
 
+/* Allow smb_retry to be interrupted. Not sure of the benefit ... */
+/* #define SMB_RETRY_INTR */
+
 #define SMB_VWV(packet)  ((packet) + SMB_HEADER_LEN)
 #define SMB_CMD(packet)  (*(packet+8))
 #define SMB_WCT(packet)  (*(packet+SMB_HEADER_LEN - 1))
@@ -48,6 +53,20 @@ static int
 smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir,
                    struct smb_fattr *fattr);
 
+
+static inline void
+smb_lock_server(struct smb_sb_info *server)
+{
+       down(&(server->sem));
+}
+
+static inline void
+smb_unlock_server(struct smb_sb_info *server)
+{
+       up(&(server->sem));
+}
+
+
 static void
 str_upper(char *name, int len)
 {
@@ -83,6 +102,96 @@ static void reverse_string(char *buf, int len)
        }
 }
 
+/* no conversion, just a wrapper for memcpy. */
+static int convert_memcpy(char *output, int olen,
+                         const char *input, int ilen,
+                         struct nls_table *nls_from,
+                         struct nls_table *nls_to)
+{
+       memcpy(output, input, ilen);
+       return ilen;
+}
+
+/* convert from one "codepage" to another (possibly being utf8). */
+static int convert_cp(char *output, int olen,
+                     const char *input, int ilen,
+                     struct nls_table *nls_from,
+                     struct nls_table *nls_to)
+{
+       int len = 0;
+       int n;
+       wchar_t ch;
+
+       if (!nls_from || !nls_to) {
+               PARANOIA("nls_from=%p, nls_to=%p\n", nls_from, nls_to);
+               return convert_memcpy(output, olen, input, ilen, NULL, NULL);
+       }
+
+       while (ilen > 0) {
+               /* convert by changing to unicode and back to the new cp */
+               n = nls_from->char2uni((unsigned char *)input, ilen, &ch);
+               if (n < 0)
+                       goto out;
+               input += n;
+               ilen -= n;
+
+               n = nls_to->uni2char(ch, output, olen);
+               if (n < 0)
+                       goto out;
+               output += n;
+               olen -= n;
+
+               len += n;
+       }
+out:
+       return len;
+}
+
+static int setcodepage(struct smb_sb_info *server,
+                      struct nls_table **p, char *name)
+{
+       struct nls_table *nls;
+
+       if (!name || !*name) {
+               nls = NULL;
+       } else if ( (nls = load_nls(name)) == NULL) {
+               printk (KERN_ERR "smbfs: failed to load nls '%s'\n", name);
+               return -EINVAL;
+       }
+
+       /* if already set, unload the previous one. */
+       if (*p)
+               unload_nls(*p);
+       *p = nls;
+
+       return 0;
+}
+
+/* Handles all changes to codepage settings. */
+int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp)
+{
+       int n;
+
+       smb_lock_server(server);
+
+       n = setcodepage(server, &server->local_nls, cp->local_name);
+       if (n != 0)
+               goto out;
+       n = setcodepage(server, &server->remote_nls, cp->remote_name);
+       if (n != 0)
+               setcodepage(server, &server->local_nls, NULL);
+
+out:
+       if (server->local_nls != NULL && server->remote_nls != NULL)
+               server->convert = convert_cp;
+       else
+               server->convert = convert_memcpy;
+
+       smb_unlock_server(server);
+       return n;
+}
+
+
 /*****************************************************************************/
 /*                                                                           */
 /*  Encoding/Decoding section                                                */
@@ -107,9 +216,11 @@ smb_encode_smb_length(__u8 * p, __u32 len)
  * smb_build_path: build the path to entry and name storing it in buf.
  * The path returned will have the trailing '\0'.
  */
-static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf)
+static int smb_build_path(struct smb_sb_info *server, char * buf,
+                         struct dentry * entry, struct qstr * name)
 {
        char *path = buf;
+       int len;
 
        if (entry == NULL)
                goto test_name_and_out;
@@ -129,9 +240,16 @@ static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf)
         * and store it in reversed order [see reverse_string()]
         */
        for (;;) {
-               memcpy(path, entry->d_name.name, entry->d_name.len);
-               reverse_string(path, entry->d_name.len);
-               path += entry->d_name.len;
+               if (entry->d_name.len > SMB_MAXNAMELEN)
+                       return -ENAMETOOLONG;
+               if (path - buf + entry->d_name.len > SMB_MAXPATHLEN)
+                       return -ENAMETOOLONG;
+
+               len = server->convert(path, SMB_MAXNAMELEN, 
+                                     entry->d_name.name, entry->d_name.len,
+                                     server->local_nls, server->remote_nls);
+               reverse_string(path, len);
+               path += len;
 
                *(path++) = '\\';
 
@@ -147,25 +265,28 @@ test_name_and_out:
        if (name != NULL) {
                *(path++) = '\\';
 name_and_out:
-               memcpy(path, name->name, name->len);
-               path += name->len;
+               len = server->convert(path, SMB_MAXNAMELEN, 
+                                     name->name, name->len,
+                                     server->local_nls, server->remote_nls);
+               path += len;
        }
 out:
        *(path++) = '\0';
        return (path-buf);
 }
 
-static char *smb_encode_path(struct smb_sb_info *server, char *buf,
-                            struct dentry *dir, struct qstr *name)
+static int smb_encode_path(struct smb_sb_info *server, char *buf,
+                          struct dentry *dir, struct qstr *name)
 {
-       char *start = buf;
-
-       buf += smb_build_path(dir, name, buf);
+       int result;
 
+       result = smb_build_path(server, buf, dir, name);
+       if (result < 0)
+               goto out;
        if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
-               str_upper(start, buf - start);
-
-       return buf;
+               str_upper(buf, result);
+out:
+       return result;
 }
 
 /* The following are taken directly from msdos-fs */
@@ -464,18 +585,6 @@ err_unknown:
        return EIO;
 }
 
-static inline void
-smb_lock_server(struct smb_sb_info *server)
-{
-       down(&(server->sem));
-}
-
-static inline void
-smb_unlock_server(struct smb_sb_info *server)
-{
-       up(&(server->sem));
-}
-
 /*
  * smb_retry: This function should be called when smb_request_ok has
  * indicated an error. If the error was indicated because the
@@ -495,8 +604,7 @@ smb_retry(struct smb_sb_info *server)
 
        smb_close_socket(server);
 
-       if (pid == 0)
-       {
+       if (pid == 0) {
                printk(KERN_ERR "smb_retry: no connection process\n");
                server->state = CONN_RETRIED;
                goto out;
@@ -511,26 +619,35 @@ smb_retry(struct smb_sb_info *server)
         * Note: use the "priv" flag, as a user process may need to reconnect.
         */
        error = kill_proc(pid, SIGUSR1, 1);
-       if (error)
-       {
+       if (error) {
                printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
                goto out_restore;
        }
-       VERBOSE("signalled pid %d, waiting for new connection\n",
-               server->conn_pid);
+       VERBOSE("signalled pid %d, waiting for new connection\n", pid);
 
        /*
         * Wait for the new connection.
         */
+#ifdef SMB_RETRY_INTR
        interruptible_sleep_on_timeout(&server->wait,  5*HZ);
        if (signal_pending(current))
                printk(KERN_INFO "smb_retry: caught signal\n");
+#else
+       /*
+        * We don't want to be interrupted. For example, what if 'current'
+        * already has recieved a signal? sleep_on would terminate immediately
+        * and smbmount would not be able to re-establish connection.
+        *
+        * smbmount should be able to reconnect later, but it can't because
+        * it will get an -EIO on attempts to open the mountpoint!
+        */
+       sleep_on_timeout(&server->wait, 5*HZ);
+#endif
 
        /*
         * Check for a valid connection.
         */
-       if (server->state == CONN_VALID)
-       {
+       if (server->state == CONN_VALID) {
                /* This should be changed to VERBOSE, except many smbfs
                   problems is with the userspace daemon not reconnecting. */
                PARANOIA("sucessful, new pid=%d, generation=%d\n",
@@ -656,7 +773,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
        if (server->opt.protocol == SMB_PROTOCOL_NT1 &&
            (server->opt.max_xmit < 0x1000) &&
            !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
-               server->mnt->version |= SMB_FIX_WIN95;
+               server->mnt->flags |= SMB_MOUNT_WIN95;
 #ifdef SMBFS_DEBUG_VERBOSE
                printk(KERN_NOTICE "smb_newconn: detected WIN95 server\n");
 #endif
@@ -667,7 +784,11 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
                server->opt.capabilities);
 
 out:
+#ifdef SMB_RETRY_INTR
        wake_up_interruptible(&server->wait);
+#else
+       wake_up(&server->wait);
+#endif
        return error;
 
 out_putf:
@@ -738,7 +859,7 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
 {
        struct inode *ino = dentry->d_inode;
        int mode, read_write = 0x42, read_only = 0x40;
-       int error;
+       int res;
        char *p;
 
        /*
@@ -748,6 +869,9 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
        if (!(ino->i_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
                mode = read_only;
 #if 0
+       /* FIXME: why is this code not in? below we fix it so that a caller
+          wanting RO doesn't get RW. smb_revalidate_inode does some 
+          optimization based on access mode. tail -f needs it to be correct. */
        if (!(wish & (O_WRONLY | O_RDWR)))
                mode = read_only;
 #endif
@@ -757,20 +881,23 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
        WSET(server->packet, smb_vwv0, mode);
        WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
        *p++ = 4;
-       p = smb_encode_path(server, p, dentry, NULL);
+       res = smb_encode_path(server, p, dentry, NULL);
+       if (res < 0)
+               goto out;
+       p += res;
+
        smb_setup_bcc(server, p);
 
-       error = smb_request_ok(server, SMBopen, 7, 0);
-       if (error != 0)
-       {
+       res = smb_request_ok(server, SMBopen, 7, 0);
+       if (res != 0) {
                if (smb_retry(server))
                        goto retry;
 
                if (mode == read_write &&
-                   (error == -EACCES || error == -ETXTBSY || error == -EROFS))
+                   (res == -EACCES || res == -ETXTBSY || res == -EROFS))
                {
                        VERBOSE("%s/%s R/W failed, error=%d, retrying R/O\n",
-                               DENTRY_PATH(dentry), error);
+                               DENTRY_PATH(dentry), res);
                        mode = read_only;
                        goto retry;
                }
@@ -783,10 +910,12 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
        /* smb_vwv2 has mtime */
        /* smb_vwv4 has size  */
        ino->u.smbfs_i.access = (WVAL(server->packet, smb_vwv6) & SMB_ACCMASK);
+       if (!(wish & (O_WRONLY | O_RDWR)))
+               ino->u.smbfs_i.access = SMB_O_RDONLY;
        ino->u.smbfs_i.open = server->generation;
 
 out:
-       return error;
+       return res;
 }
 
 /*
@@ -1025,7 +1154,7 @@ smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
 {
        struct smb_sb_info *server = server_from_dentry(dentry);
        char *p;
-       int error;
+       int result;
 
        smb_lock_server(server);
 
@@ -1034,22 +1163,24 @@ smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
        WSET(server->packet, smb_vwv0, attr);
        DSET(server->packet, smb_vwv1, utc2local(server, ctime));
        *p++ = 4;
-       p = smb_encode_path(server, p, dentry, NULL);
+       result = smb_encode_path(server, p, dentry, NULL);
+       if (result < 0)
+               goto out;
+       p += result;
        smb_setup_bcc(server, p);
 
-       error = smb_request_ok(server, SMBcreate, 1, 0);
-       if (error < 0)
-       {
+       result = smb_request_ok(server, SMBcreate, 1, 0);
+       if (result < 0) {
                if (smb_retry(server))
                        goto retry;
                goto out;
        }
        *fileid = WVAL(server->packet, smb_vwv0);
-       error = 0;
+       result = 0;
 
 out:
        smb_unlock_server(server);
-       return error;
+       return result;
 }
 
 int
@@ -1064,14 +1195,22 @@ smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry)
       retry:
        p = smb_setup_header(server, SMBmv, 1, 0);
        WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
+
        *p++ = 4;
-       p = smb_encode_path(server, p, old_dentry, NULL);
+       result = smb_encode_path(server, p, old_dentry, NULL);
+       if (result < 0)
+               goto out;
+       p += result;
+
        *p++ = 4;
-       p = smb_encode_path(server, p, new_dentry, NULL);
+       result = smb_encode_path(server, p, new_dentry, NULL);
+       if (result < 0)
+               goto out;
+       p += result;
+
        smb_setup_bcc(server, p);
 
-       if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0)
-       {
+       if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) {
                if (smb_retry(server))
                        goto retry;
                goto out;
@@ -1097,12 +1236,14 @@ smb_proc_generic_command(struct dentry *dentry, __u8 command)
       retry:
        p = smb_setup_header(server, command, 0, 0);
        *p++ = 4;
-       p = smb_encode_path(server, p, dentry, NULL);
+       result = smb_encode_path(server, p, dentry, NULL);
+       if (result < 0)
+               goto out;
+       p += result;
        smb_setup_bcc(server, p);
 
        result = smb_request_ok(server, command, 0, 0);
-       if (result < 0)
-       {
+       if (result < 0) {
                if (smb_retry(server))
                        goto retry;
                goto out;
@@ -1165,11 +1306,13 @@ smb_proc_unlink(struct dentry *dentry)
        p = smb_setup_header(server, SMBunlink, 1, 0);
        WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
        *p++ = 4;
-       p = smb_encode_path(server, p, dentry, NULL);
+       result = smb_encode_path(server, p, dentry, NULL);
+       if (result < 0)
+               goto out;
+       p += result;
        smb_setup_bcc(server, p);
 
-       if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0)
-       {
+       if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) {
 #if SMBFS_POSIX_UNLINK
                if (result == -EACCES && !flag) {
                        /* Posix semantics is for the read-only state
@@ -1220,8 +1363,7 @@ smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length)
        *p++ = 0;
        smb_setup_bcc(server, p);
 
-       if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0)
-       {
+       if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) {
                if (smb_retry(server))
                        goto retry;
                goto out;
@@ -1306,6 +1448,8 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p,
                len--;
        entry->len = len;
 
+       /* FIXME: These only work for ascii chars, and recent smbmount doesn't
+          allow the flag to be set anyway. Remove? */
        switch (server->opt.case_handling) {
        case SMB_CASE_UPPER:
                str_upper(entry->name, len);
@@ -1316,7 +1460,13 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p,
        default:
                break;
        }
-       DEBUG1("len=%d, name=%.*s\n", len, len, entry->name);
+
+       entry->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
+                                    entry->name, len,
+                                    server->remote_nls, server->local_nls);
+       entry->name = server->name_buf;
+
+       DEBUG1("len=%d, name=%.*s\n", entry->len, entry->len, entry->name);
        return p + 22;
 }
 
@@ -1355,7 +1505,10 @@ retry:
                WSET(server->packet, smb_vwv1, aDIR);
                *p++ = 4;
                if (first == 1) {
-                       p = smb_encode_path(server, p, dir, &mask);
+                       result = smb_encode_path(server, p, dir, &mask);
+                       if (result < 0)
+                               goto unlock_return;
+                       p += result;
                        *p++ = 5;
                        WSET(p, 0, 0);
                        p += 2;
@@ -1467,12 +1620,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
        switch (level) {
        case 1:
                len = *((unsigned char *) p + 22);
-               entry->len = len;
                entry->name = p + 23;
                result = p + 24 + len;
 
                VERBOSE("info 1 at %p, len=%d, name=%.*s\n",
-                       p, entry->len, entry->len, entry->name);
+                       p, len, len, entry->name);
                break;
        case 260:
                result = p + WVAL(p, 0);
@@ -1482,14 +1634,14 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
                entry->name = p + 94;
                if (len && entry->name[len-1] == '\0')
                        len--;
-               entry->len = len;
 
                VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
-                       p, entry->len, entry->len, entry->name);
+                       p, len, len, entry->name);
                break;
        default:
                PARANOIA("Unknown info level %d\n", level);
                result = p + WVAL(p, 0);
+               goto out;
        }
 
        switch (server->opt.case_handling) {
@@ -1503,6 +1655,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
                break;
        }
 
+       entry->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
+                                    entry->name, len,
+                                    server->remote_nls, server->local_nls);
+       entry->name = server->name_buf;
+out:
        return result;
 }
 
@@ -1561,7 +1718,12 @@ retry:
         * Encode the initial path
         */
        mask = param + 12;
-       mask_len = smb_encode_path(server, mask, dir, &star) - mask;
+
+       mask_len = smb_encode_path(server, mask, dir, &star);
+       if (mask_len < 0) {
+               entries = mask_len;
+               goto unlock_return;
+       }
        first = 1;
        VERBOSE("starting fpos=%d, mask=%s\n", fpos, mask);
 
@@ -1753,7 +1915,11 @@ smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
        int mask_len, result;
 
 retry:
-       mask_len = smb_encode_path(server, mask, dentry, NULL) - mask;
+       mask_len = smb_encode_path(server, mask, dentry, NULL);
+       if (mask_len < 0) {
+               result = mask_len;
+               goto out;
+       }
        VERBOSE("name=%s, len=%d\n", mask, mask_len);
        WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
        WSET(param, 2, 1);      /* max count */
@@ -1828,7 +1994,10 @@ smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
       retry:
        p = smb_setup_header(server, SMBgetatr, 0, 0);
        *p++ = 4;
-       p = smb_encode_path(server, p, dir, NULL);
+       result = smb_encode_path(server, p, dir, NULL);
+       if (result < 0)
+               goto out;
+       p += result;
        smb_setup_bcc(server, p);
 
        if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
@@ -1874,7 +2043,10 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
       retry:
        WSET(param, 0, 1);      /* Info level SMB_INFO_STANDARD */
        DSET(param, 2, 0);
-       p = smb_encode_path(server, param + 6, dir, NULL);
+       result = smb_encode_path(server, param + 6, dir, NULL);
+       if (result < 0)
+               goto out;
+       p = param + 6 + result;
 
        result = smb_trans2_request(server, TRANSACT2_QPATHINFO,
                                    0, NULL, p - param, param,
@@ -1905,7 +2077,7 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
         * Kludge alert: Win 95 swaps the date and time field,
         * contrary to the CIFS docs and Win NT practice.
         */
-       if (server->mnt->version & SMB_FIX_WIN95) {
+       if (server->mnt->flags & SMB_MOUNT_WIN95) {
                off_date = 2;
                off_time = 0;
        }
@@ -1945,21 +2117,16 @@ smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir,
 
        /*
         * Select whether to use core or trans2 getattr.
+        * Win 95 appears to break with the trans2 getattr.
         */
-       if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) {
-               /*
-                * Win 95 appears to break with the trans2 getattr.
-                * Note: mnt->version options are set at mount time (inode.c)
-                */
-               if (server->mnt->version & (SMB_FIX_OLDATTR|SMB_FIX_WIN95))
-                       goto core_attr;
-               if (server->mnt->version & SMB_FIX_DIRATTR)
+       if (server->opt.protocol < SMB_PROTOCOL_LANMAN2 ||
+           (server->mnt->flags & (SMB_MOUNT_OLDATTR|SMB_MOUNT_WIN95)) ) {
+               result = smb_proc_getattr_core(server, dir, fattr);
+       } else {
+               if (server->mnt->flags & SMB_MOUNT_DIRATTR)
                        result = smb_proc_getattr_ff(server, dir, fattr);
                else
                        result = smb_proc_getattr_trans2(server, dir, fattr);
-       } else {
-       core_attr:
-               result = smb_proc_getattr_core(server, dir, fattr);
        }
 
        smb_finish_dirent(server, fattr);
@@ -2008,14 +2175,16 @@ smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
        WSET(server->packet, smb_vwv6, 0);
        WSET(server->packet, smb_vwv7, 0);
        *p++ = 4;
-       p = smb_encode_path(server, p, dentry, NULL);
+       result = smb_encode_path(server, p, dentry, NULL);
+       if (result < 0)
+               goto out;
+       p += result;
        *p++ = 4;
        *p++ = 0;
        smb_setup_bcc(server, p);
 
        result = smb_request_ok(server, SMBsetatr, 0, 0);
-       if (result < 0)
-       {
+       if (result < 0) {
                if (smb_retry(server))
                        goto retry;
                goto out;
@@ -2073,8 +2242,7 @@ smb_proc_setattr_ext(struct smb_sb_info *server,
 #endif
 
        result = smb_request_ok(server, SMBsetattrE, 0, 0);
-       if (result < 0)
-       {
+       if (result < 0) {
                if (smb_retry(server))
                        goto retry;
                goto out;
@@ -2107,7 +2275,10 @@ smb_proc_setattr_trans2(struct smb_sb_info *server,
       retry:
        WSET(param, 0, 1);      /* Info level SMB_INFO_STANDARD */
        DSET(param, 2, 0);
-       p = smb_encode_path(server, param + 6, dir, NULL);
+       result = smb_encode_path(server, param + 6, dir, NULL);
+       if (result < 0)
+               goto out;
+       p = param + 6 + result;
 
        WSET(data, 0, 0); /* creation time */
        WSET(data, 2, 0);
@@ -2170,8 +2341,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
        smb_lock_server(server);
        /* setting the time on a Win95 server fails (tridge) */
        if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 && 
-           !(server->mnt->version & SMB_FIX_WIN95))
-       {
+           !(server->mnt->flags & SMB_MOUNT_WIN95)) {
                if (smb_is_open(inode) &&
                    inode->u.smbfs_i.access != SMB_O_RDONLY)
                        result = smb_proc_setattr_ext(server, inode, fattr);
@@ -2182,8 +2352,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
                 * Fail silently on directories ... timestamp can't be set?
                 */
                result = 0;
-               if (S_ISREG(inode->i_mode))
-               {
+               if (S_ISREG(inode->i_mode)) {
                        /*
                         * Set the mtime by opening and closing the file.
                         * Note that the file is opened read-only, but this
@@ -2192,8 +2361,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
                        result = -EACCES;
                        if (!smb_is_open(inode))
                                smb_proc_open(server, dentry, SMB_O_RDONLY);
-                       if (smb_is_open(inode))
-                       {
+                       if (smb_is_open(inode)) {
                                inode->i_mtime = fattr->f_mtime;
                                result = smb_proc_close_inode(server, inode);
                        }
@@ -2208,7 +2376,7 @@ int
 smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
 {
        struct smb_sb_info *server = &(sb->u.smbfs_sb);
-       int error;
+       int result;
        char *p;
 
        smb_lock_server(server);
@@ -2216,8 +2384,7 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
       retry:
        smb_setup_header(server, SMBdskattr, 0, 0);
 
-       if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0)
-       {
+       if ((result = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) {
                if (smb_retry(server))
                        goto retry;
                goto out;
@@ -2226,11 +2393,11 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
        attr->f_blocks = WVAL(p, 0);
        attr->f_bsize  = WVAL(p, 2) * WVAL(p, 4);
        attr->f_bavail = attr->f_bfree = WVAL(p, 6);
-       error = 0;
+       result = 0;
 
 out:
        smb_unlock_server(server);
-       return error;
+       return result;
 }
 
 int
index 0c52bf8712f4a942fc1d92cf7d2b9c2cbb0ee8ca..01ae6ec8786c66cb9ec9a640a2de85839fdb2a48 100644 (file)
@@ -111,12 +111,16 @@ smb_data_callback(void* ptr)
        unsigned char peek_buf[4];
        int result;
        mm_segment_t fs;
+       int count = 100;   /* this is a lot, we should have some data waiting */
+       int found = 0;
 
        fs = get_fs();
        set_fs(get_ds());
 
        lock_kernel();
-       while (1) {
+       while (count-- > 0) {
+               peek_buf[0] = 0;
+
                result = -EIO;
                if (job->sk->dead) {
                        PARANOIA("sock dead!\n");
@@ -125,7 +129,7 @@ smb_data_callback(void* ptr)
 
                result = _recvfrom(socket, (void *) peek_buf, 1,
                                   MSG_PEEK | MSG_DONTWAIT);
-               if (result == -EAGAIN)
+               if (result < 0)
                        break;
                if (peek_buf[0] != 0x85)
                        break;
@@ -136,13 +140,15 @@ smb_data_callback(void* ptr)
 
                DEBUG1("got SESSION KEEPALIVE\n");
 
-               if (result == -EAGAIN)
+               if (result < 0)
                        break;
+               found = 1;
        }
        unlock_kernel();
        set_fs(fs);
 
-       if (result != -EAGAIN)
+       DEBUG1("found=%d, count=%d, result=%d\n", found, count, result);
+       if (found)
                found_data(job->sk);
        kfree(ptr);
 }
index 7a922e991ad414765376dfba4002a2a4390109a4..61997a1b21a0a0ef5c8b54565b081bc19e683846 100644 (file)
@@ -10,6 +10,7 @@
  *   11-01-1998        RMK     Added mask_and_ack_irq
  *   22-08-1998        RMK     Restructured IRQ routines
  */
+#include <linux/config.h>
 #include <asm/ioc.h>
 
 #ifdef CONFIG_ARCH_ARC
index d80ddd13f5ad7209780e784a470cfa01eb9d004b..0caf739d66bb9631654302d7c418b935723f2f1b 100644 (file)
@@ -3,7 +3,6 @@
  *
  * Copyright (c) 1996-1999 Russell King and Dave Gilbert
  */
-#include <linux/config.h>
 
 static void arch_idle(void)
 {
index 2debbf0849658ffee4562d67d21d6eaffb08584f..8562fc287d1c618ae37c32a754541b45cda13142 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.101 2000/08/09 00:00:17 davem Exp $ */
+/* $Id: pgtable.h,v 1.102 2000/08/14 00:46:13 anton Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -201,11 +201,9 @@ extern unsigned long empty_zero_page;
 
 #define SIZEOF_PTR_LOG2   2
 
-BTFIXUPDEF_CALL_CONST(unsigned long, sparc_pte_pagenr, pte_t)
 BTFIXUPDEF_CALL_CONST(unsigned long, pmd_page, pmd_t)
 BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page, pgd_t)
 
-#define sparc_pte_pagenr(pte) BTFIXUP_CALL(sparc_pte_pagenr)(pte)
 #define pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd)
 #define pgd_page(pgd) BTFIXUP_CALL(pgd_page)(pgd)
 
@@ -305,7 +303,9 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t)
 
 /* Permanent address of a page. */
 #define page_address(page)  ((page)->virtual)
-#define pte_page(x) (mem_map+sparc_pte_pagenr(x))
+
+BTFIXUPDEF_CALL(struct page *, pte_page, pte_t)
+#define pte_page(pte) BTFIXUP_CALL(pte_page)(pte)
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
index 0b3df22b9b7fc7b28e8f6f4498413d68b341e69c..84b0f03f550607ec360981b9422e3dd2372da433 100644 (file)
@@ -16,7 +16,7 @@
  * Define this to use the verbose/debugging versions in
  * arch/sparc/lib/debuglocks.c
  *
- * Be sure to make check_asm whenever changing this option.
+ * Be sure to make dep whenever changing this option.
  */
 #define SPIN_LOCK_DEBUG
 
@@ -28,7 +28,7 @@ struct _spinlock_debug {
 typedef struct _spinlock_debug spinlock_t;
 
 #define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0, 0 }
-#define spin_lock_init(lp)     do { (lp)->owner_pc = 0; (lp)->lock = 0; } while(0)
+#define spin_lock_init(lp)     do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
 #define spin_is_locked(lp)  (*((volatile unsigned char *)(&((lp)->lock))) != 0)
 #define spin_unlock_wait(lp)   do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
 
@@ -49,6 +49,8 @@ typedef struct _rwlock_debug rwlock_t;
 
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, {0} }
 
+#define rwlock_init(lp)        do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
+
 extern void _do_read_lock(rwlock_t *rw, char *str);
 extern void _do_read_unlock(rwlock_t *rw, char *str);
 extern void _do_write_lock(rwlock_t *rw, char *str);
@@ -144,6 +146,9 @@ typedef struct { volatile unsigned int lock; } rwlock_t;
 
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
 
+#define rwlock_init(lp)        do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
+
+
 /* Sort of like atomic_t's on Sparc, but even more clever.
  *
  *     ------------------------------------
index 6dc3569429a274c39377edf606c1c110d08001da..741949c5e4e2abd8f0ef9654fcb39c64c79ed800 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.68 2000/08/12 20:49:49 jj Exp $ */
+/* $Id: unistd.h,v 1.70 2000/08/14 05:39:07 jj Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
 /* #define __NR_putmsg          152    SunOS Specific                              */
 #define __NR_poll               153 /* Common                                      */
 #define __NR_getdents64                154 /* Linux specific                              */
-#define __NR_fstat64           155 /* Linux sparc32 Specific                      */
+#define __NR_fcntl64           155 /* Linux sparc32 Specific                      */
 /* #define __NR_getdirentries   156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
 #define __NR_fstatfs            158 /* Common                                      */
index ea34fbefe733965a91cf6ec1e1a56748bf539816..a6f5aa9ae7f428fd019d488dae0bdb16524975b0 100644 (file)
@@ -109,6 +109,7 @@ extern int _spin_trylock (spinlock_t *lock);
 
 typedef unsigned int rwlock_t;
 #define RW_LOCK_UNLOCKED       0
+#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
 
 extern void __read_lock(rwlock_t *);
 extern void __read_unlock(rwlock_t *);
@@ -128,6 +129,7 @@ typedef struct {
        unsigned int reader_pc[4];
 } rwlock_t;
 #define RW_LOCK_UNLOCKED       (rwlock_t) { 0, 0, 0xff, { 0, 0, 0, 0 } }
+#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
 
 extern void _do_read_lock(rwlock_t *rw, char *str);
 extern void _do_read_unlock(rwlock_t *rw, char *str);
index e66e4abd6f98e7057f13ef65466884d948880950..f89c5d50a196105aebe5bb9b468c0953a282e2e1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.46 2000/08/12 20:49:49 jj Exp $ */
+/* $Id: unistd.h,v 1.47 2000/08/14 05:39:07 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
 /* #define __NR_putmsg          152    SunOS Specific                              */
 #define __NR_poll               153 /* Common                                      */
 #define __NR_getdents64                154 /* Linux specific                              */
-/* #define __NR_fstat64         155    Linux sparc32 Specific                      */
+/* #define __NR_fcntl64         155    Linux sparc32 Specific                      */
 /* #define __NR_getdirentries   156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
 #define __NR_fstatfs            158 /* Common                                      */
index 852d5b0dd89cb915527462dc917ab80e1c5265fe..1382db0dce85c5866dc0b7fa3f6b4061b3e38a19 100644 (file)
@@ -62,6 +62,13 @@ struct smb_conn_opt {
 
 #ifdef __KERNEL__
 
+#define SMB_NLS_MAXNAMELEN 20
+struct smb_nls_codepage {
+       char local_name[SMB_NLS_MAXNAMELEN];
+       char remote_name[SMB_NLS_MAXNAMELEN];
+};
+
+
 #define SMB_MAXNAMELEN 255
 #define SMB_MAXPATHLEN 1024
 
index 375ff311222db8934ac6d7de3b8e562a3ae91812..e475057fc1340f6ab579b330cc7e1a2e477e503c 100644 (file)
@@ -73,13 +73,6 @@ smb_vfree(void *obj)
 #define SMB_F_CACHEVALID       0x01    /* directory cache valid */
 #define SMB_F_LOCALWRITE       0x02    /* file modified locally */
 
-/*
- * Bug fix flags
- */
-#define SMB_FIX_WIN95  0x0001  /* Win 95 server */
-#define SMB_FIX_OLDATTR        0x0002  /* Use core getattr (Win 95 speedup) */
-#define SMB_FIX_DIRATTR        0x0004  /* Use find_first for getattr */
-
 
 /* NT1 protocol capability bits */
 #define SMB_CAP_RAW_MODE         0x0001
@@ -122,6 +115,7 @@ unsigned long smb_invent_inos(unsigned long);
 struct inode *smb_iget(struct super_block *, struct smb_fattr *);
 
 /* linux/fs/smbfs/proc.c */
+int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
 __u32 smb_len(unsigned char *);
 __u8 *smb_encode_smb_length(__u8 *, __u32);
 __u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16);
index 31052af1f5e6b448d4f2d85946c56a58403d722f..4bad7e9280096e33695813e3a203167f32d2099a 100644 (file)
@@ -23,7 +23,7 @@ struct smb_sb_info {
         enum smb_conn_state state;
        struct file * sock_file;
 
-        struct smb_mount_data *mnt;
+        struct smb_mount_data_kernel *mnt;
         unsigned char *temp_buf;
 
        /* Connections are counted. Each time a new socket arrives,
@@ -41,8 +41,20 @@ struct smb_sb_info {
         unsigned short     rcls; /* The error codes we received */
         unsigned short     err;
 
-        /* We use our on data_ready callback, but need the original one */
+        /* We use our own data_ready callback, but need the original one */
         void *data_ready;
+
+       /* nls pointers for codepage conversions */
+       struct nls_table *remote_nls;
+       struct nls_table *local_nls;
+
+       /* utf8 can make strings longer so we can't do in-place conversion.
+          This is a buffer for temporary stuff. We only need one so no need
+          to put it on the stack. This points to temp_buf space. */
+       char *name_buf;
+
+       int (*convert)(char *, int, const char *, int,
+                      struct nls_table *, struct nls_table *);
 };
 
 #endif /* __KERNEL__ */
index 886d945d5fe0a4bd1b5fbbd3bd1c1bdcc727f061..ea240db51acbfd43a81db251a8a01af4dd430946 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <linux/types.h>
 
-#define SMB_MOUNT_VERSION 6
+#define SMB_MOUNT_VERSION      6
 
 struct smb_mount_data {
        int version;
@@ -22,4 +22,37 @@ struct smb_mount_data {
        __kernel_mode_t dir_mode;
 };
 
+
+#ifdef __KERNEL__
+
+/* "vers" in big-endian */
+#define SMB_MOUNT_ASCII 0x76657273
+
+#define SMB_MOUNT_OLDVERSION   6
+#undef SMB_MOUNT_VERSION
+#define SMB_MOUNT_VERSION      7
+
+/* flags */
+#define SMB_MOUNT_WIN95                0x0001  /* Win 95 server */
+#define SMB_MOUNT_OLDATTR      0x0002  /* Use core getattr (Win 95 speedup) */
+#define SMB_MOUNT_DIRATTR      0x0004  /* Use find_first for getattr */
+#define SMB_MOUNT_CASE         0x0008  /* Be case sensitive */
+
+
+struct smb_mount_data_kernel {
+       int version;
+
+       __kernel_uid_t mounted_uid;     /* Who may umount() this filesystem? */
+       __kernel_uid_t uid;
+       __kernel_gid_t gid;
+       __kernel_mode_t file_mode;
+       __kernel_mode_t dir_mode;
+
+       u32 flags;
+
+       struct smb_nls_codepage codepage;
+};
+
+#endif
+
 #endif
index bcc6d2e31014e2249311dae079e7bcb0b8d6561b..660d492f68ce9615c7f2bfa38cc40323957d0507 100644 (file)
@@ -527,6 +527,7 @@ EXPORT_SYMBOL(get_fast_time);
 /* library functions */
 EXPORT_SYMBOL(strnicmp);
 EXPORT_SYMBOL(strspn);
+EXPORT_SYMBOL(strsep);
 
 /* software interrupts */
 EXPORT_SYMBOL(tasklet_hi_vec);
index 58f642b301e2863e547afddf14a8ae164c720e56..54b66fbd78e87f4d4fa20e8d4f1354c136e7bdf3 100644 (file)
@@ -414,7 +414,7 @@ static int writeout_one_page(struct page *page)
                if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh))
                        continue;
 
-               bh->b_flushtime = 0;
+               bh->b_flushtime = jiffies;
                ll_rw_block(WRITE, 1, &bh);     
        } while ((bh = bh->b_this_page) != head);
        return 0;
index 6208e347dfc5bb410b2eaca03e0ac561d0f4a858..3be601c6f266cbbcc2edfc503c3fb0f6b2ff4267 100644 (file)
@@ -339,7 +339,7 @@ repeat_page:
        bh->b_count = bh_orig->b_count;
        bh->b_rdev = bh_orig->b_rdev;
        bh->b_state = bh_orig->b_state;
-       bh->b_flushtime = 0;
+       bh->b_flushtime = jiffies;
        bh->b_next_free = NULL;
        bh->b_prev_free = NULL;
        /* bh->b_this_page */
index fe78e71f1c85620ca45e4484f9a7aaa84a604786..8968a8d7245512b34a3ebbab12d1bf1abe9c84fd 100644 (file)
@@ -359,6 +359,7 @@ EXPORT_SYMBOL(tcp_sockets_allocated);
 EXPORT_SYMBOL(sysctl_tcp_reordering);
 EXPORT_SYMBOL(sysctl_tcp_rmem);
 EXPORT_SYMBOL(sysctl_tcp_wmem);
+EXPORT_SYMBOL(sysctl_tcp_ecn);
 EXPORT_SYMBOL(tcp_cwnd_application_limited);
 
 EXPORT_SYMBOL(xrlim_allow);