Commit 4f8db550 authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.4.0-test7-pre5

    - 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
parent 369c1bc4
...@@ -11305,6 +11305,21 @@ CONFIG_SMB_FS ...@@ -11305,6 +11305,21 @@ CONFIG_SMB_FS
want), say M here and read Documentation/modules.txt. The module want), say M here and read Documentation/modules.txt. The module
will be called smbfs.o. Most people say N, however. 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) Coda file system support (advanced network fs)
CONFIG_CODA_FS CONFIG_CODA_FS
Coda is an advanced network file system, similar to NFS in that it Coda is an advanced network file system, similar to NFS in that it
......
...@@ -450,6 +450,13 @@ M: asun@cobaltnet.com ...@@ -450,6 +450,13 @@ M: asun@cobaltnet.com
L: linux-kernel@vger.rutgers.edu L: linux-kernel@vger.rutgers.edu
S: Maintained 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 HIGH-SPEED SCC DRIVER FOR AX.25
P: Klaus Kudielka P: Klaus Kudielka
M: klaus.kudielka@ieee.org M: klaus.kudielka@ieee.org
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* *
* Modified for ARM by Russell King * Modified for ARM by Russell King
*/ */
#include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
......
/* $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. * srmmu.c: SRMMU specific routines for memory management.
* *
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
...@@ -137,8 +137,8 @@ static inline unsigned long srmmu_pgd_page(pgd_t pgd) ...@@ -137,8 +137,8 @@ static inline unsigned long srmmu_pgd_page(pgd_t pgd)
static inline unsigned long srmmu_pmd_page(pmd_t pmd) 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); } { 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) static inline struct page *srmmu_pte_page(pte_t pte)
{ return srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT); } { 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) static inline int srmmu_pte_none(pte_t pte)
{ return !(pte_val(pte) & 0xFFFFFFF); } { return !(pte_val(pte) & 0xFFFFFFF); }
...@@ -2153,7 +2153,7 @@ void __init ld_mmu_srmmu(void) ...@@ -2153,7 +2153,7 @@ void __init ld_mmu_srmmu(void)
BTFIXUPSET_CALL(set_pte, srmmu_set_pte, BTFIXUPCALL_SWAPO0O1); BTFIXUPSET_CALL(set_pte, srmmu_set_pte, BTFIXUPCALL_SWAPO0O1);
BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM); 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(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM);
......
/* $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. * sun4c.c: Doing in software what should be done in hardware.
* *
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) * 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) ...@@ -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)); 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) static inline unsigned long sun4c_pmd_page(pmd_t pmd)
...@@ -2650,7 +2650,7 @@ void __init ld_mmu_sun4c(void) ...@@ -2650,7 +2650,7 @@ void __init ld_mmu_sun4c(void)
BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0); 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 #if PAGE_SHIFT <= 12
BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1)); BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1));
#else #else
......
...@@ -36,10 +36,6 @@ static struct i2c_bus *busses[I2C_BUS_MAX]; ...@@ -36,10 +36,6 @@ static struct i2c_bus *busses[I2C_BUS_MAX];
static struct i2c_driver *drivers[I2C_DRIVER_MAX]; static struct i2c_driver *drivers[I2C_DRIVER_MAX];
static int bus_count = 0, driver_count = 0; 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 #ifdef CONFIG_VIDEO_BUZ
extern int saa7111_init(void); extern int saa7111_init(void);
extern int saa7185_init(void); extern int saa7185_init(void);
...@@ -54,10 +50,6 @@ int i2c_init(void) ...@@ -54,10 +50,6 @@ int i2c_init(void)
printk(KERN_INFO "i2c: initialized%s\n", printk(KERN_INFO "i2c: initialized%s\n",
scan ? " (i2c bus scan enabled)" : ""); scan ? " (i2c bus scan enabled)" : "");
/* anything to do here ? */ /* anything to do here ? */
#ifdef CONFIG_VIDEO_BT848
i2c_tuner_init();
msp3400c_init();
#endif
#ifdef CONFIG_VIDEO_BUZ #ifdef CONFIG_VIDEO_BUZ
saa7111_init(); saa7111_init();
saa7185_init(); saa7185_init();
......
/* /*
* $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 * Copyright (c) 1998-2000 Vojtech Pavlik
* *
...@@ -77,7 +77,7 @@ static int amijoy_open(struct input_dev *dev) ...@@ -77,7 +77,7 @@ static int amijoy_open(struct input_dev *dev)
return 0; return 0;
if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", NULL)) { 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); printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", amijoy_irq);
return -EBUSY; return -EBUSY;
} }
...@@ -89,7 +89,7 @@ static void amijoy_close(struct input_dev *dev) ...@@ -89,7 +89,7 @@ static void amijoy_close(struct input_dev *dev)
{ {
int *used = dev->private; int *used = dev->private;
if (!--(*port->used)) if (!--(*used))
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
} }
...@@ -112,13 +112,21 @@ static int __init amijoy_init(void) ...@@ -112,13 +112,21 @@ static int __init amijoy_init(void)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (amijoy[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].open = amijoy_open;
amijoy_dev[i].close = amijoy_close; amijoy_dev[i].close = amijoy_close;
amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 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].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); 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].absmin[ABS_X + j] = -1;
amijoy_dev[i].absmax[ABS_X + j] = 1; amijoy_dev[i].absmax[ABS_X + j] = 1;
} }
...@@ -134,6 +142,7 @@ static int __init amijoy_init(void) ...@@ -134,6 +142,7 @@ static int __init amijoy_init(void)
input_register_device(amijoy_dev + i); input_register_device(amijoy_dev + i);
printk(KERN_INFO "input%d: %s at joy%ddat\n", amijoy_dev[i].number, amijoy_name, 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) static void _exit amijoy_exit(void)
...@@ -141,8 +150,10 @@ static void _exit amijoy_exit(void) ...@@ -141,8 +150,10 @@ static void _exit amijoy_exit(void)
int i; int i;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if (amijoy[i]) if (amijoy[i]) {
input_unregister_device(amijoy_dev + i); input_unregister_device(amijoy_dev + i);
release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
}
} }
module_init(amijoy_init); module_init(amijoy_init);
......
/* /*
* $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 * 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, ...@@ -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 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 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 }; 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", 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", 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) ...@@ -113,36 +113,36 @@ static void db9_timer(unsigned long private)
data = parport_read_data(port) >> 3; 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev + 1, ABS_Y, (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); input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
case DB9_MULTI_0802: case DB9_MULTI_0802:
data = parport_read_status(port) >> 3; 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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_TRIGGER, data & DB9_FIRE1);
break; break;
case DB9_MULTI_STICK: case DB9_MULTI_STICK:
data = parport_read_data(port); 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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_TRIGGER, ~data & DB9_FIRE1);
break; break;
case DB9_MULTI2_STICK: case DB9_MULTI2_STICK:
data = parport_read_data(port); 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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_TRIGGER, ~data & DB9_FIRE1);
input_report_key(dev, BTN_THUMB, ~data&DB9_FIRE2); input_report_key(dev, BTN_THUMB, ~data & DB9_FIRE2);
break; break;
case DB9_GENESIS_PAD: case DB9_GENESIS_PAD:
...@@ -150,16 +150,16 @@ static void db9_timer(unsigned long private) ...@@ -150,16 +150,16 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NOSELECT); parport_write_control(port, DB9_NOSELECT);
data = parport_read_data(port); 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data&DB9_FIRE2); input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
data=parport_read_data(port); data=parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_FIRE1); input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data&DB9_FIRE2); input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
break; break;
case DB9_GENESIS5_PAD: case DB9_GENESIS5_PAD:
...@@ -167,18 +167,18 @@ static void db9_timer(unsigned long private) ...@@ -167,18 +167,18 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NOSELECT); parport_write_control(port, DB9_NOSELECT);
data=parport_read_data(port); 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data&DB9_FIRE2); input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
data=parport_read_data(port); data=parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_FIRE1); input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data&DB9_FIRE2); input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
input_report_key(dev, BTN_Y, ~data&DB9_LEFT); input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
input_report_key(dev, BTN_START, ~data&DB9_RIGHT); input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
break; break;
case DB9_GENESIS6_PAD: case DB9_GENESIS6_PAD:
...@@ -187,17 +187,17 @@ static void db9_timer(unsigned long private) ...@@ -187,17 +187,17 @@ static void db9_timer(unsigned long private)
udelay(DB9_GENESIS6_DELAY); udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port); 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data&DB9_FIRE2); input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY); udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port); data=parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_FIRE1); input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data&DB9_FIRE2); input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NOSELECT); /* 2 */ parport_write_control(port, DB9_NOSELECT); /* 2 */
udelay(DB9_GENESIS6_DELAY); udelay(DB9_GENESIS6_DELAY);
...@@ -207,10 +207,10 @@ static void db9_timer(unsigned long private) ...@@ -207,10 +207,10 @@ static void db9_timer(unsigned long private)
udelay(DB9_GENESIS6_DELAY); udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port); data=parport_read_data(port);
input_report_key(dev, BTN_Y, ~data&DB9_LEFT); input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
input_report_key(dev, BTN_Z, ~data&DB9_DOWN); input_report_key(dev, BTN_Z, ~data & DB9_DOWN);
input_report_key(dev, BTN_MODE, ~data&DB9_UP); input_report_key(dev, BTN_MODE, ~data & DB9_UP);
input_report_key(dev, BTN_START, ~data&DB9_RIGHT); input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
parport_write_control(port, DB9_NORMAL); parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY); udelay(DB9_GENESIS6_DELAY);
...@@ -224,32 +224,32 @@ static void db9_timer(unsigned long private) ...@@ -224,32 +224,32 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_SATURN0); parport_write_control(port, DB9_SATURN0);
data = parport_read_data(port); data = parport_read_data(port);
input_report_key(dev, BTN_Y, ~data&DB9_LEFT); input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
input_report_key(dev, BTN_Z, ~data&DB9_DOWN); input_report_key(dev, BTN_Z, ~data & DB9_DOWN);
input_report_key(dev, BTN_TL,~data&DB9_UP); input_report_key(dev, BTN_TL, ~data & DB9_UP);
input_report_key(dev, BTN_TR,~data&DB9_RIGHT); input_report_key(dev, BTN_TR, ~data & DB9_RIGHT);
parport_write_control(port, DB9_SATURN2); parport_write_control(port, DB9_SATURN2);
data = parport_read_data(port); 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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); parport_write_control(port, DB9_NORMAL);
data = parport_read_data(port); data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data&DB9_LEFT); input_report_key(dev, BTN_A, ~data & DB9_LEFT);
input_report_key(dev, BTN_B, ~data&DB9_UP); input_report_key(dev, BTN_B, ~data & DB9_UP);
input_report_key(dev, BTN_C, ~data&DB9_DOWN); input_report_key(dev, BTN_C, ~data & DB9_DOWN);
input_report_key(dev, BTN_X, ~data&DB9_RIGHT); input_report_key(dev, BTN_X, ~data & DB9_RIGHT);
break; break;
case DB9_CD32_PAD: case DB9_CD32_PAD:
data=parport_read_data(port); 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_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (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); parport_write_control(port, 0x0a);
...@@ -257,7 +257,7 @@ static void db9_timer(unsigned long private) ...@@ -257,7 +257,7 @@ static void db9_timer(unsigned long private)
data = parport_read_data(port); data = parport_read_data(port);
parport_write_control(port, 0x02); parport_write_control(port, 0x02);
parport_write_control(port, 0x0a); 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); parport_write_control(port, 0x00);
......
/* /*
* $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 * Copyright (c) 1999-2000 Vojtech Pavlik
* *
...@@ -157,7 +157,7 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) ...@@ -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_nes_bytes[] = { 0, 1, 2, 3 };
static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; 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. * gc_nes_read_packet() reads a NES/SNES packet.
...@@ -515,7 +515,7 @@ static struct gc __init *gc_probe(int *config) ...@@ -515,7 +515,7 @@ static struct gc __init *gc_probe(int *config)
case GC_N64: case GC_N64:
for (j = 0; j < 10; j++) 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++) { for (j = 0; j < 2; j++) {
set_bit(ABS_X + j, gc->dev[i].absbit); set_bit(ABS_X + j, gc->dev[i].absbit);
...@@ -530,18 +530,15 @@ static struct gc __init *gc_probe(int *config) ...@@ -530,18 +530,15 @@ static struct gc __init *gc_probe(int *config)
break; break;
case GC_SNES: case GC_SNES:
for (j = 0; j < 8; j++) for (j = 4; j < 8; j++)
set_bit(gc_snes_btn[j], gc->dev[j].keybit); set_bit(gc_snes_btn[j], gc->dev[i].keybit);
break;
case GC_NES: case GC_NES:
for (j = 0; j < 4; j++) 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; break;
case GC_MULTI2: case GC_MULTI2:
set_bit(BTN_THUMB, gc->dev[i].keybit); set_bit(BTN_THUMB, gc->dev[i].keybit);
case GC_MULTI: case GC_MULTI:
set_bit(BTN_TRIGGER, gc->dev[i].keybit); set_bit(BTN_TRIGGER, gc->dev[i].keybit);
break; break;
...@@ -656,12 +653,13 @@ void __exit gc_exit(void) ...@@ -656,12 +653,13 @@ void __exit gc_exit(void)
{ {
int i, j; int i, j;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++)
for (j = 0; j < 5; j++) if (gc_base[i]) {
if (gc_base[i]->pads[0] & gc_status_bit[j]) for (j = 0; j < 5; j++)
input_unregister_device(gc_base[i]->dev + j); if (gc_base[i]->pads[0] & gc_status_bit[j])
parport_unregister_device(gc_base[i]->pd); input_unregister_device(gc_base[i]->dev + j);
} parport_unregister_device(gc_base[i]->pd);
}
} }
module_init(gc_init); module_init(gc_init);
......
/* /*
* $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 * Copyright (c) 1998-2000 Vojtech Pavlik
* *
...@@ -330,8 +330,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw) ...@@ -330,8 +330,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_parity(GB(i*15,15))) return -1; 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_abs(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_Y, GB(i*15+0,1) - GB(i*15+1,1));
for (j = 0; j < 10; j++) for (j = 0; j < 10; j++)
input_report_key(dev, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1)); input_report_key(dev, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
......
/* /*
* $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 * Copyright (c) 1999-2000 Vojtech Pavlik
* *
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
*/ */
#define JS_SBALL_MAX_LENGTH 128 #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"; static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX";
/* /*
...@@ -70,10 +70,12 @@ static void spaceball_process_packet(struct spaceball* spaceball) ...@@ -70,10 +70,12 @@ static void spaceball_process_packet(struct spaceball* spaceball)
{ {
struct input_dev *dev = &spaceball->dev; struct input_dev *dev = &spaceball->dev;
unsigned char *data = spaceball->data; unsigned char *data = spaceball->data;
int i, d; int i;
if (spaceball->idx < 2) return; if (spaceball->idx < 2) return;
printk("%c %d\n", spaceball->data[0], spaceball->idx);
switch (spaceball->data[0]) { switch (spaceball->data[0]) {
case '@': /* Reset packet */ case '@': /* Reset packet */
...@@ -84,17 +86,17 @@ static void spaceball_process_packet(struct spaceball* spaceball) ...@@ -84,17 +86,17 @@ static void spaceball_process_packet(struct spaceball* spaceball)
break; break;
case 'D': /* Ball data */ case 'D': /* Ball data */
if (spaceball->idx != 16) return; if (spaceball->idx != 15) return;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
d = ((data[2 * i + 3] << 8) | data[2 * i + 2]); input_report_abs(dev, spaceball_axes[i],
input_report_abs(dev, spaceball_axes[i], d - ((d & 0x8000) ? 0x10000 : 0)); (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
} }
break; break;
case '.': /* Button data, part2 */ case '.': /* Button data, part2 */
if (spaceball->idx != 4) return; if (spaceball->idx != 3) return;
input_report_key(dev, BTN_LEFT, data[2] & 1); input_report_key(dev, BTN_0, data[2] & 1);
input_report_key(dev, BTN_RIGHT, data[2] & 2); input_report_key(dev, BTN_1, data[2] & 2);
break; break;
case '?': /* Error packet */ case '?': /* Error packet */
...@@ -118,22 +120,27 @@ static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigne ...@@ -118,22 +120,27 @@ static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigne
switch (data) { switch (data) {
case 0xd: case 0xd:
if (spaceball->idx) spaceball_process_packet(spaceball);
spaceball_process_packet(spaceball);
spaceball->idx = 0; spaceball->idx = 0;
spaceball->escape = 0; spaceball->escape = 0;
return; return;
case '^':
if (!spaceball->escape) {
spaceball->escape ^= 1;
return;
}
spaceball->escape = 0;
case 'M': case 'M':
case 'Q': case 'Q':
case 'S': case 'S':
if (spaceball->escape) if (spaceball->escape) {
spaceball->escape = 0;
data = 0xd; data = 0xd;
case '^': }
spaceball->escape ^= 1;
default: default:
if (spaceball->escape) { if (spaceball->escape) {
printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x\n", data);
spaceball->escape = 0; spaceball->escape = 0;
printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data);
} }
if (spaceball->idx < JS_SBALL_MAX_LENGTH) if (spaceball->idx < JS_SBALL_MAX_LENGTH)
spaceball->data[spaceball->idx++] = data; spaceball->data[spaceball->idx++] = data;
...@@ -172,15 +179,15 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev) ...@@ -172,15 +179,15 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
memset(spaceball, 0, sizeof(struct spaceball)); memset(spaceball, 0, sizeof(struct spaceball));
spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 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++) { for (i = 0; i < 6; i++) {
t = spaceball_axes[i]; t = spaceball_axes[i];
set_bit(t, spaceball->dev.absbit); set_bit(t, spaceball->dev.absbit);
spaceball->dev.absmin[t] = i < 3 ? -10000 : -2000; spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
spaceball->dev.absmax[t] = i < 3 ? 10000 : 2000; spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600;
spaceball->dev.absflat[t] = i < 3 ? 50 : 10; spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
spaceball->dev.absfuzz[t] = i < 3 ? 12 : 2; spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
} }
spaceball->serio = serio; spaceball->serio = serio;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
*/ */
#include <linux/config.h>
#include <linux/fs.h> #include <linux/fs.h>
#undef N_DATA #undef N_DATA
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* *
* History: * 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 * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
* minor fixes * minor fixes
* - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for * - 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; ...@@ -107,19 +109,23 @@ spinlock_t hga_reg_lock = SPIN_LOCK_UNLOCKED;
/* Framebuffer driver structures */ /* Framebuffer driver structures */
static struct fb_var_screeninfo hga_default_var = { static struct fb_var_screeninfo hga_default_var = {
720, 348, /* xres, yres */ xres: 720,
720, 348, /* xres_virtual, yres_virtual */ yres: 348,
0, 0, /* xoffset, yoffset */ xres_virtual: 720,
1, /* bits_per_pixel */ yres_virtual: 348,
0, /* grayscale */ xoffset: 0,
{0, 1, 0}, /* red */ yoffset: 0,
{0, 1, 0}, /* green */ bits_per_pixel: 1,
{0, 1, 0}, /* blue */ grayscale: 0,
{0, 0, 0}, /* transp */ red: {0, 1, 0},
0, /* nonstd (FB_NONSTD_HGA ?) */ green: {0, 1, 0},
0, /* activate */ blue: {0, 1, 0},
-1, -1, /* height, width */ transp: {0, 0, 0},
0, /* accel_flags */ nonstd: 0, /* (FB_NONSTD_HGA ?) */
activate: 0,
height: -1,
width: -1,
accel_flags: 0,
/* pixclock */ /* pixclock */
/* left_margin, right_margin */ /* left_margin, right_margin */
/* upper_margin, lower_margin */ /* upper_margin, lower_margin */
...@@ -129,19 +135,19 @@ static struct fb_var_screeninfo hga_default_var = { ...@@ -129,19 +135,19 @@ static struct fb_var_screeninfo hga_default_var = {
}; };
static struct fb_fix_screeninfo hga_fix = { static struct fb_fix_screeninfo hga_fix = {
"HGA", /* id */ id: "HGA",
(unsigned long) NULL, /* smem_start */ smem_start: (unsigned long) NULL,
0, /* smem_len */ smem_len: 0,
FB_TYPE_PACKED_PIXELS, /* type (not sure) */ type: FB_TYPE_PACKED_PIXELS, /* (not sure) */
0, /* type_aux (not sure) */ type_aux: 0, /* (not sure) */
FB_VISUAL_MONO10, /* visual */ visual: FB_VISUAL_MONO10,
8, /* xpanstep */ xpanstep: 8,
8, /* ypanstep */ ypanstep: 8,
0, /* ywrapstep */ ywrapstep: 0,
90, /* line_length */ line_length: 90,
0, /* mmio_start */ mmio_start: 0,
0, /* mmio_len */ mmio_len: 0,
FB_ACCEL_NONE /* accel */ accel: FB_ACCEL_NONE
}; };
static struct fb_info fb_info; static struct fb_info fb_info;
...@@ -377,9 +383,15 @@ static int __init hga_card_detect(void) ...@@ -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) 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) ...@@ -390,10 +402,15 @@ int hga_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
return 0; return 0;
} }
/**
/* * hga_get_var - get the user defined part of the display
* 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) 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) ...@@ -404,13 +421,23 @@ int hga_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
return 0; return 0;
} }
/* /**
* Set the User Defined Part of the Display * hga_set_var - set the user defined part of the display
* This is the most mystical function (at least for me). * @var:new video mode
* What is the exact specification of xxx_set_var? * @con:unused
* Should it handle xoffset, yoffset? Should it do pannig? * @info:pointer to fb_info object containing info for current hga board
* What does vmode mean? *
*/ * 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) 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) ...@@ -431,10 +458,20 @@ int hga_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
return 0; return 0;
} }
/**
/* * hga_getcolreg - read color registers
* Get the Colormap * @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, static int hga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info) 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, ...@@ -450,6 +487,17 @@ static int hga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
return 0; 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, int hga_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info) struct fb_info *info)
{ {
...@@ -458,9 +506,19 @@ int hga_get_cmap(struct fb_cmap *cmap, int kspc, int con, ...@@ -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); 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, static int hga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info) 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, ...@@ -470,6 +528,17 @@ static int hga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 0; 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, int hga_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info) struct fb_info *info)
{ {
...@@ -478,11 +547,17 @@ int hga_set_cmap(struct fb_cmap *cmap, int kspc, int con, ...@@ -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); return fb_set_cmap(cmap, kspc, hga_setcolreg, info);
} }
/* /**
* Pan or Wrap the Display * hga_pan_display - pan or wrap the display
* * @var:contains new xoffset, yoffset and vmode values
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag * @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, int hga_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info) struct fb_info *info)
...@@ -531,6 +606,18 @@ static struct fb_ops hgafb_ops = { ...@@ -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) static int hgafbcon_switch(int con, struct fb_info *info)
{ {
CHKINFO(-EINVAL); CHKINFO(-EINVAL);
...@@ -564,6 +651,17 @@ static int hgafbcon_switch(int con, struct fb_info *info) ...@@ -564,6 +651,17 @@ static int hgafbcon_switch(int con, struct fb_info *info)
return 0; 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) static int hgafbcon_updatevar(int con, struct fb_info *info)
{ {
CHKINFO(-EINVAL); CHKINFO(-EINVAL);
...@@ -571,17 +669,21 @@ static int hgafbcon_updatevar(int con, struct fb_info *info) ...@@ -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); 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) 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( ); CHKINFO( );
DPRINTK("hga_blank: blank_mode:%d, info:%x, fb_info:%x\n", blank_mode, (unsigned)info, (unsigned)&fb_info); DPRINTK("hga_blank: blank_mode:%d, info:%x, fb_info:%x\n", blank_mode, (unsigned)info, (unsigned)&fb_info);
......
...@@ -99,7 +99,9 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -99,7 +99,9 @@ if [ "$CONFIG_NET" = "y" ]; then
fi fi
dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET 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 if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then
tristate 'NCP file system support (to mount NetWare volumes)' CONFIG_NCP_FS tristate 'NCP file system support (to mount NetWare volumes)' CONFIG_NCP_FS
source fs/ncpfs/Config.in source fs/ncpfs/Config.in
......
...@@ -119,7 +119,7 @@ union bdflush_param { ...@@ -119,7 +119,7 @@ union bdflush_param {
when trying to refill buffers. */ when trying to refill buffers. */
int interval; /* jiffies delay between kupdate flushes */ int interval; /* jiffies delay between kupdate flushes */
int age_buffer; /* Time for normal buffer to age before we flush it */ 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 dummy2; /* unused */
int dummy3; /* unused */ int dummy3; /* unused */
} b_un; } b_un;
...@@ -894,7 +894,7 @@ void balance_dirty(kdev_t dev) ...@@ -894,7 +894,7 @@ void balance_dirty(kdev_t dev)
static __inline__ void __mark_dirty(struct buffer_head *bh, int flag) 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); refile_buffer(bh);
} }
...@@ -1714,8 +1714,10 @@ int generic_commit_write(struct file *file, struct page *page, ...@@ -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; loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
__block_commit_write(inode,page,from,to); __block_commit_write(inode,page,from,to);
kunmap(page); kunmap(page);
if (pos > inode->i_size) if (pos > inode->i_size) {
inode->i_size = pos; inode->i_size = pos;
mark_inode_dirty(inode);
}
return 0; return 0;
} }
...@@ -1837,6 +1839,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], ...@@ -1837,6 +1839,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
int pageind; int pageind;
int bhind; int bhind;
int offset; int offset;
int sectors = size>>9;
unsigned long blocknr; unsigned long blocknr;
struct kiobuf * iobuf = NULL; struct kiobuf * iobuf = NULL;
struct page * map; struct page * map;
...@@ -1888,9 +1891,10 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], ...@@ -1888,9 +1891,10 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
tmp->b_this_page = tmp; tmp->b_this_page = tmp;
init_buffer(tmp, end_buffer_io_kiobuf, iobuf); 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_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) { if (rw == WRITE) {
set_bit(BH_Uptodate, &tmp->b_state); set_bit(BH_Uptodate, &tmp->b_state);
......
...@@ -771,6 +771,7 @@ void iput(struct inode *inode) ...@@ -771,6 +771,7 @@ void iput(struct inode *inode)
list_del(&inode->i_list); list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list); INIT_LIST_HEAD(&inode->i_list);
inode->i_state|=I_FREEING; inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
if (inode->i_data.nrpages) if (inode->i_data.nrpages)
...@@ -799,11 +800,11 @@ void iput(struct inode *inode) ...@@ -799,11 +800,11 @@ void iput(struct inode *inode)
list_del(&inode->i_list); list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list); INIT_LIST_HEAD(&inode->i_list);
inode->i_state|=I_FREEING; inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
clear_inode(inode); clear_inode(inode);
} }
} }
inodes_stat.nr_inodes--;
destroy_inode(inode); destroy_inode(inode);
} }
} }
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
# msdos and Joliet want NLS # msdos and Joliet want NLS
if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \ 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 define_bool CONFIG_NLS y
else else
define_bool CONFIG_NLS n define_bool CONFIG_NLS n
......
ChangeLog for smbfs. 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> 2000-07-25 Urban Widmark <urban@svenskatest.se>
* proc.c: fix 3 places where bad server responses could cause an Oops. * proc.c: fix 3 places where bad server responses could cause an Oops.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# Note 2! The CFLAGS definitions are now in the main makefile... # Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := smbfs.o 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) M_OBJS := $(O_TARGET)
# If you want debugging output, you may add these flags to the EXTRA_CFLAGS # If you want debugging output, you may add these flags to the EXTRA_CFLAGS
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/smb_fs.h> #include <linux/smb_fs.h>
#include <linux/smb_mount.h>
#include <linux/smbno.h> #include <linux/smbno.h>
#include "smb_debug.h" #include "smb_debug.h"
...@@ -142,7 +143,7 @@ smb_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -142,7 +143,7 @@ smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
} }
/* /*
* 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. * mount point, we don't revalidate if conn_pid is NULL.
*/ */
static int static int
...@@ -190,6 +191,13 @@ static struct dentry_operations smbfs_dentry_operations = ...@@ -190,6 +191,13 @@ static struct dentry_operations smbfs_dentry_operations =
d_delete: smb_delete_dentry, 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. * 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) ...@@ -249,8 +257,7 @@ smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
if (a->len != b->len) if (a->len != b->len)
goto out; 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])) if (tolower(a->name[i]) != tolower(b->name[i]))
goto out; goto out;
} }
...@@ -300,6 +307,7 @@ smb_lookup(struct inode *dir, struct dentry *dentry) ...@@ -300,6 +307,7 @@ smb_lookup(struct inode *dir, struct dentry *dentry)
struct smb_fattr finfo; struct smb_fattr finfo;
struct inode *inode; struct inode *inode;
int error; int error;
struct smb_sb_info *server;
error = -ENAMETOOLONG; error = -ENAMETOOLONG;
if (dentry->d_name.len > SMB_MAXNAMELEN) if (dentry->d_name.len > SMB_MAXNAMELEN)
...@@ -315,15 +323,18 @@ smb_lookup(struct inode *dir, struct dentry *dentry) ...@@ -315,15 +323,18 @@ smb_lookup(struct inode *dir, struct dentry *dentry)
inode = NULL; inode = NULL;
if (error == -ENOENT) if (error == -ENOENT)
goto add_entry; goto add_entry;
if (!error) if (!error) {
{
error = -EACCES; error = -EACCES;
finfo.f_ino = smb_invent_inos(1); finfo.f_ino = smb_invent_inos(1);
inode = smb_iget(dir->i_sb, &finfo); inode = smb_iget(dir->i_sb, &finfo);
if (inode) if (inode) {
{
add_entry: 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); d_add(dentry, inode);
smb_renew_times(dentry); smb_renew_times(dentry);
error = 0; error = 0;
......
/*
* 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;
}
#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 */
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/nls.h>
#include <linux/smb_fs.h> #include <linux/smb_fs.h>
#include <linux/smbno.h> #include <linux/smbno.h>
...@@ -29,6 +30,7 @@ ...@@ -29,6 +30,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "smb_debug.h" #include "smb_debug.h"
#include "getopt.h"
static void smb_delete_inode(struct inode *); static void smb_delete_inode(struct inode *);
static void smb_put_super(struct super_block *); static void smb_put_super(struct super_block *);
...@@ -282,6 +284,82 @@ smb_delete_inode(struct inode *ino) ...@@ -282,6 +284,82 @@ smb_delete_inode(struct inode *ino)
clear_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 static void
smb_put_super(struct super_block *sb) smb_put_super(struct super_block *sb)
{ {
...@@ -300,18 +378,32 @@ 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); kfree(sb->u.smbfs_sb.temp_buf);
if (server->packet) if (server->packet)
smb_vfree(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 * struct super_block *
smb_read_super(struct super_block *sb, void *raw_data, int silent) 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 inode *root_inode;
struct smb_fattr root; struct smb_fattr root;
int ver;
if (!raw_data) if (!raw_data)
goto out_no_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; goto out_wrong_data;
sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize = 1024; /* Eh... Is this correct? */
...@@ -320,6 +412,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) ...@@ -320,6 +412,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_flags = 0; sb->s_flags = 0;
sb->s_op = &smb_sops; sb->s_op = &smb_sops;
sb->u.smbfs_sb.mnt = NULL;
sb->u.smbfs_sb.sock_file = NULL; sb->u.smbfs_sb.sock_file = NULL;
init_MUTEX(&sb->u.smbfs_sb.sem); init_MUTEX(&sb->u.smbfs_sb.sem);
init_waitqueue_head(&sb->u.smbfs_sb.wait); init_waitqueue_head(&sb->u.smbfs_sb.wait);
...@@ -332,30 +425,61 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) ...@@ -332,30 +425,61 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
goto out_no_mem; goto out_no_mem;
/* Allocate the global temp buffer */ /* 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) if (!sb->u.smbfs_sb.temp_buf)
goto out_no_temp; 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 */ /* 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) if (!mnt)
goto out_no_mount; 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; 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 * Display the enabled options
* Note: smb_proc_getattr uses these in 2.4 (but was changed in 2.2) * 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"); 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"); printk("SMBFS: Using dir ff getattr\n");
/* /*
...@@ -374,16 +498,18 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) ...@@ -374,16 +498,18 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
out_no_root: out_no_root:
iput(root_inode); iput(root_inode);
out_bad_option:
kfree(sb->u.smbfs_sb.mnt); kfree(sb->u.smbfs_sb.mnt);
out_no_mount: out_no_mount:
kfree(sb->u.smbfs_sb.temp_buf); kfree(sb->u.smbfs_sb.temp_buf);
out_no_temp: out_no_temp:
smb_vfree(sb->u.smbfs_sb.packet); smb_vfree(sb->u.smbfs_sb.packet);
out_no_mem: 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; goto out_fail;
out_wrong_data: 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; goto out_fail;
out_no_data: out_no_data:
printk(KERN_ERR "smb_read_super: missing data argument\n"); printk(KERN_ERR "smb_read_super: missing data argument\n");
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/dirent.h> #include <linux/dirent.h>
#include <linux/nls.h>
#include <linux/smb_fs.h> #include <linux/smb_fs.h>
#include <linux/smbno.h> #include <linux/smbno.h>
...@@ -25,10 +26,14 @@ ...@@ -25,10 +26,14 @@
#include "smb_debug.h" #include "smb_debug.h"
/* Features. Undefine if they cause problems, this should perhaps be a /* Features. Undefine if they cause problems, this should perhaps be a
config option. */ config option. */
#define SMBFS_POSIX_UNLINK 1 #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_VWV(packet) ((packet) + SMB_HEADER_LEN)
#define SMB_CMD(packet) (*(packet+8)) #define SMB_CMD(packet) (*(packet+8))
#define SMB_WCT(packet) (*(packet+SMB_HEADER_LEN - 1)) #define SMB_WCT(packet) (*(packet+SMB_HEADER_LEN - 1))
...@@ -48,6 +53,20 @@ static int ...@@ -48,6 +53,20 @@ static int
smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir, smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir,
struct smb_fattr *fattr); 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 static void
str_upper(char *name, int len) str_upper(char *name, int len)
{ {
...@@ -83,6 +102,96 @@ static void reverse_string(char *buf, 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 */ /* Encoding/Decoding section */
...@@ -107,9 +216,11 @@ smb_encode_smb_length(__u8 * p, __u32 len) ...@@ -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. * smb_build_path: build the path to entry and name storing it in buf.
* The path returned will have the trailing '\0'. * 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; char *path = buf;
int len;
if (entry == NULL) if (entry == NULL)
goto test_name_and_out; goto test_name_and_out;
...@@ -129,9 +240,16 @@ static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf) ...@@ -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()] * and store it in reversed order [see reverse_string()]
*/ */
for (;;) { for (;;) {
memcpy(path, entry->d_name.name, entry->d_name.len); if (entry->d_name.len > SMB_MAXNAMELEN)
reverse_string(path, entry->d_name.len); return -ENAMETOOLONG;
path += entry->d_name.len; 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++) = '\\'; *(path++) = '\\';
...@@ -147,25 +265,28 @@ static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf) ...@@ -147,25 +265,28 @@ static int smb_build_path(struct dentry * entry, struct qstr * name, char * buf)
if (name != NULL) { if (name != NULL) {
*(path++) = '\\'; *(path++) = '\\';
name_and_out: name_and_out:
memcpy(path, name->name, name->len); len = server->convert(path, SMB_MAXNAMELEN,
path += name->len; name->name, name->len,
server->local_nls, server->remote_nls);
path += len;
} }
out: out:
*(path++) = '\0'; *(path++) = '\0';
return (path-buf); return (path-buf);
} }
static char *smb_encode_path(struct smb_sb_info *server, char *buf, static int smb_encode_path(struct smb_sb_info *server, char *buf,
struct dentry *dir, struct qstr *name) struct dentry *dir, struct qstr *name)
{ {
char *start = buf; int result;
buf += smb_build_path(dir, name, buf);
result = smb_build_path(server, buf, dir, name);
if (result < 0)
goto out;
if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS) if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
str_upper(start, buf - start); str_upper(buf, result);
out:
return buf; return result;
} }
/* The following are taken directly from msdos-fs */ /* The following are taken directly from msdos-fs */
...@@ -464,18 +585,6 @@ smb_errno(struct smb_sb_info *server) ...@@ -464,18 +585,6 @@ smb_errno(struct smb_sb_info *server)
return EIO; 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 * smb_retry: This function should be called when smb_request_ok has
* indicated an error. If the error was indicated because the * indicated an error. If the error was indicated because the
...@@ -495,8 +604,7 @@ smb_retry(struct smb_sb_info *server) ...@@ -495,8 +604,7 @@ smb_retry(struct smb_sb_info *server)
smb_close_socket(server); smb_close_socket(server);
if (pid == 0) if (pid == 0) {
{
printk(KERN_ERR "smb_retry: no connection process\n"); printk(KERN_ERR "smb_retry: no connection process\n");
server->state = CONN_RETRIED; server->state = CONN_RETRIED;
goto out; goto out;
...@@ -511,26 +619,35 @@ smb_retry(struct smb_sb_info *server) ...@@ -511,26 +619,35 @@ smb_retry(struct smb_sb_info *server)
* Note: use the "priv" flag, as a user process may need to reconnect. * Note: use the "priv" flag, as a user process may need to reconnect.
*/ */
error = kill_proc(pid, SIGUSR1, 1); error = kill_proc(pid, SIGUSR1, 1);
if (error) if (error) {
{
printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error); printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
goto out_restore; goto out_restore;
} }
VERBOSE("signalled pid %d, waiting for new connection\n", VERBOSE("signalled pid %d, waiting for new connection\n", pid);
server->conn_pid);
/* /*
* Wait for the new connection. * Wait for the new connection.
*/ */
#ifdef SMB_RETRY_INTR
interruptible_sleep_on_timeout(&server->wait, 5*HZ); interruptible_sleep_on_timeout(&server->wait, 5*HZ);
if (signal_pending(current)) if (signal_pending(current))
printk(KERN_INFO "smb_retry: caught signal\n"); 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. * Check for a valid connection.
*/ */
if (server->state == CONN_VALID) if (server->state == CONN_VALID) {
{
/* This should be changed to VERBOSE, except many smbfs /* This should be changed to VERBOSE, except many smbfs
problems is with the userspace daemon not reconnecting. */ problems is with the userspace daemon not reconnecting. */
PARANOIA("sucessful, new pid=%d, generation=%d\n", PARANOIA("sucessful, new pid=%d, generation=%d\n",
...@@ -656,7 +773,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt) ...@@ -656,7 +773,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
if (server->opt.protocol == SMB_PROTOCOL_NT1 && if (server->opt.protocol == SMB_PROTOCOL_NT1 &&
(server->opt.max_xmit < 0x1000) && (server->opt.max_xmit < 0x1000) &&
!(server->opt.capabilities & SMB_CAP_NT_SMBS)) { !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
server->mnt->version |= SMB_FIX_WIN95; server->mnt->flags |= SMB_MOUNT_WIN95;
#ifdef SMBFS_DEBUG_VERBOSE #ifdef SMBFS_DEBUG_VERBOSE
printk(KERN_NOTICE "smb_newconn: detected WIN95 server\n"); printk(KERN_NOTICE "smb_newconn: detected WIN95 server\n");
#endif #endif
...@@ -667,7 +784,11 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt) ...@@ -667,7 +784,11 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
server->opt.capabilities); server->opt.capabilities);
out: out:
#ifdef SMB_RETRY_INTR
wake_up_interruptible(&server->wait); wake_up_interruptible(&server->wait);
#else
wake_up(&server->wait);
#endif
return error; return error;
out_putf: out_putf:
...@@ -738,7 +859,7 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish) ...@@ -738,7 +859,7 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
{ {
struct inode *ino = dentry->d_inode; struct inode *ino = dentry->d_inode;
int mode, read_write = 0x42, read_only = 0x40; int mode, read_write = 0x42, read_only = 0x40;
int error; int res;
char *p; char *p;
/* /*
...@@ -748,6 +869,9 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish) ...@@ -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))) if (!(ino->i_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
mode = read_only; mode = read_only;
#if 0 #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))) if (!(wish & (O_WRONLY | O_RDWR)))
mode = read_only; mode = read_only;
#endif #endif
...@@ -757,20 +881,23 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish) ...@@ -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_vwv0, mode);
WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR); WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
*p++ = 4; *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); smb_setup_bcc(server, p);
error = smb_request_ok(server, SMBopen, 7, 0); res = smb_request_ok(server, SMBopen, 7, 0);
if (error != 0) if (res != 0) {
{
if (smb_retry(server)) if (smb_retry(server))
goto retry; goto retry;
if (mode == read_write && 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", VERBOSE("%s/%s R/W failed, error=%d, retrying R/O\n",
DENTRY_PATH(dentry), error); DENTRY_PATH(dentry), res);
mode = read_only; mode = read_only;
goto retry; goto retry;
} }
...@@ -783,10 +910,12 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish) ...@@ -783,10 +910,12 @@ smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
/* smb_vwv2 has mtime */ /* smb_vwv2 has mtime */
/* smb_vwv4 has size */ /* smb_vwv4 has size */
ino->u.smbfs_i.access = (WVAL(server->packet, smb_vwv6) & SMB_ACCMASK); 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; ino->u.smbfs_i.open = server->generation;
out: out:
return error; return res;
} }
/* /*
...@@ -1025,7 +1154,7 @@ smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid) ...@@ -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); struct smb_sb_info *server = server_from_dentry(dentry);
char *p; char *p;
int error; int result;
smb_lock_server(server); smb_lock_server(server);
...@@ -1034,22 +1163,24 @@ smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid) ...@@ -1034,22 +1163,24 @@ smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
WSET(server->packet, smb_vwv0, attr); WSET(server->packet, smb_vwv0, attr);
DSET(server->packet, smb_vwv1, utc2local(server, ctime)); DSET(server->packet, smb_vwv1, utc2local(server, ctime));
*p++ = 4; *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); smb_setup_bcc(server, p);
error = smb_request_ok(server, SMBcreate, 1, 0); result = smb_request_ok(server, SMBcreate, 1, 0);
if (error < 0) if (result < 0) {
{
if (smb_retry(server)) if (smb_retry(server))
goto retry; goto retry;
goto out; goto out;
} }
*fileid = WVAL(server->packet, smb_vwv0); *fileid = WVAL(server->packet, smb_vwv0);
error = 0; result = 0;
out: out:
smb_unlock_server(server); smb_unlock_server(server);
return error; return result;
} }
int int
...@@ -1064,14 +1195,22 @@ smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry) ...@@ -1064,14 +1195,22 @@ smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry)
retry: retry:
p = smb_setup_header(server, SMBmv, 1, 0); p = smb_setup_header(server, SMBmv, 1, 0);
WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR); WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
*p++ = 4; *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++ = 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); 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)) if (smb_retry(server))
goto retry; goto retry;
goto out; goto out;
...@@ -1097,12 +1236,14 @@ smb_proc_generic_command(struct dentry *dentry, __u8 command) ...@@ -1097,12 +1236,14 @@ smb_proc_generic_command(struct dentry *dentry, __u8 command)
retry: retry:
p = smb_setup_header(server, command, 0, 0); p = smb_setup_header(server, command, 0, 0);
*p++ = 4; *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); smb_setup_bcc(server, p);
result = smb_request_ok(server, command, 0, 0); result = smb_request_ok(server, command, 0, 0);
if (result < 0) if (result < 0) {
{
if (smb_retry(server)) if (smb_retry(server))
goto retry; goto retry;
goto out; goto out;
...@@ -1165,11 +1306,13 @@ smb_proc_unlink(struct dentry *dentry) ...@@ -1165,11 +1306,13 @@ smb_proc_unlink(struct dentry *dentry)
p = smb_setup_header(server, SMBunlink, 1, 0); p = smb_setup_header(server, SMBunlink, 1, 0);
WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN); WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
*p++ = 4; *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); 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 SMBFS_POSIX_UNLINK
if (result == -EACCES && !flag) { if (result == -EACCES && !flag) {
/* Posix semantics is for the read-only state /* Posix semantics is for the read-only state
...@@ -1220,8 +1363,7 @@ smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length) ...@@ -1220,8 +1363,7 @@ smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length)
*p++ = 0; *p++ = 0;
smb_setup_bcc(server, p); 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)) if (smb_retry(server))
goto retry; goto retry;
goto out; goto out;
...@@ -1306,6 +1448,8 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p, ...@@ -1306,6 +1448,8 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p,
len--; len--;
entry->len = 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) { switch (server->opt.case_handling) {
case SMB_CASE_UPPER: case SMB_CASE_UPPER:
str_upper(entry->name, len); str_upper(entry->name, len);
...@@ -1316,7 +1460,13 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p, ...@@ -1316,7 +1460,13 @@ smb_decode_dirent(struct smb_sb_info *server, __u8 *p,
default: default:
break; 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; return p + 22;
} }
...@@ -1355,7 +1505,10 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos, ...@@ -1355,7 +1505,10 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos,
WSET(server->packet, smb_vwv1, aDIR); WSET(server->packet, smb_vwv1, aDIR);
*p++ = 4; *p++ = 4;
if (first == 1) { 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; *p++ = 5;
WSET(p, 0, 0); WSET(p, 0, 0);
p += 2; p += 2;
...@@ -1467,12 +1620,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p, ...@@ -1467,12 +1620,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
switch (level) { switch (level) {
case 1: case 1:
len = *((unsigned char *) p + 22); len = *((unsigned char *) p + 22);
entry->len = len;
entry->name = p + 23; entry->name = p + 23;
result = p + 24 + len; result = p + 24 + len;
VERBOSE("info 1 at %p, len=%d, name=%.*s\n", VERBOSE("info 1 at %p, len=%d, name=%.*s\n",
p, entry->len, entry->len, entry->name); p, len, len, entry->name);
break; break;
case 260: case 260:
result = p + WVAL(p, 0); result = p + WVAL(p, 0);
...@@ -1482,14 +1634,14 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p, ...@@ -1482,14 +1634,14 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
entry->name = p + 94; entry->name = p + 94;
if (len && entry->name[len-1] == '\0') if (len && entry->name[len-1] == '\0')
len--; len--;
entry->len = len;
VERBOSE("info 260 at %p, len=%d, name=%.*s\n", VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
p, entry->len, entry->len, entry->name); p, len, len, entry->name);
break; break;
default: default:
PARANOIA("Unknown info level %d\n", level); PARANOIA("Unknown info level %d\n", level);
result = p + WVAL(p, 0); result = p + WVAL(p, 0);
goto out;
} }
switch (server->opt.case_handling) { switch (server->opt.case_handling) {
...@@ -1503,6 +1655,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p, ...@@ -1503,6 +1655,11 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
break; 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; return result;
} }
...@@ -1561,7 +1718,12 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos, ...@@ -1561,7 +1718,12 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
* Encode the initial path * Encode the initial path
*/ */
mask = param + 12; 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; first = 1;
VERBOSE("starting fpos=%d, mask=%s\n", fpos, mask); 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, ...@@ -1753,7 +1915,11 @@ smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
int mask_len, result; int mask_len, result;
retry: 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); VERBOSE("name=%s, len=%d\n", mask, mask_len);
WSET(param, 0, aSYSTEM | aHIDDEN | aDIR); WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
WSET(param, 2, 1); /* max count */ WSET(param, 2, 1); /* max count */
...@@ -1828,7 +1994,10 @@ smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir, ...@@ -1828,7 +1994,10 @@ smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
retry: retry:
p = smb_setup_header(server, SMBgetatr, 0, 0); p = smb_setup_header(server, SMBgetatr, 0, 0);
*p++ = 4; *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); smb_setup_bcc(server, p);
if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) 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, ...@@ -1874,7 +2043,10 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
retry: retry:
WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */ WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
DSET(param, 2, 0); 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, result = smb_trans2_request(server, TRANSACT2_QPATHINFO,
0, NULL, p - param, param, 0, NULL, p - param, param,
...@@ -1905,7 +2077,7 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir, ...@@ -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, * Kludge alert: Win 95 swaps the date and time field,
* contrary to the CIFS docs and Win NT practice. * 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_date = 2;
off_time = 0; off_time = 0;
} }
...@@ -1945,21 +2117,16 @@ smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir, ...@@ -1945,21 +2117,16 @@ smb_proc_do_getattr(struct smb_sb_info *server, struct dentry *dir,
/* /*
* Select whether to use core or trans2 getattr. * Select whether to use core or trans2 getattr.
* Win 95 appears to break with the trans2 getattr.
*/ */
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) { if (server->opt.protocol < SMB_PROTOCOL_LANMAN2 ||
/* (server->mnt->flags & (SMB_MOUNT_OLDATTR|SMB_MOUNT_WIN95)) ) {
* Win 95 appears to break with the trans2 getattr. result = smb_proc_getattr_core(server, dir, fattr);
* Note: mnt->version options are set at mount time (inode.c) } else {
*/ if (server->mnt->flags & SMB_MOUNT_DIRATTR)
if (server->mnt->version & (SMB_FIX_OLDATTR|SMB_FIX_WIN95))
goto core_attr;
if (server->mnt->version & SMB_FIX_DIRATTR)
result = smb_proc_getattr_ff(server, dir, fattr); result = smb_proc_getattr_ff(server, dir, fattr);
else else
result = smb_proc_getattr_trans2(server, dir, fattr); result = smb_proc_getattr_trans2(server, dir, fattr);
} else {
core_attr:
result = smb_proc_getattr_core(server, dir, fattr);
} }
smb_finish_dirent(server, fattr); smb_finish_dirent(server, fattr);
...@@ -2008,14 +2175,16 @@ smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry, ...@@ -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_vwv6, 0);
WSET(server->packet, smb_vwv7, 0); WSET(server->packet, smb_vwv7, 0);
*p++ = 4; *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++ = 4;
*p++ = 0; *p++ = 0;
smb_setup_bcc(server, p); smb_setup_bcc(server, p);
result = smb_request_ok(server, SMBsetatr, 0, 0); result = smb_request_ok(server, SMBsetatr, 0, 0);
if (result < 0) if (result < 0) {
{
if (smb_retry(server)) if (smb_retry(server))
goto retry; goto retry;
goto out; goto out;
...@@ -2073,8 +2242,7 @@ smb_proc_setattr_ext(struct smb_sb_info *server, ...@@ -2073,8 +2242,7 @@ smb_proc_setattr_ext(struct smb_sb_info *server,
#endif #endif
result = smb_request_ok(server, SMBsetattrE, 0, 0); result = smb_request_ok(server, SMBsetattrE, 0, 0);
if (result < 0) if (result < 0) {
{
if (smb_retry(server)) if (smb_retry(server))
goto retry; goto retry;
goto out; goto out;
...@@ -2107,7 +2275,10 @@ smb_proc_setattr_trans2(struct smb_sb_info *server, ...@@ -2107,7 +2275,10 @@ smb_proc_setattr_trans2(struct smb_sb_info *server,
retry: retry:
WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */ WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
DSET(param, 2, 0); 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, 0, 0); /* creation time */
WSET(data, 2, 0); WSET(data, 2, 0);
...@@ -2170,8 +2341,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr) ...@@ -2170,8 +2341,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
smb_lock_server(server); smb_lock_server(server);
/* setting the time on a Win95 server fails (tridge) */ /* setting the time on a Win95 server fails (tridge) */
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 && if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 &&
!(server->mnt->version & SMB_FIX_WIN95)) !(server->mnt->flags & SMB_MOUNT_WIN95)) {
{
if (smb_is_open(inode) && if (smb_is_open(inode) &&
inode->u.smbfs_i.access != SMB_O_RDONLY) inode->u.smbfs_i.access != SMB_O_RDONLY)
result = smb_proc_setattr_ext(server, inode, fattr); result = smb_proc_setattr_ext(server, inode, fattr);
...@@ -2182,8 +2352,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr) ...@@ -2182,8 +2352,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
* Fail silently on directories ... timestamp can't be set? * Fail silently on directories ... timestamp can't be set?
*/ */
result = 0; result = 0;
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode)) {
{
/* /*
* Set the mtime by opening and closing the file. * Set the mtime by opening and closing the file.
* Note that the file is opened read-only, but this * Note that the file is opened read-only, but this
...@@ -2192,8 +2361,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr) ...@@ -2192,8 +2361,7 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
result = -EACCES; result = -EACCES;
if (!smb_is_open(inode)) if (!smb_is_open(inode))
smb_proc_open(server, dentry, SMB_O_RDONLY); smb_proc_open(server, dentry, SMB_O_RDONLY);
if (smb_is_open(inode)) if (smb_is_open(inode)) {
{
inode->i_mtime = fattr->f_mtime; inode->i_mtime = fattr->f_mtime;
result = smb_proc_close_inode(server, inode); result = smb_proc_close_inode(server, inode);
} }
...@@ -2208,7 +2376,7 @@ int ...@@ -2208,7 +2376,7 @@ int
smb_proc_dskattr(struct super_block *sb, struct statfs *attr) smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
{ {
struct smb_sb_info *server = &(sb->u.smbfs_sb); struct smb_sb_info *server = &(sb->u.smbfs_sb);
int error; int result;
char *p; char *p;
smb_lock_server(server); smb_lock_server(server);
...@@ -2216,8 +2384,7 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr) ...@@ -2216,8 +2384,7 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
retry: retry:
smb_setup_header(server, SMBdskattr, 0, 0); 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)) if (smb_retry(server))
goto retry; goto retry;
goto out; goto out;
...@@ -2226,11 +2393,11 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr) ...@@ -2226,11 +2393,11 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
attr->f_blocks = WVAL(p, 0); attr->f_blocks = WVAL(p, 0);
attr->f_bsize = WVAL(p, 2) * WVAL(p, 4); attr->f_bsize = WVAL(p, 2) * WVAL(p, 4);
attr->f_bavail = attr->f_bfree = WVAL(p, 6); attr->f_bavail = attr->f_bfree = WVAL(p, 6);
error = 0; result = 0;
out: out:
smb_unlock_server(server); smb_unlock_server(server);
return error; return result;
} }
int int
......
...@@ -111,12 +111,16 @@ smb_data_callback(void* ptr) ...@@ -111,12 +111,16 @@ smb_data_callback(void* ptr)
unsigned char peek_buf[4]; unsigned char peek_buf[4];
int result; int result;
mm_segment_t fs; mm_segment_t fs;
int count = 100; /* this is a lot, we should have some data waiting */
int found = 0;
fs = get_fs(); fs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
lock_kernel(); lock_kernel();
while (1) { while (count-- > 0) {
peek_buf[0] = 0;
result = -EIO; result = -EIO;
if (job->sk->dead) { if (job->sk->dead) {
PARANOIA("sock dead!\n"); PARANOIA("sock dead!\n");
...@@ -125,7 +129,7 @@ smb_data_callback(void* ptr) ...@@ -125,7 +129,7 @@ smb_data_callback(void* ptr)
result = _recvfrom(socket, (void *) peek_buf, 1, result = _recvfrom(socket, (void *) peek_buf, 1,
MSG_PEEK | MSG_DONTWAIT); MSG_PEEK | MSG_DONTWAIT);
if (result == -EAGAIN) if (result < 0)
break; break;
if (peek_buf[0] != 0x85) if (peek_buf[0] != 0x85)
break; break;
...@@ -136,13 +140,15 @@ smb_data_callback(void* ptr) ...@@ -136,13 +140,15 @@ smb_data_callback(void* ptr)
DEBUG1("got SESSION KEEPALIVE\n"); DEBUG1("got SESSION KEEPALIVE\n");
if (result == -EAGAIN) if (result < 0)
break; break;
found = 1;
} }
unlock_kernel(); unlock_kernel();
set_fs(fs); set_fs(fs);
if (result != -EAGAIN) DEBUG1("found=%d, count=%d, result=%d\n", found, count, result);
if (found)
found_data(job->sk); found_data(job->sk);
kfree(ptr); kfree(ptr);
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* 11-01-1998 RMK Added mask_and_ack_irq * 11-01-1998 RMK Added mask_and_ack_irq
* 22-08-1998 RMK Restructured IRQ routines * 22-08-1998 RMK Restructured IRQ routines
*/ */
#include <linux/config.h>
#include <asm/ioc.h> #include <asm/ioc.h>
#ifdef CONFIG_ARCH_ARC #ifdef CONFIG_ARCH_ARC
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* Copyright (c) 1996-1999 Russell King and Dave Gilbert * Copyright (c) 1996-1999 Russell King and Dave Gilbert
*/ */
#include <linux/config.h>
static void arch_idle(void) static void arch_idle(void)
{ {
......
/* $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 #ifndef _SPARC_PGTABLE_H
#define _SPARC_PGTABLE_H #define _SPARC_PGTABLE_H
...@@ -201,11 +201,9 @@ extern unsigned long empty_zero_page; ...@@ -201,11 +201,9 @@ extern unsigned long empty_zero_page;
#define SIZEOF_PTR_LOG2 2 #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, pmd_page, pmd_t)
BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page, pgd_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 pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd)
#define pgd_page(pgd) BTFIXUP_CALL(pgd_page)(pgd) #define pgd_page(pgd) BTFIXUP_CALL(pgd_page)(pgd)
...@@ -305,7 +303,9 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t) ...@@ -305,7 +303,9 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t)
/* Permanent address of a page. */ /* Permanent address of a page. */
#define page_address(page) ((page)->virtual) #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, * Conversion functions: convert a page and protection to a page entry,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Define this to use the verbose/debugging versions in * Define this to use the verbose/debugging versions in
* arch/sparc/lib/debuglocks.c * 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 #define SPIN_LOCK_DEBUG
...@@ -28,7 +28,7 @@ struct _spinlock_debug { ...@@ -28,7 +28,7 @@ struct _spinlock_debug {
typedef struct _spinlock_debug spinlock_t; typedef struct _spinlock_debug spinlock_t;
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0 } #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_is_locked(lp) (*((volatile unsigned char *)(&((lp)->lock))) != 0)
#define spin_unlock_wait(lp) do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock)) #define spin_unlock_wait(lp) do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
...@@ -49,6 +49,8 @@ typedef struct _rwlock_debug rwlock_t; ...@@ -49,6 +49,8 @@ typedef struct _rwlock_debug rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, {0} } #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_lock(rwlock_t *rw, char *str);
extern void _do_read_unlock(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); extern void _do_write_lock(rwlock_t *rw, char *str);
...@@ -144,6 +146,9 @@ typedef struct { volatile unsigned int lock; } rwlock_t; ...@@ -144,6 +146,9 @@ typedef struct { volatile unsigned int lock; } rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { 0 } #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. /* Sort of like atomic_t's on Sparc, but even more clever.
* *
* ------------------------------------ * ------------------------------------
......
/* $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 #ifndef _SPARC_UNISTD_H
#define _SPARC_UNISTD_H #define _SPARC_UNISTD_H
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
/* #define __NR_putmsg 152 SunOS Specific */ /* #define __NR_putmsg 152 SunOS Specific */
#define __NR_poll 153 /* Common */ #define __NR_poll 153 /* Common */
#define __NR_getdents64 154 /* Linux specific */ #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_getdirentries 156 SunOS Specific */
#define __NR_statfs 157 /* Common */ #define __NR_statfs 157 /* Common */
#define __NR_fstatfs 158 /* Common */ #define __NR_fstatfs 158 /* Common */
......
...@@ -109,6 +109,7 @@ extern int _spin_trylock (spinlock_t *lock); ...@@ -109,6 +109,7 @@ extern int _spin_trylock (spinlock_t *lock);
typedef unsigned int rwlock_t; typedef unsigned int rwlock_t;
#define RW_LOCK_UNLOCKED 0 #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_lock(rwlock_t *);
extern void __read_unlock(rwlock_t *); extern void __read_unlock(rwlock_t *);
...@@ -128,6 +129,7 @@ typedef struct { ...@@ -128,6 +129,7 @@ typedef struct {
unsigned int reader_pc[4]; unsigned int reader_pc[4];
} rwlock_t; } rwlock_t;
#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0xff, { 0, 0, 0, 0 } } #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_lock(rwlock_t *rw, char *str);
extern void _do_read_unlock(rwlock_t *rw, char *str); extern void _do_read_unlock(rwlock_t *rw, char *str);
......
/* $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 #ifndef _SPARC64_UNISTD_H
#define _SPARC64_UNISTD_H #define _SPARC64_UNISTD_H
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
/* #define __NR_putmsg 152 SunOS Specific */ /* #define __NR_putmsg 152 SunOS Specific */
#define __NR_poll 153 /* Common */ #define __NR_poll 153 /* Common */
#define __NR_getdents64 154 /* Linux specific */ #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_getdirentries 156 SunOS Specific */
#define __NR_statfs 157 /* Common */ #define __NR_statfs 157 /* Common */
#define __NR_fstatfs 158 /* Common */ #define __NR_fstatfs 158 /* Common */
......
...@@ -62,6 +62,13 @@ struct smb_conn_opt { ...@@ -62,6 +62,13 @@ struct smb_conn_opt {
#ifdef __KERNEL__ #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_MAXNAMELEN 255
#define SMB_MAXPATHLEN 1024 #define SMB_MAXPATHLEN 1024
......
...@@ -73,13 +73,6 @@ smb_vfree(void *obj) ...@@ -73,13 +73,6 @@ smb_vfree(void *obj)
#define SMB_F_CACHEVALID 0x01 /* directory cache valid */ #define SMB_F_CACHEVALID 0x01 /* directory cache valid */
#define SMB_F_LOCALWRITE 0x02 /* file modified locally */ #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 */ /* NT1 protocol capability bits */
#define SMB_CAP_RAW_MODE 0x0001 #define SMB_CAP_RAW_MODE 0x0001
...@@ -122,6 +115,7 @@ unsigned long smb_invent_inos(unsigned long); ...@@ -122,6 +115,7 @@ unsigned long smb_invent_inos(unsigned long);
struct inode *smb_iget(struct super_block *, struct smb_fattr *); struct inode *smb_iget(struct super_block *, struct smb_fattr *);
/* linux/fs/smbfs/proc.c */ /* linux/fs/smbfs/proc.c */
int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
__u32 smb_len(unsigned char *); __u32 smb_len(unsigned char *);
__u8 *smb_encode_smb_length(__u8 *, __u32); __u8 *smb_encode_smb_length(__u8 *, __u32);
__u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16); __u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16);
......
...@@ -23,7 +23,7 @@ struct smb_sb_info { ...@@ -23,7 +23,7 @@ struct smb_sb_info {
enum smb_conn_state state; enum smb_conn_state state;
struct file * sock_file; struct file * sock_file;
struct smb_mount_data *mnt; struct smb_mount_data_kernel *mnt;
unsigned char *temp_buf; unsigned char *temp_buf;
/* Connections are counted. Each time a new socket arrives, /* Connections are counted. Each time a new socket arrives,
...@@ -41,8 +41,20 @@ struct smb_sb_info { ...@@ -41,8 +41,20 @@ struct smb_sb_info {
unsigned short rcls; /* The error codes we received */ unsigned short rcls; /* The error codes we received */
unsigned short err; 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; 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__ */ #endif /* __KERNEL__ */
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/types.h> #include <linux/types.h>
#define SMB_MOUNT_VERSION 6 #define SMB_MOUNT_VERSION 6
struct smb_mount_data { struct smb_mount_data {
int version; int version;
...@@ -22,4 +22,37 @@ struct smb_mount_data { ...@@ -22,4 +22,37 @@ struct smb_mount_data {
__kernel_mode_t dir_mode; __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 #endif
...@@ -527,6 +527,7 @@ EXPORT_SYMBOL(get_fast_time); ...@@ -527,6 +527,7 @@ EXPORT_SYMBOL(get_fast_time);
/* library functions */ /* library functions */
EXPORT_SYMBOL(strnicmp); EXPORT_SYMBOL(strnicmp);
EXPORT_SYMBOL(strspn); EXPORT_SYMBOL(strspn);
EXPORT_SYMBOL(strsep);
/* software interrupts */ /* software interrupts */
EXPORT_SYMBOL(tasklet_hi_vec); EXPORT_SYMBOL(tasklet_hi_vec);
......
...@@ -414,7 +414,7 @@ static int writeout_one_page(struct page *page) ...@@ -414,7 +414,7 @@ static int writeout_one_page(struct page *page)
if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh)) if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh))
continue; continue;
bh->b_flushtime = 0; bh->b_flushtime = jiffies;
ll_rw_block(WRITE, 1, &bh); ll_rw_block(WRITE, 1, &bh);
} while ((bh = bh->b_this_page) != head); } while ((bh = bh->b_this_page) != head);
return 0; return 0;
......
...@@ -339,7 +339,7 @@ struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig) ...@@ -339,7 +339,7 @@ struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig)
bh->b_count = bh_orig->b_count; bh->b_count = bh_orig->b_count;
bh->b_rdev = bh_orig->b_rdev; bh->b_rdev = bh_orig->b_rdev;
bh->b_state = bh_orig->b_state; bh->b_state = bh_orig->b_state;
bh->b_flushtime = 0; bh->b_flushtime = jiffies;
bh->b_next_free = NULL; bh->b_next_free = NULL;
bh->b_prev_free = NULL; bh->b_prev_free = NULL;
/* bh->b_this_page */ /* bh->b_this_page */
......
...@@ -359,6 +359,7 @@ EXPORT_SYMBOL(tcp_sockets_allocated); ...@@ -359,6 +359,7 @@ EXPORT_SYMBOL(tcp_sockets_allocated);
EXPORT_SYMBOL(sysctl_tcp_reordering); EXPORT_SYMBOL(sysctl_tcp_reordering);
EXPORT_SYMBOL(sysctl_tcp_rmem); EXPORT_SYMBOL(sysctl_tcp_rmem);
EXPORT_SYMBOL(sysctl_tcp_wmem); EXPORT_SYMBOL(sysctl_tcp_wmem);
EXPORT_SYMBOL(sysctl_tcp_ecn);
EXPORT_SYMBOL(tcp_cwnd_application_limited); EXPORT_SYMBOL(tcp_cwnd_application_limited);
EXPORT_SYMBOL(xrlim_allow); EXPORT_SYMBOL(xrlim_allow);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment