]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.79pre1 2.1.79pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:14:24 +0000 (15:14 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:14:24 +0000 (15:14 -0500)
83 files changed:
Documentation/Configure.help
Documentation/filesystems/fat_cvf.txt [new file with mode: 0644]
Makefile
arch/alpha/kernel/entry.S
arch/i386/kernel/entry.S
arch/i386/kernel/i386_ksyms.c
arch/i386/lib/Makefile
arch/i386/lib/getuser.S [new file with mode: 0644]
arch/i386/lib/putuser.S [new file with mode: 0644]
arch/i386/lib/usercopy.c [new file with mode: 0644]
arch/i386/mm/fault.c
drivers/block/ide-cd.c
drivers/block/ide-disk.c
drivers/block/ide-floppy.c
drivers/block/ide-probe.c
drivers/block/ide-proc.c
drivers/block/ide-tape.c
drivers/block/ide.c
drivers/block/ide.h
drivers/net/de4x5.c
drivers/scsi/ide-scsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_obsolete.c
drivers/scsi/scsi_syms.c
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/scsi/sr_ioctl.c
drivers/scsi/sr_vendor.c
drivers/sound/Config.in
drivers/sound/ad1848.c
drivers/sound/pas2_card.c
fs/affs/Changes
fs/affs/file.c
fs/affs/namei.c
fs/affs/super.c
fs/affs/symlink.c
fs/coda/cache.c
fs/coda/cnode.c
fs/coda/coda_linux.c
fs/coda/dir.c
fs/coda/file.c
fs/coda/inode.c [deleted file]
fs/coda/psdev.c
fs/coda/super.c
fs/coda/symlink.c
fs/dcache.c
fs/ext2/inode.c
fs/fat/Makefile
fs/fat/buffer.c
fs/fat/cache.c
fs/fat/cvf.c [new file with mode: 0644]
fs/fat/dir.c
fs/fat/fatfs_syms.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
fs/fat/mmap.c
fs/minix/namei.c
fs/namei.c
fs/nfs/nfsroot.c
fs/nfs/proc.c
fs/proc/link.c
fs/proc/root.c
fs/sysv/inode.c
fs/sysv/namei.c
include/asm-i386/uaccess.h
include/linux/affs_fs.h
include/linux/coda.h
include/linux/coda_cnode.h
include/linux/coda_linux.h
include/linux/coda_psdev.h
include/linux/fat_cvf.h [new file with mode: 0644]
include/linux/hdreg.h
include/linux/minix_fs.h
include/linux/msdos_fs.h
include/linux/msdos_fs_sb.h
include/linux/proc_fs.h
include/linux/sched.h
include/linux/sysv_fs.h
include/linux/umsdos_fs.h
kernel/exit.c
kernel/sysctl.c
net/ipv4/ipconfig.c

index f0ede54497a8ebd313961e602c23ba457b669d32..7d2145230ebc1587779611edcc86d688b0deea83 100644 (file)
@@ -333,17 +333,6 @@ CONFIG_BLK_DEV_IDEDMA
   enable DMA for drives which were not enabled automatically.
   You can get the latest version of the hdparm utility via anonymous
   FTP from sunsite.unc.edu/pub/Linux/system/hardware/
-   It is safe to say Y to this question.
-
-  If your PCI system uses IDE drive(s) (as opposed to SCSI, say)
-  and is capable of bus-master DMA operation (most Pentium PCI
-  systems), you will want to enable this option to allow use of 
-  bus-mastering DMA data transfers. Read the comments at the
-  beginning of drivers/block/idedma.c and Documentation/ide.txt.
-  You can get the latest version of the hdparm utility via 
-  ftp (user: anonymous) from
-  sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/; it is
-  used to tune your harddisk. 
   It is safe to say Y to this question.
 
 Other IDE chipset support
diff --git a/Documentation/filesystems/fat_cvf.txt b/Documentation/filesystems/fat_cvf.txt
new file mode 100644 (file)
index 0000000..9e7062e
--- /dev/null
@@ -0,0 +1,190 @@
+This is the main documentation for the CVF-FAT filesystem extension.  31DEC1997
+
+
+Table of Contents:
+
+1. The idea of CVF-FAT
+2. Restrictions
+3. Mount options
+4. Description of the CVF-FAT interface
+5. CVF Modules
+
+------------------------------------------------------------------------------
+
+
+1. The idea of CVF-FAT
+------------------------------------------------------------------------------
+
+CVF-FAT is a FAT filesystem extension that provides a generic interface for
+Compressed Volume Files in FAT partitions. Popular CVF software, for
+example, are Microsoft's Doublespace/Drivespace and Stac's Stacker.
+Using the CVF-FAT interface, it is possible to load a module that handles
+all the low-level disk access that has to do with on-the-fly compression
+and decompression. All other part of FAT filesystem access is still handled
+by the FAT, MSDOS or VFAT or even UMSDOS driver.
+
+CVF access works by redirecting certain low-level routines from the FAT
+driver to a loadable, CVF-format specific module. This module must fake
+a normal FAT filesystem to the FAT driver while doing all the extra stuff
+like compression and decompression silently.
+
+
+2. Restrictions
+------------------------------------------------------------------------------
+
+- BMAP problems
+
+  CVF filesystems cannot do bmap. It's impossible by principle. Thus
+  all actions that require bmap do not work (swapping, writable mmapping).
+  Read-only mmapping works because the FAT driver has a hack for this
+  situation :) Well, with some tricks writable mmapping could work,
+  (proof: they did under old dmsdos), but..... (hint: readpage/writepage
+  interface functions) ...... but the FAT driver has to support them 
+  first without bmap :-)
+
+  We'll see. If someone points me to an application that needs this, I
+  might be persuaded to implement it :). CVF-FAT is already prepared
+  for using readpage.
+  
+- DOSEMU users attention 
+
+  You may have to unmount all CVF partitions before running DOSEMU depending 
+  on your configuration. If DOSEMU is configured to use wholedisk or 
+  partition access (this is often the case to let DOSEMU access 
+  compressed partitions) there's a risk of destroying your compressed 
+  partitions or crashing your system because of confused drivers.
+  
+  Note that it is always safe to redirect the compressed partitions with 
+  lredir or emufs.sys. Refer to the DOSEMU documentation for details.
+
+
+3. Mount options
+------------------------------------------------------------------------------
+
+The CVF-FAT extension currently adds the following options to the FAT
+driver's standard options:
+
+  cvf_format=xxx
+    Forces the driver to use the CVF module "xxx" instead of auto-detection.
+    This is only necessary if the CVF format is not recognized corrrectly
+    because of bugs or incompatibilities in the CVF modules. (It skips
+    the detect_cvf call.) "xxx" may be the text "none" (without the quotes)
+    to inhibit using any of the loaded CVF modules, just in case a CVF
+    module insists on mounting plain FAT filesystems by misunderstanding :)
+
+  cvf_options=yyy
+    Option string passed to the CVF module. I.e. only the "yyy" is passed
+    (without the quotes). The documentation for each CVF module should 
+    explain it since it is interpreted only by the CVF module. Note that 
+    the string must not contain a comma (",") - this would lead to 
+    misinterpretation by the FAT driver, which would recognize the text 
+    after a comma as a FAT driver option and might get confused or print 
+    strange error messages. The documentation for the CVF module should 
+    offer a different seperation symbol, for example the dot ".", which
+    is only valid inside the string "yyy".
+
+
+4. Description of the CVF-FAT interface
+------------------------------------------------------------------------------
+
+Assuming you want to write your own CVF module, you need to write a lot of
+interface funtions. Most of them are covered in the kernel documentation
+you can find on the net, and thus won't be described here. They have been
+marked with "[...]" :-) Take a look at include/linux/fat_cvf.h.
+
+struct cvf_format
+{ int cvf_version;
+  char* cvf_version_text;
+  unsigned long int flags;
+  int (*detect_cvf) (struct super_block*sb);
+  int (*mount_cvf) (struct super_block*sb,char*options);
+  int (*unmount_cvf) (struct super_block*sb);
+  [...]
+  void (*cvf_zero_cluster) (struct inode*inode,int clusternr);
+}
+
+This structure defines the capabilities of a CVF module. It must be filled
+out completely by a CVF module. Consider it as a kind of form that is used
+to introduce the module to the FAT/CVF-FAT driver.
+
+It contains...
+  - cvf_version:
+      A version id which must be uniqe. Choose one.
+  - cvf_version_text:
+      A human readable version string that should be one short word 
+      describing the CVF format the module implements. This text is used
+      for the cvf_format option. This name must also be uniqe.
+  - flags:
+      Bit coded flags, currently only used for a readpage/mmap hack that 
+      provides both mmap and readpage functionality. If CVF_USE_READPAGE
+      is set, mmap is set to generic_file_mmap and readpage is caught
+      and redirected to the cvf_readpage function. If it is not set,
+      readpage is set to generic_readpage and mmap is caught and redirected
+      to cvf_mmap.
+  - detect_cvf:
+      A function that is called to decide whether the filesystem is a CVF of
+      the type the module supports. The detect_cvf function must return 0
+      for "NO, I DON'T KNOW THIS GARBAGE" or anything !=0 for "YES, THIS IS
+      THE KIND OF CVF I SUPPORT". The function must maintain the module
+      usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning
+      and MOD_DEC_USE_COUNT at the end. The function *must not* assume that
+      successful recongition would lead to a call of the mount_cvf function
+      later. 
+  - mount_cvf:
+      A function that sets up some values or initializes something additional
+      to what has to be done when a CVF is mounted. This is called at the
+      end of fat_read_super and must return 0 on success. Definitely, this
+      function must increment the module usage counter by MOD_INC_USE_COUNT.
+      This mount_cvf function is also responsible for interpreting a CVF
+      module specific option string (the "yyy" from the FAT mount option
+      "cvf_options=yyy") which cannot contain a comma (use for example the
+      dot "." as option separator symbol).
+  - unmount_cvf:
+      A function that is called when the filesystem is unmounted. Most likely
+      it only frees up some memory and calls MOD_DEC_USE_COUNT. The return
+      value might be ignored (it currently is ignored).
+  - [...]:
+      All other interface functions are "caught" FAT driver functions, i.e.
+      are executed by the FAT driver *instead* of the original FAT driver
+      functions. NULL means use the original FAT driver functions instead.
+      If you really want "no action", write a function that does nothing and 
+      hang it in instead.
+  - cvf_zero_cluster:
+      The cvf_zero_cluster function is called when the fat driver wants to
+      zero out a (new) cluster. This is important for directories (mkdir).
+      If it is NULL, the FAT driver defaults to overwriting the whole
+      cluster with zeros. Note that clusternr is absolute, not relative
+      to the provided inode.
+
+Notes:
+  1. The cvf_bmap function should be ignored. It really should never
+     get called from somewhere. I recommend redirecting it to a panic
+     or fatal error message so bugs show up immediately.
+  2. The cvf_writepage function is ignored. This is because the fat
+     driver doesn't support it. This might change in future. I recommend
+     setting it to NULL (i.e use default).
+
+int register_cvf_format(struct cvf_format*cvf_format);
+  If you have just set up a variable containing the above structure,
+  call this function to introduce your CVF format to the FAT/CVF-FAT
+  driver. This is usually done in init_module. Be sure to check the
+  return value. Zero means success, everything else causes a kernel
+  message printed in the syslog describing the error that occured.
+  Typical errors are:
+    - a module with the same version id is already registered or 
+    - too many CVF formats. Hack fs/fat/cvf.c if you need more.
+
+int unregister_cvf_format(struct cvf_format*cvf_format);
+  This is usually called in cleanup_module. Return value =0 means
+  success. An error only occurs if you try to unregister a CVF format
+  that has not been previously registered. The code uses the version id
+  to distinguish the modules, so be sure to keep it uniqe.
+
+5. CVS Modules
+------------------------------------------------------------------------------
+
+Refer to the dmsdos module (the successor of the dmsdos filesystem) for a
+sample implementation.  It can currently be found at
+
+  ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos
+
index f07be525c02e90db78eed634382f0b418cd19e4a..2d5c48b4bb02353df4c233b6f6d96945e8299747 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 78
+SUBLEVEL = 79
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
index f703c668a7dff1b54f26bdb8aa9fe88f48c3d792..222d042ed9992d35bf9d772afca38c3500130465 100644 (file)
 /*
  * task structure offsets
  */
-#define TASK_STATE     0
-#define TASK_COUNTER   8
-#define TASK_PRIORITY  16
-#define TASK_FLAGS     24
-#define TASK_SIGPENDING        32      
+#define TASK_STATE      0
+#define TASK_FLAGS      8
+#define TASK_SIGPENDING        16
+#define TASK_SIZE      24      
 
 /*
  * task flags (must match include/linux/sched.h):
index cf99d6e2ef83cfc05d66a538a966600f9b91fdd3..fd71492ad7b1da480948d5a59ba659dcc64c9f13 100644 (file)
@@ -71,13 +71,10 @@ VM_MASK             = 0x00020000
  * these are offsets into the task-struct.
  */
 state          =  0
-counter                =  4
-priority       =  8
-flags          = 12
-sigpending     = 16
-dbgreg6                = 44
-dbgreg7                = 48
-exec_domain    = 52
+flags          =  4
+sigpending     =  8
+addr_limit     = 12
+exec_domain    = 16
 
 ENOSYS = 38
 
index 3433bc5dc5c91bd019cc4017a11e11372fb2fbd0..393b070aa5b965d9bc054489b2a5a2cd09f3e50a 100644 (file)
@@ -47,6 +47,20 @@ EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__delay);
 EXPORT_SYMBOL(__const_udelay);
 
+EXPORT_SYMBOL_NOVERS(__get_user_1);
+EXPORT_SYMBOL_NOVERS(__get_user_2);
+EXPORT_SYMBOL_NOVERS(__get_user_4);
+EXPORT_SYMBOL_NOVERS(__put_user_1);
+EXPORT_SYMBOL_NOVERS(__put_user_2);
+EXPORT_SYMBOL_NOVERS(__put_user_4);
+
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(clear_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__generic_copy_from_user);
+EXPORT_SYMBOL(__generic_copy_to_user);
+EXPORT_SYMBOL(strlen_user);
 
 #ifdef __SMP__
 EXPORT_SYMBOL(apic_reg);       /* Needed internally for the I386 inlines */
@@ -79,3 +93,4 @@ EXPORT_SYMBOL(mca_set_adapter_procfn);
 EXPORT_SYMBOL(mca_isenabled);
 EXPORT_SYMBOL(mca_isadapter);
 #endif
+
index 6b76e32d601ac9442276ae7415de0d3c17a11112..a4e4b1486b5d5f02e5f84fde6dc21ac2894e9f5c 100644 (file)
@@ -11,6 +11,6 @@ else
 endif
 
 L_TARGET = lib.a
-L_OBJS  = checksum.o semaphore.o locks.o delay.o
+L_OBJS  = checksum.o semaphore.o locks.o delay.o usercopy.o getuser.o putuser.o
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/i386/lib/getuser.S b/arch/i386/lib/getuser.S
new file mode 100644 (file)
index 0000000..e0c016f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * __get_user functions.
+ *
+ * (C) Copyright 1998 Linus Torvalds
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
+ */
+
+/*
+ * __get_user_X
+ *
+ * Inputs:     %eax contains the address
+ *
+ * Outputs:    %eax is error code (0 or -EFAULT)
+ *             %edx contains zero-extended value
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+addr_limit = 12
+
+.text
+.align 4
+.globl __get_user_1
+__get_user_1:
+       movl %esp,%edx
+       andl $0xffffe000,%edx
+       cmpl %eax,addr_limit(%edx)
+       jnb bad_get_user
+1:     movzbl (%eax),%edx
+       xorl %eax,%eax
+       ret
+
+.align 4
+.globl __get_user_2
+__get_user_2:
+       addl $1,%eax
+       movl %esp,%edx
+       jc bad_get_user
+       andl $0xffffe000,%edx
+       cmpl %eax,addr_limit(%edx)
+       jnb bad_get_user
+2:     movzwl -1(%eax),%edx
+       xorl %eax,%eax
+       ret
+
+.align 4
+.globl __get_user_4
+__get_user_4:
+       addl $3,%eax
+       movl %esp,%edx
+       jc bad_get_user
+       andl $0xffffe000,%edx
+       cmpl %eax,addr_limit(%edx)
+       jnb bad_get_user
+3:     movl -3(%eax),%edx
+       xorl %eax,%eax
+       ret
+
+bad_get_user:
+       xorl %edx,%edx
+       movl $-14,%eax
+       ret
+
+.section __ex_table,"a"
+       .long 1b,bad_get_user
+       .long 2b,bad_get_user
+       .long 3b,bad_get_user
+.previous
diff --git a/arch/i386/lib/putuser.S b/arch/i386/lib/putuser.S
new file mode 100644 (file)
index 0000000..0c24470
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * __put_user functions.
+ *
+ * (C) Copyright 1998 Linus Torvalds
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient.
+ */
+
+/*
+ * __put_user_X
+ *
+ * Inputs:     %eax contains the address
+ *             %edx contains the value
+ *
+ * Outputs:    %eax is error code (0 or -EFAULT)
+ *             %ecx is corrupted (will contain "current_task").
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+addr_limit = 12
+
+.text
+.align 4
+.globl __put_user_1
+__put_user_1:
+       movl %esp,%ecx
+       andl $0xffffe000,%ecx
+       cmpl %eax,addr_limit(%ecx)
+       jnb bad_put_user
+1:     movb %dl,(%eax)
+       xorl %eax,%eax
+       ret
+
+.align 4
+.globl __put_user_2
+__put_user_2:
+       addl $1,%eax
+       movl %esp,%ecx
+       jc bad_put_user
+       andl $0xffffe000,%ecx
+       cmpl %eax,addr_limit(%ecx)
+       jnb bad_put_user
+2:     movw %dx,-1(%eax)
+       xorl %eax,%eax
+       ret
+
+.align 4
+.globl __put_user_4
+__put_user_4:
+       addl $3,%eax
+       movl %esp,%ecx
+       jc bad_put_user
+       andl $0xffffe000,%ecx
+       cmpl %eax,addr_limit(%ecx)
+       jnb bad_put_user
+3:     movl %edx,-3(%eax)
+       xorl %eax,%eax
+       ret
+
+bad_put_user:
+       movl $-14,%eax
+       ret
+
+.section __ex_table,"a"
+       .long 1b,bad_put_user
+       .long 2b,bad_put_user
+       .long 3b,bad_put_user
+.previous
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
new file mode 100644 (file)
index 0000000..24b080f
--- /dev/null
@@ -0,0 +1,136 @@
+/* 
+ * User address space access functions.
+ * The non inlined parts of asm-i386/uaccess.h are here.
+ *
+ * Copyright 1997 Andi Kleen <ak@muc.de>
+ * Copyright 1997 Linus Torvalds
+ */
+#include <asm/uaccess.h>
+
+inline unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               __copy_user(to,from,n);
+       return n;
+}
+
+inline unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_READ, from, n))
+               __copy_user(to,from,n);
+       return n;
+}
+
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+
+#define __do_strncpy_from_user(dst,src,count,res)                         \
+       __asm__ __volatile__(                                              \
+               "       testl %1,%1\n"                                     \
+               "       jz 2f\n"                                           \
+               "0:     lodsb\n"                                           \
+               "       stosb\n"                                           \
+               "       testb %%al,%%al\n"                                 \
+               "       jz 1f\n"                                           \
+               "       decl %1\n"                                         \
+               "       jnz 0b\n"                                          \
+               "1:     subl %1,%0\n"                                      \
+               "2:\n"                                                     \
+               ".section .fixup,\"ax\"\n"                                 \
+               "3:     movl %2,%0\n"                                      \
+               "       jmp 2b\n"                                          \
+               ".previous\n"                                              \
+               ".section __ex_table,\"a\"\n"                              \
+               "       .align 4\n"                                        \
+               "       .long 0b,3b\n"                                     \
+               ".previous"                                                \
+               : "=d"(res), "=c"(count)                                   \
+               : "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \
+               : "si", "di", "ax", "memory")
+
+long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+       long res;
+       __do_strncpy_from_user(dst, src, count, res);
+       return res;
+}
+
+long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+       long res = -EFAULT;
+       if (access_ok(VERIFY_READ, src, 1))
+               __do_strncpy_from_user(dst, src, count, res);
+       return res;
+}
+
+
+/*
+ * Zero Userspace
+ */
+
+#define __do_clear_user(addr,size)                                             \
+       __asm__ __volatile__(                                           \
+               "0:     rep; stosl\n"                                   \
+               "       movl %1,%0\n"                                   \
+               "1:     rep; stosb\n"                                   \
+               "2:\n"                                                  \
+               ".section .fixup,\"ax\"\n"                              \
+               "3:     lea 0(%1,%0,4),%0\n"                            \
+               "       jmp 2b\n"                                       \
+               ".previous\n"                                           \
+               ".section __ex_table,\"a\"\n"                           \
+               "       .align 4\n"                                     \
+               "       .long 0b,3b\n"                                  \
+               "       .long 1b,2b\n"                                  \
+               ".previous"                                             \
+               : "=c"(size)                                            \
+               : "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0)       \
+               : "di")
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               __do_clear_user(to, n);
+       return n;
+}
+
+unsigned long
+__clear_user(void *to, unsigned long n)
+{
+       __do_clear_user(to, n);
+       return n;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+
+long strlen_user(const char *s)
+{
+       unsigned long res;
+
+       __asm__ __volatile__(
+               "0:     repne; scasb\n"
+               "       notl %0\n"
+               "1:\n"
+               ".section .fixup,\"ax\"\n"
+               "2:     xorl %0,%0\n"
+               "       jmp 1b\n"
+               ".previous\n"
+               ".section __ex_table,\"a\"\n"
+               "       .align 4\n"
+               "       .long 0b,2b\n"
+               ".previous"
+               :"=c" (res), "=D" (s)
+               :"1" (s), "a" (0), "0" (-__addr_ok(s)));
+       return res & -__addr_ok(s);
+}
index 75ada6ba033c42eec3f5ad3c212f585197d73ccd..79b0f5da893009af2db28e0a19d294517d9a76cc 100644 (file)
@@ -192,11 +192,6 @@ bad_area:
 
        /* Are we prepared to handle this kernel fault?  */
        if ((fixup = search_exception_table(regs->eip)) != 0) {
-               printk(KERN_DEBUG "%s: Exception at [<%lx>] cr2=%lx (fixup: %lx)\n",
-                       tsk->comm,
-                       regs->eip,
-                       address,
-                       fixup);
                regs->eip = fixup;
                goto out;
        }
index 13d6df9f6e02e5d159969b9bde943c5f6d51227f..caf334d27d56f0bcaf35e99e361c2feead829918 100644 (file)
@@ -2772,6 +2772,17 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        return nslots;
 }
 
+static void ide_cdrom_add_settings(ide_drive_t *drive)
+{
+       int major = HWIF(drive)->major;
+       int minor = drive->select.b.unit << PARTN_BITS;
+
+       ide_add_setting(drive,  "breada_readahead",     SETTING_RW,                                     BLKRAGET,               BLKRASET,               TYPE_INT,       0,      255,                            1,      2,      &read_ahead[major],             NULL);
+       ide_add_setting(drive,  "file_readahead",       SETTING_RW,                                     BLKFRAGET,              BLKFRASET,              TYPE_INTA,      0,      INT_MAX,                        1,      1024,   &max_readahead[major][minor],   NULL);
+       ide_add_setting(drive,  "max_kb_per_request",   SETTING_RW,                                     BLKSECTGET,             BLKSECTSET,             TYPE_INTA,      1,      255,                            1,      2,      &max_sectors[major][minor],     NULL);
+       ide_add_setting(drive,  "dsc_overlap",          SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      1,                              1,      1,      &drive->dsc_overlap,            NULL);
+}
+
 static
 int ide_cdrom_setup (ide_drive_t *drive)
 {
@@ -2884,6 +2895,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
                info->devinfo.handle = NULL;
                return 1;
        }
+       ide_cdrom_add_settings(drive);
        return 0;
 }
 
@@ -2942,13 +2954,6 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
        return 0;
 }
 
-int ide_cdrom_init (void);
-static ide_module_t ide_cdrom_module = {
-       IDE_DRIVER_MODULE,
-       ide_cdrom_init,
-       NULL
-};
-
 static ide_driver_t ide_cdrom_driver = {
        "ide-cdrom",                    /* name */
        IDECD_VERSION,                  /* version */
@@ -2969,6 +2974,13 @@ static ide_driver_t ide_cdrom_driver = {
        NULL                            /* proc */
 };
 
+int ide_cdrom_init (void);
+static ide_module_t ide_cdrom_module = {
+       IDE_DRIVER_MODULE,
+       ide_cdrom_init,
+       &ide_cdrom_driver,
+       NULL
+};
 
 #ifdef MODULE
 int init_module (void)
@@ -2981,7 +2993,7 @@ void cleanup_module(void)
        ide_drive_t *drive;
        int failed = 0;
 
-       while ((drive = ide_scan_devices (ide_cdrom, &ide_cdrom_driver, failed)) != NULL)
+       while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL)
                if (ide_cdrom_cleanup (drive)) {
                        printk ("%s: cleanup_module() called while still busy\n", drive->name);
                        failed++;
@@ -2997,7 +3009,7 @@ int ide_cdrom_init (void)
        int failed = 0;
 
        MOD_INC_USE_COUNT;
-       while ((drive = ide_scan_devices (ide_cdrom, NULL, failed++)) != NULL) {
+       while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) {
                info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
                if (info == NULL) {
                        printk ("%s: Can't allocate a cdrom structure\n", drive->name);
index 67221e10d8181b827ea514b4f0b38ec9cbf51c27..933d946977fa3b347ea075a48b20ccfbddf722fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide-disk.c     Version 1.03  Nov  30, 1997
+ *  linux/drivers/block/ide-disk.c     Version 1.04  Jan   7, 1998
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
  * Version 1.00                move disk only code from ide.c to ide-disk.c
  *                     support optional byte-swapping of all data
  * Version 1.01                fix previous byte-swapping code
- * Verions 1.02                remove ", LBA" from drive identification msgs
- * Verions 1.03                fix display of id->buf_size for big-endian
+ * Version 1.02                remove ", LBA" from drive identification msgs
+ * Version 1.03                fix display of id->buf_size for big-endian
+ * Version 1.04                add /proc configurable settings and S.M.A.R.T support
  */
 
-#define IDEDISK_VERSION        "1.03"
+#define IDEDISK_VERSION        "1.04"
 
 #undef REALLY_SLOW_IO          /* most systems can safely undef this */
 
@@ -372,17 +373,13 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr
 {
        MOD_INC_USE_COUNT;
        if (drive->removable && drive->usage == 1) {
-               byte door_lock[] = {WIN_DOORLOCK,0,0,0};
-               struct request rq;
                check_disk_change(inode->i_rdev);
-               ide_init_drive_cmd (&rq);
-               rq.buffer = door_lock;
                /*
                 * Ignore the return code from door_lock,
                 * since the open() has already succeeded,
                 * and the door_lock is irrelevant at this point.
                 */
-               (void) ide_do_drive_cmd(drive, &rq, ide_wait);
+               (void) ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL);
        }
        return 0;
 }
@@ -390,12 +387,8 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr
 static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
        if (drive->removable && !drive->usage) {
-               byte door_unlock[] = {WIN_DOORUNLOCK,0,0,0};
-               struct request rq;
                invalidate_buffers(inode->i_rdev);
-               ide_init_drive_cmd (&rq);
-               rq.buffer = door_unlock;
-               (void) ide_do_drive_cmd(drive, &rq, ide_wait);
+               (void) ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL);
        }
        MOD_DEC_USE_COUNT;
 }
@@ -481,18 +474,106 @@ static int proc_idedisk_read_cache
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
+static int smart_enable(ide_drive_t *drive)
+{
+       return ide_wait_cmd(drive, WIN_SMART, 0, SMART_ENABLE, 0, NULL);
+}
+
+static int get_smart_values(ide_drive_t *drive, byte *buf)
+{
+       (void) smart_enable(drive);
+       return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_VALUES, 1, buf);
+}
+
+static int get_smart_thresholds(ide_drive_t *drive, byte *buf)
+{
+       (void) smart_enable(drive);
+       return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_THRESHOLDS, 1, buf);
+}
+
+static int proc_idedisk_read_smart_thresholds
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       ide_drive_t     *drive = (ide_drive_t *)data;
+       int             len = 0, i = 0;
+
+       if (!get_smart_thresholds(drive, page)) {
+               unsigned short *val = ((unsigned short *)page) + 2;
+               char *out = ((char *)val) + (SECTOR_WORDS * 4);
+               page = out;
+               do {
+                       out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+                       val += 1;
+               } while (i < (SECTOR_WORDS * 2));
+               len = out - page;
+       }
+       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
+static int proc_idedisk_read_smart_values
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       ide_drive_t     *drive = (ide_drive_t *)data;
+       int             len = 0, i = 0;
+
+       if (!get_smart_values(drive, page)) {
+               unsigned short *val = ((unsigned short *)page) + 2;
+               char *out = ((char *)val) + (SECTOR_WORDS * 4);
+               page = out;
+               do {
+                       out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+                       val += 1;
+               } while (i < (SECTOR_WORDS * 2));
+               len = out - page;
+       }
+       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
 static ide_proc_entry_t idedisk_proc[] = {
        { "cache", proc_idedisk_read_cache, NULL },
        { "geometry", proc_ide_read_geometry, NULL },
+       { "smart_values", proc_idedisk_read_smart_values, NULL },
+       { "smart_thresholds", proc_idedisk_read_smart_thresholds, NULL },
        { NULL, NULL, NULL }
 };
 
-int idedisk_init (void);
-static ide_module_t idedisk_module = {
-       IDE_DRIVER_MODULE,
-       idedisk_init,
-       NULL
-};
+static int set_multcount(ide_drive_t *drive, int arg)
+{
+       struct request rq;
+
+       if (drive->special.b.set_multmode)
+               return -EBUSY;
+       ide_init_drive_cmd (&rq);
+       drive->mult_req = arg;
+       drive->special.b.set_multmode = 1;
+       (void) ide_do_drive_cmd (drive, &rq, ide_wait);
+       return (drive->mult_count == arg) ? 0 : -EIO;
+}
+
+static int set_nowerr(ide_drive_t *drive, int arg)
+{
+       drive->nowerr = arg;
+       drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
+       return 0;
+}
+
+static void idedisk_add_settings(ide_drive_t *drive)
+{
+       struct hd_driveid *id = drive->id;
+       int major = HWIF(drive)->major;
+       int minor = drive->select.b.unit << PARTN_BITS;
+
+       ide_add_setting(drive,  "bios_cyl",             SETTING_RW,                                     -1,                     -1,                     TYPE_SHORT,     0,      1023,                           1,      1,      &drive->bios_cyl,               NULL);
+       ide_add_setting(drive,  "bios_head",            SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      255,                            1,      1,      &drive->bios_head,              NULL);
+       ide_add_setting(drive,  "bios_sect",            SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      63,                             1,      1,      &drive->bios_sect,              NULL);
+       ide_add_setting(drive,  "bswap",                SETTING_READ,                                   -1,                     -1,                     TYPE_BYTE,      0,      1,                              1,      1,      &drive->bswap,                  NULL);
+       ide_add_setting(drive,  "multcount",            id ? SETTING_RW : SETTING_READ,                 HDIO_GET_MULTCOUNT,     HDIO_SET_MULTCOUNT,     TYPE_BYTE,      0,      id ? id->max_multsect : 0,      1,      2,      &drive->mult_count,             set_multcount);
+       ide_add_setting(drive,  "nowerr",               SETTING_RW,                                     HDIO_GET_NOWERR,        HDIO_SET_NOWERR,        TYPE_BYTE,      0,      1,                              1,      1,      &drive->nowerr,                 set_nowerr);
+       ide_add_setting(drive,  "breada_readahead",     SETTING_RW,                                     BLKRAGET,               BLKRASET,               TYPE_INT,       0,      255,                            1,      2,      &read_ahead[major],             NULL);
+       ide_add_setting(drive,  "file_readahead",       SETTING_RW,                                     BLKFRAGET,              BLKFRASET,              TYPE_INTA,      0,      INT_MAX,                        1,      1024,   &max_readahead[major][minor],   NULL);
+       ide_add_setting(drive,  "max_kb_per_request",   SETTING_RW,                                     BLKSECTGET,             BLKSECTSET,             TYPE_INTA,      1,      255,                            1,      2,      &max_sectors[major][minor],     NULL);
+
+}
 
 /*
  *     IDE subdriver functions, registered with ide.c
@@ -517,6 +598,14 @@ static ide_driver_t idedisk_driver = {
        idedisk_proc            /* proc */
 };
 
+int idedisk_init (void);
+static ide_module_t idedisk_module = {
+       IDE_DRIVER_MODULE,
+       idedisk_init,
+       &idedisk_driver,
+       NULL
+};
+
 static int idedisk_cleanup (ide_drive_t *drive)
 {
        return ide_unregister_subdriver(drive);
@@ -527,6 +616,8 @@ static void idedisk_setup (ide_drive_t *drive)
        struct hd_driveid *id = drive->id;
        unsigned long capacity, check;
        
+       idedisk_add_settings(drive);
+
        if (id == NULL)
                return;
 
@@ -615,7 +706,7 @@ int idedisk_init (void)
        int failed = 0;
        
        MOD_INC_USE_COUNT;
-       while ((drive = ide_scan_devices (ide_disk, NULL, failed++)) != NULL) {
+       while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) {
 
                /* SunDisk drives: ignore "second" drive;   can mess up non-Sun systems!  FIXME */
                struct hd_driveid *id = drive->id;
@@ -650,7 +741,7 @@ void cleanup_module (void)
        ide_drive_t *drive;
        int failed = 0;
 
-       while ((drive = ide_scan_devices (ide_disk, &idedisk_driver, failed)) != NULL)
+       while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL)
                if (idedisk_cleanup (drive)) {
                        printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
                        failed++;
index 8e6d47d72e393fd7f62d086cafb24f678ad3dd4d..d79f79ac4d272f4ed18e7a2affac460ca2587460 100644 (file)
@@ -1327,6 +1327,20 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id)
        return 0;
 }
 
+static void idefloppy_add_settings(ide_drive_t *drive)
+{
+       int major = HWIF(drive)->major;
+       int minor = drive->select.b.unit << PARTN_BITS;
+
+       ide_add_setting(drive,  "bios_cyl",             SETTING_RW,                                     -1,                     -1,                     TYPE_SHORT,     0,      1023,                           1,      1,      &drive->bios_cyl,               NULL);
+       ide_add_setting(drive,  "bios_head",            SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      255,                            1,      1,      &drive->bios_head,              NULL);
+       ide_add_setting(drive,  "bios_sect",            SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      63,                             1,      1,      &drive->bios_sect,              NULL);
+       ide_add_setting(drive,  "breada_readahead",     SETTING_RW,                                     BLKRAGET,               BLKRASET,               TYPE_INT,       0,      255,                            1,      2,      &read_ahead[major],             NULL);
+       ide_add_setting(drive,  "file_readahead",       SETTING_RW,                                     BLKFRAGET,              BLKFRASET,              TYPE_INTA,      0,      INT_MAX,                        1,      1024,   &max_readahead[major][minor],   NULL);
+       ide_add_setting(drive,  "max_kb_per_request",   SETTING_RW,                                     BLKSECTGET,             BLKSECTSET,             TYPE_INTA,      1,      255,                            1,      2,      &max_sectors[major][minor],     NULL);
+
+}
+
 /*
  *     Driver initialization.
  */
@@ -1351,6 +1365,7 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
        }
 
        (void) idefloppy_get_capacity (drive);
+       idefloppy_add_settings(drive);
 }
 
 static int idefloppy_cleanup (ide_drive_t *drive)
@@ -1369,13 +1384,6 @@ static ide_proc_entry_t idefloppy_proc[] = {
        { NULL, NULL, NULL }
 };
 
-int idefloppy_init (void);
-static ide_module_t idefloppy_module = {
-       IDE_DRIVER_MODULE,
-       idefloppy_init,
-       NULL
-};
-
 /*
  *     IDE subdriver functions, registered with ide.c
  */
@@ -1399,6 +1407,14 @@ static ide_driver_t idefloppy_driver = {
        idefloppy_proc          /* proc */
 };
 
+int idefloppy_init (void);
+static ide_module_t idefloppy_module = {
+       IDE_DRIVER_MODULE,
+       idefloppy_init,
+       &idefloppy_driver,
+       NULL
+};
+
 /*
  *     idefloppy_init will register the driver for each floppy.
  */
@@ -1409,7 +1425,7 @@ int idefloppy_init (void)
        int failed = 0;
 
        MOD_INC_USE_COUNT;
-       while ((drive = ide_scan_devices (ide_floppy, NULL, failed++)) != NULL) {
+       while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) {
                if (!idefloppy_identify_device (drive, drive->id)) {
                        printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name);
                        continue;
@@ -1442,7 +1458,7 @@ void cleanup_module (void)
        ide_drive_t *drive;
        int failed = 0;
 
-       while ((drive = ide_scan_devices (ide_floppy, &idefloppy_driver, failed)) != NULL)
+       while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL)
                if (idefloppy_cleanup (drive)) {
                        printk ("%s: cleanup_module() called while still busy\n", drive->name);
                        failed++;
index d8280959edc2990ebe6d6ba01f1d322bb6802458..57b4a1f0646b38a3a9bdca6985dc38d54d8260ed 100644 (file)
@@ -624,6 +624,11 @@ static void init_gendisk (ide_hwif_t *hwif)
 
        for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) ;
        hwif->gd = *gdp = gd;                   /* link onto tail of list */
+
+       for (unit = 0; unit < units; ++unit) {
+               if (hwif->drives[unit].present)
+                       ide_add_generic_settings(hwif->drives + unit);
+       }
 }
 
 static int hwif_init (ide_hwif_t *hwif)
index ea377e447400e357dd44a5569a8071de5b586b68..86718864ae928e3dce6063bf99a5d8a7296ed986 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide-proc.c     Version 1.02    December 31, 1997
+ *  linux/drivers/block/ide-proc.c     Version 1.03    January   2, 1998
  *
  *  Copyright (C) 1997-1998    Mark Lord
  */
  * If there is an error *anywhere* in the string of registers/data
  * then *none* of the writes will be performed.
  *
- * Also useful, "cat /proc/ide0/hda/identify" will issue an IDENTIFY
- * (or PACKET_IDENTIFY) command to /dev/hda, and then dump out the
+ * Drive/Driver settings can be retrieved by reading the drive's
+ * "settings" files.  e.g.    "cat /proc/ide0/hda/settings"
+ * To write a new value "val" into a specific setting "name", use:
+ *   echo "name:val" >/proc/ide/ide0/hda/settings
+ *
+ * Also useful, "cat /proc/ide0/hda/[identify, smart_values,
+ * smart_thresholds, capabilities]" will issue an IDENTIFY /
+ * PACKET_IDENTIFY / SMART_READ_VALUES / SMART_READ_THRESHOLDS /
+ * SENSE CAPABILITIES command to /dev/hda, and then dump out the
  * returned data as 256 16-bit words.  The "hdparm" utility will
  * be updated someday soon to use this mechanism.
  *
@@ -80,6 +87,16 @@ static int ide_getxdigit(char c)
        return digit;
 }
 
+static int ide_getdigit(char c)
+{
+       int digit;
+       if (isdigit(c))
+               digit = c - '0';
+       else
+               digit = -1;
+       return digit;
+}
+
 static int xx_xx_parse_error (const char *data, unsigned long len, const char *msg)
 {
        char errbuf[16];
@@ -237,6 +254,24 @@ parse_error:
        return xx_xx_parse_error(start, startn, msg);
 }
 
+static int proc_ide_read_drivers
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       char            *out = page;
+       int             len;
+       ide_module_t    *p = ide_modules;
+       ide_driver_t    *driver;
+
+       while (p) {
+               driver = (ide_driver_t *) p->info;
+               if (p->type == IDE_DRIVER_MODULE && driver)
+                       out += sprintf(out, "%s version %s\n", driver->name, driver->version);
+               p = p->next;
+       }
+       len = out - page;
+       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
 static int proc_ide_read_config
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -325,22 +360,9 @@ static int proc_ide_read_channel
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
-static int proc_ide_get_identify (ide_drive_t *drive, byte *buf)
+static int proc_ide_get_identify(ide_drive_t *drive, byte *buf)
 {
-       struct request rq;
-       byte *end;
-
-       ide_init_drive_cmd(&rq);
-       rq.buffer = buf;
-       *buf++ = (drive->media == ide_disk) ? WIN_IDENTIFY : WIN_PIDENTIFY;
-       *buf++ = 0;
-       *buf++ = 0;
-       *buf++ = 1;
-       end = buf + (SECTOR_WORDS * 4);
-       while (buf != end)
-               *buf++ = 0;     /* pre-zero it, in case identify fails */
-       (void) ide_do_drive_cmd(drive, &rq, ide_wait);
-       return 0;
+       return ide_wait_cmd(drive, (drive->media == ide_disk) ? WIN_IDENTIFY : WIN_PIDENTIFY, 0, 0, 1, buf);
 }
 
 static int proc_ide_read_identify
@@ -366,25 +388,130 @@ static int proc_ide_read_settings
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
        ide_drive_t     *drive = (ide_drive_t *) data;
-       int             major = HWIF(drive)->major;
-       int             minor = drive->select.b.unit << PARTN_BITS;
+       ide_settings_t  *setting = (ide_settings_t *) drive->settings;
        char            *out = page;
-       int             len;
-
-       out += sprintf(out,"multcount    %i\n", drive->mult_count);
-       out += sprintf(out,"io_32bit     %i\n", drive->io_32bit);
-       out += sprintf(out,"unmaskirq    %i\n", drive->unmask);
-       out += sprintf(out,"using_dma    %i\n", drive->using_dma);
-       out += sprintf(out,"nowerr       %i\n", drive->bad_wstat == BAD_R_STAT);
-       out += sprintf(out,"keepsettings %i\n", drive->keep_settings);
-       out += sprintf(out,"nice         %i/%i/%i\n", drive->nice0, drive->nice1, drive->nice2);
-       out += sprintf(out,"dsc_overlap  %i\n", drive->dsc_overlap);
-       out += sprintf(out,"max_sectors  %i\n", max_sectors[major][minor]);
-       out += sprintf(out,"readahead    %i\n", max_readahead[major][minor] / 1024);
+       int             len, rc, mul_factor, div_factor;
+
+       out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
+       out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
+       while(setting) {
+               mul_factor = setting->mul_factor;
+               div_factor = setting->div_factor;
+               out += sprintf(out, "%-24s", setting->name);
+               if ((rc = ide_read_setting(drive, setting)) >= 0)
+                       out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
+               else
+                       out += sprintf(out, "%-16s", "write-only");
+               out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
+               if (setting->rw & SETTING_READ)
+                       out += sprintf(out, "r");
+               if (setting->rw & SETTING_WRITE)
+                       out += sprintf(out, "w");
+               out += sprintf(out, "\n");
+               setting = setting->next;
+       }
        len = out - page;
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
+#define MAX_LEN        30
+
+static int proc_ide_write_settings
+       (struct file *file, const char *buffer, unsigned long count, void *data)
+{
+       ide_drive_t     *drive = (ide_drive_t *) data;
+       ide_hwif_t      *hwif = HWIF(drive);
+       char            name[MAX_LEN + 1];
+       int             for_real = 0, len;
+       unsigned long   n, flags;
+       const char      *start = NULL;
+       ide_settings_t  *setting;
+
+       if (!suser())
+               return -EACCES;
+
+       /*
+        * Skip over leading whitespace
+        */
+       while (count && isspace(*buffer)) {
+               --count;
+               ++buffer;
+       }
+       /*
+        * Do one full pass to verify all parameters,
+        * then do another to actually write the pci regs.
+        */
+       save_flags(flags);
+       do {
+               const char *p;
+               if (for_real) {
+                       unsigned long timeout = jiffies + (3 * HZ);
+                       ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup);
+                       ide_hwgroup_t *mategroup = NULL;
+                       if (hwif->mate && hwif->mate->hwgroup)
+                               mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
+                       cli();  /* ensure all PCI writes are done together */
+                       while (mygroup->active || (mategroup && mategroup->active)) {
+                               restore_flags(flags);
+                               if (0 < (signed long)(jiffies - timeout)) {
+                                       printk("/proc/ide/%s/pci: channel(s) busy, cannot write\n", hwif->name);
+                                       return -EBUSY;
+                               }
+                               cli();
+                       }
+               }
+               p = buffer;
+               n = count;
+               while (n > 0) {
+                       int d, digits;
+                       unsigned int val = 0;
+                       start = p;
+
+                       while (n > 0 && *p != ':') {
+                               --n;
+                               p++;
+                       }
+                       if (*p != ':')
+                               goto parse_error;
+                       len = IDE_MIN(p - start, MAX_LEN);
+                       strncpy(name, start, IDE_MIN(len, MAX_LEN));
+                       name[len] = 0;
+
+                       if (n > 0) {
+                               --n;
+                               p++;
+                       } else
+                               goto parse_error;
+                       
+                       digits = 0;
+                       while (n > 0 && (d = ide_getdigit(*p)) >= 0) {
+                               val = (val * 10) + d;
+                               --n;
+                               ++p;
+                               ++digits;
+                       }
+                       if (n > 0 && !isspace(*p))
+                               goto parse_error;
+                       while (n > 0 && isspace(*p)) {
+                               --n;
+                               ++p;
+                       }
+                       setting = ide_find_setting_by_name(drive, name);
+                       if (!setting)
+                               goto parse_error;
+
+                       if (for_real)
+                               ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
+               }
+       } while (!for_real++);
+       restore_flags(flags);
+       return count;
+parse_error:
+       restore_flags(flags);
+       printk("proc_ide_write_settings(): parse error\n");
+       return -EINVAL;
+}
+
 int proc_ide_read_capacity
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -437,6 +564,18 @@ static int proc_ide_read_driver
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
+static int proc_ide_write_driver
+       (struct file *file, const char *buffer, unsigned long count, void *data)
+{
+       ide_drive_t     *drive = (ide_drive_t *) data;
+
+       if (!suser())
+               return -EACCES;
+       if (ide_replace_subdriver(drive, buffer))
+               return -EINVAL;
+       return count;
+}
+
 static int proc_ide_read_media
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -461,13 +600,12 @@ static int proc_ide_read_media
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
-
 static ide_proc_entry_t generic_drive_entries[] = {
-       { "driver", proc_ide_read_driver, NULL },
+       { "driver", proc_ide_read_driver, proc_ide_write_driver },
        { "identify", proc_ide_read_identify, NULL },
        { "media", proc_ide_read_media, NULL },
        { "model", proc_ide_read_dmodel, NULL },
-       { "settings", proc_ide_read_settings, NULL },
+       { "settings", proc_ide_read_settings, proc_ide_write_settings },
        { NULL, NULL, NULL }
 };
 
@@ -497,9 +635,16 @@ void ide_remove_proc_entries(ide_drive_t *drive, ide_proc_entry_t *p)
        }
 }
 
-static void create_proc_ide_drives (ide_hwif_t *hwif, struct proc_dir_entry *parent)
+static int proc_ide_readlink(struct proc_dir_entry *de, char *page)
+{
+       int n = (de->name[2] - 'a') / 2;
+       return sprintf(page, "ide%d/%s", n, de->name);
+}
+
+static void create_proc_ide_drives (ide_hwif_t *hwif, struct proc_dir_entry *parent, struct proc_dir_entry *root)
 {
        int     d;
+       struct proc_dir_entry *ent;
 
        for (d = 0; d < MAX_DRIVES; d++) {
                ide_drive_t *drive = &hwif->drives[d];
@@ -509,6 +654,12 @@ static void create_proc_ide_drives (ide_hwif_t *hwif, struct proc_dir_entry *par
                drive->proc = create_proc_entry(drive->name, S_IFDIR, parent);
                if (drive->proc)
                        ide_add_proc_entries(drive, generic_drive_entries);
+
+               ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, root);
+               if (!ent) return;
+               ent->data = drive;
+               ent->readlink_proc = proc_ide_readlink;
+               ent->nlink = 1;
        }
 }
 
@@ -555,14 +706,18 @@ static void create_proc_ide_interfaces (struct proc_dir_entry *parent)
                ent->data = hwif;
                ent->read_proc  = proc_ide_read_type;
 
-               create_proc_ide_drives(hwif, hwif_ent);
+               create_proc_ide_drives(hwif, hwif_ent, parent);
        }
 }
 
 void proc_ide_init(void)
 {
-       struct proc_dir_entry *ent;
-       ent = create_proc_entry("ide", S_IFDIR, 0);
+       struct proc_dir_entry *root, *ent;
+       root = create_proc_entry("ide", S_IFDIR, 0);
+       if (!root) return;
+       create_proc_ide_interfaces(root);
+
+       ent = create_proc_entry("drivers", 0, root);
        if (!ent) return;
-       create_proc_ide_interfaces(ent);
+       ent->read_proc  = proc_ide_read_drivers;
 }
index 3083debfda8d1f6084436411d2f116066837f0dd..f3f4ef8f197eeae9f7613f9d05ab45e5e9d5eb73 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * linux/drivers/block/ide-tape.c      Version 1.12            Dec   7, 1997
+ * linux/drivers/block/ide-tape.c      Version 1.13            Jan   2, 1998
  *
- * Copyright (C) 1995, 1996 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1995 - 1998 Gadi Oxman <gadio@netvision.net.il>
  *
  * This driver was constructed as a student project in the software laboratory
  * of the faculty of electrical engineering in the Technion - Israel's
  *                        of bytes written to the tape was not an integral
  *                        number of tape blocks.
  *                       Add support for INTERRUPT DRQ devices.
+ * Ver 1.13  Jan  2 98   Add "speed == 0" work-around for HP COLORADO 5GB
  *
  * Here are some words from the first releases of hd.c, which are quoted
  * in ide.c and apply here as well:
  *             sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
  */
 
-#define IDETAPE_VERSION "1.12"
+#define IDETAPE_VERSION "1.13"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -675,7 +676,7 @@ typedef struct {
         */
        int nr_stages;                          /* Number of currently used stages */
        int nr_pending_stages;                  /* Number of pending stages */
-       int max_stages;                         /* We will not allocate more than this number of stages */
+       int max_stages, min_pipeline, max_pipeline; /* We will not allocate more than this number of stages */
        idetape_stage_t *first_stage;           /* The first stage which will be removed from the pipeline */
        idetape_stage_t *active_stage;          /* The currently active stage */
        idetape_stage_t *next_stage;            /* Will be serviced after the currently active request */
@@ -1409,12 +1410,15 @@ static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage
 static void idetape_increase_max_pipeline_stages (ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
+       int increase = (tape->max_pipeline - tape->min_pipeline) / 10;
        
 #if IDETAPE_DEBUG_LOG
        printk (KERN_INFO "Reached idetape_increase_max_pipeline_stages\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
-       tape->max_stages = IDE_MIN (tape->max_stages + IDETAPE_INCREASE_STAGES_RATE, IDETAPE_MAX_PIPELINE_STAGES);
+       tape->max_stages += increase;
+       tape->max_stages = IDE_MAX(tape->max_stages, tape->min_pipeline);
+       tape->max_stages = IDE_MIN(tape->max_stages, tape->max_pipeline);
 }
 
 /*
@@ -2520,7 +2524,7 @@ static void idetape_discard_read_pipeline (ide_drive_t *drive)
        while (tape->first_stage != NULL)
                idetape_remove_stage_head (drive);
        tape->nr_pending_stages = 0;
-       tape->max_stages = IDETAPE_MIN_PIPELINE_STAGES;
+       tape->max_stages = tape->min_pipeline;
 }
 
 /*
@@ -2610,7 +2614,7 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
         *       as some systems are constantly on, and the system load
         *       can be totally different on the next backup).
         */
-       tape->max_stages = IDETAPE_MIN_PIPELINE_STAGES;
+       tape->max_stages = tape->min_pipeline;
 #if IDETAPE_DEBUG_BUGS
        if (tape->first_stage != NULL || tape->next_stage != NULL || tape->last_stage != NULL || tape->nr_stages != 0) {
                printk (KERN_ERR "ide-tape: ide-tape pipeline bug\n");          
@@ -3460,6 +3464,15 @@ static void idetape_get_mode_sense_results (ide_drive_t *drive)
        capabilities->speed = ntohs (capabilities->speed);
        capabilities->buffer_size = ntohs (capabilities->buffer_size);
 
+       if (!capabilities->speed) {
+               printk("ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name);
+               capabilities->speed = 650;
+       }
+       if (!capabilities->max_speed) {
+               printk("ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name);
+               capabilities->max_speed = 650;
+       }
+
        tape->capabilities = *capabilities;             /* Save us a copy */
        tape->tape_block_size = capabilities->blk512 ? 512:1024;
 #if IDETAPE_DEBUG_LOG
@@ -3493,6 +3506,24 @@ static void idetape_get_mode_sense_results (ide_drive_t *drive)
 #endif /* IDETAPE_DEBUG_LOG */
 }
 
+static void idetape_add_settings(ide_drive_t *drive)
+{
+       idetape_tape_t *tape = drive->driver_data;
+
+/*
+ *                     drive   setting name    read/write      ioctl   ioctl           data type       min                     max                     mul_factor                      div_factor                      data pointer                            set function
+ */
+       ide_add_setting(drive,  "buffer",       SETTING_READ,   -1,     -1,             TYPE_SHORT,     0,                      0xffff,                 1,                              2,                              &tape->capabilities.buffer_size,        NULL);
+       ide_add_setting(drive,  "pipeline_min", SETTING_RW,     -1,     -1,             TYPE_INT,       0,                      0xffff,                 tape->stage_size / 1024,        1,                              &tape->min_pipeline,                    NULL);
+       ide_add_setting(drive,  "pipeline",     SETTING_RW,     -1,     -1,             TYPE_INT,       0,                      0xffff,                 tape->stage_size / 1024,        1,                              &tape->max_stages,                      NULL);
+       ide_add_setting(drive,  "pipeline_max", SETTING_RW,     -1,     -1,             TYPE_INT,       0,                      0xffff,                 tape->stage_size / 1024,        1,                              &tape->max_pipeline,                    NULL);
+       ide_add_setting(drive,  "pipeline_used",SETTING_READ,   -1,     -1,             TYPE_INT,       0,                      0xffff,                 tape->stage_size / 1024,        1,                              &tape->nr_stages,                       NULL);
+       ide_add_setting(drive,  "speed",        SETTING_READ,   -1,     -1,             TYPE_SHORT,     0,                      0xffff,                 1,                              1,                              &tape->capabilities.speed,              NULL);
+       ide_add_setting(drive,  "stage",        SETTING_READ,   -1,     -1,             TYPE_INT,       0,                      0xffff,                 1,                              1024,                           &tape->stage_size,                      NULL);
+       ide_add_setting(drive,  "tdsc",         SETTING_RW,     -1,     -1,             TYPE_INT,       IDETAPE_DSC_RW_MIN,     IDETAPE_DSC_RW_MAX,     1000,                           HZ,                             &tape->best_dsc_rw_frequency,           NULL);
+       ide_add_setting(drive,  "dsc_overlap",  SETTING_RW,     -1,     -1,             TYPE_BYTE,      0,                      1,                      1,                              1,                              &drive->dsc_overlap,                    NULL);
+}
+
 /*
  *     ide_setup is called to:
  *
@@ -3521,7 +3552,9 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
        tape->name[0] = 'h'; tape->name[1] = 't'; tape->name[2] = '0' + minor;
        tape->chrdev_direction = idetape_direction_none;
        tape->pc = tape->pc_stack;
-       tape->max_stages = IDETAPE_MIN_PIPELINE_STAGES;
+       tape->min_pipeline = IDETAPE_MIN_PIPELINE_STAGES;
+       tape->max_pipeline = IDETAPE_MAX_PIPELINE_STAGES;
+       tape->max_stages = tape->min_pipeline;
        *((unsigned short *) &gcw) = drive->id->config;
        if (gcw.drq_type == 1)
                set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags);
@@ -3577,6 +3610,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
                drive->name, tape->name, tape->capabilities.speed, (tape->capabilities.buffer_size * 512) / tape->stage_size,
                tape->stage_size / 1024, tape->max_stages * tape->stage_size / 1024,
                tape->best_dsc_rw_frequency * 1000 / HZ, drive->using_dma ? ", DMA":"");
+
+       idetape_add_settings(drive);
 }
 
 static int idetape_cleanup (ide_drive_t *drive)
@@ -3605,18 +3640,6 @@ static int idetape_cleanup (ide_drive_t *drive)
        return 0;
 }
 
-static int proc_idetape_read_buffer
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t     *drive = (ide_drive_t *) data;
-       idetape_tape_t  *tape = drive->driver_data;
-       char            *out = page;
-       int             len;
-
-       len = sprintf(out,"%d\n", tape->capabilities.buffer_size / 2);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
 static int proc_idetape_read_name
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -3629,72 +3652,11 @@ static int proc_idetape_read_name
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
-static int proc_idetape_read_pipeline
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t     *drive = (ide_drive_t *) data;
-       idetape_tape_t  *tape = drive->driver_data;
-       char            *out = page;
-       int             len;
-
-       len = sprintf(out,"%d\n", tape->max_stages * tape->stage_size / 1024);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
-static int proc_idetape_read_speed
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t     *drive = (ide_drive_t *) data;
-       idetape_tape_t  *tape = drive->driver_data;
-       char            *out = page;
-       int             len;
-
-       len = sprintf(out,"%d\n", tape->capabilities.speed);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
-static int proc_idetape_read_stage
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t     *drive = (ide_drive_t *) data;
-       idetape_tape_t  *tape = drive->driver_data;
-       char            *out = page;
-       int             len;
-
-       len = sprintf(out,"%d\n", tape->stage_size / 1024);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
-static int proc_idetape_read_tdsc
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t     *drive = (ide_drive_t *) data;
-       idetape_tape_t  *tape = drive->driver_data;
-       char            *out = page;
-       int             len;
-
-       len = sprintf(out,"%lu\n", tape->best_dsc_rw_frequency * 1000 / HZ);
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
 static ide_proc_entry_t idetape_proc[] = {
-       { "buffer", proc_idetape_read_buffer, NULL },
        { "name", proc_idetape_read_name, NULL },
-       { "pipeline", proc_idetape_read_pipeline, NULL },
-       { "speed", proc_idetape_read_speed, NULL },
-       { "stage", proc_idetape_read_stage, NULL },
-       { "tdsc", proc_idetape_read_tdsc, NULL },
        { NULL, NULL, NULL }
 };
 
-int idetape_init (void);
-
-static ide_module_t idetape_module = {
-       IDE_DRIVER_MODULE,
-       idetape_init,
-       NULL
-};
-
 /*
  *     IDE subdriver functions, registered with ide.c
  */
@@ -3718,6 +3680,14 @@ static ide_driver_t idetape_driver = {
        idetape_proc            /* proc */
 };
 
+int idetape_init (void);
+static ide_module_t idetape_module = {
+       IDE_DRIVER_MODULE,
+       idetape_init,
+       &idetape_driver,
+       NULL
+};
+
 /*
  *     Our character device supporting functions, passed to register_chrdev.
  */
@@ -3751,7 +3721,7 @@ int idetape_init (void)
                for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ )
                        idetape_chrdevs[minor].drive = NULL;
 
-       if ((drive = ide_scan_devices (ide_tape, NULL, failed++)) == NULL) {
+       if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) {
                ide_register_module (&idetape_module);
                MOD_DEC_USE_COUNT;
                return 0;
@@ -3780,7 +3750,7 @@ int idetape_init (void)
                idetape_setup (drive, tape, minor);
                idetape_chrdevs[minor].drive = drive;
                supported++; failed--;
-       } while ((drive = ide_scan_devices (ide_tape, NULL, failed++)) != NULL);
+       } while ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) != NULL);
        if (!idetape_chrdev_present && !supported) {
                unregister_chrdev (IDETAPE_MAJOR, "ht");
        } else
index 9a5bbc3a31d8707c54ef5d3198d90f8b7a216029..4bba14198c2d23ec64247e4ec7496b29759bbc60 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c  Version 6.11  December 5, 1997
+ *  linux/drivers/block/ide.c  Version 6.12  January  2, 1998
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -98,6 +98,8 @@
  * Version 6.11                fix probe error in ide_scan_devices()
  *                     fix ancient "jiffies" polling bugs
  *                     mask all hwgroup interrupts on each irq entry
+ * Version 6.12                integrate ioctl and proc interfaces
+ *                     fix parsing of "idex=" command line parameter
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -151,7 +153,7 @@ static int  ide_lock = 0;
 /*
  * ide_modules keeps track of the available IDE chipset/probe/driver modules.
  */
-static ide_module_t *ide_modules = NULL;
+ide_module_t *ide_modules = NULL;
 
 /*
  * This is declared extern in ide.h, for access by other IDE modules:
@@ -809,7 +811,8 @@ static void drive_cmd_intr (ide_drive_t *drive)
 {
        struct request *rq = HWGROUP(drive)->rq;
        byte *args = (byte *) rq->buffer;
-       byte test, stat = GET_STAT();
+       byte stat = GET_STAT();
+       int retries = 10;
 
        ide_sti();
        if ((stat & DRQ_STAT) && args && args[3]) {
@@ -817,12 +820,11 @@ static void drive_cmd_intr (ide_drive_t *drive)
                drive->io_32bit = 0;
                ide_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
                drive->io_32bit = io_32bit;
-               stat = GET_STAT();
+               while (((stat = GET_STAT()) & BUSY_STAT) && retries--)
+                       udelay(100);
        }
-       test = stat;
-       if (drive->media == ide_cdrom)
-               test = stat &~BUSY_STAT;
-       if (OK_STAT(test,READY_STAT,BAD_STAT))
+
+       if (OK_STAT(stat, READY_STAT, BAD_STAT))
                ide_end_drive_cmd (drive, stat, GET_ERR());
        else
                ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */
@@ -901,6 +903,10 @@ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq)
                printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x xx=0x%02x\n",
                 drive->name, args[0], args[1], args[2], args[3]);
 #endif
+               if (args[0] == WIN_SMART) {
+                       OUT_BYTE(0x4f, IDE_LCYL_REG);
+                       OUT_BYTE(0xc2, IDE_HCYL_REG);
+               }
                OUT_BYTE(args[2],IDE_FEATURE_REG);
                ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
                return;
@@ -1556,6 +1562,22 @@ static int ide_release(struct inode * inode, struct file * file)
        return 0;
 }
 
+int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
+{
+       if (!drive->present || drive->busy || drive->usage)
+               goto abort;
+       if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
+               goto abort;
+       strncpy(drive->driver_req, driver, 9);
+       ide_init_module(IDE_DRIVER_MODULE);
+       drive->driver_req[0] = 0;
+       ide_init_module(IDE_DRIVER_MODULE);
+       if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver))
+               return 0;
+abort:
+       return 1;
+}
+
 void ide_unregister (unsigned int index)
 {
        struct gendisk *gd, **gdp;
@@ -1697,20 +1719,229 @@ found:
        return hwif->present ? index : -1;
 }
 
+void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
+{
+       ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
+
+       while ((*p) && strcmp((*p)->name, name) < 0)
+               p = &((*p)->next);
+       if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
+               goto abort;
+       memset(setting, 0, sizeof(*setting));
+       if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
+               goto abort;
+       strcpy(setting->name, name);            setting->rw = rw;
+       setting->read_ioctl = read_ioctl;       setting->write_ioctl = write_ioctl;
+       setting->data_type = data_type;         setting->min = min;
+       setting->max = max;                     setting->mul_factor = mul_factor;
+       setting->div_factor = div_factor;       setting->data = data;
+       setting->set = set;                     setting->next = *p;
+       if (drive->driver)
+               setting->auto_remove = 1;
+       *p = setting;
+       return;
+abort:
+       if (setting)
+               kfree(setting);
+}
+
+void ide_remove_setting(ide_drive_t *drive, char *name)
+{
+       ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting;
+
+       while ((*p) && strcmp((*p)->name, name))
+               p = &((*p)->next);
+       if ((setting = (*p)) == NULL)
+               return;
+       (*p) = setting->next;
+       kfree(setting->name);
+       kfree(setting);
+}
+
+static ide_settings_t *ide_find_setting_by_ioctl(ide_drive_t *drive, int cmd)
+{
+       ide_settings_t *setting = drive->settings;
+
+       while (setting) {
+               if (setting->read_ioctl == cmd || setting->write_ioctl == cmd)
+                       break;
+               setting = setting->next;
+       }
+       return setting;
+}
+
+ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
+{
+       ide_settings_t *setting = drive->settings;
+
+       while (setting) {
+               if (strcmp(setting->name, name) == 0)
+                       break;
+               setting = setting->next;
+       }
+       return setting;
+}
+
+static void auto_remove_settings(ide_drive_t *drive)
+{
+       ide_settings_t *setting;
+repeat:
+       setting = drive->settings;
+       while (setting) {
+               if (setting->auto_remove) {
+                       ide_remove_setting(drive, setting->name);
+                       goto repeat;
+               }
+               setting = setting->next;
+       }
+}
+
+int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
+{
+       if (!(setting->rw & SETTING_READ))
+               return -EINVAL;
+       switch(setting->data_type) {
+               case TYPE_BYTE:
+                       return *((u8 *) setting->data);
+               case TYPE_SHORT:
+                       return *((u16 *) setting->data);
+               case TYPE_INT:
+               case TYPE_INTA:
+                       return *((u32 *) setting->data);
+               default:
+                       return -EINVAL;
+       }
+}
+
+int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
+{
+       unsigned long flags;
+       int i, rc = 0;
+       u32 *p;
+
+       if (!suser())
+               return -EACCES;
+       if (!(setting->rw & SETTING_WRITE))
+               return -EPERM;
+       if (val < setting->min || val > setting->max)
+               return -EINVAL;
+       save_flags(flags);
+       cli();
+       if (setting->set)
+               rc = setting->set(drive, val);
+       else switch (setting->data_type) {
+               case TYPE_BYTE:
+                       *((u8 *) setting->data) = val;
+                       break;
+               case TYPE_SHORT:
+                       *((u16 *) setting->data) = val;
+                       break;
+               case TYPE_INT:
+                       *((u32 *) setting->data) = val;
+                       break;
+               case TYPE_INTA:
+                       p = (u32 *) setting->data;
+                       for (i = 0; i < 1 << PARTN_BITS; i++, p++)
+                               *p = val;
+                       break;
+       }
+       restore_flags(flags);
+       return rc;
+}
+
+static int set_io_32bit(ide_drive_t *drive, int arg)
+{
+       drive->io_32bit = arg;
+#ifdef CONFIG_BLK_DEV_DTC2278
+       if (HWIF(drive)->chipset == ide_dtc2278)
+               HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
+#endif /* CONFIG_BLK_DEV_DTC2278 */
+       return 0;
+}
+
+static int set_using_dma(ide_drive_t *drive, int arg)
+{
+       if (!drive->driver || !DRIVER(drive)->supports_dma)
+               return -EPERM;
+       if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
+               return -EPERM;
+       if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive))
+               return -EIO;
+       return 0;
+}
+
+static int set_pio_mode(ide_drive_t *drive, int arg)
+{
+       struct request rq;
+
+       if (!HWIF(drive)->tuneproc)
+               return -ENOSYS;
+       if (drive->special.b.set_tune)
+               return -EBUSY;
+       ide_init_drive_cmd(&rq);
+       drive->tune_req = (byte) arg;
+       drive->special.b.set_tune = 1;
+       (void) ide_do_drive_cmd (drive, &rq, ide_wait);
+       return 0;
+}
+
+void ide_add_generic_settings(ide_drive_t *drive)
+{
+/*
+ *                     drive   setting name            read/write access                               read ioctl              write ioctl             data type       min     max                             mul_factor      div_factor      data pointer                    set function
+ */
+       ide_add_setting(drive,  "io_32bit",             drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT,         HDIO_SET_32BIT,         TYPE_BYTE,      0,      1 + (SUPPORT_VLB_SYNC << 1),    1,              1,              &drive->io_32bit,               set_io_32bit);
+       ide_add_setting(drive,  "keepsettings",         SETTING_RW,                                     HDIO_GET_KEEPSETTINGS,  HDIO_SET_KEEPSETTINGS,  TYPE_BYTE,      0,      1,                              1,              1,              &drive->keep_settings,          NULL);
+       ide_add_setting(drive,  "nice1",                SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      1,                              1,              1,              &drive->nice1,                  NULL);
+       ide_add_setting(drive,  "pio_mode",             SETTING_WRITE,                                  -1,                     HDIO_SET_PIO_MODE,      TYPE_BYTE,      0,      255,                            1,              1,              NULL,                           set_pio_mode);
+       ide_add_setting(drive,  "slow",                 SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      1,                              1,              1,              &drive->slow,                   NULL);
+       ide_add_setting(drive,  "unmaskirq",            drive->no_unmask ? SETTING_READ : SETTING_RW,   HDIO_GET_UNMASKINTR,    HDIO_SET_UNMASKINTR,    TYPE_BYTE,      0,      1,                              1,              1,              &drive->unmask,                 NULL);
+       ide_add_setting(drive,  "using_dma",            SETTING_RW,                                     HDIO_GET_DMA,           HDIO_SET_DMA,           TYPE_BYTE,      0,      1,                              1,              1,              &drive->using_dma,              set_using_dma);
+}
+
+int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf)
+{
+       struct request rq;
+       byte buffer[4];
+
+       if (!buf)
+               buf = buffer;
+       memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
+       ide_init_drive_cmd(&rq);
+       rq.buffer = buf;
+       *buf++ = cmd;
+       *buf++ = nsect;
+       *buf++ = feature;
+       *buf++ = sectors;
+       return ide_do_drive_cmd(drive, &rq, ide_wait);
+}
+
 static int ide_ioctl (struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        int err, major, minor;
        ide_drive_t *drive;
-       unsigned long flags;
        struct request rq;
        kdev_t dev;
+       ide_settings_t *setting;
 
        if (!inode || !(dev = inode->i_rdev))
                return -EINVAL;
        major = MAJOR(dev); minor = MINOR(dev);
        if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
                return -ENODEV;
+
+       if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {
+               if (cmd == setting->read_ioctl) {
+                       err = ide_read_setting(drive, setting);
+                       return err >= 0 ? put_user(err, (long *) arg) : err;
+               } else {
+                       if ((MINOR(inode->i_rdev) & PARTN_MASK))
+                               return -EINVAL;
+                       return ide_write_setting(drive, setting, arg);
+               }
+       }
+
        ide_init_drive_cmd (&rq);
        switch (cmd) {
                case HDIO_GETGEO:
@@ -1730,54 +1961,13 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                        invalidate_buffers(inode->i_rdev);
                        return 0;
 
-               case BLKRASET:
-                       if (!suser()) return -EACCES;
-                       if(arg > 0xff) return -EINVAL;
-                       read_ahead[MAJOR(inode->i_rdev)] = arg;
-                       return 0;
-
-               case BLKRAGET:
-                       return put_user(read_ahead[MAJOR(inode->i_rdev)], (long *) arg);
-
                case BLKGETSIZE:   /* Return device size */
                        return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg);
 
-               case BLKFRASET:
-                       if (!suser()) return -EACCES;
-                       max_readahead[major][minor] = arg;
-                       return 0;
-
-               case BLKFRAGET:
-                       return put_user(max_readahead[major][minor], (long *) arg);
-
-               case BLKSECTSET:
-                       if (!suser()) return -EACCES;
-                       if (!arg || arg > 0xff) return -EINVAL;
-                       max_sectors[major][minor] = arg;
-                       return 0;
-
-               case BLKSECTGET:
-                       return put_user(max_sectors[major][minor], (long *) arg);
-
                case BLKRRPART: /* Re-read partition tables */
                        if (!suser()) return -EACCES;
                        return ide_revalidate_disk(inode->i_rdev);
 
-               case HDIO_GET_KEEPSETTINGS:
-                       return put_user(drive->keep_settings, (long *) arg);
-
-               case HDIO_GET_UNMASKINTR:
-                       return put_user(drive->unmask, (long *) arg);
-
-               case HDIO_GET_DMA:
-                       return put_user(drive->using_dma, (long *) arg);
-
-               case HDIO_GET_32BIT:
-                       return put_user(drive->io_32bit, (long *) arg);
-
-               case HDIO_GET_MULTCOUNT:
-                       return put_user(drive->mult_count, (long *) arg);
-
                case HDIO_GET_IDENTITY:
                        if (MINOR(inode->i_rdev) & PARTN_MASK)
                                return -EINVAL;
@@ -1792,99 +1982,13 @@ static int ide_ioctl (struct inode *inode, struct file *file,
 #endif
                        return 0;
 
-               case HDIO_GET_NOWERR:
-                       return put_user(drive->bad_wstat == BAD_R_STAT, (long *) arg);
-
                case HDIO_GET_NICE:
-               {
-                       long nice = 0;
-
-                       nice |= drive->dsc_overlap << IDE_NICE_DSC_OVERLAP;
-                       nice |= drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP;
-                       nice |= drive->nice0 << IDE_NICE_0;
-                       nice |= drive->nice1 << IDE_NICE_1;
-                       nice |= drive->nice2 << IDE_NICE_2;
-                       return put_user(nice, (long *) arg);
-               }
-
-               case HDIO_SET_DMA:
-                       if (!suser()) return -EACCES;
-                       if (drive->driver != NULL && !DRIVER(drive)->supports_dma)
-                               return -EPERM;
-                       if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
-                               return -EPERM;
-               case HDIO_SET_KEEPSETTINGS:
-               case HDIO_SET_UNMASKINTR:
-               case HDIO_SET_NOWERR:
-                       if (arg > 1)
-                               return -EINVAL;
-               case HDIO_SET_32BIT:
-                       if (!suser()) return -EACCES;
-                       if ((MINOR(inode->i_rdev) & PARTN_MASK))
-                               return -EINVAL;
-                       save_flags(flags);
-                       cli();
-                       switch (cmd) {
-                               case HDIO_SET_DMA:
-                                       if (!(HWIF(drive)->dmaproc)) {
-                                               restore_flags(flags);
-                                               return -EPERM;
-                                       }
-                                       if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive)) {
-                                               restore_flags(flags);
-                                               return -EIO;
-                                       }
-                                       break;
-                               case HDIO_SET_KEEPSETTINGS:
-                                       drive->keep_settings = arg;
-                                       break;
-                               case HDIO_SET_UNMASKINTR:
-                                       if (arg && drive->no_unmask) {
-                                               restore_flags(flags);
-                                               return -EPERM;
-                                       }
-                                       drive->unmask = arg;
-                                       break;
-                               case HDIO_SET_NOWERR:
-                                       drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
-                                       break;
-                               case HDIO_SET_32BIT:
-                                       if (arg > (1 + (SUPPORT_VLB_SYNC<<1))) {
-                                               restore_flags(flags);
-                                               return -EINVAL;
-                                       }
-                                       if (arg && drive->no_io_32bit) {
-                                               restore_flags(flags);
-                                               return -EPERM;
-                                       }
-                                       drive->io_32bit = arg;
-#ifdef CONFIG_BLK_DEV_DTC2278
-                                       if (HWIF(drive)->chipset == ide_dtc2278)
-                                               HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
-#endif /* CONFIG_BLK_DEV_DTC2278 */
-                                       break;
-                       }
-                       restore_flags(flags);
-                       return 0;
-
-               case HDIO_SET_MULTCOUNT:
-                       if (!suser()) return -EACCES;
-                       if (MINOR(inode->i_rdev) & PARTN_MASK)
-                               return -EINVAL;
-                       if (drive->id && arg > drive->id->max_multsect)
-                               return -EINVAL;
-                       save_flags(flags);
-                       cli();
-                       if (drive->special.b.set_multmode) {
-                               restore_flags(flags);
-                               return -EBUSY;
-                       }
-                       drive->mult_req = arg;
-                       drive->special.b.set_multmode = 1;
-                       restore_flags(flags);
-                       (void) ide_do_drive_cmd (drive, &rq, ide_wait);
-                       return (drive->mult_count == arg) ? 0 : -EIO;
-
+                       return put_user(drive->dsc_overlap      <<      IDE_NICE_DSC_OVERLAP    |
+                                       drive->atapi_overlap    <<      IDE_NICE_ATAPI_OVERLAP  |
+                                       drive->nice0            <<      IDE_NICE_0              |
+                                       drive->nice1            <<      IDE_NICE_1              |
+                                       drive->nice2            <<      IDE_NICE_2,
+                                       (long *) arg);
                case HDIO_DRIVE_CMD:
                {
                        byte args[4], *argbuf = args;
@@ -1901,31 +2005,13 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                                        return -ENOMEM;
                                memcpy(argbuf, args, 4);
                        }
-                       rq.buffer = argbuf;
-                       err = ide_do_drive_cmd(drive, &rq, ide_wait);
+                       err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
                        if (copy_to_user((void *)arg, argbuf, argsize))
                                err = -EFAULT;
                        if (argsize > 4)
                                kfree(argbuf);
                        return err;
                }
-               case HDIO_SET_PIO_MODE:
-                       if (!suser()) return -EACCES;
-                       if (MINOR(inode->i_rdev) & PARTN_MASK)
-                               return -EINVAL;
-                       if (!HWIF(drive)->tuneproc)
-                               return -ENOSYS;
-                       save_flags(flags);
-                       cli();
-                       if (drive->special.b.set_tune) {
-                               restore_flags(flags);
-                               return -EBUSY;
-                       }
-                       drive->tune_req = (byte) arg;
-                       drive->special.b.set_tune = 1;
-                       restore_flags(flags);
-                       (void) ide_do_drive_cmd (drive, &rq, ide_wait);
-                       return 0;
 
                case HDIO_SCAN_HWIF:
                {
@@ -2223,7 +2309,7 @@ __initfunc(void ide_setup (char *s))
                if (i > 0 || i <= -7) {                 /* is parameter a chipset name? */
                        if (hwif->chipset != ide_unknown)
                                goto bad_option;        /* chipset already specified */
-                       if (i != -7 && hw != 0)
+                       if (i <= -7 && hw != 0)
                                goto bad_hwif;          /* chipset drivers are for "ide0=" only */
                        if (ide_hwifs[hw^1].chipset != ide_unknown)
                                goto bad_option;        /* chipset for 2nd port already specified */
@@ -2578,7 +2664,7 @@ static void setup_driver_defaults (ide_drive_t *drive)
        if (d->special == NULL)         d->special = default_special;
 }
 
-ide_drive_t *ide_scan_devices (byte media, ide_driver_t *driver, int n)
+ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n)
 {
        unsigned int unit, index, i;
 
@@ -2588,12 +2674,15 @@ ide_drive_t *ide_scan_devices (byte media, ide_driver_t *driver, int n)
 search:
        for (index = 0, i = 0; index < MAX_HWIFS; ++index) {
                ide_hwif_t *hwif = &ide_hwifs[index];
-               if (hwif->present) {
-                       for (unit = 0; unit < MAX_DRIVES; ++unit) {
-                               ide_drive_t *drive = &hwif->drives[unit];
-                               if (drive->present && drive->media == media && drive->driver == driver && ++i > n)
-                                       return drive;
-                       }
+               if (!hwif->present)
+                       continue;
+               for (unit = 0; unit < MAX_DRIVES; ++unit) {
+                       ide_drive_t *drive = &hwif->drives[unit];
+                       char *req = drive->driver_req;
+                       if (*req && !strstr(name, req))
+                               continue;
+                       if (drive->present && drive->media == media && drive->driver == driver && ++i > n)
+                               return drive;
                }
        }
        return NULL;
@@ -2642,6 +2731,7 @@ int ide_unregister_subdriver (ide_drive_t *drive)
        }
        ide_remove_proc_entries(drive, DRIVER(drive)->proc);
        ide_remove_proc_entries(drive, generic_subdriver_entries);
+       auto_remove_settings(drive);
        drive->driver = NULL;
        restore_flags(flags);
        return 0;
@@ -2735,6 +2825,8 @@ EXPORT_SYMBOL(ide_cmd);
 EXPORT_SYMBOL(ide_stall_queue);
 EXPORT_SYMBOL(ide_add_proc_entries);
 EXPORT_SYMBOL(ide_remove_proc_entries);
+EXPORT_SYMBOL(ide_add_setting);
+EXPORT_SYMBOL(ide_remove_setting);
 EXPORT_SYMBOL(proc_ide_read_geometry);
 
 EXPORT_SYMBOL(ide_register);
index fde3f5b3e5a0a1185d47930e2e9b87d878fa06cc..2daae4f81f2ba9038bf2d7181f92172f32387241 100644 (file)
@@ -206,23 +206,23 @@ typedef struct ide_drive_s {
        special_t       special;        /* special action flags */
        unsigned present        : 1;    /* drive is physically present */
        unsigned noprobe        : 1;    /* from:  hdx=noprobe */
-       unsigned keep_settings  : 1;    /* restore settings after drive reset */
+       byte     keep_settings;         /* restore settings after drive reset */
        unsigned busy           : 1;    /* currently doing revalidate_disk() */
        unsigned removable      : 1;    /* 1 if need to do check_media_change */
-       unsigned using_dma      : 1;    /* disk is using dma for read/write */
+       byte     using_dma;             /* disk is using dma for read/write */
        unsigned forced_geom    : 1;    /* 1 if hdx=c,h,s was given at boot */
-       unsigned unmask         : 1;    /* flag: okay to unmask other irqs */
+       byte     unmask;                /* flag: okay to unmask other irqs */
        unsigned no_unmask      : 1;    /* disallow setting unmask bit */
        unsigned no_io_32bit    : 1;    /* disallow enabling 32bit I/O */
        unsigned nobios         : 1;    /* flag: do not probe bios for drive */
-       unsigned slow           : 1;    /* flag: slow data port */
+       byte     slow;                  /* flag: slow data port */
        unsigned autotune       : 2;    /* 1=autotune, 2=noautotune, 0=default */
        unsigned revalidate     : 1;    /* request revalidation */
-       unsigned bswap          : 1;    /* flag: byte swap data */
-       unsigned dsc_overlap    : 1;    /* flag: DSC overlap */
+       byte     bswap;                 /* flag: byte swap data */
+       byte     dsc_overlap;           /* flag: DSC overlap */
        unsigned atapi_overlap  : 1;    /* flag: ATAPI overlap (not supported) */
        unsigned nice0          : 1;    /* flag: give obvious excess bandwidth */
-       unsigned nice1          : 1;    /* flag: give potential excess bandwidth */
+       byte     nice1;                 /* flag: give potential excess bandwidth */
        unsigned nice2          : 1;    /* flag: give a share in our own bandwidth */
 #if FAKE_FDISK_FOR_EZDRIVE
        unsigned remap_0_to_1   : 1;    /* flag: partitioned with ezdrive */
@@ -236,6 +236,7 @@ typedef struct ide_drive_s {
        byte            tune_req;       /* requested drive tuning setting */
        byte            io_32bit;       /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
        byte            bad_wstat;      /* used for ignoring WRERR_STAT */
+       byte            nowerr;         /* used for ignoring WRERR_STAT */
        byte            sect0;          /* offset of first sector for DM6:DDO */
        byte            usage;          /* current "open()" count for drive */
        byte            head;           /* "real" number of heads */
@@ -253,6 +254,8 @@ typedef struct ide_drive_s {
        void            *driver;        /* (ide_driver_t *) */
        void            *driver_data;   /* extra driver data */
        struct proc_dir_entry *proc;    /* /proc/ide/ directory entry */
+       void            *settings;      /* /proc/ide/ drive settings */
+       char            driver_req[10]; /* requests specific driver */
        } ide_drive_t;
 
 /*
@@ -361,6 +364,43 @@ typedef struct hwgroup_s {
        int                     active; /* set when servicing requests */
        } ide_hwgroup_t;
 
+/*
+ * configurable drive settings
+ */
+
+#define TYPE_INT       0
+#define TYPE_INTA      1
+#define TYPE_BYTE      2
+#define TYPE_SHORT     3
+
+#define SETTING_READ   (1 << 0)
+#define SETTING_WRITE  (1 << 1)
+#define SETTING_RW     (SETTING_READ | SETTING_WRITE)
+
+typedef int (ide_procset_t)(ide_drive_t *, int);
+typedef struct ide_settings_s {
+       char                    *name;
+       int                     rw;
+       int                     read_ioctl;
+       int                     write_ioctl;
+       int                     data_type;
+       int                     min;
+       int                     max;
+       int                     mul_factor;
+       int                     div_factor;
+       void                    *data;
+       ide_procset_t           *set;
+       int                     auto_remove;
+       struct ide_settings_s   *next;
+} ide_settings_t;
+
+void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
+void ide_remove_setting(ide_drive_t *drive, char *name);
+ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
+int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
+int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);
+void ide_add_generic_settings(ide_drive_t *drive);
+
 /*
  * /proc/ide interface
  */
@@ -407,6 +447,7 @@ typedef int (ide_check_media_change_proc)(ide_drive_t *);
 typedef void   (ide_pre_reset_proc)(ide_drive_t *);
 typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
 typedef void   (ide_special_proc)(ide_drive_t *);
+typedef void   (ide_setting_proc)(ide_drive_t *);
 
 typedef struct ide_driver_s {
        const char                      *name;
@@ -442,6 +483,7 @@ typedef int (ide_module_init_proc)(void);
 typedef struct ide_module_s {
        int                             type;
        ide_module_init_proc            *init;
+       void                            *info;
        struct ide_module_s             *next;
 } ide_module_t;
 
@@ -455,6 +497,7 @@ typedef struct ide_module_s {
  */
 #ifndef _IDE_C
 extern ide_hwif_t      ide_hwifs[];            /* master data repository */
+extern  ide_module_t   *ide_modules;
 #endif
 
 /*
@@ -587,6 +630,11 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
  */
 void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
 
+/*
+ * Issue ATA command and wait for completion.
+ */
+int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
+
 /*
  * ide_system_bus_speed() returns what we think is the system VESA/PCI
  * bus speed (in MHz).  This is used for calculating interface PIO timings.
@@ -651,9 +699,10 @@ int idescsi_init (void);
 
 int ide_register_module (ide_module_t *module);
 void ide_unregister_module (ide_module_t *module);
-ide_drive_t *ide_scan_devices (byte media, ide_driver_t *driver, int n);
+ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n);
 int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
 int ide_unregister_subdriver (ide_drive_t *drive);
+int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 unsigned long ide_find_free_region (unsigned short size) __init;
index 2df067bbef04b02d039cad1f539fded1b9672656..d21df7bbb435f49a953287b13b218962bc2897bd 100644 (file)
                          Added generic MII PHY functionality to deal with
                           newer PHY chips.
                          Fix the mess in 2.1.67.
+      0.532   5-Jan-98    Fix bug in mii_get_phy() reported by 
+                           <redhat@cococo.net>.
+                          Fix bug in pci_probe() for 64 bit systems reported
+                          by <belliott@accessone.com>.
+      0.533   9-Jan-98    Fix more 64 bit bugs reported by <jal@cs.brown.edu>.
 
     =========================================================================
 */
 
-static const char *version = "de4x5.c:T0.531 1997/12/21 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.533 1998/1/9 davies@maniac.ultranet.com\n";
 
 #include <linux/module.h>
 
@@ -763,7 +768,7 @@ struct de4x5_private {
     struct {
        void *priv;                         /* Original kmalloc'd mem addr  */
        void *buf;                          /* Original kmalloc'd mem addr  */
-       int lock;                           /* Lock the cache accesses      */
+       u_long lock;                        /* Lock the cache accesses      */
        s32 csr0;                           /* Saved Bus Mode Register      */
        s32 csr6;                           /* Saved Operating Mode Reg.    */
        s32 csr7;                           /* Saved IRQ Mask Register      */
@@ -2076,8 +2081,8 @@ pci_probe(struct device *dev, u_long ioaddr))
 {
     u_char pb, pbus, dev_num, dnum, dev_fn, timer;
     u_short dev_id, vendor, index, status;
-    u_int irq = 0, device, class = DE4X5_CLASS_CODE;
-    u_long iobase;
+    u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE;
+    u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     struct bus_type *lp = &bus;
 
     if (lastPCI == NO_MORE_PCI) return;
@@ -2137,8 +2142,8 @@ pci_probe(struct device *dev, u_long ioaddr))
 
            /* Get the board I/O address (64 bits on sparc64) */
 #ifndef __sparc_v9__
-           pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, 
-                                                              (int *)&iobase);
+           pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+           iobase = tmp;
 #else
            iobase = pdev->base_address[0];
 #endif
@@ -2211,8 +2216,8 @@ srom_search(int index))
 {
     u_char pb, dev_fn;
     u_short dev_id, dev_num, vendor, status;
-    u_int irq = 0, device, class = DE4X5_CLASS_CODE;
-    u_long iobase;
+    u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE;
+    u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     int i, j;
     struct bus_type *lp = &bus;
 
@@ -2250,8 +2255,8 @@ srom_search(int index))
 
        /* Get the board I/O address (64 bits on sparc64) */
 #ifndef __sparc_v9__
-       pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, 
-                                                              (int *)&iobase);
+       pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+       iobase = tmp;
 #else
        iobase = pdev->base_address[0];
 #endif
@@ -4985,7 +4990,9 @@ mii_get_phy(struct device *dev)
            lp->phy[k].spd.reg = GENERIC_REG;      /* ANLPA register         */
            lp->phy[k].spd.mask = GENERIC_MASK;    /* 100Mb/s technologies   */
            lp->phy[k].spd.value = GENERIC_VALUE;  /* TX & T4, H/F Duplex    */
-           printk("%s: Found MII device not currently supported. Please mail the following dump to\nthe author:\n", dev->name);
+           lp->mii_cnt++;
+           lp->active++;
+           printk("%s: Using generic MII device control. If the board doesn't operate, \nplease mail the following dump to the author:\n", dev->name);
            j = de4x5_debug;
            de4x5_debug |= DEBUG_MII;
            de4x5_dbg_mii(dev, k);
index ff3264da30ad30a28a3bd1820eb6d28eae809b5e..0bfa8d8763462adc63a6622f62b42b143464acd0 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * linux/drivers/scsi/ide-scsi.c       Version 0.4             Dec   7, 1997
+ * linux/drivers/scsi/ide-scsi.c       Version 0.5             Jan   2, 1998
  *
- * Copyright (C) 1996, 1997 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1996 - 1998 Gadi Oxman <gadio@netvision.net.il>
  */
 
 /*
  *                       Added Scatter/Gather and DMA support.
  * Ver 0.4   Dec  7 97   Add support for ATAPI PD/CD drives.
  *                       Use variable timeout for each command.
+ * Ver 0.5   Jan  2 98   Fix previous PD/CD support.
+ *                       Allow disabling of SCSI-6 to SCSI-10 transformation.
  */
 
-#define IDESCSI_VERSION "0.4"
+#define IDESCSI_VERSION "0.5"
 
 #include <linux/module.h>
 #include <linux/types.h>
@@ -71,6 +73,7 @@ typedef struct {
        ide_drive_t *drive;
        idescsi_pc_t *pc;                       /* Current packet command */
        unsigned int flags;                     /* Status/Action flags */
+       int transform;                          /* Transform SCSI-6 commands */
 } idescsi_scsi_t;
 
 /*
@@ -102,7 +105,7 @@ static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount)
 }
 
 /*
- *     PIO data transfer routines using the scather gather table.
+ *     PIO data transfer routines using the scatter gather table.
  */
 static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
 {
@@ -110,7 +113,7 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
 
        while (bcount) {
                if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
-                       printk (KERN_ERR "ide-scsi: scather gather table too small, discarding data\n");
+                       printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
                        idescsi_discard_data (drive, bcount);
                        return;
                }
@@ -130,7 +133,7 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
 
        while (bcount) {
                if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
-                       printk (KERN_ERR "ide-scsi: scather gather table too small, padding with zeros\n");
+                       printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
                        idescsi_output_zeros (drive, bcount);
                        return;
                }
@@ -150,14 +153,17 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
  */
 static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc)
 {
+       idescsi_scsi_t *scsi = drive->driver_data;
        u8 *c = pc->c, *buf = pc->buffer, *sc = pc->scsi_cmd->cmnd;
        int i;
 
+       if (!scsi->transform)
+               return;
        if (drive->media == ide_cdrom) {
                if (c[0] == READ_6 || c[0] == WRITE_6) {
                        c[8] = c[4];            c[5] = c[3];            c[4] = c[2];
                        c[3] = c[1] & 0x1f;     c[2] = 0;               c[1] &= 0xe0;
-                       c[0] = READ_10;
+                       c[0] += (READ_10 - READ_6);
                }
                if (c[0] == MODE_SENSE || (c[0] == MODE_SELECT && buf[3] == 8)) {
                        pc->request_transfer -= 4;
@@ -172,9 +178,12 @@ static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc)
 
 static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc)
 {
+       idescsi_scsi_t *scsi = drive->driver_data;
        u8 *buf = pc->buffer;
        int i;
 
+       if (!scsi->transform)
+               return;
        if (drive->media == ide_cdrom) {
                if (pc->c[0] == MODE_SENSE_10 && pc->scsi_cmd->cmnd[0] == MODE_SENSE) {
                        buf[0] = buf[1];        buf[1] = buf[2];
@@ -182,6 +191,8 @@ static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc)
                        for (i = pc->buffer_size - 1; i >= 12; i--) buf[i] = buf[i - 4];
                        for (i = 11; i >= 4; i--) buf[i] = 0;
                }
+               if (pc->c[0] == INQUIRY)
+                       buf[2] |= 2;
        }
 }
 
@@ -400,6 +411,19 @@ static void idescsi_ide_release (struct inode *inode, struct file *filp, ide_dri
 static ide_drive_t *idescsi_drives[MAX_HWIFS * MAX_DRIVES];
 static int idescsi_initialized = 0;
 
+static void idescsi_add_settings(ide_drive_t *drive)
+{
+       idescsi_scsi_t *scsi = drive->driver_data;
+
+/*
+ *                     drive   setting name    read/write      ioctl   ioctl           data type       min     max     mul_factor      div_factor      data pointer            set function
+ */
+       ide_add_setting(drive,  "bios_cyl",     SETTING_RW,     -1,     -1,             TYPE_SHORT,     0,      1023,   1,              1,              &drive->bios_cyl,       NULL);
+       ide_add_setting(drive,  "bios_head",    SETTING_RW,     -1,     -1,             TYPE_BYTE,      0,      255,    1,              1,              &drive->bios_head,      NULL);
+       ide_add_setting(drive,  "bios_sect",    SETTING_RW,     -1,     -1,             TYPE_BYTE,      0,      63,     1,              1,              &drive->bios_sect,      NULL);
+       ide_add_setting(drive,  "transform",    SETTING_RW,     -1,     -1,             TYPE_INT,       0,      1,      1,              1,              &scsi->transform,       NULL);
+}
+
 /*
  *     Driver initialization.
  */
@@ -413,6 +437,8 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id)
        scsi->drive = drive;
        if (drive->id && (drive->id->config & 0x0060) == 0x20)
                set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
+       scsi->transform = 1;
+       idescsi_add_settings(drive);
 }
 
 static int idescsi_cleanup (ide_drive_t *drive)
@@ -426,13 +452,6 @@ static int idescsi_cleanup (ide_drive_t *drive)
        return 0;
 }
 
-int idescsi_init (void);
-static ide_module_t idescsi_module = {
-       IDE_DRIVER_MODULE,
-       idescsi_init,
-       NULL
-};
-
 /*
  *     IDE subdriver functions, registered with ide.c
  */
@@ -456,6 +475,14 @@ static ide_driver_t idescsi_driver = {
        NULL                    /* proc */
 };
 
+int idescsi_init (void);
+static ide_module_t idescsi_module = {
+       IDE_DRIVER_MODULE,
+       idescsi_init,
+       &idescsi_driver,
+       NULL
+};
+
 static struct proc_dir_entry idescsi_proc_dir = {PROC_SCSI_IDESCSI, 8, "ide-scsi", S_IFDIR | S_IRUGO | S_IXUGO, 2};
 
 /*
@@ -476,7 +503,7 @@ int idescsi_init (void)
        MOD_INC_USE_COUNT;
        for (i = 0; media[i] != 255; i++) {
                failed = 0;
-               while ((drive = ide_scan_devices (media[i], NULL, failed++)) != NULL) {
+               while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) {
                        if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) {
                                printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name);
                                continue;
@@ -664,10 +691,10 @@ int idescsi_bios (Disk *disk, kdev_t dev, int *parm)
 {
        ide_drive_t *drive = idescsi_drives[disk->device->id];
 
-       if (drive->cyl && drive->head && drive->sect) {
-               parm[0] = drive->head;
-               parm[1] = drive->sect;
-               parm[2] = drive->cyl;
+       if (drive->bios_cyl && drive->bios_head && drive->bios_sect) {
+               parm[0] = drive->bios_head;
+               parm[1] = drive->bios_sect;
+               parm[2] = drive->bios_cyl;
        }
        return 0;
 }
@@ -692,7 +719,7 @@ void cleanup_module (void)
        scsi_unregister_module (MODULE_SCSI_HA, &idescsi_template);
        for (i = 0; media[i] != 255; i++) {
                failed = 0;
-               while ((drive = ide_scan_devices (media[i], &idescsi_driver, failed)) != NULL)
+               while ((drive = ide_scan_devices (media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL)
                        if (idescsi_cleanup (drive)) {
                                printk ("%s: cleanup_module() called while still busy\n", drive->name);
                                failed++;
index 771f1419278838dab7429930ddb94aa5b8c5246b..f5e19c5472443b8d250f003616e88fe7e3786c18 100644 (file)
@@ -62,7 +62,7 @@
 #define HOST_RESET_SETTLE_TIME  10*HZ
 
 
-static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_error.c,v 1.9 1997/12/07 23:38:23 eric Exp $";
+static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_error.c,v 1.10 1997/12/08 04:50:35 eric Exp $";
 
 STATIC int         scsi_check_sense (Scsi_Cmnd * SCpnt);
 STATIC int         scsi_request_sense(Scsi_Cmnd *);
@@ -1088,10 +1088,12 @@ STATIC  int scsi_check_sense (Scsi_Cmnd * SCpnt)
     case MEDIUM_ERROR:
        return FAILED;
 
+    case ILLEGAL_REQUEST:
+       return SUCCESS;
+
     case BLANK_CHECK:
     case DATA_PROTECT:
     case HARDWARE_ERROR:
-    case ILLEGAL_REQUEST:
     default:
        return FAILED;
     }
index b76f8c7e0e488257c21d2e149a2e5da52632c0c9..ef4ea936bf1e9aed5330109301e1acebe15cc661 100644 (file)
@@ -76,7 +76,7 @@
 #undef USE_STATIC_SCSI_MEMORY
 
 /*
-static const char RCSid[] = "$Header: /mnt/ide/home/eric/linux/drivers/scsi/RCS/scsi_obsolete.c,v 1.3 1997/04/29 04:25:08 eric Exp $";
+static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_obsolete.c,v 1.1 1997/05/18 23:27:21 eric Exp $";
 */
 
 
index cb4c989c450f933f3048e32c59d1bd607aa03059..924ec8e0c27b53eebf10a4ee68b5cab2be89ed99 100644 (file)
@@ -69,6 +69,8 @@ EXPORT_SYMBOL(scsi_mark_host_reset);
 EXPORT_SYMBOL(scsi_logging_level);
 #endif
 
+EXPORT_SYMBOL(scsi_sleep);
+
 #if defined(CONFIG_PROC_FS)
 EXPORT_SYMBOL(proc_print_scsidevice);
 #endif
index 295a32a36e578a5dc6a33819a04f1e816b6d46f4..3a6273df0d90691d1b50ea10eb80f6e0b4d5224b 100644 (file)
@@ -1494,12 +1494,19 @@ static int sd_init()
 
 static void sd_finish()
 {
+    struct gendisk *gendisk;
     int i;
 
     blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 
-    sd_gendisk.next = gendisk_head;
-    gendisk_head = &sd_gendisk;
+    for (gendisk = gendisk_head; gendisk != NULL; gendisk = gendisk->next)
+      if (gendisk == &sd_gendisk)
+       break;
+    if (gendisk == NULL)
+      {
+       sd_gendisk.next = gendisk_head;
+       gendisk_head = &sd_gendisk;
+      }
 
     for (i = 0; i < sd_template.dev_max; ++i)
        if (!rscsi_disks[i].capacity &&
index 153e3b73877b8177b8465f843d39be51f73200db..efc10389559a8a93134e6d8dc8e29998bf2b4905 100644 (file)
@@ -854,8 +854,6 @@ static int sr_attach(Scsi_Device * SDp){
     SDp->scsi_request_fn = do_sr_request;
     scsi_CDs[i].device = SDp;
 
-    sr_vendor_init(i);
-
     sr_template.nr_dev++;
     if(sr_template.nr_dev > sr_template.dev_max)
        panic ("scsi_devices corrupt (sr)");
@@ -986,13 +984,11 @@ void get_capabilities(int i){
     if (-EINVAL == rc) {
         /* failed, drive has'nt this mode page */
         scsi_CDs[i].cdi.speed      = 1;
-        scsi_CDs[i].cdi.capacity   = 1;
         /* disable speed select, drive probably can't do this either */
         scsi_CDs[i].cdi.mask      |= CDC_SELECT_SPEED;
     } else {
         n = buffer[3]+4;
         scsi_CDs[i].cdi.speed    = ((buffer[n+8] << 8) + buffer[n+9])/176;
-        scsi_CDs[i].cdi.capacity = 1;
        scsi_CDs[i].readcd_known = 1;
         scsi_CDs[i].readcd_cdda  = buffer[n+5] & 0x01;
         /* print some capability bits */
@@ -1085,7 +1081,9 @@ void sr_finish()
        scsi_CDs[i].cdi.handle     = &scsi_CDs[i];
        scsi_CDs[i].cdi.dev        = MKDEV(MAJOR_NR,i);
        scsi_CDs[i].cdi.mask       = 0;
+        scsi_CDs[i].cdi.capacity   = 1;
        get_capabilities(i);
+       sr_vendor_init(i);
 
        sprintf(name, "sr%d", i);
        strcpy(scsi_CDs[i].cdi.name, name);
index 344c1665456b98942f1c074b28cef48665c1a878..3973e866a8beca30fedaec349b6de2893c7b7da3 100644 (file)
@@ -30,7 +30,7 @@ extern void get_sectorsize(int);
 #define IOCTL_RETRIES 3
 /* The CDROM is fairly slow, so we need a little extra time */
 /* In fact, it is very slow if it has to spin up first */
-#define IOCTL_TIMEOUT 3000
+#define IOCTL_TIMEOUT 30*HZ
 
 static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
 {
@@ -51,11 +51,15 @@ static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
 int sr_do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength, int quiet)
 {
     Scsi_Cmnd * SCpnt;
+    Scsi_Device * SDev;
     int result, err = 0, retries = 0;
 
+    SDev  = scsi_CDs[target].device;
     SCpnt = scsi_allocate_device(NULL, scsi_CDs[target].device, 1);
 
 retry:
+    if( !scsi_block_when_processing_errors(SDev) )
+        return -ENODEV;
     {
        struct semaphore sem = MUTEX_LOCKED;
        SCpnt->request.sem = &sem;
@@ -69,7 +73,7 @@ retry:
     result = SCpnt->result;
     
     /* Minimal error checking.  Ignore cases we know about, and report the rest. */
-    if(driver_byte(result) != 0)
+    if(driver_byte(result) != 0) {
        switch(SCpnt->sense_buffer[2] & 0xf) {
        case UNIT_ATTENTION:
            scsi_CDs[target].device->changed = 1;
@@ -86,9 +90,7 @@ retry:
                     printk(KERN_INFO "sr%d: CDROM not ready yet.\n", target);
                if (retries++ < 10) {
                    /* sleep 2 sec and try again */
-                    current->state = TASK_INTERRUPTIBLE;
-                    current->timeout = jiffies + 200;
-                    schedule ();
+                   scsi_sleep(2*HZ);
                     goto retry;
                } else {
                    /* 20 secs are enouth? */
@@ -123,7 +125,8 @@ retry:
            print_command(sr_cmd);
            print_sense("sr", SCpnt);
             err = -EIO;
-       };
+       }
+    }
     
     result = SCpnt->result;
     /* Wake up a process waiting for device*/
@@ -279,23 +282,10 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
 int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void* arg)
 {
     u_char  sr_cmd[10];    
-    Scsi_Device * SDev;
     int result, target;
     
     target = MINOR(cdi->dev);
     
-    SDev = scsi_CDs[target].device;
-    /*
-     * If we are in the middle of error recovery, don't let anyone
-     * else try and use this device.  Also, if error recovery fails, it
-     * may try and take the device offline, in which case all further
-     * access to the device is prohibited.
-     */
-    if( !scsi_block_when_processing_errors(SDev) )
-      {
-        return -ENODEV;
-      }
-
     switch (cmd) 
     {
        /* Sun-compatible */
@@ -718,22 +708,9 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
                  unsigned int cmd, unsigned long arg)
 {
     int target, err;
-    Scsi_Device * SDev;
     
     target = MINOR(cdi->dev);
     
-    SDev = scsi_CDs[target].device;
-    /*
-     * If we are in the middle of error recovery, don't let anyone
-     * else try and use this device.  Also, if error recovery fails, it
-     * may try and take the device offline, in which case all further
-     * access to the device is prohibited.
-     */
-    if( !scsi_block_when_processing_errors(SDev) )
-      {
-        return -ENODEV;
-      }
-
     switch (cmd) {
     case CDROMREADMODE1:
     case CDROMREADMODE2:
index 7fec8fea15655aaa4b10182ec23adcbf8d7180eb..943c682bfcbe3cabfe1d113dfc483890533de3e2 100644 (file)
@@ -56,8 +56,7 @@
 
 #define VENDOR_NEC             2
 #define VENDOR_TOSHIBA         3
-#define VENDOR_HP_4020         4   /* HP 4xxx writers, others too ?? */
-#define VENDOR_HP_6020         5   /* HP 6020 writers */
+#define VENDOR_WRITER          4   /* pre-scsi3 writers */
 
 #define VENDOR_ID (scsi_CDs[minor].vendor)
 
@@ -72,13 +71,12 @@ sr_vendor_init(int minor)
 
        /* default */
        VENDOR_ID = VENDOR_SCSI3;
+       if (scsi_CDs[minor].readcd_known)
+               /* this is true for scsi3/mmc drives - no more checks */
+               return;
 
-       if ((!strncmp(vendor,"HP",2) || !strncmp(vendor,"PHILIPS",7)) &&
-           scsi_CDs[minor].device->type == TYPE_WORM) {
-               if (!strncmp(model,"CD-Writer 6020",14))
-                    VENDOR_ID = VENDOR_HP_6020;
-                else
-                    VENDOR_ID = VENDOR_HP_4020;
+       if (scsi_CDs[minor].device->type == TYPE_WORM) {
+               VENDOR_ID = VENDOR_WRITER;
 
        } else if (!strncmp (vendor, "NEC", 3)) {
                VENDOR_ID = VENDOR_NEC;
@@ -233,16 +231,13 @@ int sr_cd_check(struct cdrom_device_info *cdi)
                        sector -= CD_MSF_OFFSET;
                break;
 
-       case VENDOR_HP_4020:
-               /* Fallthrough */
-       case VENDOR_HP_6020:
+       case VENDOR_WRITER:
+               memset(cmd,0,12);
                cmd[0] = READ_TOC;
                cmd[1] = (scsi_CDs[minor].device->lun << 5);
-               cmd[8] = (VENDOR_ID == VENDOR_HP_4020) ?
-                       0x04 : 0x0c;
+               cmd[8] = 0x04;
                cmd[9] = 0x40;
-               rc = sr_do_ioctl(minor, cmd, buffer,
-                   (VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c, 0);
+               rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 0);
                if (rc != 0) {
                        break;
                }
@@ -252,16 +247,14 @@ int sr_cd_check(struct cdrom_device_info *cdi)
                        break;
                }
 
-               if (VENDOR_ID == VENDOR_HP_4020) {
-                   cmd[0] = READ_TOC; /* Read TOC */
-                   cmd[1] = (scsi_CDs[minor].device->lun << 5);
-                   cmd[6] = rc & 0x7f;  /* number of last session */
-                   cmd[8] = 0x0c;
-                   cmd[9] = 0x40;
-                   rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);        
-                   if (rc != 0) {
-                           break;
-                   }
+               cmd[0] = READ_TOC; /* Read TOC */
+               cmd[1] = (scsi_CDs[minor].device->lun << 5);
+               cmd[6] = rc & 0x7f;  /* number of last session */
+               cmd[8] = 0x0c;
+               cmd[9] = 0x40;
+               rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);    
+               if (rc != 0) {
+                       break;
                }
 
                sector = buffer[11] + (buffer[10] << 8) +
index 344853ccfedd2bdfbd86d7abf1a74143ae346718..901ae12ef65cb707de84f4ae0638000eb200e169 100644 (file)
@@ -149,7 +149,7 @@ bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
 if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    dep_tristate 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER $CONFIG_SOUND
    dep_tristate 'AWE32 synth' CONFIG_AWE32_SYNTH $CONFIG_SOUND
-   dep_tristate 'Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_AEDSP16
+   dep_tristate 'Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_AEDSP16 $CONFIG_SOUND
 
    if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then
       hex '  I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220
index c299a3d47276039df12efe589a995b1d234740d6..39365bd2f6e41eee68186f2124d3e565fd54b325 100644 (file)
 #include "ad1848_mixer.h"
 
 typedef struct
-  {
-         int             base;
-         int             irq;
-         int             dma1, dma2;
-         int             dual_dma;     /* 1, when two DMA channels allocated */
-         unsigned char   MCE_bit;
-         unsigned char   saved_regs[16];
-         int             debug_flag;
-
-         int             audio_flags;
-         int             record_dev, playback_dev;
-
-         int             xfer_count;
-         int             audio_mode;
-         int             open_mode;
-         int             intr_active;
-         char           *chip_name, *name;
-         int             model;
+{
+       int             base;
+       int             irq;
+       int             dma1, dma2;
+       int             dual_dma;       /* 1, when two DMA channels allocated */
+       unsigned char   MCE_bit;
+       unsigned char   saved_regs[16];
+       int             debug_flag;
+
+       int             audio_flags;
+       int             record_dev, playback_dev;
+
+       int             xfer_count;
+       int             audio_mode;
+       int             open_mode;
+       int             intr_active;
+       char           *chip_name, *name;
+       int             model;
 #define MD_1848                1
 #define MD_4231                2
 #define MD_4231A       3
@@ -66,44 +66,47 @@ typedef struct
 #define MD_C930                6
 #define MD_IWAVE       7
 
-         /* Mixer parameters */
-         int             recmask;
-         int             supported_devices, orig_devices;
-         int             supported_rec_devices, orig_rec_devices;
-         int            *levels;
-         short           mixer_reroute[32];
-         int             dev_no;
-         volatile unsigned long timer_ticks;
-         int             timer_running;
-         int             irq_ok;
-         mixer_ents     *mix_devices;
-         int             mixer_output_port;
-         int             c930_password_port;
-  }
-ad1848_info;
+       /* Mixer parameters */
+       int             recmask;
+       int             supported_devices, orig_devices;
+       int             supported_rec_devices, orig_rec_devices;
+       int            *levels;
+       short           mixer_reroute[32];
+       int             dev_no;
+       volatile unsigned long timer_ticks;
+       int             timer_running;
+       int             irq_ok;
+       mixer_ents     *mix_devices;
+       int             mixer_output_port;
+       int             c930_password_port;
+} ad1848_info;
 
 typedef struct ad1848_port_info
-  {
-         int             open_mode;
-         int             speed;
-         unsigned char   speed_bits;
-         int             channels;
-         int             audio_format;
-         unsigned char   format_bits;
-  }
+{
+       int             open_mode;
+       int             speed;
+       unsigned char   speed_bits;
+       int             channels;
+       int             audio_format;
+       unsigned char   format_bits;
+}
 ad1848_port_info;
 
-static int      nr_ad1848_devs = 0;
-static volatile char irq2dev[17] =
-{-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1};
+static int nr_ad1848_devs = 0;
+int deskpro_xl = 0;
+
+static volatile char irq2dev[17] = {
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
 
 #if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)
-static int      timer_installed = -1;
+
+static int timer_installed = -1;
 
 #endif
 
-static int      ad_format_mask[8 /*devc->model */ ] =
+static int ad_format_mask[8 /*devc->model */ ] =
 {
        0,
        AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
@@ -134,13 +137,12 @@ static void     ad1848_halt_output(int dev);
 static void     ad1848_trigger(int dev, int bits);
 
 #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE)
-static int      ad1848_tmr_install(int dev);
-static void     ad1848_tmr_reprogram(int dev);
+static int ad1848_tmr_install(int dev);
+static void ad1848_tmr_reprogram(int dev);
 
 #endif
 
-static int
-ad_read(ad1848_info * devc, int reg)
+static int ad_read(ad1848_info * devc, int reg)
 {
        unsigned long   flags;
        int             x;
@@ -159,8 +161,7 @@ ad_read(ad1848_info * devc, int reg)
        return x;
 }
 
-static void
-ad_write(ad1848_info * devc, int reg, int data)
+static void ad_write(ad1848_info * devc, int reg, int data)
 {
        unsigned long   flags;
        int             timeout = 900000;
@@ -177,23 +178,22 @@ ad_write(ad1848_info * devc, int reg, int data)
        restore_flags(flags);
 }
 
-static void
-wait_for_calibration(ad1848_info * devc)
+static void wait_for_calibration(ad1848_info * devc)
 {
        int             timeout = 0;
 
        /*
-          * Wait until the auto calibration process has finished.
-          *
-          * 1)       Wait until the chip becomes ready (reads don't return 0x80).
-          * 2)       Wait until the ACI bit of I11 gets on and then off.
+        * Wait until the auto calibration process has finished.
+        *
+        * 1)       Wait until the chip becomes ready (reads don't return 0x80).
+        * 2)       Wait until the ACI bit of I11 gets on and then off.
         */
 
        timeout = 100000;
        while (timeout > 0 && inb(devc->base) == 0x80)
                timeout--;
        if (inb(devc->base) & 0x80)
-               printk("ad1848: Auto calibration timed out(1).\n");
+               printk(KERN_WARNING "ad1848: Auto calibration timed out(1).\n");
 
        timeout = 100;
        while (timeout > 0 && !(ad_read(devc, 11) & 0x20))
@@ -206,36 +206,34 @@ wait_for_calibration(ad1848_info * devc)
                timeout--;
        if (ad_read(devc, 11) & 0x20)
                if (devc->model != MD_1845)
-                       printk("ad1848: Auto calibration timed out(3).\n");
+                       printk(KERN_WARNING "ad1848: Auto calibration timed out(3).\n");
 }
 
-static void
-ad_mute(ad1848_info * devc)
+static void ad_mute(ad1848_info * devc)
 {
-       int             i;
-       unsigned char   prev;
+       int i;
+       unsigned char prev;
 
        /*
-          * Save old register settings and mute output channels
+        * Save old register settings and mute output channels
         */
+        
        for (i = 6; i < 8; i++)
-         {
-                 prev = devc->saved_regs[i] = ad_read(devc, i);
-         }
+       {
+               prev = devc->saved_regs[i] = ad_read(devc, i);
+       }
 
 }
 
-static void
-ad_unmute(ad1848_info * devc)
+static void ad_unmute(ad1848_info * devc)
 {
 }
 
-static void
-ad_enter_MCE(ad1848_info * devc)
+static void ad_enter_MCE(ad1848_info * devc)
 {
-       unsigned long   flags;
-       int             timeout = 1000;
-       unsigned short  prev;
+       unsigned long flags;
+       int timeout = 1000;
+       unsigned short prev;
 
        while (timeout > 0 && inb(devc->base) == 0x80)  /*Are we initializing */
                timeout--;
@@ -246,20 +244,19 @@ ad_enter_MCE(ad1848_info * devc)
        devc->MCE_bit = 0x40;
        prev = inb(io_Index_Addr(devc));
        if (prev & 0x40)
-         {
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               restore_flags(flags);
+               return;
+       }
        outb((devc->MCE_bit), io_Index_Addr(devc));
        restore_flags(flags);
 }
 
-static void
-ad_leave_MCE(ad1848_info * devc)
+static void ad_leave_MCE(ad1848_info * devc)
 {
-       unsigned long   flags;
-       unsigned char   prev, acal;
-       int             timeout = 1000;
+       unsigned long flags;
+       unsigned char prev, acal;
+       int timeout = 1000;
 
        while (timeout > 0 && inb(devc->base) == 0x80)  /*Are we initializing */
                timeout--;
@@ -274,18 +271,17 @@ ad_leave_MCE(ad1848_info * devc)
        outb((0x00), io_Index_Addr(devc));      /* Clear the MCE bit */
 
        if ((prev & 0x40) == 0) /* Not in MCE mode */
-         {
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               restore_flags(flags);
+               return;
+       }
        outb((0x00), io_Index_Addr(devc));      /* Clear the MCE bit */
        if (acal & 0x08)        /* Auto calibration is enabled */
                wait_for_calibration(devc);
        restore_flags(flags);
 }
 
-static int
-ad1848_set_recmask(ad1848_info * devc, int mask)
+static int ad1848_set_recmask(ad1848_info * devc, int mask)
 {
        unsigned char   recdev;
        int             i, n;
@@ -294,12 +290,17 @@ ad1848_set_recmask(ad1848_info * devc, int mask)
 
        /* Rename the mixer bits if necessary */
        for (i = 0; i < 32; i++)
+       {
                if (devc->mixer_reroute[i] != i)
+               {
                        if (mask & (1 << i))
-                         {
-                                 mask &= ~(1 << i);
-                                 mask |= (1 << devc->mixer_reroute[i]);
-                         }
+                       {
+                               mask &= ~(1 << i);
+                               mask |= (1 << devc->mixer_reroute[i]);
+                       }
+               }
+       }
+       
        n = 0;
        for (i = 0; i < 32; i++)        /* Count selected device bits */
                if (mask & (1 << i))
@@ -308,41 +309,41 @@ ad1848_set_recmask(ad1848_info * devc, int mask)
        if (n == 0)
                mask = SOUND_MASK_MIC;
        else if (n != 1)        /* Too many devices selected */
-         {
+       {
                  mask &= ~devc->recmask;       /* Filter out active settings */
 
-                 n = 0;
-                 for (i = 0; i < 32; i++)      /* Count selected device bits */
-                         if (mask & (1 << i))
-                                 n++;
+               n = 0;
+               for (i = 0; i < 32; i++)        /* Count selected device bits */
+                       if (mask & (1 << i))
+                               n++;
 
-                 if (n != 1)
-                         mask = SOUND_MASK_MIC;
-         }
+               if (n != 1)
+                       mask = SOUND_MASK_MIC;
+       }
        switch (mask)
-         {
-         case SOUND_MASK_MIC:
-                 recdev = 2;
-                 break;
-
-         case SOUND_MASK_LINE:
-         case SOUND_MASK_LINE3:
-                 recdev = 0;
-                 break;
-
-         case SOUND_MASK_CD:
-         case SOUND_MASK_LINE1:
-                 recdev = 1;
-                 break;
-
-         case SOUND_MASK_IMIX:
-                 recdev = 3;
-                 break;
-
-         default:
-                 mask = SOUND_MASK_MIC;
-                 recdev = 2;
-         }
+       {
+               case SOUND_MASK_MIC:
+                       recdev = 2;
+                       break;
+
+               case SOUND_MASK_LINE:
+               case SOUND_MASK_LINE3:
+                       recdev = 0;
+                       break;
+
+               case SOUND_MASK_CD:
+               case SOUND_MASK_LINE1:
+                       recdev = 1;
+                       break;
+
+               case SOUND_MASK_IMIX:
+                       recdev = 3;
+                       break;
+
+               default:
+                       mask = SOUND_MASK_MIC;
+                       recdev = 2;
+       }
 
        recdev <<= 6;
        ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
@@ -350,24 +351,27 @@ ad1848_set_recmask(ad1848_info * devc, int mask)
 
        /* Rename the mixer bits back if necessary */
        for (i = 0; i < 32; i++)
+       {
                if (devc->mixer_reroute[i] != i)
+               {
                        if (mask & (1 << devc->mixer_reroute[i]))
-                         {
-                                 mask &= ~(1 << devc->mixer_reroute[i]);
-                                 mask |= (1 << i);
-                         }
+                       {
+                               mask &= ~(1 << devc->mixer_reroute[i]);
+                               mask |= (1 << i);
+                       }
+               }
+       }
        devc->recmask = mask;
        return mask;
 }
 
-static void
-change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
+static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
 {
-       unsigned char   mask;
-       int             shift;
-       int             mute;
-       int             mutemask;
-       int             set_mute_bit;
+       unsigned char mask;
+       int shift;
+       int mute;
+       int mutemask;
+       int set_mute_bit;
 
        set_mute_bit = (newval == 0);
 
@@ -378,22 +382,22 @@ change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int new
        shift = devc->mix_devices[dev][chn].bitpos;
 
        if (devc->mix_devices[dev][chn].mutepos == 8)
-         {                     /* if there is no mute bit */
-                 mute = 0;     /* No mute bit; do nothing special */
-                 mutemask = ~0;        /* No mute bit; do nothing special */
-       } else
-         {
-                 mute = (set_mute_bit << devc->mix_devices[dev][chn].mutepos);
-                 mutemask = ~(1 << devc->mix_devices[dev][chn].mutepos);
-         }
+       {                       /* if there is no mute bit */
+               mute = 0;       /* No mute bit; do nothing special */
+               mutemask = ~0;  /* No mute bit; do nothing special */
+       }
+       else
+       {
+               mute = (set_mute_bit << devc->mix_devices[dev][chn].mutepos);
+               mutemask = ~(1 << devc->mix_devices[dev][chn].mutepos);
+       }
 
        newval = (int) ((newval * mask) + 50) / 100;    /* Scale it */
        *regval &= (~(mask << shift)) & (mutemask);     /* Clear bits */
        *regval |= ((newval & mask) << shift) | mute;   /* Set new value */
 }
 
-static int
-ad1848_mixer_get(ad1848_info * devc, int dev)
+static int ad1848_mixer_get(ad1848_info * devc, int dev)
 {
        if (!((1 << dev) & devc->supported_devices))
                return -EINVAL;
@@ -403,15 +407,14 @@ ad1848_mixer_get(ad1848_info * devc, int dev)
        return devc->levels[dev];
 }
 
-static int
-ad1848_mixer_set(ad1848_info * devc, int dev, int value)
+static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
 {
-       int             left = value & 0x000000ff;
-       int             right = (value & 0x0000ff00) >> 8;
-       int             retvol;
+       int left = value & 0x000000ff;
+       int right = (value & 0x0000ff00) >> 8;
+       int retvol;
 
-       int             regoffs;
-       unsigned char   val;
+       int regoffs;
+       unsigned char val;
 
        if (dev > 31)
                return -EINVAL;
@@ -445,7 +448,7 @@ ad1848_mixer_set(ad1848_info * devc, int dev, int value)
        devc->levels[dev] = retvol;
 
        /*
-          * Set the left channel
+        * Set the left channel
         */
 
        regoffs = devc->mix_devices[dev][LEFT_CHN].regno;
@@ -455,7 +458,7 @@ ad1848_mixer_set(ad1848_info * devc, int dev, int value)
        devc->saved_regs[regoffs] = val;
 
        /*
-          * Set the right channel
+        * Set the right channel
         */
 
        if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)
@@ -470,11 +473,10 @@ ad1848_mixer_set(ad1848_info * devc, int dev, int value)
        return retvol;
 }
 
-static void
-ad1848_mixer_reset(ad1848_info * devc)
+static void ad1848_mixer_reset(ad1848_info * devc)
 {
-       int             i;
-       char            name[32];
+       int i;
+       char name[32];
 
        devc->mix_devices = &(ad1848_mix_devices[0]);
 
@@ -484,30 +486,30 @@ ad1848_mixer_reset(ad1848_info * devc)
                devc->mixer_reroute[i] = i;
 
        switch (devc->model)
-         {
-         case MD_4231:
-         case MD_4231A:
-         case MD_1845:
-                 devc->supported_devices = MODE2_MIXER_DEVICES;
-                 break;
-
-         case MD_C930:
-                 devc->supported_devices = C930_MIXER_DEVICES;
-                 devc->mix_devices = &(c930_mix_devices[0]);
-                 break;
-
-         case MD_IWAVE:
-                 devc->supported_devices = MODE3_MIXER_DEVICES;
-                 devc->mix_devices = &(iwave_mix_devices[0]);
-                 break;
-
-         case MD_4232:
-                 devc->supported_devices = MODE3_MIXER_DEVICES;
-                 break;
-
-         default:
-                 devc->supported_devices = MODE1_MIXER_DEVICES;
-         }
+       {
+               case MD_4231:
+               case MD_4231A:
+               case MD_1845:
+                       devc->supported_devices = MODE2_MIXER_DEVICES;
+                       break;
+
+               case MD_C930:
+                       devc->supported_devices = C930_MIXER_DEVICES;
+                       devc->mix_devices = &(c930_mix_devices[0]);
+                       break;
+
+               case MD_IWAVE:
+                       devc->supported_devices = MODE3_MIXER_DEVICES;
+                       devc->mix_devices = &(iwave_mix_devices[0]);
+                       break;
+
+               case MD_4232:
+                       devc->supported_devices = MODE3_MIXER_DEVICES;
+                       break;
+
+               default:
+                       devc->supported_devices = MODE1_MIXER_DEVICES;
+       }
 
        devc->supported_rec_devices = MODE1_REC_DEVICES;
        devc->orig_devices = devc->supported_devices;
@@ -516,9 +518,13 @@ ad1848_mixer_reset(ad1848_info * devc)
        devc->levels = load_mixer_volumes(name, default_mixer_levels, 1);
 
        for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+       {
                if (devc->supported_devices & (1 << i))
                        ad1848_mixer_set(devc, i, devc->levels[i]);
+       }
+       
        ad1848_set_recmask(devc, SOUND_MASK_MIC);
+       
        devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT;
        if (devc->mixer_output_port & AUDIO_SPEAKER)
                ad_write(devc, 26, ad_read(devc, 26) & ~0x40);  /* Unmute mono out */
@@ -531,11 +537,13 @@ static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
        ad1848_info *devc = mixer_devs[dev]->devc;
        int val;
 
-       if (cmd == SOUND_MIXER_PRIVATE1) {
+       if (cmd == SOUND_MIXER_PRIVATE1) 
+       {
                if (get_user(val, (int *)arg))
                        return -EFAULT;
 
-               if (val != 0xffff) {
+               if (val != 0xffff) 
+               {
                        val &= (AUDIO_SPEAKER | AUDIO_HEADPHONE | AUDIO_LINE_OUT);
                        devc->mixer_output_port = val;
                        val |= AUDIO_HEADPHONE | AUDIO_LINE_OUT;        /* Always on */
@@ -548,75 +556,85 @@ static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
                val = devc->mixer_output_port;
                return put_user(val, (int *)arg);
        }
-       if (((cmd >> 8) & 0xff) == 'M') {
+       if (((cmd >> 8) & 0xff) == 'M') 
+       {
                if (_SIOC_DIR(cmd) & _SIOC_WRITE)
-                       switch (cmd & 0xff) {
-                       case SOUND_MIXER_RECSRC:
-                               if (get_user(val, (int *)arg))
-                                       return -EFAULT;
-                               val = ad1848_set_recmask(devc, val);
-                               return put_user(val, (int *)arg);
+               {
+                       switch (cmd & 0xff) 
+                       {
+                               case SOUND_MIXER_RECSRC:
+                                       if (get_user(val, (int *)arg))
+                                               return -EFAULT;
+                                       val = ad1848_set_recmask(devc, val);
+                                       break;
                                
-                           default:
-                               if (get_user(val, (int *)arg))
+                               default:
+                                       if (get_user(val, (int *)arg))
                                        return -EFAULT;
-                               val = ad1848_mixer_set(devc, cmd & 0xff, val);
-                               return put_user(val, (int *)arg);
+                                       val = ad1848_mixer_set(devc, cmd & 0xff, val);
+                                       break;
                        } 
+                       return put_user(val, (int *)arg);
+               }
                else
-                       switch (cmd & 0xff) {
+               {
+                       switch (cmd & 0xff) 
+                       {
                                /*
                                 * Return parameters
                                 */
                            
-                       case SOUND_MIXER_RECSRC:
-                               val = devc->recmask;
-                               return put_user(val, (int *)arg);
+                               case SOUND_MIXER_RECSRC:
+                                       val = devc->recmask;
+                                       break;
                                
-                       case SOUND_MIXER_DEVMASK:
-                               val = devc->supported_devices;
-                               return put_user(val, (int *)arg);
+                               case SOUND_MIXER_DEVMASK:
+                                       val = devc->supported_devices;
+                                       break;
                                
-                       case SOUND_MIXER_STEREODEVS:
-                               val = devc->supported_devices;
-                               if (devc->model != MD_C930)
-                                       val &= ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
-                               return put_user(val, (int *)arg);
+                               case SOUND_MIXER_STEREODEVS:
+                                       val = devc->supported_devices;
+                                       if (devc->model != MD_C930)
+                                               val &= ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
+                                       break;
                                
-                       case SOUND_MIXER_RECMASK:
-                               val = devc->supported_rec_devices;
-                               return put_user(val, (int *)arg);
+                               case SOUND_MIXER_RECMASK:
+                                       val = devc->supported_rec_devices;
+                                       break;
 
-                       case SOUND_MIXER_CAPS:
-                               return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
+                               case SOUND_MIXER_CAPS:
+                                       val=SOUND_CAP_EXCL_INPUT;
+                                       break;
 
-                       default:
-                               val = ad1848_mixer_get(devc, cmd & 0xff);
-                               return put_user(val, (int *)arg);
+                               default:
+                                       val = ad1848_mixer_get(devc, cmd & 0xff);
+                                       break;
                        }
-       } else
+                       return put_user(val, (int *)arg);
+               }
+       }
+       else
                return -EINVAL;
 }
 
-static int
-ad1848_set_speed(int dev, int arg)
+static int ad1848_set_speed(int dev, int arg)
 {
-       ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+       ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
        ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
 
        /*
-          * The sampling speed is encoded in the least significant nibble of I8. The
-          * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other
-          * three bits select the divisor (indirectly):
-          *
-          * The available speeds are in the following table. Keep the speeds in
-          * the increasing order.
+        * The sampling speed is encoded in the least significant nibble of I8. The
+        * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other
+        * three bits select the divisor (indirectly):
+        *
+        * The available speeds are in the following table. Keep the speeds in
+        * the increasing order.
         */
        typedef struct
-         {
-                 int             speed;
-                 unsigned char   bits;
-         }
+       {
+               int             speed;
+               unsigned char   bits;
+       }
        speed_struct;
 
        static speed_struct speed_table[] =
@@ -638,7 +656,7 @@ ad1848_set_speed(int dev, int arg)
                {48000, (6 << 1) | 0}
        };
 
-       int             i, n, selected = -1;
+       int i, n, selected = -1;
 
        n = sizeof(speed_table) / sizeof(speed_struct);
 
@@ -646,48 +664,49 @@ ad1848_set_speed(int dev, int arg)
                return portc->speed;
 
        if (devc->model == MD_1845)     /* AD1845 has different timer than others */
-         {
-                 if (arg < 4000)
-                         arg = 4000;
-                 if (arg > 50000)
-                         arg = 50000;
-
-                 portc->speed = arg;
-                 portc->speed_bits = speed_table[3].bits;
-                 return portc->speed;
-         }
+       {
+               if (arg < 4000)
+                       arg = 4000;
+               if (arg > 50000)
+                       arg = 50000;
+
+               portc->speed = arg;
+               portc->speed_bits = speed_table[3].bits;
+               return portc->speed;
+       }
        if (arg < speed_table[0].speed)
                selected = 0;
        if (arg > speed_table[n - 1].speed)
                selected = n - 1;
 
        for (i = 1 /*really */ ; selected == -1 && i < n; i++)
+       {
                if (speed_table[i].speed == arg)
                        selected = i;
                else if (speed_table[i].speed > arg)
-                 {
-                         int             diff1, diff2;
+               {
+                       int diff1, diff2;
 
-                         diff1 = arg - speed_table[i - 1].speed;
-                         diff2 = speed_table[i].speed - arg;
+                       diff1 = arg - speed_table[i - 1].speed;
+                       diff2 = speed_table[i].speed - arg;
 
-                         if (diff1 < diff2)
-                                 selected = i - 1;
-                         else
-                                 selected = i;
-                 }
+                       if (diff1 < diff2)
+                               selected = i - 1;
+                       else
+                               selected = i;
+               }
+       }
        if (selected == -1)
-         {
-                 printk("ad1848: Can't find speed???\n");
-                 selected = 3;
-         }
+       {
+               printk(KERN_WARNING "ad1848: Can't find speed???\n");
+               selected = 3;
+       }
        portc->speed = speed_table[selected].speed;
        portc->speed_bits = speed_table[selected].bits;
        return portc->speed;
 }
 
-static short
-ad1848_set_channels(int dev, short arg)
+static short ad1848_set_channels(int dev, short arg)
 {
        ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
 
@@ -698,17 +717,16 @@ ad1848_set_channels(int dev, short arg)
        return arg;
 }
 
-static unsigned int
-ad1848_set_bits(int dev, unsigned int arg)
+static unsigned int ad1848_set_bits(int dev, unsigned int arg)
 {
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
        ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
 
        static struct format_tbl
-         {
+       {
                  int             format;
                  unsigned char   bits;
-         }
+       }
        format2bits[] =
        {
                {
@@ -751,7 +769,7 @@ ad1848_set_bits(int dev, unsigned int arg)
                        AFMT_U16_BE, 0
                }
        };
-       int             i, n = sizeof(format2bits) / sizeof(struct format_tbl);
+       int i, n = sizeof(format2bits) / sizeof(struct format_tbl);
 
        if (arg == 0)
                return portc->audio_format;
@@ -763,12 +781,12 @@ ad1848_set_bits(int dev, unsigned int arg)
 
        for (i = 0; i < n; i++)
                if (format2bits[i].format == arg)
-                 {
-                         if ((portc->format_bits = format2bits[i].bits) == 0)
-                                 return portc->audio_format = AFMT_U8;         /* Was not supported */
+               {
+                       if ((portc->format_bits = format2bits[i].bits) == 0)
+                               return portc->audio_format = AFMT_U8;           /* Was not supported */
 
-                         return arg;
-                 }
+                       return arg;
+               }
        /* Still hanging here. Something must be terribly wrong */
        portc->format_bits = 0;
        return portc->audio_format = AFMT_U8;
@@ -801,8 +819,7 @@ static struct mixer_operations ad1848_mixer_operations =
        ad1848_mixer_ioctl
 };
 
-static int
-ad1848_open(int dev, int mode)
+static int ad1848_open(int dev, int mode)
 {
        ad1848_info    *devc = NULL;
        ad1848_port_info *portc;
@@ -817,16 +834,16 @@ ad1848_open(int dev, int mode)
        save_flags(flags);
        cli();
        if (portc->open_mode || (devc->open_mode & mode))
-         {
-                 restore_flags(flags);
-                 return -EBUSY;
-         }
+       {
+               restore_flags(flags);
+               return -EBUSY;
+       }
        devc->dual_dma = 0;
 
        if (audio_devs[dev]->flags & DMA_DUPLEX)
-         {
-                 devc->dual_dma = 1;
-         }
+       {
+               devc->dual_dma = 1;
+       }
        devc->intr_active = 0;
        devc->audio_mode = 0;
        devc->open_mode |= mode;
@@ -846,8 +863,7 @@ ad1848_open(int dev, int mode)
        return 0;
 }
 
-static void
-ad1848_close(int dev)
+static void ad1848_close(int dev)
 {
        unsigned long   flags;
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
@@ -869,8 +885,7 @@ ad1848_close(int dev)
        restore_flags(flags);
 }
 
-static void
-ad1848_output_block(int dev, unsigned long buf, int count, int intrflag)
+static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag)
 {
        unsigned long   flags, cnt;
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
@@ -879,13 +894,14 @@ ad1848_output_block(int dev, unsigned long buf, int count, int intrflag)
        cnt = count;
 
        if (portc->audio_format == AFMT_IMA_ADPCM)
-         {
-                 cnt /= 4;
-       } else
-         {
-                 if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))        /* 16 bit data */
-                         cnt >>= 1;
-         }
+       {
+               cnt /= 4;
+       }
+       else
+       {
+               if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))  /* 16 bit data */
+                       cnt >>= 1;
+       }
        if (portc->channels > 1)
                cnt >>= 1;
        cnt--;
@@ -893,13 +909,13 @@ ad1848_output_block(int dev, unsigned long buf, int count, int intrflag)
        if (devc->audio_mode & PCM_ENABLE_OUTPUT && audio_devs[dev]->flags & DMA_AUTOMODE &&
            intrflag &&
            cnt == devc->xfer_count)
-         {
-                 devc->audio_mode |= PCM_ENABLE_OUTPUT;
-                 devc->intr_active = 1;
-                 return;       /*
-                                * Auto DMA mode on. No need to react
-                                */
-         }
+       {
+               devc->audio_mode |= PCM_ENABLE_OUTPUT;
+               devc->intr_active = 1;
+               return; /*
+                        * Auto DMA mode on. No need to react
+                        */
+       }
        save_flags(flags);
        cli();
 
@@ -912,8 +928,7 @@ ad1848_output_block(int dev, unsigned long buf, int count, int intrflag)
        restore_flags(flags);
 }
 
-static void
-ad1848_start_input(int dev, unsigned long buf, int count, int intrflag)
+static void ad1848_start_input(int dev, unsigned long buf, int count, int intrflag)
 {
        unsigned long   flags, cnt;
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
@@ -921,39 +936,41 @@ ad1848_start_input(int dev, unsigned long buf, int count, int intrflag)
 
        cnt = count;
        if (portc->audio_format == AFMT_IMA_ADPCM)
-         {
-                 cnt /= 4;
-       } else
-         {
-                 if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))        /* 16 bit data */
-                         cnt >>= 1;
-         }
+       {
+               cnt /= 4;
+       }
+       else
+       {
+               if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))  /* 16 bit data */
+                       cnt >>= 1;
+       }
        if (portc->channels > 1)
                cnt >>= 1;
        cnt--;
 
        if (devc->audio_mode & PCM_ENABLE_INPUT && audio_devs[dev]->flags & DMA_AUTOMODE &&
-           intrflag &&
-           cnt == devc->xfer_count)
-         {
-                 devc->audio_mode |= PCM_ENABLE_INPUT;
-                 devc->intr_active = 1;
-                 return;       /*
-                                * Auto DMA mode on. No need to react
-                                */
-         }
+               intrflag &&
+               cnt == devc->xfer_count)
+       {
+               devc->audio_mode |= PCM_ENABLE_INPUT;
+               devc->intr_active = 1;
+               return; /*
+                        * Auto DMA mode on. No need to react
+                        */
+       }
        save_flags(flags);
        cli();
 
        if (devc->model == MD_1848)
-         {
+       {
                  ad_write(devc, 15, (unsigned char) (cnt & 0xff));
                  ad_write(devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
-       } else
-         {
+       }
+       else
+       {
                  ad_write(devc, 31, (unsigned char) (cnt & 0xff));
                  ad_write(devc, 30, (unsigned char) ((cnt >> 8) & 0xff));
-         }
+       }
 
        ad_unmute(devc);
 
@@ -963,8 +980,7 @@ ad1848_start_input(int dev, unsigned long buf, int count, int intrflag)
        restore_flags(flags);
 }
 
-static int
-ad1848_prepare_for_output(int dev, int bsize, int bcount)
+static int ad1848_prepare_for_output(int dev, int bsize, int bcount)
 {
        int             timeout;
        unsigned char   fs, old_fs, tmp = 0;
@@ -984,26 +1000,28 @@ ad1848_prepare_for_output(int dev, int bsize, int bcount)
        ad_enter_MCE(devc);     /* Enables changes to the format select reg */
 
        if (devc->model == MD_1845)     /* Use alternate speed select registers */
-         {
-                 fs &= 0xf0;   /* Mask off the rate select bits */
+       {
+               fs &= 0xf0;     /* Mask off the rate select bits */
 
-                 ad_write(devc, 22, (portc->speed >> 8) & 0xff);       /* Speed MSB */
-                 ad_write(devc, 23, portc->speed & 0xff);      /* Speed LSB */
-         }
+               ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */
+               ad_write(devc, 23, portc->speed & 0xff);        /* Speed LSB */
+       }
        old_fs = ad_read(devc, 8);
 
        if (devc->model == MD_4232)
-         {
-                 tmp = ad_read(devc, 16);
-                 ad_write(devc, 16, tmp | 0x30);
-         }
+       {
+               tmp = ad_read(devc, 16);
+               ad_write(devc, 16, tmp | 0x30);
+       }
        if (devc->model == MD_IWAVE)
                ad_write(devc, 17, 0xc2);       /* Disable variable frequency select */
 
        ad_write(devc, 8, fs);
+
        /*
         * Write to I8 starts resynchronization. Wait until it completes.
         */
+
        timeout = 0;
        while (timeout < 100 && inb(devc->base) != 0x80)
                timeout++;
@@ -1023,21 +1041,20 @@ ad1848_prepare_for_output(int dev, int bsize, int bcount)
 #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE)
        if (dev == timer_installed && devc->timer_running)
                if ((fs & 0x01) != (old_fs & 0x01))
-                 {
-                         ad1848_tmr_reprogram(dev);
-                 }
+               {
+                       ad1848_tmr_reprogram(dev);
+               }
 #endif
        ad1848_halt_output(dev);
        return 0;
 }
 
-static int
-ad1848_prepare_for_input(int dev, int bsize, int bcount)
+static int ad1848_prepare_for_input(int dev, int bsize, int bcount)
 {
-       int             timeout;
-       unsigned char   fs, old_fs, tmp = 0;
-       unsigned long   flags;
-       ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+       int timeout;
+       unsigned char fs, old_fs, tmp = 0;
+       unsigned long flags;
+       ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
        ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
 
        if (devc->audio_mode)
@@ -1053,75 +1070,78 @@ ad1848_prepare_for_input(int dev, int bsize, int bcount)
        ad_enter_MCE(devc);     /* Enables changes to the format select reg */
 
        if (devc->model == MD_1845)     /* Use alternate speed select registers */
-         {
-                 fs &= 0xf0;   /* Mask off the rate select bits */
+       {
+               fs &= 0xf0;     /* Mask off the rate select bits */
 
-                 ad_write(devc, 22, (portc->speed >> 8) & 0xff);       /* Speed MSB */
-                 ad_write(devc, 23, portc->speed & 0xff);      /* Speed LSB */
-         }
+               ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */
+               ad_write(devc, 23, portc->speed & 0xff);        /* Speed LSB */
+       }
        if (devc->model == MD_4232)
-         {
-                 tmp = ad_read(devc, 16);
-                 ad_write(devc, 16, tmp | 0x30);
-         }
+       {
+               tmp = ad_read(devc, 16);
+               ad_write(devc, 16, tmp | 0x30);
+       }
        if (devc->model == MD_IWAVE)
                ad_write(devc, 17, 0xc2);       /* Disable variable frequency select */
 
        /*
         * If mode >= 2 (CS4231), set I28. It's the capture format register.
         */
+       
        if (devc->model != MD_1848)
-         {
-                 old_fs = ad_read(devc, 28);
-                 ad_write(devc, 28, fs);
-
-                 /*
-                  * Write to I28 starts resynchronization. Wait until it completes.
-                  */
-                 timeout = 0;
-                 while (timeout < 100 && inb(devc->base) != 0x80)
-                         timeout++;
-
-                 timeout = 0;
-                 while (timeout < 10000 && inb(devc->base) == 0x80)
-                         timeout++;
-
-                 if (devc->model != MD_1848 && devc->model != MD_1845)
-                   {
-                           /*
-                            * CS4231 compatible devices don't have separate sampling rate selection
-                            * register for recording an playback. The I8 register is shared so we have to
-                            * set the speed encoding bits of it too.
-                            */
-                           unsigned char   tmp = portc->speed_bits | (ad_read(devc, 8) & 0xf0);
-
-                           ad_write(devc, 8, tmp);
-                           /*
-                            * Write to I8 starts resynchronization. Wait until it completes.
-                            */
-                           timeout = 0;
-                           while (timeout < 100 && inb(devc->base) != 0x80)
-                                   timeout++;
-
-                           timeout = 0;
-                           while (timeout < 10000 && inb(devc->base) == 0x80)
-                                   timeout++;
-                   }
-       } else
-         {                     /* For AD1848 set I8. */
-
-                 old_fs = ad_read(devc, 8);
-                 ad_write(devc, 8, fs);
-                 /*
-                  * Write to I8 starts resynchronization. Wait until it completes.
-                  */
-                 timeout = 0;
-                 while (timeout < 100 && inb(devc->base) != 0x80)
-                         timeout++;
-                 timeout = 0;
-                 while (timeout < 10000 && inb(devc->base) == 0x80)
-                         timeout++;
-         }
+       {
+               old_fs = ad_read(devc, 28);
+               ad_write(devc, 28, fs);
+
+               /*
+                * Write to I28 starts resynchronization. Wait until it completes.
+                */
+               
+               timeout = 0;
+               while (timeout < 100 && inb(devc->base) != 0x80)
+                       timeout++;
+
+               timeout = 0;
+               while (timeout < 10000 && inb(devc->base) == 0x80)
+                       timeout++;
+
+               if (devc->model != MD_1848 && devc->model != MD_1845)
+               {
+                       /*
+                        * CS4231 compatible devices don't have separate sampling rate selection
+                        * register for recording an playback. The I8 register is shared so we have to
+                        * set the speed encoding bits of it too.
+                        */
+                       unsigned char   tmp = portc->speed_bits | (ad_read(devc, 8) & 0xf0);
+
+                       ad_write(devc, 8, tmp);
+                       /*
+                        * Write to I8 starts resynchronization. Wait until it completes.
+                        */
+                       timeout = 0;
+                       while (timeout < 100 && inb(devc->base) != 0x80)
+                               timeout++;
+
+                       timeout = 0;
+                       while (timeout < 10000 && inb(devc->base) == 0x80)
+                               timeout++;
+               }
+       }
+       else
+       {                       /* For AD1848 set I8. */
+
+               old_fs = ad_read(devc, 8);
+               ad_write(devc, 8, fs);
+               /*
+                * Write to I8 starts resynchronization. Wait until it completes.
+                */
+               timeout = 0;
+               while (timeout < 100 && inb(devc->base) != 0x80)
+                       timeout++;
+               timeout = 0;
+               while (timeout < 10000 && inb(devc->base) == 0x80)
+                       timeout++;
+       }
 
        if (devc->model == MD_4232)
                ad_write(devc, 16, tmp & ~0x30);
@@ -1134,19 +1154,20 @@ ad1848_prepare_for_input(int dev, int bsize, int bcount)
 
 #if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)
        if (dev == timer_installed && devc->timer_running)
+       {
                if ((fs & 0x01) != (old_fs & 0x01))
-                 {
-                         ad1848_tmr_reprogram(dev);
-                 }
+               {
+                       ad1848_tmr_reprogram(dev);
+               }
+       }
 #endif
        ad1848_halt_input(dev);
        return 0;
 }
 
-static void
-ad1848_halt(int dev)
+static void ad1848_halt(int dev)
 {
-       ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
+       ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
        ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
 
        unsigned char   bits = ad_read(devc, 9);
@@ -1159,8 +1180,7 @@ ad1848_halt(int dev)
        devc->audio_mode = 0;
 }
 
-static void
-ad1848_halt_input(int dev)
+static void ad1848_halt_input(int dev)
 {
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
        unsigned long   flags;
@@ -1187,19 +1207,18 @@ ad1848_halt_input(int dev)
                devc->audio_mode &= ~PCM_ENABLE_INPUT;
        }
 
-       outb((0), io_Status(devc));     /* Clear interrupt status */
-       outb((0), io_Status(devc));     /* Clear interrupt status */
+       outb(0, io_Status(devc));       /* Clear interrupt status */
+       outb(0, io_Status(devc));       /* Clear interrupt status */
 
        devc->audio_mode &= ~PCM_ENABLE_INPUT;
 
        restore_flags(flags);
 }
 
-static void
-ad1848_halt_output(int dev)
+static void ad1848_halt_output(int dev)
 {
-       ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
-       unsigned long   flags;
+       ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
+       unsigned long flags;
 
        if (!(ad_read(devc, 9) & 0x01))
                return;         /* Playback not enabled */
@@ -1230,8 +1249,7 @@ ad1848_halt_output(int dev)
        restore_flags(flags);
 }
 
-static void
-ad1848_trigger(int dev, int state)
+static void ad1848_trigger(int dev, int state)
 {
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
        ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
@@ -1245,32 +1263,31 @@ ad1848_trigger(int dev, int state)
        tmp = old = ad_read(devc, 9);
 
        if (portc->open_mode & OPEN_READ)
-         {
+       {
                  if (state & PCM_ENABLE_INPUT)
                          tmp |= 0x02;
                  else
                          tmp &= ~0x02;
-         }
+       }
        if (portc->open_mode & OPEN_WRITE)
-         {
-                 if (state & PCM_ENABLE_OUTPUT)
-                         tmp |= 0x01;
-                 else
-                         tmp &= ~0x01;
-         }
+       {
+               if (state & PCM_ENABLE_OUTPUT)
+                       tmp |= 0x01;
+               else
+                       tmp &= ~0x01;
+       }
        /* ad_mute(devc); */
        if (tmp != old)
-         {
+       {
                  ad_write(devc, 9, tmp);
                  ad_unmute(devc);
-         }
+       }
        restore_flags(flags);
 }
 
-static void
-ad1848_init_hw(ad1848_info * devc)
+static void ad1848_init_hw(ad1848_info * devc)
 {
-       int             i;
+       int i;
 
        /*
         * Initial values for the indirect registers of CS4248/AD1848.
@@ -1294,40 +1311,40 @@ ad1848_init_hw(ad1848_info * devc)
        ad_unmute(devc);        /* Leave it unmuted now */
 
        if (devc->model > MD_1848)
-         {
-                 ad_write(devc, 12, ad_read(devc, 12) | 0x40);         /* Mode2 = enabled */
-
-                 if (devc->model == MD_IWAVE)
-                         ad_write(devc, 12, 0x6c);     /* Select codec mode 3 */
+       {
+               ad_write(devc, 12, ad_read(devc, 12) | 0x40);           /* Mode2 = enabled */
 
-                 for (i = 16; i < 32; i++)
-                         ad_write(devc, i, init_values[i]);
+               if (devc->model == MD_IWAVE)
+                       ad_write(devc, 12, 0x6c);       /* Select codec mode 3 */
 
-                 if (devc->model == MD_IWAVE)
-                         ad_write(devc, 16, 0x30);     /* Playback and capture counters enabled */
+               for (i = 16; i < 32; i++)
+                       ad_write(devc, i, init_values[i]);
 
-         }
+               if (devc->model == MD_IWAVE)
+                       ad_write(devc, 16, 0x30);       /* Playback and capture counters enabled */
+       }
        if (devc->model > MD_1848)
-         {
-                 if (devc->audio_flags & DMA_DUPLEX)
-                         ad_write(devc, 9, ad_read(devc, 9) & ~0x04);  /* Dual DMA mode */
-                 else
-                         ad_write(devc, 9, ad_read(devc, 9) | 0x04);   /* Single DMA mode */
+       {
+               if (devc->audio_flags & DMA_DUPLEX)
+                       ad_write(devc, 9, ad_read(devc, 9) & ~0x04);    /* Dual DMA mode */
+               else
+                       ad_write(devc, 9, ad_read(devc, 9) | 0x04);     /* Single DMA mode */
 
-                 if (devc->model == MD_1845)
-                         ad_write(devc, 27, ad_read(devc, 27) | 0x08);         /* Alternate freq select enabled */
+               if (devc->model == MD_1845)
+                       ad_write(devc, 27, ad_read(devc, 27) | 0x08);           /* Alternate freq select enabled */
 
-                 if (devc->model == MD_IWAVE)
-                   {           /* Some magic Interwave specific initialization */
-                           ad_write(devc, 12, 0x6c);   /* Select codec mode 3 */
-                           ad_write(devc, 16, 0x30);   /* Playback and capture counters enabled */
-                           ad_write(devc, 17, 0xc2);   /* Alternate feature enable */
-                   }
-       } else
-         {
+               if (devc->model == MD_IWAVE)
+               {               /* Some magic Interwave specific initialization */
+                       ad_write(devc, 12, 0x6c);       /* Select codec mode 3 */
+                       ad_write(devc, 16, 0x30);       /* Playback and capture counters enabled */
+                       ad_write(devc, 17, 0xc2);       /* Alternate feature enable */
+               }
+       }
+       else
+       {
                  devc->audio_flags &= ~DMA_DUPLEX;
                  ad_write(devc, 9, ad_read(devc, 9) | 0x04);   /* Single DMA mode */
-         }
+       }
 
        outb((0), io_Status(devc));     /* Clear pending interrupts */
 
@@ -1341,45 +1358,43 @@ ad1848_init_hw(ad1848_info * devc)
        ad1848_mixer_reset(devc);
 }
 
-int
-ad1848_detect(int io_base, int *ad_flags, int *osp)
+int ad1848_detect(int io_base, int *ad_flags, int *osp)
 {
+       unsigned char tmp;
+       ad1848_info *devc = &adev_info[nr_ad1848_devs];
+       unsigned char tmp1 = 0xff, tmp2 = 0xff;
+       int optiC930 = 0;       /* OPTi 82C930 flag */
+       int interwave = 0;
+       int ad1847_flag = 0;
+       int cs4248_flag = 0;
 
-       unsigned char   tmp;
-       ad1848_info    *devc = &adev_info[nr_ad1848_devs];
-       unsigned char   tmp1 = 0xff, tmp2 = 0xff;
-       int             optiC930 = 0;   /* OPTi 82C930 flag */
-       int             interwave = 0;
-       int             ad1847_flag = 0;
-       int             cs4248_flag = 0;
-
-       int             i;
+       int i;
 
        DDB(printk("ad1848_detect(%x)\n", io_base));
 
        if (ad_flags)
-         {
-                 if (*ad_flags == 0x12345678)
-                   {
-                           interwave = 1;
-                           *ad_flags = 0;
-                   }
-                 if (*ad_flags == 0x12345677)
-                   {
-                           cs4248_flag = 1;
-                           *ad_flags = 0;
-                   }
-         }
+       {
+               if (*ad_flags == 0x12345678)
+               {
+                       interwave = 1;
+                       *ad_flags = 0;
+               }
+               if (*ad_flags == 0x12345677)
+               {
+                   cs4248_flag = 1;
+                   *ad_flags = 0;
+               }
+       }
        if (nr_ad1848_devs >= MAX_AUDIO_DEV)
-         {
-                 printk("ad1848 - Too many audio devices\n");
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "ad1848 - Too many audio devices\n");
+               return 0;
+       }
        if (check_region(io_base, 4))
-         {
-                 printk("ad1848.c: Port %x not free.\n", io_base);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base);
+               return 0;
+       }
        devc->base = io_base;
        devc->irq_ok = 0;
        devc->timer_running = 0;
@@ -1393,31 +1408,33 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
        devc->debug_flag = 0;
 
        /*
-          * Check that the I/O address is in use.
-          *
-          * The bit 0x80 of the base I/O port is known to be 0 after the
-          * chip has performed its power on initialization. Just assume
-          * this has happened before the OS is starting.
-          *
-          * If the I/O address is unused, it typically returns 0xff.
+        * Check that the I/O address is in use.
+        *
+        * The bit 0x80 of the base I/O port is known to be 0 after the
+        * chip has performed its power on initialization. Just assume
+        * this has happened before the OS is starting.
+        *
+        * If the I/O address is unused, it typically returns 0xff.
         */
 
        if (inb(devc->base) == 0xff)
-         {
-                 DDB(printk("ad1848_detect: The base I/O address appears to be dead\n"));
-         }
-/*
- * Wait for the device to stop initialization
- */
+       {
+               DDB(printk("ad1848_detect: The base I/O address appears to be dead\n"));
+       }
+
+       /*
+        * Wait for the device to stop initialization
+        */
+       
        DDB(printk("ad1848_detect() - step 0\n"));
 
        for (i = 0; i < 10000000; i++)
-         {
-                 unsigned char   x = inb(devc->base);
+       {
+               unsigned char   x = inb(devc->base);
 
-                 if (x == 0xff || !(x & 0x80))
-                         break;
-         }
+               if (x == 0xff || !(x & 0x80))
+                       break;
+       }
 
        DDB(printk("ad1848_detect() - step A\n"));
 
@@ -1425,14 +1442,15 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
                ad_leave_MCE(devc);
 
        if ((inb(devc->base) & 0x80) != 0x00)   /* Not a AD1848 */
-         {
-                 DDB(printk("ad1848 detect error - step A (%02x)\n", (int) inb(devc->base)));
-                 return 0;
-         }
+       {
+               DDB(printk("ad1848 detect error - step A (%02x)\n", (int) inb(devc->base)));
+               return 0;
+       }
+       
        /*
-          * Test if it's possible to change contents of the indirect registers.
-          * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only
-          * so try to avoid using it.
+        * Test if it's possible to change contents of the indirect registers.
+        * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only
+        * so try to avoid using it.
         */
 
        DDB(printk("ad1848_detect() - step B\n"));
@@ -1440,28 +1458,33 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
        ad_write(devc, 1, 0x45);        /* 0x55 with bit 0x10 clear */
 
        if ((tmp1 = ad_read(devc, 0)) != 0xaa || (tmp2 = ad_read(devc, 1)) != 0x45)
+       {
                if (tmp2 == 0x65)       /* AD1847 has couple of bits hardcoded to 1 */
                        ad1847_flag = 1;
                else
-                 {
-                         DDB(printk("ad1848 detect error - step B (%x/%x)\n", tmp1, tmp2));
-                         return 0;
-                 }
+               {
+                       DDB(printk("ad1848 detect error - step B (%x/%x)\n", tmp1, tmp2));
+                       return 0;
+               }
+       }
        DDB(printk("ad1848_detect() - step C\n"));
        ad_write(devc, 0, 0x45);
        ad_write(devc, 1, 0xaa);
 
        if ((tmp1 = ad_read(devc, 0)) != 0x45 || (tmp2 = ad_read(devc, 1)) != 0xaa)
+       {
                if (tmp2 == 0x8a)       /* AD1847 has few bits hardcoded to 1 */
                        ad1847_flag = 1;
                else
-                 {
-                         DDB(printk("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2));
-                         return 0;
-                 }
+               {
+                       DDB(printk("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2));
+                       return 0;
+               }
+       }
+
        /*
-          * The indirect register I12 has some read only bits. Lets
-          * try to change them.
+        * The indirect register I12 has some read only bits. Lets
+        * try to change them.
         */
 
        DDB(printk("ad1848_detect() - step D\n"));
@@ -1469,43 +1492,47 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
        ad_write(devc, 12, (~tmp) & 0x0f);
 
        if ((tmp & 0x0f) != ((tmp1 = ad_read(devc, 12)) & 0x0f))
-         {
-                 DDB(printk("ad1848 detect error - step D (%x)\n", tmp1));
-                 return 0;
-         }
+       {
+               DDB(printk("ad1848 detect error - step D (%x)\n", tmp1));
+               return 0;
+       }
+       
        /*
-          * NOTE! Last 4 bits of the reg I12 tell the chip revision.
-          *   0x01=RevB and 0x0A=RevC.
+        * NOTE! Last 4 bits of the reg I12 tell the chip revision.
+        *   0x01=RevB and 0x0A=RevC.
         */
 
        /*
-          * The original AD1848/CS4248 has just 15 indirect registers. This means
-          * that I0 and I16 should return the same value (etc.).
-          * However this doesn't work with CS4248. Actually it seems to be impossible
-          * to detect if the chip is a CS4231 or CS4248.
-          * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails
-          * with CS4231.
+        * The original AD1848/CS4248 has just 15 indirect registers. This means
+        * that I0 and I16 should return the same value (etc.).
+        * However this doesn't work with CS4248. Actually it seems to be impossible
+        * to detect if the chip is a CS4231 or CS4248.
+        * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails
+        * with CS4231.
         */
 
-/*
- * OPTi 82C930 has mode2 control bit in another place. This test will fail
- * with it. Accept this situation as a possible indication of this chip.
- */
+       /*
       * OPTi 82C930 has mode2 control bit in another place. This test will fail
       * with it. Accept this situation as a possible indication of this chip.
       */
 
        DDB(printk("ad1848_detect() - step F\n"));
        ad_write(devc, 12, 0);  /* Mode2=disabled */
 
        for (i = 0; i < 16; i++)
+       {
                if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16)))
-                 {
-                         DDB(printk("ad1848 detect step F(%d/%x/%x) - OPTi chip???\n", i, tmp1, tmp2));
-                         if (!ad1847_flag)
-                                 optiC930 = 1;
-                         break;
-                 }
+               {
+                       DDB(printk("ad1848 detect step F(%d/%x/%x) - OPTi chip???\n", i, tmp1, tmp2));
+                       if (!ad1847_flag)
+                               optiC930 = 1;
+                       break;
+               }
+       }
+
        /*
-          * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40).
-          * The bit 0x80 is always 1 in CS4248 and CS4231.
+        * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40).
+        * The bit 0x80 is always 1 in CS4248 and CS4231.
         */
 
        DDB(printk("ad1848_detect() - step G\n"));
@@ -1521,66 +1548,67 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
 
        tmp1 = ad_read(devc, 12);
        if (tmp1 & 0x80)
-         {
-                 if (ad_flags)
-                         *ad_flags |= AD_F_CS4248;
+       {
+               if (ad_flags)
+                       *ad_flags |= AD_F_CS4248;
 
-                 devc->chip_name = "CS4248";   /* Our best knowledge just now */
-         }
+               devc->chip_name = "CS4248";     /* Our best knowledge just now */
+       }
        if (optiC930 || (tmp1 & 0xc0) == (0x80 | 0x40))
-         {
-                 /*
-                    *      CS4231 detected - is it?
-                    *
-                    *      Verify that setting I0 doesn't change I16.
-                  */
-                 DDB(printk("ad1848_detect() - step H\n"));
-                 ad_write(devc, 16, 0);        /* Set I16 to known value */
-
-                 ad_write(devc, 0, 0x45);
-                 if ((tmp1 = ad_read(devc, 16)) != 0x45)       /* No change -> CS4231? */
-                   {
-
-                           ad_write(devc, 0, 0xaa);
-                           if ((tmp1 = ad_read(devc, 16)) == 0xaa)     /* Rotten bits? */
-                             {
-                                     DDB(printk("ad1848 detect error - step H(%x)\n", tmp1));
-                                     return 0;
-                             }
-                           /*
-                              * Verify that some bits of I25 are read only.
-                            */
-
-                           DDB(printk("ad1848_detect() - step I\n"));
-                           tmp1 = ad_read(devc, 25);   /* Original bits */
-                           ad_write(devc, 25, ~tmp1);  /* Invert all bits */
-                           if ((ad_read(devc, 25) & 0xe7) == (tmp1 & 0xe7))
-                             {
-                                     int             id, full_id;
-
-                                     /*
-                                      *      It's at least CS4231
-                                      */
-                                     devc->chip_name = "CS4231";
-
-                                     devc->model = MD_4231;
-
-                                     /*
-                                      * It could be an AD1845 or CS4231A as well.
-                                      * CS4231 and AD1845 report the same revision info in I25
-                                      * while the CS4231A reports different.
-                                      */
-
-                                     id = ad_read(devc, 25) & 0xe7;
-                                     full_id = ad_read(devc, 25);
-                                     if (id == 0x80)   /* Device busy??? */
-                                             id = ad_read(devc, 25) & 0xe7;
-                                     if (id == 0x80)   /* Device still busy??? */
-                                             id = ad_read(devc, 25) & 0xe7;
-                                     DDB(printk("ad1848_detect() - step J (%02x/%02x)\n", id, ad_read(devc, 25)));
-
-                                     switch (id)
-                                       {
+       {
+               /*
+                *      CS4231 detected - is it?
+                *
+                *      Verify that setting I0 doesn't change I16.
+                */
+               
+               DDB(printk("ad1848_detect() - step H\n"));
+               ad_write(devc, 16, 0);  /* Set I16 to known value */
+
+               ad_write(devc, 0, 0x45);
+               if ((tmp1 = ad_read(devc, 16)) != 0x45) /* No change -> CS4231? */
+               {
+                       ad_write(devc, 0, 0xaa);
+                       if ((tmp1 = ad_read(devc, 16)) == 0xaa) /* Rotten bits? */
+                       {
+                               DDB(printk("ad1848 detect error - step H(%x)\n", tmp1));
+                               return 0;
+                       }
+                       
+                       /*
+                        * Verify that some bits of I25 are read only.
+                        */
+
+                       DDB(printk("ad1848_detect() - step I\n"));
+                       tmp1 = ad_read(devc, 25);       /* Original bits */
+                       ad_write(devc, 25, ~tmp1);      /* Invert all bits */
+                       if ((ad_read(devc, 25) & 0xe7) == (tmp1 & 0xe7))
+                       {
+                               int id, full_id;
+
+                               /*
+                                *      It's at least CS4231
+                                */
+                               
+                               devc->chip_name = "CS4231";
+                               devc->model = MD_4231;
+
+                               /*
+                                * It could be an AD1845 or CS4231A as well.
+                                * CS4231 and AD1845 report the same revision info in I25
+                                * while the CS4231A reports different.
+                                */
+
+                               id = ad_read(devc, 25) & 0xe7;
+                               full_id = ad_read(devc, 25);
+                               if (id == 0x80) /* Device busy??? */
+                                       id = ad_read(devc, 25) & 0xe7;
+                               if (id == 0x80) /* Device still busy??? */
+                                       id = ad_read(devc, 25) & 0xe7;
+                               DDB(printk("ad1848_detect() - step J (%02x/%02x)\n", id, ad_read(devc, 25)));
+
+                               switch (id)
+                               {
 
                                        case 0xa0:
                                                devc->chip_name = "CS4231A";
@@ -1618,25 +1646,26 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
                                                         */
 
                                                        unsigned char   tmp = ad_read(devc, 23);
-
                                                        ad_write(devc, 23, ~tmp);
+
                                                        if (interwave)
-                                                         {
-                                                                 devc->model = MD_IWAVE;
-                                                                 devc->chip_name = "IWave";
-                                                       } else if (ad_read(devc, 23) != tmp)    /* AD1845 ? */
-                                                         {
-                                                                 devc->chip_name = "AD1845";
-                                                                 devc->model = MD_1845;
-                                                       } else if (cs4248_flag)
-                                                         {
-                                                                 if (ad_flags)
+                                                       {
+                                                               devc->model = MD_IWAVE;
+                                                               devc->chip_name = "IWave";
+                                                       }
+                                                       else if (ad_read(devc, 23) != tmp)      /* AD1845 ? */
+                                                       {
+                                                               devc->chip_name = "AD1845";
+                                                               devc->model = MD_1845;
+                                                       }
+                                                       else if (cs4248_flag)
+                                                       {
+                                                               if (ad_flags)
                                                                          *ad_flags |= AD_F_CS4248;
-
-                                                                 devc->chip_name = "CS4248";
-                                                                 devc->model = MD_1848;
-                                                                 ad_write(devc, 12, ad_read(devc, 12) & ~0x40);        /* Mode2 off */
-                                                         }
+                                                               devc->chip_name = "CS4248";
+                                                               devc->model = MD_1848;
+                                                               ad_write(devc, 12, ad_read(devc, 12) & ~0x40);  /* Mode2 off */
+                                                       }
                                                        ad_write(devc, 23, tmp);        /* Restore */
                                                }
                                                break;
@@ -1644,27 +1673,27 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
                                        default:        /* Assume CS4231 or OPTi 82C930 */
                                                DDB(printk("ad1848: I25 = %02x/%02x\n", ad_read(devc, 25), ad_read(devc, 25) & 0xe7));
                                                if (optiC930)
-                                                 {
-                                                         devc->chip_name = "82C930";
-                                                         devc->model = MD_C930;
-                                               } else
-                                                 {
-                                                         devc->model = MD_4231;
-                                                 }
-
-                                       }
-                             }
-                           ad_write(devc, 25, tmp1);   /* Restore bits */
-
-                           DDB(printk("ad1848_detect() - step K\n"));
-                   }
-         }
+                                               {
+                                                       devc->chip_name = "82C930";
+                                                       devc->model = MD_C930;
+                                               }
+                                               else
+                                               {
+                                                       devc->model = MD_4231;
+                                               }
+                               }
+                       }
+                       ad_write(devc, 25, tmp1);       /* Restore bits */
+
+                       DDB(printk("ad1848_detect() - step K\n"));
+               }
+       }
        DDB(printk("ad1848_detect() - step L\n"));
        if (ad_flags)
-         {
+       {
                  if (devc->model != MD_1848)
                          *ad_flags |= AD_F_CS4231;
-         }
+       }
        DDB(printk("ad1848_detect() - Detected OK\n"));
 
        if (devc->model == MD_1848 && ad1847_flag)
@@ -1674,19 +1703,18 @@ ad1848_detect(int io_base, int *ad_flags, int *osp)
        return 1;
 }
 
-int
-ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp)
+int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp)
 {
        /*
-          * NOTE! If irq < 0, there is another driver which has allocated the IRQ
-          *   so that this driver doesn't need to allocate/deallocate it.
-          *   The actually used IRQ is ABS(irq).
+        * NOTE! If irq < 0, there is another driver which has allocated the IRQ
+        *   so that this driver doesn't need to allocate/deallocate it.
+        *   The actually used IRQ is ABS(irq).
         */
 
 
-       int             my_dev;
-       char            dev_name[100];
-       int             e;
+       int my_dev;
+       char dev_name[100];
+       int e;
 
        ad1848_info    *devc = &adev_info[nr_ad1848_devs];
 
@@ -1711,19 +1739,19 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture,
 
        request_region(devc->base, 4, devc->name);
 
-       conf_printf2(dev_name,
-                    devc->base, devc->irq, dma_playback, dma_capture);
+       conf_printf2(dev_name, devc->base, devc->irq, dma_playback, dma_capture);
 
        if (devc->model == MD_1848 || devc->model == MD_C930)
                devc->audio_flags |= DMA_HARDSTOP;
 
        if (devc->model > MD_1848)
-         {
-                 if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1)
-                         devc->audio_flags &= ~DMA_DUPLEX;
-                 else
-                         devc->audio_flags |= DMA_DUPLEX;
-         }
+       {
+               if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1)
+                       devc->audio_flags &= ~DMA_DUPLEX;
+               else
+                       devc->audio_flags |= DMA_DUPLEX;
+       }
+       
        if ((my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
                                             dev_name,
                                             &ad1848_audio_driver,
@@ -1733,9 +1761,9 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture,
                                             devc,
                                             dma_playback,
                                             dma_capture)) < 0)
-         {
-                 return -1;
-         }
+       {
+               return -1;
+       }
        portc = (ad1848_port_info *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(ad1848_port_info)));
        sound_mem_sizes[sound_nblocks] = sizeof(ad1848_port_info);
        if (sound_nblocks < 1024)
@@ -1748,37 +1776,38 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture,
        ad1848_init_hw(devc);
 
        if (irq > 0)
-         {
-                 irq2dev[irq] = devc->dev_no = my_dev;
-                 if (snd_set_irq_handler(devc->irq, adintr,
+       {
+               irq2dev[irq] = devc->dev_no = my_dev;
+               if (snd_set_irq_handler(devc->irq, adintr,
                                          devc->name,
                                          NULL) < 0)
-                   {
-                           printk(KERN_WARNING "ad1848: IRQ in use\n");
-                   }
-                 if (devc->model != MD_1848 && devc->model != MD_C930)
-                   {
-                           int             x;
-                           unsigned char   tmp = ad_read(devc, 16);
-
-                           devc->timer_ticks = 0;
-
-                           ad_write(devc, 21, 0x00);   /* Timer MSB */
-                           ad_write(devc, 20, 0x10);   /* Timer LSB */
-
-                           ad_write(devc, 16, tmp | 0x40);     /* Enable timer */
-                           for (x = 0; x < 100000 && devc->timer_ticks == 0; x++);
-                           ad_write(devc, 16, tmp & ~0x40);    /* Disable timer */
-
-                           if (devc->timer_ticks == 0)
-                                   printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", devc->irq);
-                           else
-                             {
-                                     DDB(printk("Interrupt test OK\n"));
-                                     devc->irq_ok = 1;
-                             }
-                 } else
-                         devc->irq_ok = 1;     /* Couldn't test. assume it's OK */
+               {
+                       printk(KERN_WARNING "ad1848: IRQ in use\n");
+               }
+               if (devc->model != MD_1848 && devc->model != MD_C930)
+               {
+                       int             x;
+                       unsigned char   tmp = ad_read(devc, 16);
+
+                       devc->timer_ticks = 0;
+
+                       ad_write(devc, 21, 0x00);       /* Timer MSB */
+                       ad_write(devc, 20, 0x10);       /* Timer LSB */
+
+                       ad_write(devc, 16, tmp | 0x40); /* Enable timer */
+                       for (x = 0; x < 100000 && devc->timer_ticks == 0; x++);
+                       ad_write(devc, 16, tmp & ~0x40);        /* Disable timer */
+
+                       if (devc->timer_ticks == 0)
+                               printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", devc->irq);
+                       else
+                       {
+                               DDB(printk("Interrupt test OK\n"));
+                               devc->irq_ok = 1;
+                       }
+               }
+               else
+                       devc->irq_ok = 1;       /* Couldn't test. assume it's OK */
        } else if (irq < 0)
                irq2dev[-irq] = devc->dev_no = my_dev;
 
@@ -1789,22 +1818,22 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture,
 #endif
 
        if (!share_dma)
-         {
-                 if (sound_alloc_dma(dma_playback, devc->name))
-                         printk("ad1848.c: Can't allocate DMA%d\n", dma_playback);
-
-                 if (dma_capture != dma_playback)
-                         if (sound_alloc_dma(dma_capture, devc->name))
-                                 printk("ad1848.c: Can't allocate DMA%d\n", dma_capture);
-         }
+       {
+               if (sound_alloc_dma(dma_playback, devc->name))
+                       printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_playback);
+
+               if (dma_capture != dma_playback)
+                       if (sound_alloc_dma(dma_capture, devc->name))
+                               printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_capture);
+       }
        if ((e = sound_install_mixer(MIXER_DRIVER_VERSION,
                                     dev_name,
                                     &ad1848_mixer_operations,
                                     sizeof(struct mixer_operations),
                                     devc)) >= 0)
-         {
-                 audio_devs[my_dev]->mixer_dev = e;
-         }
+       {
+               audio_devs[my_dev]->mixer_dev = e;
+       }
        MOD_INC_USE_COUNT;
        return my_dev;
 }
@@ -1819,76 +1848,79 @@ void ad1848_control(int cmd, int arg)
        devc = &adev_info[nr_ad1848_devs - 1];
 
        switch (cmd)
-         {
-         case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */
-                 if (devc->model != MD_1845)
-                         return;
-                 ad_enter_MCE(devc);
-                 ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5));
-                 ad_leave_MCE(devc);
-                 break;
-
-         case AD1848_MIXER_REROUTE:
-                 {
-                         int             o = (arg >> 8) & 0xff;
-                         int             n = arg & 0xff;
-
-                         if (n == SOUND_MIXER_NONE)
-                           {   /* Just hide this control */
-                                   ad1848_mixer_set(devc, o, 0);       /* Shut up it */
-                                   devc->supported_devices &= ~(1 << o);
-                                   devc->supported_rec_devices &= ~(1 << o);
-                                   return;
-                           }
-                         /* Make the mixer control identified by o to appear as n */
-
-                         if (o < 0 || o > SOUND_MIXER_NRDEVICES)
-                                 return;
-                         if (n < 0 || n > SOUND_MIXER_NRDEVICES)
-                                 return;
-                         if (!(devc->supported_devices & (1 << o)))
-                                 return;       /* Not supported */
-
-                         devc->mixer_reroute[n] = o;   /* Rename the control */
-                         devc->supported_devices &= ~(1 << o);
-                         devc->supported_devices |= (1 << n);
-                         if (devc->supported_rec_devices & (1 << o))
-                                 devc->supported_rec_devices |= (1 << n);
-                         devc->supported_rec_devices &= ~(1 << o);
-                 }
-                 break;
-         }
+       {
+               case AD1848_SET_XTAL:   /* Change clock frequency of AD1845 (only ) */
+               if (devc->model != MD_1845)
+                               return;
+                       ad_enter_MCE(devc);
+                       ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5));
+                       ad_leave_MCE(devc);
+                       break;
+
+               case AD1848_MIXER_REROUTE:
+               {
+                       int             o = (arg >> 8) & 0xff;
+                       int             n = arg & 0xff;
+
+                       if (n == SOUND_MIXER_NONE)
+                       {       /* Just hide this control */
+                               ad1848_mixer_set(devc, o, 0);   /* Shut up it */
+                               devc->supported_devices &= ~(1 << o);
+                               devc->supported_rec_devices &= ~(1 << o);
+                               return;
+                       }
+                       /* Make the mixer control identified by o to appear as n */
+
+                       if (o < 0 || o > SOUND_MIXER_NRDEVICES)
+                               return;
+                       if (n < 0 || n > SOUND_MIXER_NRDEVICES)
+                               return;
+                       if (!(devc->supported_devices & (1 << o)))
+                               return; /* Not supported */
+
+                       devc->mixer_reroute[n] = o;     /* Rename the control */
+                       devc->supported_devices &= ~(1 << o);
+                       devc->supported_devices |= (1 << n);
+                       if (devc->supported_rec_devices & (1 << o))
+                               devc->supported_rec_devices |= (1 << n);
+                       devc->supported_rec_devices &= ~(1 << o);
+               }
+               break;
+       }
        return;
 }
 
-void
-ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma)
+void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma)
 {
-       int             i, dev = 0;
-       ad1848_info    *devc = NULL;
+       int i, dev = 0;
+       ad1848_info *devc = NULL;
 
        for (i = 0; devc == NULL && i < nr_ad1848_devs; i++)
+       {
                if (adev_info[i].base == io_base)
-                 {
-                         devc = &adev_info[i];
-                         dev = devc->dev_no;
-                 }
+               {
+                       devc = &adev_info[i];
+                       dev = devc->dev_no;
+               }
+       }
+               
        if (devc != NULL)
-         {
-                 release_region(devc->base, 4);
+       {
+               release_region(devc->base, 4);
 
-                 if (!share_dma)
-                   {
-                           if (irq > 0)
-                                   snd_release_irq(devc->irq);
+               if (!share_dma)
+               {
+                       if (irq > 0)
+                               snd_release_irq(devc->irq);
 
-                           sound_free_dma(audio_devs[dev]->dmap_out->dma);
+                       sound_free_dma(audio_devs[dev]->dmap_out->dma);
 
-                           if (audio_devs[dev]->dmap_in->dma != audio_devs[dev]->dmap_out->dma)
-                                   sound_free_dma(audio_devs[dev]->dmap_in->dma);
-                   }
-       } else
-               printk("ad1848: Can't find device to be unloaded. Base=%x\n", io_base);
+                       if (audio_devs[dev]->dmap_in->dma != audio_devs[dev]->dmap_out->dma)
+                               sound_free_dma(audio_devs[dev]->dmap_in->dma);
+               }
+       }
+       else
+               printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base);
        MOD_DEC_USE_COUNT;
 }
 
@@ -1902,94 +1934,96 @@ void adintr(int irq, void *dev_id, struct pt_regs *dummy)
        int             cnt = 0;
 
        if (irq < 0 || irq > 15)
-         {
-                 dev = -1;
-       } else
+       {
+               dev = -1;
+       }
+       else
                dev = irq2dev[irq];
 
        if (dev < 0 || dev >= num_audiodevs)
-         {
-                 for (irq = 0; irq < 17; irq++)
-                         if (irq2dev[irq] != -1)
-                                 break;
-
-                 if (irq > 15)
-                   {
-                           /* printk("ad1848.c: Bogus interrupt %d\n", irq); */
-                           return;
-                   }
-                 dev = irq2dev[irq];
-                 devc = (ad1848_info *) audio_devs[dev]->devc;
+       {
+               for (irq = 0; irq < 17; irq++)
+                       if (irq2dev[irq] != -1)
+                               break;
+
+               if (irq > 15)
+               {
+                       /* printk("ad1848.c: Bogus interrupt %d\n", irq); */
+                       return;
+               }
+               dev = irq2dev[irq];
+               devc = (ad1848_info *) audio_devs[dev]->devc;
        } else
                devc = (ad1848_info *) audio_devs[dev]->devc;
 
-      interrupt_again:         /* Jump back here if int status doesn't reset */
+interrupt_again:               /* Jump back here if int status doesn't reset */
 
        status = inb(io_Status(devc));
 
        if (status == 0x80)
-               printk("adintr: Why?\n");
+               printk(KERN_DEBUG "adintr: Why?\n");
        if (devc->model == MD_1848)
                outb((0), io_Status(devc));     /* Clear interrupt status */
 
        if (status & 0x01)
-         {
-                 if (devc->model == MD_C930)
-                   {           /* 82C930 has interrupt status register in MAD16 register MC11 */
-                           unsigned long   flags;
-
-                           save_flags(flags);
-                           cli();
-
-                           alt_stat = 0;
-
-                           if (devc->c930_password_port)
-                                   outb((0xe4), devc->c930_password_port);     /* Password */
-                           outb((11), 0xe0e);
-                           c930_stat = inb(0xe0f);
-
-                           if (c930_stat & 0x04)
-                                   alt_stat |= 0x10;   /* Playback intr */
-                           if (c930_stat & 0x08)
-                                   alt_stat |= 0x20;   /* Playback intr */
-                           restore_flags(flags);
-                 } else if (devc->model != MD_1848)
-                         alt_stat = ad_read(devc, 24);
-
-                 /* Acknowledge the intr before proceeding */
-                 if (devc->model == MD_C930)
-                   {           /* 82C930 has interrupt status register in MAD16 register MC11 */
-                           unsigned long   flags;
-
-                           save_flags(flags);
-                           cli();
-
-                           if (devc->c930_password_port)
-                                   outb((0xe4), devc->c930_password_port);     /* Password */
-                           outb((11), 0xe0e);
-                           outb((~c930_stat), 0xe0f);
-                           restore_flags(flags);
-                 } else if (devc->model != MD_1848)
-                         ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat);    /* Selective ack */
-
-                 if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
-                   {
-                           DMAbuf_inputintr(devc->record_dev);
-                   }
-                 if (devc->open_mode & OPEN_WRITE && devc->audio_mode & PCM_ENABLE_OUTPUT &&
+       {
+               if (devc->model == MD_C930)
+               {               /* 82C930 has interrupt status register in MAD16 register MC11 */
+                       unsigned long   flags;
+
+                       save_flags(flags);
+                       cli();
+
+                       alt_stat = 0;
+
+                       if (devc->c930_password_port)
+                               outb((0xe4), devc->c930_password_port); /* Password */
+                       outb(11, 0xe0e);
+                       c930_stat = inb(0xe0f);
+
+                       if (c930_stat & 0x04)
+                               alt_stat |= 0x10;       /* Playback intr */
+                       if (c930_stat & 0x08)
+                               alt_stat |= 0x20;       /* Playback intr */
+                       restore_flags(flags);
+               } else if (devc->model != MD_1848)
+                       alt_stat = ad_read(devc, 24);
+
+               /* Acknowledge the intr before proceeding */
+               if (devc->model == MD_C930)
+               {               /* 82C930 has interrupt status register in MAD16 register MC11 */
+                       unsigned long   flags;
+
+                       save_flags(flags);
+                       cli();
+
+                       if (devc->c930_password_port)
+                               outb((0xe4), devc->c930_password_port); /* Password */
+                       outb((11), 0xe0e);
+                       outb((~c930_stat), 0xe0f);
+                       restore_flags(flags);
+               }
+               else if (devc->model != MD_1848)
+                       ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat);      /* Selective ack */
+
+               if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
+               {
+                       DMAbuf_inputintr(devc->record_dev);
+               }
+               if (devc->open_mode & OPEN_WRITE && devc->audio_mode & PCM_ENABLE_OUTPUT &&
                      alt_stat & 0x10)
-                   {
-                           DMAbuf_outputintr(devc->playback_dev, 1);
-                   }
-                 if (devc->model != MD_1848 && alt_stat & 0x40)        /* Timer interrupt */
-                   {
-                           devc->timer_ticks++;
+               {
+                       DMAbuf_outputintr(devc->playback_dev, 1);
+               }
+               if (devc->model != MD_1848 && alt_stat & 0x40)  /* Timer interrupt */
+               {
+                       devc->timer_ticks++;
 #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE)
-                           if (timer_installed == dev && devc->timer_running)
-                                   sound_timer_interrupt();
+                       if (timer_installed == dev && devc->timer_running)
+                               sound_timer_interrupt();
 #endif
-                   }
-         }
+               }
+       }
 /*
  * Sometimes playback or capture interrupts occur while a timer interrupt
  * is being handled. The interrupt will not be retriggered if we don't
@@ -1997,63 +2031,61 @@ void adintr(int irq, void *dev_id, struct pt_regs *dummy)
  * the handler in this case.
  */
        if (inb(io_Status(devc)) & 0x01 && cnt++ < 4)
-         {
+       {
                  goto interrupt_again;
-         }
+       }
 }
 
-#ifdef DESKPROXL
 /*
- * Very experimental initialization sequence for the integrated sound system
- * of Compaq Deskpro XL. Will be moved somewhere else in future.
+ *     Experimental initialization sequence for the integrated sound system
+ *     of Compaq Deskpro XL.
  */
 
-static int
-init_deskpro(struct address_info *hw_config)
+static int init_deskpro(struct address_info *hw_config)
 {
        unsigned char   tmp;
 
        if ((tmp = inb(0xc44)) == 0xff)
-         {
-                 DDB(printk("init_deskpro: Dead port 0xc44\n"));
-                 return 0;
-         }
+       {
+               DDB(printk("init_deskpro: Dead port 0xc44\n"));
+               return 0;
+       }
        outb((tmp | 0x04), 0xc44);      /* Select bank 1 */
        if (inb(0xc44) != 0x04)
-         {
-                 DDB(printk("init_deskpro: Invalid bank1 signature in port 0xc44\n"));
-                 return 0;
-         }
-/*
- * OK. It looks like a Deskpro so let's proceed.
- */
+       {
+               DDB(printk("init_deskpro: Invalid bank1 signature in port 0xc44\n"));
+               return 0;
+       }
+       /*
       * OK. It looks like a Deskpro so let's proceed.
       */
 
-/*
- * I/O port 0xc44 Audio configuration register.
- *
- * bits 0xc0:   Audio revision bits
- *              0x00 = Compaq Business Audio
- *              0x40 = MS Sound System Compatible (reset default)
- *              0x80 = Reserved
- *              0xc0 = Reserved
- * bit 0x20:    No Wait State Enable
- *              0x00 = Disabled (reset default, DMA mode)
- *              0x20 = Enabled (programmed I/O mode)
- * bit 0x10:    MS Sound System Decode Enable
- *              0x00 = Decoding disabled (reset default)
- *              0x10 = Decoding enabled
- * bit 0x08:    FM Synthesis Decode Enable
- *              0x00 = Decoding Disabled (reset default)
- *              0x08 = Decoding enabled
- * bit 0x04     Bank select
- *              0x00 = Bank 0
- *              0x04 = Bank 1
- * bits 0x03    MSS Base address
- *              0x00 = 0x530 (reset default)
- *              0x01 = 0x604
- *              0x02 = 0xf40
- *              0x03 = 0xe80
- */
+       /*
       * I/O port 0xc44 Audio configuration register.
       *
       * bits 0xc0:   Audio revision bits
       *              0x00 = Compaq Business Audio
       *              0x40 = MS Sound System Compatible (reset default)
       *              0x80 = Reserved
       *              0xc0 = Reserved
       * bit 0x20:    No Wait State Enable
       *              0x00 = Disabled (reset default, DMA mode)
       *              0x20 = Enabled (programmed I/O mode)
       * bit 0x10:    MS Sound System Decode Enable
       *              0x00 = Decoding disabled (reset default)
       *              0x10 = Decoding enabled
       * bit 0x08:    FM Synthesis Decode Enable
       *              0x00 = Decoding Disabled (reset default)
       *              0x08 = Decoding enabled
       * bit 0x04     Bank select
       *              0x00 = Bank 0
       *              0x04 = Bank 1
       * bits 0x03    MSS Base address
       *              0x00 = 0x530 (reset default)
       *              0x01 = 0x604
       *              0x02 = 0xf40
       *              0x03 = 0xe80
       */
 
 #ifdef DEBUGXL
        /* Debug printing */
@@ -2068,23 +2100,23 @@ init_deskpro(struct address_info *hw_config)
        tmp = 0x58;             /* MSS Mode, MSS&FM decode enabled */
 
        switch (hw_config->io_base)
-         {
-         case 0x530:
-                 tmp |= 0x00;
-                 break;
-         case 0x604:
-                 tmp |= 0x01;
-                 break;
-         case 0xf40:
-                 tmp |= 0x02;
-                 break;
-         case 0xe80:
-                 tmp |= 0x03;
-                 break;
-         default:
-                 DDB(printk("init_deskpro: Invalid MSS port %x\n", hw_config->io_base));
-                 return 0;
-         }
+       {
+               case 0x530:
+                       tmp |= 0x00;
+                       break;
+               case 0x604:
+                       tmp |= 0x01;
+                       break;
+               case 0xf40:
+                       tmp |= 0x02;
+                       break;
+               case 0xe80:
+                       tmp |= 0x03;
+                       break;
+               default:
+                       DDB(printk("init_deskpro: Invalid MSS port %x\n", hw_config->io_base));
+                       return 0;
+       }
        outb((tmp & ~0x04), 0xc44);     /* Write to bank=0 */
 
 #ifdef DEBUGXL
@@ -2096,15 +2128,15 @@ init_deskpro(struct address_info *hw_config)
        printk("%02x\n", inb(0xc44));
 #endif
 
-/*
- * I/O port 0xc45 FM Address Decode/MSS ID Register.
- *
- * bank=0, bits 0xfe:   FM synthesis Decode Compare bits 7:1 (default=0x88)
- * bank=0, bit 0x01:    SBIC Power Control Bit
- *                      0x00 = Powered up
- *                      0x01 = Powered down
- * bank=1, bits 0xfc:   MSS ID (default=0x40)
- */
+       /*
       * I/O port 0xc45 FM Address Decode/MSS ID Register.
       *
       * bank=0, bits 0xfe:   FM synthesis Decode Compare bits 7:1 (default=0x88)
       * bank=0, bit 0x01:    SBIC Power Control Bit
       *                      0x00 = Powered up
       *                      0x01 = Powered down
       * bank=1, bits 0xfc:   MSS ID (default=0x40)
       */
 
 #ifdef DEBUGXL
        /* Debug printing */
@@ -2130,12 +2162,12 @@ init_deskpro(struct address_info *hw_config)
 #endif
 
 
-/*
- * I/O port 0xc46 FM Address Decode/Address ASIC Revision Register.
- *
- * bank=0, bits 0xff:   FM synthesis Decode Compare bits 15:8 (default=0x03)
- * bank=1, bits 0xff:   Audio addressing ASIC id
- */
+       /*
       * I/O port 0xc46 FM Address Decode/Address ASIC Revision Register.
       *
       * bank=0, bits 0xff:   FM synthesis Decode Compare bits 15:8 (default=0x03)
       * bank=1, bits 0xff:   Audio addressing ASIC id
       */
 
 #ifdef DEBUGXL
        /* Debug printing */
@@ -2160,12 +2192,12 @@ init_deskpro(struct address_info *hw_config)
        printk("%02x\n", inb(0xc46));
 #endif
 
-/*
- * I/O port 0xc47 FM Address Decode Register.
- *
- * bank=0, bits 0xff:   Decode enable selection for various FM address bits
- * bank=1, bits 0xff:   Reserved
- */
+       /*
       * I/O port 0xc47 FM Address Decode Register.
       *
       * bank=0, bits 0xff:   Decode enable selection for various FM address bits
       * bank=1, bits 0xff:   Reserved
       */
 
 #ifdef DEBUGXL
        /* Debug printing */
@@ -2190,9 +2222,9 @@ init_deskpro(struct address_info *hw_config)
        printk("%02x\n", inb(0xc47));
 #endif
 
-/*
- * I/O port 0xc6f = Audio Disable Function Register
- */
+       /*
       * I/O port 0xc6f = Audio Disable Function Register
       */
 
 #ifdef DEBUGXL
        printk("Port 0xc6f (before) = %02x\n", inb(0xc6f));
@@ -2206,32 +2238,29 @@ init_deskpro(struct address_info *hw_config)
 
        return 1;
 }
-#endif
 
-int
-probe_ms_sound(struct address_info *hw_config)
+int probe_ms_sound(struct address_info *hw_config)
 {
        unsigned char   tmp;
 
        DDB(printk("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype));
 
        if (check_region(hw_config->io_base, 8))
-         {
-                 printk("MSS: I/O port conflict\n");
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "MSS: I/O port conflict\n");
+               return 0;
+       }
        if (hw_config->card_subtype == 1)       /* Has no IRQ/DMA registers */
-         {
-                 /* check_opl3(0x388, hw_config); */
-                 return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
-         }
-#ifdef DESKPROXL
-       if (hw_config->card_subtype == 2)       /* Compaq Deskpro XL */
-         {
-                 if (!init_deskpro(hw_config))
-                         return 0;
-         }
-#endif
+       {
+               /* check_opl3(0x388, hw_config); */
+               return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
+       }
+
+       if (deskpro_xl && hw_config->card_subtype == 2) /* Compaq Deskpro XL */
+       {
+               if (!init_deskpro(hw_config))
+                       return 0;
+       }
 
        /*
           * Check if the IO port returns valid signature. The original MS Sound
@@ -2240,58 +2269,57 @@ probe_ms_sound(struct address_info *hw_config)
         */
 
        if ((tmp = inb(hw_config->io_base + 3)) == 0xff)        /* Bus float */
-         {
+       {
                  int             ret;
 
                  DDB(printk("I/O address is inactive (%x)\n", tmp));
                  if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp)))
                          return 0;
                  return 1;
-         }
+       }
        DDB(printk("MSS signature = %x\n", tmp & 0x3f));
        if ((tmp & 0x3f) != 0x04 &&
            (tmp & 0x3f) != 0x0f &&
            (tmp & 0x3f) != 0x00)
-         {
-                 int             ret;
+       {
+               int ret;
 
-                 MDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3)));
-                 DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n"));
-                 if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp)))
-                         return 0;
+               MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3)));
+               DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n"));
+               if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp)))
+                       return 0;
 
-                 hw_config->card_subtype = 1;
-                 return 1;
-         }
+               hw_config->card_subtype = 1;
+               return 1;
+       }
        if (hw_config->irq > 11)
-         {
-                 printk("MSS: Bad IRQ %d\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
+               return 0;
+       }
        if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-         {
-                 printk("MSS: Bad DMA %d\n", hw_config->dma);
+       {
+                 printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma);
                  return 0;
-         }
+       }
        /*
-          * Check that DMA0 is not in use with a 8 bit board.
+        * Check that DMA0 is not in use with a 8 bit board.
         */
 
        if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
-         {
-                 printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "MSS: Can't use DMA0 with a 8 bit card/slot\n");
+               return 0;
+       }
        if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
-         {
-                 printk("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
+               return 0;
+       }
        return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
 }
 
-void
-attach_ms_sound(struct address_info *hw_config)
+void attach_ms_sound(struct address_info *hw_config)
 {
        static char     interrupt_bits[12] =
        {
@@ -2304,63 +2332,65 @@ attach_ms_sound(struct address_info *hw_config)
                1, 2, 0, 3
        };
 
-       int             config_port = hw_config->io_base + 0;
-       int             version_port = hw_config->io_base + 3;
-       int             dma = hw_config->dma;
-       int             dma2 = hw_config->dma2;
+       int config_port = hw_config->io_base + 0;
+       int version_port = hw_config->io_base + 3;
+       int dma = hw_config->dma;
+       int dma2 = hw_config->dma2;
 
        if (hw_config->card_subtype == 1)       /* Has no IRQ/DMA registers */
-         {
-                 hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
+       {
+               hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
                                                    hw_config->irq,
                                                    hw_config->dma,
                                     hw_config->dma2, 0, hw_config->osp);
-                 request_region(hw_config->io_base, 4, "WSS config");
-                 return;
-         }
+               request_region(hw_config->io_base, 4, "WSS config");
+               return;
+       }
        /*
-          * Set the IRQ and DMA addresses.
+        * Set the IRQ and DMA addresses.
         */
 
        bits = interrupt_bits[hw_config->irq];
        if (bits == -1)
-         {
-                 printk("MSS: Bad IRQ %d\n", hw_config->irq);
-                 return;
-         }
+       {
+               printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
+               return;
+       }
        outb((bits | 0x40), config_port);
        if ((inb(version_port) & 0x40) == 0)
-               printk("[MSS: IRQ Conflict?]");
+               printk(KERN_ERR "[MSS: IRQ Conflict?]\n");
 
 /*
  * Handle the capture DMA channel
  */
 
        if (dma2 != -1 && dma2 != dma)
-         {
-                 if (!((dma == 0 && dma2 == 1) ||
+       {
+               if (!((dma == 0 && dma2 == 1) ||
                        (dma == 1 && dma2 == 0) ||
                        (dma == 3 && dma2 == 0)))
-                   {           /* Unsupported combination. Try to swap channels */
-                           int             tmp = dma;
-
-                           dma = dma2;
-                           dma2 = tmp;
-                   }
-                 if ((dma == 0 && dma2 == 1) ||
-                     (dma == 1 && dma2 == 0) ||
-                     (dma == 3 && dma2 == 0))
-                   {
-                           dma2_bit = 0x04;    /* Enable capture DMA */
-                 } else
-                   {
-                           printk("MSS: Invalid capture DMA\n");
-                           dma2 = dma;
-                   }
-       } else
-         {
-                 dma2 = dma;
-         }
+               {       /* Unsupported combination. Try to swap channels */
+                       int tmp = dma;
+
+                       dma = dma2;
+                       dma2 = tmp;
+               }
+               if ((dma == 0 && dma2 == 1) ||
+                       (dma == 1 && dma2 == 0) ||
+                       (dma == 3 && dma2 == 0))
+               {
+                       dma2_bit = 0x04;        /* Enable capture DMA */
+               }
+               else
+               {
+                       printk(KERN_WARNING "MSS: Invalid capture DMA\n");
+                       dma2 = dma;
+               }
+       }
+       else
+       {
+               dma2 = dma;
+       }
 
        hw_config->dma = dma;
        hw_config->dma2 = dma2;
@@ -2375,8 +2405,7 @@ attach_ms_sound(struct address_info *hw_config)
        request_region(hw_config->io_base, 4, "WSS config");
 }
 
-void
-unload_ms_sound(struct address_info *hw_config)
+void unload_ms_sound(struct address_info *hw_config)
 {
        int mixer = audio_devs[hw_config->slots[0]]->mixer_dev;
        ad1848_unload(hw_config->io_base + 4,
@@ -2387,18 +2416,17 @@ unload_ms_sound(struct address_info *hw_config)
                sound_unload_mixerdev(mixer);
        sound_unload_audiodev(hw_config->slots[0]);
        release_region(hw_config->io_base, 4);
-
 }
 
 #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE)
+
 /*
  * Timer stuff (for /dev/music).
  */
 
 static unsigned int current_interval = 0;
 
-static unsigned int
-ad1848_tmr_start(int dev, unsigned int usecs)
+static unsigned int ad1848_tmr_start(int dev, unsigned int usecs)
 {
        unsigned long   flags;
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
@@ -2408,16 +2436,16 @@ ad1848_tmr_start(int dev, unsigned int usecs)
        save_flags(flags);
        cli();
 
-/*
- * Length of the timer interval (in nanoseconds) depends on the
- * selected crystal oscillator. Check this from bit 0x01 of I8.
- *
- * AD1845 has just one oscillator which has cycle time of 10.050 us
- * (when a 24.576 MHz xtal oscillator is used).
- *
- * Convert requested interval to nanoseconds before computing
- * the timer divider.
- */
+       /*
       * Length of the timer interval (in nanoseconds) depends on the
       * selected crystal oscillator. Check this from bit 0x01 of I8.
       *
       * AD1845 has just one oscillator which has cycle time of 10.050 us
       * (when a 24.576 MHz xtal oscillator is used).
       *
       * Convert requested interval to nanoseconds before computing
       * the timer divider.
       */
 
        if (devc->model == MD_1845)
                xtal_nsecs = 10050;
@@ -2443,20 +2471,18 @@ ad1848_tmr_start(int dev, unsigned int usecs)
        return current_interval = (divider * xtal_nsecs + 500) / 1000;
 }
 
-static void
-ad1848_tmr_reprogram(int dev)
+static void ad1848_tmr_reprogram(int dev)
 {
-/*
- *    Audio driver has changed sampling rate so that a different xtal
- *      oscillator was selected. We have to reprogram the timer rate.
- */
+       /*
       *    Audio driver has changed sampling rate so that a different xtal
       *      oscillator was selected. We have to reprogram the timer rate.
       */
 
        ad1848_tmr_start(dev, current_interval);
        sound_timer_syncinterval(current_interval);
 }
 
-static void
-ad1848_tmr_disable(int dev)
+static void ad1848_tmr_disable(int dev)
 {
        unsigned long   flags;
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
@@ -2468,8 +2494,7 @@ ad1848_tmr_disable(int dev)
        restore_flags(flags);
 }
 
-static void
-ad1848_tmr_restart(int dev)
+static void ad1848_tmr_restart(int dev)
 {
        unsigned long   flags;
        ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
@@ -2493,10 +2518,8 @@ static struct sound_lowlev_timer ad1848_tmr =
        ad1848_tmr_restart
 };
 
-static int
-ad1848_tmr_install(int dev)
+static int ad1848_tmr_install(int dev)
 {
-
        if (timer_installed != -1)
                return 0;       /* Don't install another timer */
 
@@ -2524,6 +2547,7 @@ MODULE_PARM(irq, "i");
 MODULE_PARM(dma, "i");
 MODULE_PARM(dma2, "i");
 MODULE_PARM(type, "i");
+MODULE_PARM(deskpro_xl, "i");
 
 int io = -1;
 int irq = -1;
@@ -2538,7 +2562,7 @@ struct address_info hw_config;
 
 int init_module(void)
 {
-       printk("ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
+       printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
        if(io!=-1)
        {
                if(irq == -1 || dma == -1)
@@ -2560,8 +2584,7 @@ int init_module(void)
        return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
        SOUND_LOCK_END;
        if(loaded)
@@ -2570,8 +2593,7 @@ cleanup_module(void)
 
 #else
 
-void
-export_ad1848_syms(void)
+void export_ad1848_syms(void)
 {
 }
 
index 7e3c23f59745619a86be3bd12458a541819fe765..bc9d92d358bfa8c6fe45ab93ed62c41124fb44c4 100644 (file)
 
 #if defined(CONFIG_PAS) || defined(MODULE)
 
-static unsigned char dma_bits[] =
-{4, 1, 2, 3, 0, 5, 6, 7};
-static unsigned char irq_bits[] =
-{0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11};
-static unsigned char sb_irq_bits[] =
-{0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x08, 0x28, 0x30, 0x38, 0, 0};
-static unsigned char sb_dma_bits[] =
-{0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0};
+static unsigned char dma_bits[] = {
+       4, 1, 2, 3, 0, 5, 6, 7
+};
+
+static unsigned char irq_bits[] = {
+       0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11
+};
+
+static unsigned char sb_irq_bits[] = {
+       0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 
+       0x00, 0x08, 0x28, 0x30, 0x38, 0, 0
+};
+
+static unsigned char sb_dma_bits[] = {
+       0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0
+};
 
 /*
  * The Address Translation code is used to convert I/O register addresses to
@@ -32,32 +40,35 @@ static int      pas_sb_base = 0;
 
 
 char            pas_model = 0;
-static char    *pas_model_names[] =
-{"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"};
+static char    *pas_model_names[] = {
+       "", 
+       "Pro AudioSpectrum+", 
+       "CDPC", 
+       "Pro AudioSpectrum 16", 
+       "Pro AudioSpectrum 16D"
+};
 
 /*
  * pas_read() and pas_write() are equivalents of inb and outb 
  * These routines perform the I/O address translation required
  * to support other than the default base address
  */
+
 extern void     mix_write(unsigned char data, int ioaddr);
 
-unsigned char
-pas_read(int ioaddr)
+unsigned charpas_read(int ioaddr)
 {
        return inb(ioaddr ^ translate_code);
 }
 
-void
-pas_write(unsigned char data, int ioaddr)
+void pas_write(unsigned char data, int ioaddr)
 {
        outb((data), ioaddr ^ translate_code);
 }
 
 /******************* Begin of the Interrupt Handler ********************/
 
-static void
-pasintr(int irq, void *dev_id, struct pt_regs *dummy)
+static void pasintr(int irq, void *dev_id, struct pt_regs *dummy)
 {
        int             status;
 
@@ -65,23 +76,22 @@ pasintr(int irq, void *dev_id, struct pt_regs *dummy)
        pas_write(status, 0x0B89);      /* Clear interrupt */
 
        if (status & 0x08)
-         {
+       {
 #ifdef CONFIG_AUDIO
                  pas_pcm_interrupt(status, 1);
 #endif
                  status &= ~0x08;
-         }
+       }
        if (status & 0x10)
-         {
+       {
 #if defined(CONFIG_MIDI)
                  pas_midi_interrupt();
 #endif
                  status &= ~0x10;
-         }
+       }
 }
 
-int
-pas_set_intr(int mask)
+int pas_set_intr(int mask)
 {
        if (!mask)
                return 0;
@@ -92,8 +102,7 @@ pas_set_intr(int mask)
        return 0;
 }
 
-int
-pas_remove_intr(int mask)
+int pas_remove_intr(int mask)
 {
        if (!mask)
                return 0;
@@ -110,8 +119,7 @@ pas_remove_intr(int mask)
 
 extern struct address_info sbhw_config;
 
-static int
-config_pas_hw(struct address_info *hw_config)
+static int config_pas_hw(struct address_info *hw_config)
 {
        char            ok = 1;
        unsigned        int_ptrs;       /* scsi/sound interrupt pointers */
@@ -129,8 +137,8 @@ config_pas_hw(struct address_info *hw_config)
        pas_write(0x80 | 0x40 | 0x20 | 1, 0x0B8A);
        pas_write(0x80 | 0x20 | 0x10 | 0x08 | 0x01, 0xF8A);
        pas_write(0x01 | 0x02 | 0x04 | 0x10     /*
-                                                  * |
-                                                  * 0x80
+                                                * |
+                                                * 0x80
                                                 */ , 0xB88);
 
        pas_write(0x80
@@ -140,49 +148,53 @@ config_pas_hw(struct address_info *hw_config)
                  ,0xF388);
 
        if (pas_irq < 0 || pas_irq > 15)
-         {
-                 printk("PAS16: Invalid IRQ %d", pas_irq);
-                 ok = 0;
-       } else
-         {
-                 int_ptrs = pas_read(0xF38A);
-                 int_ptrs |= irq_bits[pas_irq] & 0xf;
-                 pas_write(int_ptrs, 0xF38A);
-                 if (!irq_bits[pas_irq])
-                   {
-                           printk("PAS16: Invalid IRQ %d", pas_irq);
-                           ok = 0;
-                 } else
-                   {
-                           if (snd_set_irq_handler(pas_irq, pasintr, "PAS16", hw_config->osp) < 0)
-                                   ok = 0;
-                   }
-         }
+       {
+               printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
+               ok = 0;
+       }
+       else
+       {
+               int_ptrs = pas_read(0xF38A);
+               int_ptrs |= irq_bits[pas_irq] & 0xf;
+               pas_write(int_ptrs, 0xF38A);
+               if (!irq_bits[pas_irq])
+               {
+                       printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
+                       ok = 0;
+               }
+               else
+               {
+                       if (snd_set_irq_handler(pas_irq, pasintr, "PAS16", hw_config->osp) < 0)
+                               ok = 0;
+               }
+       }
 
        if (hw_config->dma < 0 || hw_config->dma > 7)
-         {
-                 printk("PAS16: Invalid DMA selection %d", hw_config->dma);
-                 ok = 0;
-       } else
-         {
-                 pas_write(dma_bits[hw_config->dma], 0xF389);
-                 if (!dma_bits[hw_config->dma])
-                   {
-                           printk("PAS16: Invalid DMA selection %d", hw_config->dma);
-                           ok = 0;
-                 } else
-                   {
-                           if (sound_alloc_dma(hw_config->dma, "PAS16"))
-                             {
-                                     printk("pas2_card.c: Can't allocate DMA channel\n");
-                                     ok = 0;
-                             }
-                   }
-         }
+       {
+               printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
+               ok = 0;
+       }
+       else
+       {
+               pas_write(dma_bits[hw_config->dma], 0xF389);
+               if (!dma_bits[hw_config->dma])
+               {
+                       printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
+                       ok = 0;
+               }
+               else
+               {
+                       if (sound_alloc_dma(hw_config->dma, "PAS16"))
+                       {
+                               printk(KERN_ERR "pas2_card.c: Can't allocate DMA channel\n");
+                               ok = 0;
+                       }
+               }
+       }
 
        /*
-          * This fixes the timing problems of the PAS due to the Symphony chipset
-          * as per Media Vision.  Only define this if your PAS doesn't work correctly.
+        * This fixes the timing problems of the PAS due to the Symphony chipset
+        * as per Media Vision.  Only define this if your PAS doesn't work correctly.
         */
 #ifdef SYMPHONY_PAS
        outb((0x05), 0xa8);
@@ -215,33 +227,36 @@ config_pas_hw(struct address_info *hw_config)
                sb_config = &sbhw_config;
                if (sb_config->io_base)
 #endif
-                 {
-                         unsigned char   irq_dma;
-
-                         /*
-                          * Turn on Sound Blaster compatibility
-                          * bit 1 = SB emulation
-                          * bit 0 = MPU401 emulation (CDPC only :-( )
-                          */
-                         pas_write(0x02, 0xF788);
-
-                         /*
-                          * "Emulation address"
-                          */
-                         pas_write((sb_config->io_base >> 4) & 0x0f, 0xF789);
-                         pas_sb_base = sb_config->io_base;
-
-                         if (!sb_dma_bits[sb_config->dma])
-                                 printk("\n\nPAS16 Warning: Invalid SB DMA %d\n\n", sb_config->dma);
-
-                         if (!sb_irq_bits[sb_config->irq])
-                                 printk("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n", sb_config->irq);
-
-                         irq_dma = sb_dma_bits[sb_config->dma] |
-                             sb_irq_bits[sb_config->irq];
-
-                         pas_write(irq_dma, 0xFB8A);
-               } else
+               {
+                       unsigned char   irq_dma;
+
+                       /*
+                        * Turn on Sound Blaster compatibility
+                        * bit 1 = SB emulation
+                        * bit 0 = MPU401 emulation (CDPC only :-( )
+                        */
+                       
+                       pas_write(0x02, 0xF788);
+
+                       /*
+                        * "Emulation address"
+                        */
+                       
+                       pas_write((sb_config->io_base >> 4) & 0x0f, 0xF789);
+                       pas_sb_base = sb_config->io_base;
+
+                       if (!sb_dma_bits[sb_config->dma])
+                               printk(KERN_ERR "PAS16 Warning: Invalid SB DMA %d\n\n", sb_config->dma);
+
+                       if (!sb_irq_bits[sb_config->irq])
+                               printk(KERN_ERR "PAS16 Warning: Invalid SB IRQ %d\n\n", sb_config->irq);
+
+                       irq_dma = sb_dma_bits[sb_config->dma] |
+                               sb_irq_bits[sb_config->irq];
+
+                       pas_write(irq_dma, 0xFB8A);
+               }
+               else
                        pas_write(0x00, 0xF788);
        }
 #else
@@ -249,13 +264,12 @@ config_pas_hw(struct address_info *hw_config)
 #endif
 
        if (!ok)
-               printk("PAS16: Driver not enabled\n");
+               printk(KERN_WARNING "PAS16: Driver not enabled\n");
 
        return ok;
 }
 
-static int
-detect_pas_hw(struct address_info *hw_config)
+static int detect_pas_hw(struct address_info *hw_config)
 {
        unsigned char   board_id, foo;
 
@@ -296,40 +310,39 @@ detect_pas_hw(struct address_info *hw_config)
        return pas_model;
 }
 
-void
-attach_pas_card(struct address_info *hw_config)
+void attach_pas_card(struct address_info *hw_config)
 {
        pas_irq = hw_config->irq;
 
        if (detect_pas_hw(hw_config))
-         {
+       {
 
-                 if ((pas_model = pas_read(0xFF88)))
-                   {
-                           char            temp[100];
+               if ((pas_model = pas_read(0xFF88)))
+               {
+                       char temp[100];
 
-                           sprintf(temp,
+                       sprintf(temp,
                            "%s rev %d", pas_model_names[(int) pas_model],
                                    pas_read(0x2789));
-                           conf_printf(temp, hw_config);
-                   }
-                 if (config_pas_hw(hw_config))
-                   {
+                       conf_printf(temp, hw_config);
+               }
+               if (config_pas_hw(hw_config))
+               {
 #ifdef CONFIG_AUDIO
-                           pas_pcm_init(hw_config);
+                       pas_pcm_init(hw_config);
 #endif
 
 #if !defined(DISABLE_SB_EMULATION) && (defined(CONFIG_SB) || defined(CONFIG_SB_MODULE))
 
-                           sb_dsp_disable_midi(pas_sb_base);   /* No MIDI capability */
+                       sb_dsp_disable_midi(pas_sb_base);       /* No MIDI capability */
 #endif
 
 #if defined(CONFIG_MIDI)
-                           pas_midi_init();
+                       pas_midi_init();
 #endif
-                           pas_init_mixer();
-                   }
-         }
+                       pas_init_mixer();
+               }
+       }
 }
 
 int
@@ -357,18 +370,28 @@ int             sb_irq = -1;
 int             sb_dma = -1;
 int             sb_dma16 = -1;
 
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma16,"i");
+
+MODULE_PARM(sb_io,"i");
+MODULE_PARM(sb_irq,"i");
+MODULE_PARM(sb_dma,"i");
+MODULE_PARM(sb_dma16,"i");
+
 struct address_info config;
 struct address_info sbhw_config;
 
 int init_module(void)
 {
-       printk("MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
+       printk(KERN_INFO "MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
        if (io == -1 || dma == -1 || irq == -1)
-         {
-                 printk("I/O, IRQ, DMA and type are mandatory\n");
+       {
+                 printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
                  return -EINVAL;
-         }
+       }
        config.io_base = io;
        config.irq = irq;
        config.dma = dma;
@@ -386,8 +409,7 @@ int init_module(void)
        return 0;
 }
 
-void 
-cleanup_module(void)
+void cleanup_module(void)
 {
        unload_pas(&config);
        SOUND_LOCK_END;
index 06736aa3a2543b51266ab06d49c8bc5ffeb929ea..bab6385c49828fed27a7ee0acbad1bde08cad57b 100644 (file)
@@ -21,11 +21,32 @@ Known bugs:
   might leave a trashed file system with the
   bitmap flag set valid.
 
-- The blocks from deleted directories are 
-  sometimes reclaimed only at umount time.
+- When a file is truncated to a size that is not
+  a multiple of the blocksize, the rest of the
+  last allocated block is not cleared. Well,
+  this fs never claimed to be Posix conformant.
 
 Please direct bug reports to: hjw@zvw.de
 
+Version 3.7
+-----------
+
+- Added dentry callbacks to allow the dcache to
+  operate case insensitive and length ignorant
+  like the affs itself.
+
+- getblock() didn't update the lastblock field in the
+  inode if the fs was not an OFS. This bug only shows
+  up if a file was enlarged via truncate() and there
+  was not enough space.
+
+- Remove some more superfluous code left over from
+  the old link days ...
+
+- Fixed some oversights which were in patch 2.1.78.
+
+- Fixed a few typos.
+
 Version 3.6
 -----------
 
index df130db03ed8dd9c2d079404066e4b25fa6a2d57..79b66d0e73b49a4480797321c81b19e68ca1d30e 100644 (file)
@@ -12,6 +12,7 @@
  *  affs regular file handling primitives
  */
 
+#define DEBUG 0
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/sched.h>
@@ -417,6 +418,7 @@ affs_getblock(struct inode *inode, s32 block)
                        nkey = affs_new_data(inode);
                        if (!nkey)
                                break;
+                       inode->u.affs_i.i_lastblock++;
                        lock_super(inode->i_sb);
                        if (AFFS_BLOCK(bh->b_data,inode,j)) {
                                unlock_super(inode->i_sb);
@@ -436,7 +438,6 @@ affs_getblock(struct inode *inode, s32 block)
                                        AFFS_BLOCK(bh->b_data,inode,j) = 0;
                                        break;
                                }
-                               inode->u.affs_i.i_lastblock++;
                                DATA_FRONT(ebh)->primary_type    = cpu_to_be32(T_DATA);
                                DATA_FRONT(ebh)->header_key      = cpu_to_be32(inode->i_ino);
                                DATA_FRONT(ebh)->sequence_number = cpu_to_be32(inode->u.affs_i.i_lastblock + 1);
@@ -750,7 +751,7 @@ affs_truncate(struct inode *inode)
        int      rem;
        int      ext;
 
-       pr_debug("AFFS: file_truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
+       pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
 
        blocksize = AFFS_I2BSIZE(inode) - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0);
        first = (inode->i_size + blocksize - 1) / blocksize;
@@ -777,7 +778,7 @@ affs_truncate(struct inode *inode)
                        unlock_super(inode->i_sb);
                }
                if (!bh) {
-                       affs_error(inode->i_sb,"truncate","Cannot extend file");
+                       affs_warning(inode->i_sb,"truncate","Cannot extend file");
                        inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1);
                } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
                        rem = inode->i_size % blocksize;
@@ -798,12 +799,6 @@ affs_truncate(struct inode *inode)
                }
                ptype = be32_to_cpu(((struct file_front *)bh->b_data)->primary_type);
                stype = be32_to_cpu(FILE_END(bh->b_data,inode)->secondary_type);
-               if (ekey == inode->i_ino && ptype == T_SHORT && stype == ST_LINKFILE &&
-                   LINK_END(bh->b_data,inode)->original == 0) {
-                       pr_debug("AFFS: truncate(): dumping link\n");
-                       affs_brelse(bh);
-                       break;
-               }
                if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
                        affs_error(inode->i_sb,"truncate","Bad block (ptype=%d, stype=%d)",
                                   ptype,stype);
index 2ec0401d503cfe8d748efa95b0a87247604616a0..27e4477f7e3c366ab3909a1a07626eb64dfd3b6b 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <linux/errno.h>
 
-/* Simple toupper() for DOS\1 */
+/* Simple toupper()/tolower() for DOS\1 */
 
 static inline unsigned int
 affs_toupper(unsigned int ch)
@@ -29,7 +29,13 @@ affs_toupper(unsigned int ch)
        return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch;
 }
 
-/* International toupper() for DOS\3 */
+static inline unsigned int
+affs_tolower(unsigned int ch)
+{
+       return ch >= 'A' && ch <= 'Z' ? ch + ('a' - 'A') : ch;
+}
+
+/* International toupper()/tolower() for DOS\3 ("international") */
 
 static inline unsigned int
 affs_intl_toupper(unsigned int ch)
@@ -39,6 +45,112 @@ affs_intl_toupper(unsigned int ch)
                ch - ('a' - 'A') : ch;
 }
 
+static inline unsigned int
+affs_intl_tolower(unsigned int ch)
+{
+       return (ch >= 'A' && ch <= 'Z') || (ch >= 0xC0
+               && ch <= 0xDE && ch != 0xD7) ?
+               ch + ('a' - 'A') : ch;
+}
+
+/* We need 2 sets of dentry operations, since we cannot
+ * determine the fs flavour in the callback routines.
+ */
+
+static int      affs_hash_dentry(struct dentry *, struct qstr *);
+static int       affs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
+static int      affs_hash_dentry_intl(struct dentry *, struct qstr *);
+static int       affs_compare_dentry_intl(struct dentry *, struct qstr *, struct qstr *);
+
+struct dentry_operations affs_dentry_operations = {
+       NULL,                   /* d_validate   */
+       affs_hash_dentry,       /* d_hash       */
+       affs_compare_dentry,    /* d_compare    */
+       NULL                    /* d_delete     */
+};
+
+struct dentry_operations affs_dentry_operations_intl = {
+       NULL,                           /* d_validate   */
+       affs_hash_dentry_intl,          /* d_hash       */
+       affs_compare_dentry_intl,       /* d_compare    */
+       NULL                            /* d_delete     */
+};
+
+static int
+affs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
+{
+       unsigned long    hash;
+       int              i;
+
+       if ((i = affs_check_name(qstr->name,qstr->len)))
+               return i;
+       hash = init_name_hash();
+       for (i = 0; i < qstr->len && i < 30; i++)
+               hash = partial_name_hash(affs_tolower(qstr->name[i]),hash);
+       qstr->hash = end_name_hash(hash);
+
+       return 0;
+}
+
+static int
+affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
+{
+       int      i;
+
+       /* 'a' is the qstr of an already existing dentry, so the name
+        * must be valid. 'b' must be validated first.
+        */
+       
+       if (affs_check_name(b->name,b->len))
+               return 1;
+
+       /* If the names are longer than the allowed 30 chars,
+        * the excess is ignored, so their length may differ.
+        */
+
+       if ((a->len < 30 || b->len < 30) && a->len != b->len)
+               return 1;
+
+       for (i = 0; i < a->len && i < 30; i++)
+               if (affs_tolower(a->name[i]) != affs_tolower(b->name[i]))
+                       return 1;
+       
+       return 0;
+}
+
+static int
+affs_hash_dentry_intl(struct dentry *dentry, struct qstr *qstr)
+{
+       unsigned long    hash;
+       int              i;
+
+       if ((i = affs_check_name(qstr->name,qstr->len)))
+               return i;
+       hash = init_name_hash();
+       for (i = 0; i < qstr->len && i < 30; i++)
+               hash = partial_name_hash(affs_intl_tolower(qstr->name[i]),hash);
+       qstr->hash = end_name_hash(hash);
+
+       return 0;
+}
+
+static int
+affs_compare_dentry_intl(struct dentry *dentry, struct qstr *a, struct qstr *b)
+{
+       int      i;
+
+       if (affs_check_name(b->name,b->len))
+               return 1;
+       if ((a->len < 30 || b->len < 30) && a->len != b->len)
+               return 1;
+
+       for (i = 0; i < a->len && i < 30; i++)
+               if (affs_intl_tolower(a->name[i]) != affs_intl_tolower(b->name[i]))
+                       return 1;
+       
+       return 0;
+}
+
 /*
  * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
  */
@@ -162,6 +274,8 @@ affs_lookup(struct inode *dir, struct dentry *dentry)
                if (!inode)
                        return -EACCES;
        }
+       dentry->d_op = AFFS_I2FSTYPE(dir) ? &affs_dentry_operations_intl
+                                         : &affs_dentry_operations;
        d_add(dentry,inode);
        return 0;
 }
@@ -422,8 +536,9 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 }
 
 int
-affs_link(struct inode *oldinode, struct inode *dir, struct dentry *dentry)
+affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
+       struct inode            *oldinode = old_dentry->d_inode;
        struct inode            *inode;
        struct buffer_head      *bh;
        unsigned long            i;
index 7bd31dc5bb6d8bf1f3fbfb097c70c4349a602ac0..6579a6bb4739dfad1aace8985a764cedf2368cbc 100644 (file)
@@ -494,7 +494,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
                        if (bb) {
                                if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) &&
                                    !(s->s_flags & MS_RDONLY)) {
-                                       printk(KERN_WARNING "AFFS: Bitmap (%d,key=%lu) invalid - "
+                                       printk(KERN_WARNING "AFFS: Bitmap (%d,key=%u) invalid - "
                                               "mounting %s read only.\n",mapidx,be32_to_cpu(bm[i]),
                                                kdevname(dev));
                                        s->s_flags |= MS_RDONLY;
@@ -572,6 +572,8 @@ nobitmap:
                MOD_DEC_USE_COUNT;
                return NULL;
        }
+       s->s_root->d_op = (s->u.affs_sb.s_flags & SF_INTL) ? &affs_dentry_operations_intl
+                                                          : &affs_dentry_operations;
 
        /* Record date of last change if the bitmap was truncated and
         * create data zones if the volume is writable.
index 50e0acd3ac50f4cf0ccfc16613f57138e3ad9e7a..2bf4cd00ae25c0063c9464af4290f7621b41ea29 100644 (file)
@@ -44,7 +44,7 @@ struct inode_operations affs_symlink_inode_operations = {
 };
 
 static int
-affs_readlink(struct inode *dentry, char *buffer, int buflen)
+affs_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
        struct inode *inode = dentry->d_inode;
        struct buffer_head      *bh;
index 39f56c82f867c1b52d0d7777d371683f39622344..60060006a04f5d679e11d26d495081bed0bdd7dd 100644 (file)
@@ -236,7 +236,7 @@ void  coda_dentry_delete(struct dentry *dentry)
                if ( cnp ) 
                        CHECK_CNODE(cnp);
        } else {
-               printk("No inode for dentry_delete!\n");
+               CDEBUG(D_CACHE, "No inode for dentry_delete!\n");
                return;
        }
 
@@ -254,6 +254,14 @@ void  coda_dentry_delete(struct dentry *dentry)
        return;
 }
 
+static void coda_zap_cnode(struct cnode *cnp, int flags)
+{
+       cnp->c_flags |= flags;
+       coda_cache_clear_cnp(cnp);
+}
+
+
+
 /* the dache will notice the flags and drop entries (possibly with
    children) the moment they are no longer in use  */
 void coda_zapfid(struct ViceFid *fid, struct super_block *sb, int flag)
@@ -273,9 +281,22 @@ void coda_zapfid(struct ViceFid *fid, struct super_block *sb, int flag)
                return;
        }
 
+       if ( coda_fid_is_volroot(fid) ) {
+               struct list_head *lh, *le;
+               struct coda_sb_info *sbi = coda_sbp(sb);
+               le = lh = &sbi->sbi_volroothead;
+               while ( (le = le->next) != lh ) {
+                       cnp = list_entry(le, struct cnode, c_volrootlist);
+                       if ( cnp->c_fid.Volume == fid->Volume) 
+                               coda_zap_cnode(cnp, flag);
+               }
+               return;
+       }
+
+
        inode = coda_fid_to_inode(fid, sb);
        if ( !inode ) {
-               printk("coda_zapfid: no inode!\n");
+               CDEBUG(D_CACHE, "coda_zapfid: no inode!\n");
                return;
        }
        cnp = ITOC(inode);
@@ -284,8 +305,7 @@ void coda_zapfid(struct ViceFid *fid, struct super_block *sb, int flag)
                printk("coda_zapfid: no cnode!\n");
                return;
        }
-       cnp->c_flags |= flag;
-       coda_cache_clear_cnp(cnp);
+       coda_zap_cnode(cnp, flag);
 }
                
 
index 5f180b04afdaab76bf23744767e795c6e1c9f557..f20b0f9517cc8f5eac692dfceb86ffd6bd571cce 100644 (file)
@@ -7,8 +7,8 @@
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
-#include <linux/coda_psdev.h>
 #include <linux/coda_cnode.h>
+#include <linux/coda_psdev.h>
 
 extern int coda_debug;
 extern int coda_print_entry;
@@ -29,6 +29,7 @@ static struct cnode *coda_cnode_alloc(void)
 
         memset(result, 0, (int) sizeof(struct cnode));
         INIT_LIST_HEAD(&(result->c_cnhead));
+       INIT_LIST_HEAD(&(result->c_volrootlist));
        return result;
 }
 
@@ -70,6 +71,7 @@ static void coda_fill_inode (struct inode *inode, struct coda_vattr *attr)
 int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
 {
         struct cnode *cnp;
+       struct coda_sb_info *sbi= coda_sbp(sb);
         struct coda_vattr attr;
         int error;
        ino_t ino;
@@ -119,6 +121,9 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
        CHECK_CNODE(cnp);
 
        /* fill in the inode attributes */
+       if ( coda_fid_is_volroot(fid) ) 
+               list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
+
         coda_fill_inode(*inode, &attr);
        CDEBUG(D_CNODE, "Done linking: ino %ld,  at 0x%x with cnp 0x%x, cnp->c_vnode 0x%x\n", (*inode)->i_ino, (int) (*inode), (int) cnp, (int)cnp->c_vnode);
 
@@ -148,6 +153,7 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) {
 ENTRY;
 
        CDEBUG(D_INODE, "%s\n", coda_f2s(fid, str));
+
        nr = coda_f2i(fid);
        inode = iget(sb, nr);
 
index 0a1d425682fdbb73a5f6c0ad632b796338d60ca9..c3731662d66e5a382bcf19c34525db8ee8f59a0a 100644 (file)
@@ -97,6 +97,11 @@ unsigned short coda_flags_to_cflags(unsigned short flags)
 }
 
 
+int coda_fid_is_volroot(struct ViceFid *fid)
+{
+       return ( (fid->Vnode == 1) && (fid->Unique == 1 ) );
+}
+
 /* utility functions below */
 void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
 {
@@ -155,7 +160,6 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
 
 void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
 {
-        umode_t mode;
         unsigned int valid;
 
         /* clean out */        
@@ -170,15 +174,16 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
         vattr->va_mtime.tv_nsec = (time_t) -1;
        vattr->va_ctime.tv_nsec = (time_t) -1;
         vattr->va_type = C_VNON;
-       vattr->va_fileid = (long)-1;
-       vattr->va_gen = (long)-1;
-       vattr->va_bytes = (long)-1;
-       vattr->va_nlink = (short)-1;
-       vattr->va_blocksize = (long)-1;
-       vattr->va_rdev = (dev_t)-1;
+       vattr->va_fileid = -1;
+       vattr->va_gen = -1;
+       vattr->va_bytes = -1;
+       vattr->va_nlink = -1;
+       vattr->va_blocksize = -1;
+       vattr->va_rdev = -1;
         vattr->va_flags = 0;
 
         /* determine the type */
+#if 0
         mode = iattr->ia_mode;
                 if ( S_ISDIR(mode) ) {
                 vattr->va_type = C_VDIR; 
@@ -190,6 +195,7 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
                 /* don't do others */
                 vattr->va_type = C_VNON;
         }
+#endif 
 
         /* set those vattrs that need change */
         valid = iattr->ia_valid;
@@ -219,7 +225,6 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
        }
         
 }
-  
 
 void print_vattr(struct coda_vattr *attr)
 {
index a0c0cc6346b26ae08f0648f4d3ef1187f897af53..40ffe05cd162574dd95b040791dc155ffb6646c7 100644 (file)
@@ -27,7 +27,7 @@
 /* dir inode-ops */
 static int coda_create(struct inode *dir, struct dentry *new, int mode);
 static int coda_lookup(struct inode *dir, struct dentry *target);
-static int coda_link(struct inode *old_inode, struct inode *dir_inode, 
+static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, 
                     struct dentry *entry);
 static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
 static int coda_symlink(struct inode *dir_inode, struct dentry *entry,
@@ -243,19 +243,19 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode)
                char str[50];
                CDEBUG(D_INODE, "create: %s, result %d\n",
                       coda_f2s(&newfid, str), error); 
+               d_drop(de);
                return error;
        }
 
        error = coda_cnode_make(&result, &newfid, dir->i_sb);
        if ( error ) {
+               d_drop(de);
                result = NULL;
                return error;
        }
 
        /* invalidate the directory cnode's attributes */
        dircnp->c_flags &= ~C_VATTR;
-/*     cfsnc_zapfid(&(dircnp->c_fid)); */
-
        d_instantiate(de, result);
         return 0;
 }                           
@@ -276,8 +276,10 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
                printk("coda_mkdir: inode is NULL or not a directory\n");
                return -ENOENT;
        }
+
         if ( len > CFS_MAXNAMLEN )
                 return -ENAMETOOLONG;
+
        if (coda_isroot(dir) && coda_iscontrol(name, len))
                return -EPERM;
 
@@ -294,6 +296,7 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
         if ( error ) {
                CDEBUG(D_INODE, "mkdir error: %s result %d\n", 
                       coda_f2s(&newfid, fidstr), error); 
+               d_drop(de);
                 return error;
         }
          
@@ -301,21 +304,23 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
               coda_f2s(&newfid, fidstr)); 
 
        error = coda_cnode_make(&inode, &newfid, dir->i_sb);
-       if ( error ) 
-              return error;
+       if ( error ) {
+               d_drop(de);
+               return error;
+       }
        
        /* invalidate the directory cnode's attributes */
        dircnp->c_flags &= ~C_VATTR;
-/*     cfsnc_zapfid(&(dircnp->c_fid)); */
-
        dir->i_nlink++;
        d_instantiate(de, inode);
         return 0;
 }
 
-static int coda_link(struct inode *inode, struct inode *dir_inode, 
+/* try to make de an entry in dir_inodde linked to source_de */ 
+static int coda_link(struct dentry *source_de, struct inode *dir_inode, 
          struct dentry *de)
 {
+       struct inode *inode = source_de->d_inode;
         const char * name = de->d_name.name;
        int len = de->d_name.len;
         struct cnode *dir_cnp, *cnp;
@@ -340,19 +345,17 @@ static int coda_link(struct inode *inode, struct inode *dir_inode,
                 return -ENAMETOOLONG;
         }
 
-        /* Check for link to/from control object. */
-
         error = venus_link(dir_inode->i_sb,&(cnp->c_fid), &(dir_cnp->c_fid), 
                           (const char *)name, len);
 
        if (  ! error ) { 
-             dir_cnp->c_flags &= ~C_VATTR;
-/*           cfsnc_zapfid(&(dir_cnp->c_fid)); */
-/*           cfsnc_zapfid(&(cnp->c_fid)); */
-
-             inode->i_nlink++;
-             d_instantiate(de, inode);
+               dir_cnp->c_flags &= ~C_VATTR;
+               inode->i_nlink++;
+               d_instantiate(de, inode);
+       } else {
+               d_drop(de);
        }
+
         CDEBUG(D_INODE, "link result %d\n",error);
        EXIT;
         return(error);
@@ -382,11 +385,18 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
 
         CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);
 
+       /*
+        * This entry is now negative. Since we do not create
+        * an inode for the entry we have to drop it. 
+        */
+       d_drop(de);
+
        error = venus_symlink(dir_inode->i_sb, &(dir_cnp->c_fid), name, len, 
                              symname, symlen);
 
-       if ( !error )
-               d_drop(de);
+       if ( !error ) {
+               dir_cnp->c_flags |= C_VATTR;
+       }
 
         CDEBUG(D_INODE, "in symlink result %d\n",error);
         EXIT;
@@ -412,7 +422,6 @@ int coda_unlink(struct inode *dir, struct dentry *de)
               coda_f2s(&(dircnp->c_fid), fidstr), dir->i_ino);
 
         /* this file should no longer be in the namecache! */
-/*         cfsnc_zapfile(dircnp, (const char *)name, len); */
 
         error = venus_remove(dir->i_sb, &(dircnp->c_fid), name, len);
 
@@ -423,7 +432,6 @@ int coda_unlink(struct inode *dir, struct dentry *de)
 
         /* cache management */
        dircnp->c_flags &= ~C_VATTR;
-/*     cfsnc_zapfid(&(dircnp->c_fid)); */
        
        de->d_inode->i_nlink--;
        d_delete(de);
@@ -436,7 +444,7 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
         struct cnode *dircnp;
        const char *name = de->d_name.name;
        int len = de->d_name.len;
-        int error;
+        int error, rehash = 0;
 
        if (!dir || !S_ISDIR(dir->i_mode)) {
                printk("coda_rmdir: inode is NULL or not a directory\n");
@@ -456,7 +464,16 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
                        return error;
        }
        /* Drop the dentry to force a new lookup */
-       d_drop(de);
+       if (!list_empty(&de->d_hash)) {
+               d_drop(de);
+               rehash = 1;
+       }
+
+       /* update i_nlink and free the inode before unlinking;
+          if rmdir fails a new lookup set i_nlink right.*/
+       if (de->d_inode->i_nlink)
+               de->d_inode->i_nlink --;
+       d_delete(de);
 
        error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
 
@@ -465,8 +482,9 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
                 return error;
         }
 
-       dir->i_nlink--;
-       d_delete(de);
+       if (rehash)
+               d_add(de, NULL);
+       /* XXX how can mtime be set? */
 
         return 0;
 }
index e7ba48356e9e571d8f2a5b8c48a74f7470e321cb..e1374398e20a310e9627010fbff5ab5b760c3e5b 100644 (file)
 #include <linux/coda_cache.h>
 
 /* file operations */
-static int coda_readpage(struct dentry *, struct page *);
-static ssize_t coda_file_read(struct file *, char *, size_t, loff_t *);
-static ssize_t coda_file_write(struct file *, const char *, size_t, loff_t *);
-static int coda_file_mmap(struct file *, struct vm_area_struct *);
+static int coda_readpage(struct dentry * dentry, struct page * page);
+static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
+static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
+static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
 
 /* exported from this file */
 int coda_fsync(struct file *, struct dentry *dentry);
@@ -74,9 +74,11 @@ struct file_operations coda_file_operations = {
 };
 
 /*  File file operations */
-static int coda_readpage(struct dentry *dentry, struct page * page)
+static int coda_readpage(struct dentry *de, struct page * page)
 {
-        struct inode *open_inode, *inode = dentry->d_inode;
+       struct inode *inode = de->d_inode;
+       struct dentry cont_dentry;
+        struct inode *cont_inode;
         struct cnode *cnp;
 
         ENTRY;
@@ -89,12 +91,12 @@ static int coda_readpage(struct dentry *dentry, struct page * page)
                 return -ENXIO;
         }
 
-        open_inode = cnp->c_ovp;
+        cont_inode = cnp->c_ovp;
+       cont_dentry.d_inode = cont_inode;
 
-        CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", inode->i_ino, open_inode->i_ino, page->offset);
+        CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", inode->i_ino, cont_inode->i_ino, page->offset);
 
-       /* N.B. This needs the dentry for open_inode */
-        generic_readpage(open_inode, page);
+        generic_readpage(&cont_dentry, page);
         EXIT;
         return 0;
 }
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
deleted file mode 100644 (file)
index b295470..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Inode operations for Coda filesystem
- * Original version: (C) 1996 P. Braam and M. Callahan
- * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
- * 
- * Carnegie Mellon encourages users to contribute improvements to
- * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/string.h>
-
-#include <linux/coda.h>
-#include <linux/coda_linux.h>
-#include <linux/coda_psdev.h>
-#include <linux/coda_cnode.h>
-#include <linux/coda_namecache.h>
-
-/* prototypes */
-static int coda_readpage(struct inode *inode, struct page *page);
-static int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
-
-
-
-
-
index 70842b8fc08dd111f9597de5d11b30fff4e68f12..a7636707ececc1e49ee805c7458307d23e53514e 100644 (file)
@@ -40,8 +40,8 @@
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
-#include <linux/coda_psdev.h>
 #include <linux/coda_cnode.h>
+#include <linux/coda_psdev.h>
 #include <linux/coda_cache.h>
 #include <linux/coda_sysctl.h>
 
index 6b00a528931e916cf212e9e4543b3729e8923195..5b655eafa22b0e2cb060a2af20473143a459f577 100644 (file)
@@ -41,7 +41,7 @@
 /* VFS super_block ops */
 static struct super_block *coda_read_super(struct super_block *, void *, int);
 static void coda_read_inode(struct inode *);
-static int  coda_notify_change(struct dentry *, struct iattr *);
+static int  coda_notify_change(struct dentry *dentry, struct iattr *attr);
 static void coda_put_inode(struct inode *);
 static void coda_delete_inode(struct inode *);
 static void coda_put_super(struct super_block *);
@@ -101,6 +101,7 @@ static struct super_block * coda_read_super(struct super_block *sb,
         sbi->sbi_psdev = psdev;
        sbi->sbi_vcomm = vc;
        INIT_LIST_HEAD(&(sbi->sbi_cchead));
+       INIT_LIST_HEAD(&(sbi->sbi_volroothead));
 
         lock_super(sb);
         sb->u.generic_sbp = sbi;
@@ -133,7 +134,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
        printk("coda_read_super: rootinode is %ld dev %d\n", 
               root->i_ino, root->i_dev);
        sbi->sbi_root = root;
-       /* N.B. check this for failure */
        sb->s_root = d_alloc_root(root, NULL);
        unlock_super(sb);
        EXIT;  
@@ -141,6 +141,7 @@ static struct super_block * coda_read_super(struct super_block *sb,
 
 error:
 EXIT;  
+       MOD_DEC_USE_COUNT;
        if (sbi) {
                sbi->sbi_vcomm = NULL;
                sbi->sbi_root = NULL;
@@ -154,7 +155,6 @@ EXIT;
                 coda_cnode_free(ITOC(root));
         }
         sb->s_dev = 0;
-       MOD_DEC_USE_COUNT;
         return NULL;
 }
 
@@ -209,6 +209,10 @@ static void coda_delete_inode(struct inode *inode)
        }
 
         cnp = ITOC(inode);
+
+       if ( coda_fid_is_volroot(&cnp->c_fid) )
+               list_del(&cnp->c_volrootlist);
+
         open_inode = cnp->c_ovp;
         if ( open_inode ) {
                 CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n",  
@@ -225,9 +229,9 @@ static void coda_delete_inode(struct inode *inode)
        EXIT;
 }
 
-static int  coda_notify_change(struct dentry *dentry, struct iattr *iattr)
+static int  coda_notify_change(struct dentry *de, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = de->d_inode;
         struct cnode *cnp;
         struct coda_vattr vattr;
         int error;
index 80160d94cccf52e3d00c75de42a8b4cc4547b19c..d4f78c8783de200e74e871fdff472769617b0bab 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/coda_cnode.h>
 #include <linux/coda_cache.h>
 
-static int coda_readlink(struct dentry *dentry, char *buffer, int length);
+static int coda_readlink(struct dentry *de, char *buffer, int length);
 static struct dentry *coda_follow_link(struct dentry *, struct dentry *);
 
 struct inode_operations coda_symlink_inode_operations = {
@@ -39,41 +39,41 @@ struct inode_operations coda_symlink_inode_operations = {
        NULL,                   /* mknod */
        NULL,                   /* rename */
        coda_readlink,          /* readlink */
-       coda_follow_link,       /* follow_link */
+       coda_follow_link,       /* follow_link */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
        NULL,                   /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL,                   /* update page */
-        NULL                    /* revalidate */
+       NULL,                   /* permission */
+       NULL,                   /* smap */
+       NULL,                   /* update page */
+       NULL                    /* revalidate */
 };
 
-static int coda_readlink(struct inode *dentry, char *buffer, int length)
+static int coda_readlink(struct dentry *de, char *buffer, int length)
 {
-       struct inode *inode = dentry->d_inode;
-        int len;
+       struct inode *inode = de->d_inode;
+       int len;
        int error;
-        char *buf;
+       char *buf;
        struct cnode *cp;
-        ENTRY;
+       ENTRY;
 
-        cp = ITOC(inode);
-        CHECK_CNODE(cp);
+       cp = ITOC(inode);
+       CHECK_CNODE(cp);
 
-        /* the maximum length we receive is len */
-        if ( length > CFS_MAXPATHLEN ) 
-               len = CFS_MAXPATHLEN;
+       /* the maximum length we receive is len */
+       if ( length > CFS_MAXPATHLEN ) 
+               len = CFS_MAXPATHLEN;
        else
-               len = length;
+               len = length;
        CODA_ALLOC(buf, char *, len);
        if ( !buf ) 
-               return -ENOMEM;
+               return -ENOMEM;
        
        error = venus_readlink(inode->i_sb, &(cp->c_fid), buf, &len);
 
-        CDEBUG(D_INODE, "result %s\n", buf);
+       CDEBUG(D_INODE, "result %s\n", buf);
        if (! error) {
                copy_to_user(buffer, buf, len);
                put_user('\0', buffer + len);
@@ -84,20 +84,20 @@ static int coda_readlink(struct inode *dentry, char *buffer, int length)
        return error;
 }
 
-static struct dentry *coda_follow_link(struct dentry *dentry
-                                       struct dentry *base)
+static struct dentry *coda_follow_link(struct dentry *de, 
+                                      struct dentry *base)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = de->d_inode;
        int error;
        struct cnode *cnp;
        unsigned int len;
+       char mem[CFS_MAXPATHLEN];
        char *path;
-       char mem[CFS_MAXPATHLEN]; /* N.B. too big for the stack? */
 ENTRY;
        CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino);
        
-        cnp = ITOC(inode);
-        CHECK_CNODE(cnp);
+       cnp = ITOC(inode);
+       CHECK_CNODE(cnp);
 
        len = CFS_MAXPATHLEN;
        error = venus_readlink(inode->i_sb, &(cnp->c_fid), mem, &len);
index 84917d3ae6259c67863c69b48935dcc14c70e5e7..2894be43fccc08b3817aa1114ff413e7baaf3a0b 100644 (file)
@@ -146,8 +146,9 @@ out:
 int d_invalidate(struct dentry * dentry)
 {
        /* Check whether to do a partial shrink_dcache */
-       if (dentry->d_count > 1 && !list_empty(&dentry->d_subdirs))
+       if (!list_empty(&dentry->d_subdirs))
                shrink_dcache_parent(dentry);
+
        if (dentry->d_count != 1)
                return -EBUSY;
 
index 5282a464783d4d41cfca6e8941380da99fabaae5..96865886bee2361249abdd1af06d20dc37c1c283 100644 (file)
@@ -219,6 +219,7 @@ repeat:
            (current->rlim[RLIMIT_FSIZE].rlim_cur >>
             EXT2_BLOCK_SIZE_BITS(inode->i_sb))) {
                *err = -EFBIG;
+               send_sig(SIGXFSZ, current, 0);
                return NULL;
        }
        if (inode->u.ext2_i.i_next_alloc_block == new_block)
index d45ecfab5ce633aaa1cfd9164e9a1aac55478f44..0cbe93fb9fb818c55493967097f254e149048ef8 100644 (file)
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := fat.o
-O_OBJS   := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o
+O_OBJS   := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o cvf.o
 OX_OBJS  := fatfs_syms.o
 M_OBJS   := $(O_TARGET)
 
index 4c827711d28dec55c39f81158ead82878f97e9a2..2c4c7a89f137d92de3e79c873ed2cec18599436b 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/string.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
+#include <linux/fat_cvf.h>
 
 #if 0
 #  define PRINTK(x) printk x
@@ -28,6 +29,11 @@ struct buffer_head *fat_bread (
         * is always of size 1024 (or 2048). Doing readahead may be
         * counterproductive or just plain wrong.
         */
+
+       if(MSDOS_SB(sb)->cvf_format)
+         if(MSDOS_SB(sb)->cvf_format->cvf_bread)
+           return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block);
+
        if (sb->s_blocksize == 512) {
                ret = bread (sb->s_dev,block,512);
        } else {
@@ -92,6 +98,11 @@ struct buffer_head *fat_getblk (
 {
        struct buffer_head *ret = NULL;
        PRINTK(("fat_getblk: block=0x%x\n", block));
+
+       if(MSDOS_SB(sb)->cvf_format)
+         if(MSDOS_SB(sb)->cvf_format->cvf_getblk)
+           return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block);
+
        if (sb->s_blocksize == 512){
                ret = getblk (sb->s_dev,block,512);
        }else{
@@ -111,6 +122,10 @@ void fat_brelse (
        struct buffer_head *bh)
 {
        if (bh != NULL){
+               if(MSDOS_SB(sb)->cvf_format)
+                 if(MSDOS_SB(sb)->cvf_format->cvf_brelse)
+                   return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh);
+
                if (sb->s_blocksize == 512){
                        brelse (bh);
                }else{
@@ -128,6 +143,12 @@ void fat_mark_buffer_dirty (
        struct buffer_head *bh,
        int dirty_val)
 {
+       if(MSDOS_SB(sb)->cvf_format)
+          if(MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty)
+          { MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty_val);
+            return;
+          }
        if (sb->s_blocksize != 512){
                bh = bh->b_next;
        }
@@ -139,6 +160,12 @@ void fat_set_uptodate (
        struct buffer_head *bh,
        int val)
 {
+       if(MSDOS_SB(sb)->cvf_format)
+          if(MSDOS_SB(sb)->cvf_format->cvf_set_uptodate)
+          { MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val);
+            return;
+          }
        if (sb->s_blocksize != 512){
                bh = bh->b_next;
        }
@@ -148,6 +175,10 @@ int fat_is_uptodate (
        struct super_block *sb,
        struct buffer_head *bh)
 {
+       if(MSDOS_SB(sb)->cvf_format)
+          if(MSDOS_SB(sb)->cvf_format->cvf_is_uptodate)
+            return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh);
        if (sb->s_blocksize != 512){
                bh = bh->b_next;
        }
@@ -160,6 +191,12 @@ void fat_ll_rw_block (
        int nbreq,
        struct buffer_head *bh[32])
 {
+        if(MSDOS_SB(sb)->cvf_format)
+          if(MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block)
+          { MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh);
+            return;
+          }
        if (sb->s_blocksize == 512){
                ll_rw_block(opr,nbreq,bh);
        }else{
index ece255ca1060c0c31a7fcbc1b29ab63f202b17ec..5eb10002e15b1907d0b92b75a5b450a80807537f 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/fat_cvf.h>
 
 #include "msbuffer.h"
 
@@ -29,6 +30,10 @@ int fat_access(struct super_block *sb,int nr,int new_value)
        unsigned char *p_first,*p_last;
        int copy,first,last,next,b;
 
+       if(MSDOS_SB(sb)->cvf_format)
+         if(MSDOS_SB(sb)->cvf_format->fat_access)
+           return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value);
+
        if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters)
                return 0;
        if (MSDOS_SB(sb)->fat_bits == 32) {
@@ -240,7 +245,7 @@ void fat_cache_inval_dev(kdev_t device)
 }
 
 
-int get_cluster(struct inode *inode,int cluster)
+int fat_get_cluster(struct inode *inode,int cluster)
 {
        int nr,count;
 
@@ -262,6 +267,9 @@ int fat_smap(struct inode *inode,int sector)
        int cluster,offset;
 
        sb = MSDOS_SB(inode->i_sb);
+       if(sb->cvf_format)
+         if(sb->cvf_format->cvf_smap)
+           return sb->cvf_format->cvf_smap(inode,sector);
        if ((sb->fat_bits != 32) &&
            (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
             !MSDOS_I(inode)->i_start))) {
@@ -271,7 +279,7 @@ int fat_smap(struct inode *inode,int sector)
        }
        cluster = sector/sb->cluster_size;
        offset = sector % sb->cluster_size;
-       if (!(cluster = get_cluster(inode,cluster))) return 0;
+       if (!(cluster = fat_get_cluster(inode,cluster))) return 0;
        return (cluster-2)*sb->cluster_size+sb->data_start+offset;
 }
 
diff --git a/fs/fat/cvf.c b/fs/fat/cvf.c
new file mode 100644 (file)
index 0000000..62b70b1
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * CVF extensions for fat-based filesystems
+ *
+ * written 1997,1998 by Frank Gockel <gockel@sent13.uni-duisburg.de>
+ *
+ */
+#include<linux/sched.h>
+#include<linux/fs.h>
+#include<linux/msdos_fs.h>
+#include<linux/msdos_fs_sb.h>
+#include<linux/string.h>
+#include<linux/fat_cvf.h>
+
+#define MAX_CVF_FORMATS 3
+
+struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL};
+int cvf_format_use_count[MAX_CVF_FORMATS]={0,0,0};
+
+int register_cvf_format(struct cvf_format*cvf_format)
+{ int i,j;
+
+  for(i=0;i<MAX_CVF_FORMATS;++i)
+  { if(cvf_formats[i]==NULL)
+    { /* free slot found, now check version */
+      for(j=0;j<MAX_CVF_FORMATS;++j)
+      { if(cvf_formats[j])
+        { if(cvf_formats[j]->cvf_version==cvf_format->cvf_version)
+          { printk("register_cvf_format: version %d already registered\n",
+                   cvf_format->cvf_version);
+            return -1;
+          }
+        }
+      }
+      cvf_formats[i]=cvf_format;
+      cvf_format_use_count[i]=0;
+      printk("CVF format %s (version id %d) successfully registered.\n",
+             cvf_format->cvf_version_text,cvf_format->cvf_version);
+      return 0;
+    }
+  }
+  
+  printk("register_cvf_format: too many formats\n");
+  return -1;
+}
+
+int unregister_cvf_format(struct cvf_format*cvf_format)
+{ int i;
+
+  for(i=0;i<MAX_CVF_FORMATS;++i)
+  { if(cvf_formats[i])
+    { if(cvf_formats[i]->cvf_version==cvf_format->cvf_version)
+      { if(cvf_format_use_count[i])
+        { printk("unregister_cvf_format: format %d in use, cannot remove!\n",
+          cvf_formats[i]->cvf_version);
+          return -1;
+        }
+      
+        printk("CVF format %s (version id %d) successfully unregistered.\n",
+        cvf_formats[i]->cvf_version_text,cvf_formats[i]->cvf_version);
+        cvf_formats[i]=NULL;
+        return 0;
+      }
+    }
+  }
+  
+  printk("unregister_cvf_format: format %d is not registered\n",
+         cvf_format->cvf_version);
+  return -1;
+}
+
+void dec_cvf_format_use_count_by_version(int version)
+{ int i;
+
+  for(i=0;i<MAX_CVF_FORMATS;++i)
+  { if(cvf_formats[i])
+    { if(cvf_formats[i]->cvf_version==version)
+      { --cvf_format_use_count[i];
+        if(cvf_format_use_count[i]<0)
+        { cvf_format_use_count[i]=0;
+          printk(KERN_EMERG "FAT FS/CVF: This is a bug in cvf_version_use_count\n");
+        }
+        return;
+      }
+    }
+  }
+  
+  printk("dec_cvf_format_use_count_by_version: version %d not found ???\n",
+         version);
+}
+
+int detect_cvf(struct super_block*sb,char*force)
+{ int i;
+  int found=0;
+  int found_i=-1;
+
+  if(force)
+  { if(*force)
+    { for(i=0;i<MAX_CVF_FORMATS;++i)
+      { if(cvf_formats[i])
+        { if(!strcmp(cvf_formats[i]->cvf_version_text,force))
+            return i;
+        }
+      }
+    }
+  }
+
+  for(i=0;i<MAX_CVF_FORMATS;++i)
+  { if(cvf_formats[i])
+    { if(cvf_formats[i]->detect_cvf(sb))
+      { ++found;
+        found_i=i;
+      }
+    }
+  }
+  
+  if(found==1)return found_i;
+  if(found>1)printk("CVF detection ambiguous, use cvf_format=xxx option\n"); 
+  return -1;
+}
index 7568f876a7b922f4e51fe085e8b88e057ab81929..d7936928902732642c60bb3e122db89f3b6b6ea2 100644 (file)
@@ -434,6 +434,11 @@ int fat_dir_ioctl(struct inode * inode, struct file * filp,
                                    vfat_ioctl_fill, NULL, 1, 0, 1);
        }
        default:
+               /* forward ioctl to CVF extension */
+              if(MSDOS_SB(inode->i_sb)->cvf_format
+                 &&MSDOS_SB(inode->i_sb)->cvf_format->cvf_dir_ioctl)
+                     return MSDOS_SB(inode->i_sb)->cvf_format->
+                               cvf_dir_ioctl(inode,filp,cmd,arg);
                return -EINVAL;
        }
 
index 60e71ed9813717e155e85450a8528cc09cd90bb2..40ebe3e0ec08247efac152d93d0f18bbe44706e1 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/mm.h>
 #include <linux/msdos_fs.h>
+#include <linux/fat_cvf.h>
 
 #include "msbuffer.h"
 #include "tables.h"
@@ -47,6 +48,11 @@ EXPORT_SYMBOL(fat_truncate);
 EXPORT_SYMBOL(fat_uni2esc);
 EXPORT_SYMBOL(fat_unlock_creation);
 EXPORT_SYMBOL(fat_write_inode);
+EXPORT_SYMBOL(register_cvf_format);
+EXPORT_SYMBOL(unregister_cvf_format);
+EXPORT_SYMBOL(fat_get_cluster);
+EXPORT_SYMBOL(lock_fat);
+EXPORT_SYMBOL(unlock_fat);
 
 int init_fat_fs(void)
 {
index c1357f7845707038f27cdb7f550a12ac72848363..d0418d6c6a2df24564fb8323c77d9f30a2084c0a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/pagemap.h>
+#include <linux/fat_cvf.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -112,6 +113,40 @@ struct inode_operations fat_file_inode_operations_1024 = {
        NULL                    /* smap */
 };
 
+static struct file_operations fat_file_operations_readpage = {
+       NULL,                   /* lseek - default */
+       fat_file_read,          /* read */
+       fat_file_write,         /* write */
+       NULL,                   /* readdir - bad */
+       NULL,                   /* select v2.0.x/poll v2.1.x - default */
+       NULL,                   /* ioctl - default */
+       generic_file_mmap,      /* mmap */
+       NULL,                   /* no special open is needed */
+       NULL,                   /* release */
+       file_fsync              /* fsync */
+};
+
+struct inode_operations fat_file_inode_operations_readpage = {
+       &fat_file_operations_readpage,  /* default file operations */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       fat_readpage,           /* readpage */
+       NULL,                   /* writepage */
+       NULL,                   /* bmap */
+       fat_truncate,           /* truncate */
+       NULL,                   /* permission */
+       NULL                    /* smap */
+};
+
 #define MSDOS_PREFETCH 32
 struct fat_pre {
        int file_sector;/* Next sector to read in the prefetch table */
@@ -277,6 +312,10 @@ ssize_t fat_file_read(
        loff_t *ppos)
 {
        struct inode *inode = filp->f_dentry->d_inode;
+       if(MSDOS_SB(inode->i_sb)->cvf_format)
+          if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_file_read)
+            return MSDOS_SB(inode->i_sb)->cvf_format->cvf_file_read(filp,buf,count,ppos);
+
        if (!MSDOS_I(inode)->i_binary)
                return fat_file_read_text(filp, buf, count, ppos);
        return generic_file_read(filp, buf, count, ppos);
@@ -303,6 +342,10 @@ ssize_t fat_file_write(
                printk("fat_file_write: inode = NULL\n");
                return -EINVAL;
        }
+        if(MSDOS_SB(sb)->cvf_format)
+          if(MSDOS_SB(sb)->cvf_format->cvf_file_write)
+            return MSDOS_SB(sb)->cvf_format->cvf_file_write(filp,buf,count,ppos);
+
        /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
        if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
                printk("fat_file_write: mode = %07o\n",inode->i_mode);
index a5bf5a1ace5314d9ed3b1037254e695d85ae11dd..d84c2c2e0eb9e6d0f6c4954cfb35f89b123ab0fe 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/locks.h>
+#include <linux/fat_cvf.h>
 #include <linux/malloc.h>
 
 #include "msbuffer.h"
@@ -139,6 +140,10 @@ void fat_delete_inode(struct inode *inode)
 void fat_put_super(struct super_block *sb)
 {
        lock_super(sb);
+       if(MSDOS_SB(sb)->cvf_format)
+       { MSDOS_SB(sb)->cvf_format->unmount_cvf(sb);
+         dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version);
+       }
        if (MSDOS_SB(sb)->fat_bits == 32) {
                fat_clusters_flush(sb);
        }
@@ -169,7 +174,8 @@ void fat_put_super(struct super_block *sb)
 
 
 static int parse_options(char *options,int *fat, int *blksize, int *debug,
-                        struct fat_mount_options *opts)
+                        struct fat_mount_options *opts,
+                        char* cvf_format, char*cvf_options)
 {
        char *this_char,*value,save,*savep;
        char *p;
@@ -306,6 +312,16 @@ static int parse_options(char *options,int *fat, int *blksize, int *debug,
                                        ret = 0;
                        }
                }
+                else if (!strcmp(this_char,"cvf_format")) {
+                        if (!value)
+                                return 0;
+                        strncpy(cvf_format,value,20);
+                }
+                else if (!strcmp(this_char,"cvf_options")) {
+                        if (!value)
+                                return 0;
+                        strncpy(cvf_options,value,100);
+                }
 
                if (this_char != options) *(this_char-1) = ',';
                if (value) *savep = save;
@@ -335,6 +351,14 @@ fat_read_super(struct super_block *sb, void *data, int silent)
        int fat32;
        struct fat_mount_options opts;
        char buf[50];
+       int i;
+       char cvf_format[21];
+       char cvf_options[101];
+
+       cvf_format[0]='\0';
+       cvf_options[0]='\0';
+       MSDOS_SB(sb)->cvf_format=NULL;
+       MSDOS_SB(sb)->private_data=NULL;
 
        MOD_INC_USE_COUNT;
        if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
@@ -342,10 +366,12 @@ fat_read_super(struct super_block *sb, void *data, int silent)
                if (blksize != 512){
                        printk ("MSDOS: Hardware sector size is %d\n",blksize);
                }
+
        }
 
        opts.isvfat = MSDOS_SB(sb)->options.isvfat;
-       if (!parse_options((char *) data, &fat, &blksize, &debug, &opts)
+       if (!parse_options((char *) data, &fat, &blksize, &debug, &opts, 
+                          cvf_format, cvf_options)
            || (blksize != 512 && blksize != 1024 && blksize != 2048))
                goto out_fail;
        /* N.B. we should parse directly into the sb structure */
@@ -458,6 +484,9 @@ fat_read_super(struct super_block *sb, void *data, int silent)
                                /* because clusters (DOS) are often aligned */
                                /* on odd sectors. */
        sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11);
+       if(!strcmp(cvf_format,"none"))i=-1;
+       else i=detect_cvf(sb,cvf_format);
+       if(i>=0)error=cvf_formats[i]->mount_cvf(sb,cvf_options);
        if (error || debug) {
                /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
                printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
@@ -477,7 +506,7 @@ fat_read_super(struct super_block *sb, void *data, int silent)
                       MSDOS_SB(sb)->root_cluster,MSDOS_SB(sb)->free_clusters);
                printk ("Transaction block size = %d\n",blksize);
        }
-       if (MSDOS_SB(sb)->clusters+2 > fat_clusters)
+       if (i<0) if (MSDOS_SB(sb)->clusters+2 > fat_clusters)
                MSDOS_SB(sb)->clusters = fat_clusters-2;
        if (error)
                goto out_invalid;
@@ -517,6 +546,10 @@ fat_read_super(struct super_block *sb, void *data, int silent)
        sb->s_root = d_alloc_root(root_inode, NULL);
        if (!sb->s_root)
                goto out_no_root;
+       if(i>=0)
+       { MSDOS_SB(sb)->cvf_format=cvf_formats[i];
+         ++cvf_format_use_count[i];
+       }
        return sb;
 
 out_no_root:
@@ -540,6 +573,9 @@ out_fail:
                kfree(opts.iocharset);
        }
        sb->s_dev = 0;
+       if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data);
+       MSDOS_SB(sb)->private_data=NULL;
        MOD_DEC_USE_COUNT;
        return NULL;
 }
@@ -548,7 +584,11 @@ int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
 {
        int free,nr;
        struct statfs tmp;
-
+       
+        if(MSDOS_SB(sb)->cvf_format)
+          if(MSDOS_SB(sb)->cvf_format->cvf_statfs)
+            return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz);
+          
        lock_fat(sb);
        if (MSDOS_SB(sb)->free_clusters != -1)
                free = MSDOS_SB(sb)->free_clusters;
@@ -577,12 +617,15 @@ int fat_bmap(struct inode *inode,int block)
        int cluster,offset;
 
        sb = MSDOS_SB(inode->i_sb);
+       if(sb->cvf_format)
+         if(sb->cvf_format->cvf_bmap)
+           return sb->cvf_format->cvf_bmap(inode,block);
        if ((inode->i_ino == MSDOS_ROOT_INO) && (sb->fat_bits != 32)) {
                return sb->dir_start + block;
        }
        cluster = block/sb->cluster_size;
        offset = block % sb->cluster_size;
-       if (!(cluster = get_cluster(inode,cluster))) return 0;
+       if (!(cluster = fat_get_cluster(inode,cluster))) return 0;
        return (cluster-2)*sb->cluster_size+sb->data_start+offset;
 }
 
@@ -689,7 +732,12 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
                       !is_exec(raw_entry->ext)))
                        ? S_IRUGO|S_IWUGO : S_IRWXUGO)
                    & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG;
-               inode->i_op = (sb->s_blocksize == 1024 || sb->s_blocksize == 2048)
+               if(MSDOS_SB(sb)->cvf_format)
+                 inode->i_op = (MSDOS_SB(sb)->cvf_format->flags&CVF_USE_READPAGE)
+                       ? &fat_file_inode_operations_readpage
+                       : &fat_file_inode_operations_1024;
+               else
+                 inode->i_op = (sb->s_blocksize == 1024 || sb->s_blocksize == 2048)
                        ? &fat_file_inode_operations_1024
                        : &fat_file_inode_operations;
                MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
index 0fb7791ec41c1bfa2c9e3d8f7b6892fd0c8f045e..38cd5cb8e6814a6751566d5d439d94024755767b 100644 (file)
@@ -221,6 +221,10 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1));
 #endif
        sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size;
        last_sector = sector + cluster_size;
+       if(MSDOS_SB(sb)->cvf_format&&
+         MSDOS_SB(sb)->cvf_format->zero_out_cluster)
+           MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr);
+       else
        for ( ; sector < last_sector; sector++) {
                #ifdef DEBUG
                        printk("zeroing sector %d\n",sector);
@@ -279,9 +283,7 @@ int date_dos2unix(unsigned short time,unsigned short date)
            month < 2 ? 1 : 0)+3653);
                        /* days since 1.1.70 plus 80's leap day */
        secs += sys_tz.tz_minuteswest*60;
-       if (sys_tz.tz_dsttime) {
-           secs -= 3600;
-       }
+       if (sys_tz.tz_dsttime) secs -= 3600;
        return secs;
 }
 
@@ -293,9 +295,6 @@ void fat_date_unix2dos(int unix_date,unsigned short *time,
 {
        int day,year,nl_day,month;
 
-       if (sys_tz.tz_dsttime) {
-               unix_date += 3600;
-       }
        unix_date -= sys_tz.tz_minuteswest*60;
        if (sys_tz.tz_dsttime) unix_date += 3600;
 
index 48cbc7b4f62dc3fb4f6987459b6455ce720dfd78..e01bc14cb300e32ac5700c47b514abadaa15d7b8 100644 (file)
@@ -97,7 +97,10 @@ struct vm_operations_struct fat_file_mmap = {
 int fat_mmap(struct file * file, struct vm_area_struct * vma)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       
+       if(MSDOS_SB(inode->i_sb)->cvf_format)
+         if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap)
+           return MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap(file,vma);
+
        if (vma->vm_flags & VM_SHARED)  /* only PAGE_COW or read-only supported now */
                return -EINVAL;
        if (vma->vm_offset & (inode->i_sb->s_blocksize - 1))
@@ -115,3 +118,13 @@ int fat_mmap(struct file * file, struct vm_area_struct * vma)
 }
 
 
+int fat_readpage(struct inode * inode, struct page * page)
+{
+       if(MSDOS_SB(inode->i_sb)->cvf_format)
+         if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage)
+           return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page);
+           
+       printk("fat_readpage called with no handler (shouldn't happen)\n");
+       return -1;
+}
+
index 91902542170b99b342815c0dc3b20ce621a35b48..26eb1bd89b4e176e536cb7dd087cb3c79ee2fbed 100644 (file)
@@ -562,10 +562,11 @@ int minix_symlink(struct inode * dir, struct dentry *dentry,
        return 0;
 }
 
-int minix_link(struct inode * inode, struct inode * dir,
+int minix_link(struct dentry * old_dentry, struct inode * dir,
               struct dentry *dentry)
 {
        int error;
+       struct inode *inode = old_dentry->d_inode;
        struct minix_dir_entry * de;
        struct buffer_head * bh;
 
index d466a61acd30967bbe16119af1fe314efbdda160..adb5d5d31457dde0020146077d1d1eac18ded15f 100644 (file)
@@ -247,20 +247,13 @@ static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * nam
 
 /*
  * Internal lookup() using the new generic dcache.
- *
- * Note the revalidation: we have to drop the dcache
- * lock when we revalidate, so we need to update the
- * counts around it.
  */
 static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
 {
        struct dentry * dentry = d_lookup(parent, name);
 
        if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
-               int validated, (*revalidate)(struct dentry *) = dentry->d_op->d_revalidate;
-
-               validated = revalidate(dentry) || d_invalidate(dentry);
-               if (!validated) {
+               if (!dentry->d_op->d_revalidate(dentry) && !d_invalidate(dentry)) {
                        dput(dentry);
                        dentry = NULL;
                }
@@ -840,7 +833,7 @@ static inline int do_rmdir(const char * name)
 
        /* Disallow removals of mountpoints. */
        error = -EBUSY;
-       if (dentry == dir)
+       if (dentry->d_mounts != dentry->d_covers)
                goto exit_lock;
 
        error = -EPERM;
index 8c816e2b98d7c39d56c9b87936a5fa4c48228b22..f12cdfd6b1f38cf98d8e4e91c90a180c32048cd0 100644 (file)
@@ -58,6 +58,7 @@
  *     Martin Mares    :       Default path now contains host name instead of
  *                             host IP address (but host name defaults to IP
  *                             address anyway).
+ *     Martin Mares    :       Use root_server_addr appropriately during setup.
  */
 
 #include <linux/types.h>
@@ -86,6 +87,7 @@
 
 /* Parameters passed from the kernel command line */
 static char nfs_root_name[NFS_ROOT_NAME_LEN] __initdata = "default";
+static int nfs_params_parsed = 0;
 
 /* Address of NFS server */
 static __u32 servaddr __initdata = 0;
@@ -157,6 +159,9 @@ __initfunc(static int root_nfs_name(char *name))
        char *cp, *cq, *options, *val;
        int octets = 0;
 
+       if (nfs_params_parsed)
+               return nfs_params_parsed;
+
        /* It is possible to override the server IP number here */
        cp = cq = name;
        while (octets < 4) {
@@ -173,17 +178,12 @@ __initfunc(static int root_nfs_name(char *name))
        if (octets == 4 && (*cp == ':' || *cp == '\0')) {
                if (*cp == ':')
                        *cp++ = '\0';
-               servaddr = in_aton(name);
+               root_server_addr = in_aton(name);
                name = cp;
-       } else if ((servaddr = root_server_addr) == INADDR_NONE) {
-               printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
-               return -1;
        }
 
        /* Clear the nfs_data structure and setup the server hostname */
        memset(&nfs_data, 0, sizeof(nfs_data));
-       strncpy(nfs_data.hostname, in_ntoa(servaddr), sizeof(nfs_data.hostname)-1);
-       nfs_data.namlen = strlen(nfs_data.hostname);
 
        /* Set the name of the directory to mount */
        if (root_server_path[0] && !strcmp(name, "default"))
@@ -239,10 +239,25 @@ __initfunc(static int root_nfs_name(char *name))
                        cp = strtok(NULL, ",");
                }
        }
-       return 0;
+       return 1;
 }
 
 
+/*
+ *  Get NFS server address.
+ */
+__initfunc(static int root_nfs_addr(void))
+{
+       if ((servaddr = root_server_addr) == INADDR_NONE) {
+               printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
+               return -1;
+       }
+
+       strncpy(nfs_data.hostname, in_ntoa(servaddr), sizeof(nfs_data.hostname)-1);
+       nfs_data.namlen = strlen(nfs_data.hostname);
+       return 0;
+}
+
 /*
  *  Tell the user what's going on.
  */
@@ -274,7 +289,8 @@ __initfunc(int root_nfs_init(void))
         * be able to use the client IP address for the remote root
         * directory (necessary for pure RARP booting).
         */
-       if (root_nfs_name(nfs_root_name) < 0)
+       if (root_nfs_name(nfs_root_name) < 0 ||
+           root_nfs_addr() < 0)
                return -1;
 
 #ifdef NFSROOT_DEBUG
@@ -301,6 +317,7 @@ __initfunc(void nfs_root_setup(char *line, int *ints))
                        line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
                sprintf(nfs_root_name, NFS_ROOT, line);
        }
+       nfs_params_parsed = root_nfs_name(nfs_root_name);
 }
 
 
index 416ed294eb1b4dab94946ad4618c60fece5d4b6c..91fba9b2ace719b5e0ae5739d53d0eceddedd2c7 100644 (file)
@@ -45,8 +45,8 @@
 
 /*
  * If NFS_DEBUG is defined, you can toggle NFS debugging by causing
- * a lookup of "xyzzy". Just cd to an NFS-mounted filesystem and type
- * 'ls xyzzy' to turn on debugging.
+ * a lookup of "__xyzzy__". Just cd to an NFS-mounted filesystem and type
+ * 'ls __xyzzy__' to turn on debugging.
  */
 #ifdef NFS_DEBUG
 # define NFSDBG_FACILITY       NFSDBG_PROC
@@ -91,7 +91,7 @@ nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
 
        dprintk("NFS call  lookup %s\n", name);
 #ifdef RPC_DEBUG
-       if (!strcmp(name, "xyzzy"))
+       if (!strcmp(name, "__xyzzy__"))
                nfs_debug = ~nfs_debug;
 #endif
        status = rpc_call(server->client, NFSPROC_LOOKUP, &arg, &res, 0);
index 1272d817fd52709ff4e8393e9f581efc39aa5770..20acac98bf150cab6f12d19ecde993ba8f99dd1b 100644 (file)
@@ -146,9 +146,9 @@ static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
        pattern = NULL;
        inode = dentry->d_inode;
        if (inode && dentry->d_parent == dentry) {
-               if (inode->i_sock)
+               if (S_ISSOCK(inode->i_mode))
                        pattern = "socket:[%lu]";
-               if (inode->i_pipe)
+               if (S_ISFIFO(inode->i_mode))
                        pattern = "pipe:[%lu]";
        }
        
index 1c7858a6f7115995ab8f00de709c3127182af74f..97e66886e7e6d504f6fb522ad4e27eb3a6f0efe7 100644 (file)
@@ -50,6 +50,9 @@ static struct file_operations proc_dir_operations = {
        NULL                    /* can't fsync */
 };
 
+int proc_readlink(struct dentry * dentry, char * buffer, int buflen);
+struct dentry * proc_follow_link(struct dentry *dentry, struct dentry *base);
+
 /*
  * proc directories can do almost nothing..
  */
@@ -332,6 +335,9 @@ int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
                if (dp->ops == NULL)
                        dp->ops = &proc_dir_inode_operations;
                dir->nlink++;
+       } else if (S_ISLNK(dp->mode)) {
+               if (dp->ops == NULL)
+                       dp->ops = &proc_link_inode_operations;
        } else {
                if (dp->ops == NULL)
                        dp->ops = &proc_file_inode_operations;
@@ -389,6 +395,50 @@ static struct dentry * proc_self_follow_link(struct dentry *dentry,
        return lookup_dentry(tmp, base, 1);
 }      
 
+int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
+{
+       struct inode *inode = dentry->d_inode;
+       struct proc_dir_entry * de;
+       char    *page;
+       int len = 0;
+
+       de = (struct proc_dir_entry *) inode->u.generic_ip;
+       if (!de)
+               return -ENOENT;
+       if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+               return -ENOMEM;
+
+       if (de->readlink_proc)
+               len = de->readlink_proc(de, page);
+
+       if (len > buflen)
+               len = buflen;
+
+       copy_to_user(buffer, page, len);
+       free_page((unsigned long) page);
+       return len;
+}
+
+struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base)
+{
+       struct inode *inode = dentry->d_inode;
+       struct proc_dir_entry * de;
+       char    *page;
+       struct dentry *d;
+       int len = 0;
+
+       de = (struct proc_dir_entry *) inode->u.generic_ip;
+       if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+               return NULL;
+
+       if (de->readlink_proc)
+               len = de->readlink_proc(de, page);
+
+       d = lookup_dentry(page, base, 1);
+       free_page((unsigned long) page);
+       return d;
+}
+
 static struct inode_operations proc_self_inode_operations = {
        NULL,                   /* no file-ops */
        NULL,                   /* create */
@@ -409,6 +459,26 @@ static struct inode_operations proc_self_inode_operations = {
        NULL                    /* permission */
 };
 
+static struct inode_operations proc_link_inode_operations = {
+       NULL,                   /* no file-ops */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       proc_readlink,          /* readlink */
+       proc_follow_link,       /* follow_link */
+       NULL,                   /* readpage */
+       NULL,                   /* writepage */
+       NULL,                   /* bmap */
+       NULL,                   /* truncate */
+       NULL                    /* permission */
+};
+
 static struct proc_dir_entry proc_root_loadavg = {
        PROC_LOADAVG, 7, "loadavg",
        S_IFREG | S_IRUGO, 1, 0, 0,
index f9d2c379896a066073b09d0b857ccb7e189517d6..0201ff6458ace1e6b8441cf27d58e92252767cd9 100644 (file)
@@ -873,7 +873,7 @@ void sysv_read_inode(struct inode * inode)
 }
 
 /* To avoid inconsistencies between inodes in memory and inodes on disk. */
-extern int sysv_notify_change(struct dentry *dentry, struct iattr *attr)
+int sysv_notify_change(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
        int error;
index f641d1904968ffa62f1010439c873ea1652081c1..01ab086d2e3e84d69036774b8ef141a9a0cd819e 100644 (file)
@@ -571,9 +571,10 @@ int sysv_symlink(struct inode * dir, struct dentry * dentry,
        return 0;
 }
 
-int sysv_link(struct inode * oldinode, struct inode * dir, 
+int sysv_link(struct dentry * old_dentry, struct inode * dir, 
              struct dentry * dentry)
 {
+       struct inode *oldinode = old_dentry->d_inode;
        int error;
        struct sysv_dir_entry * de;
        struct buffer_head * bh;
index 733f7764ea764df0b8ea171e795eec2b51a452b7..2d70f17dd18b9f35e18a939e477f3e922d32ad1e 100644 (file)
@@ -97,135 +97,64 @@ extern unsigned long search_exception_table(unsigned long);
  * with a separate "access_ok()" call (this is used when we do multiple
  * accesses to the same area of user memory).
  */
-#define get_user(x,ptr) \
-  __get_user_check((x),(ptr),sizeof(*(ptr)))
-#define put_user(x,ptr) \
-  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
-#define __get_user(x,ptr) \
-  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
-#define __put_user(x,ptr) \
-  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
-
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
+extern void __get_user_1(void);
+extern void __get_user_2(void);
+extern void __get_user_4(void);
 
+#define __get_user_x(size,ret,x,ptr) \
+       __asm__ __volatile__("call __get_user_" #size \
+               :"=a" (ret),"=d" (x) \
+               :"0" (ptr))
 
+#define get_user(x,ptr) \
+({     int __ret_gu;    \
+       switch(sizeof (*(ptr))) {     \
+       case 1:  __get_user_x(1,__ret_gu,x,ptr); break; \
+       case 2:  __get_user_x(2,__ret_gu,x,ptr); break; \
+       case 4:  __get_user_x(4,__ret_gu,x,ptr); break; \
+       default: __get_user_x(X,__ret_gu,x,ptr); break; \
+       } \
+       __ret_gu; \
+})
 
-extern long __put_user_bad(void);
+extern void __put_user_1(void);
+extern void __put_user_2(void);
+extern void __put_user_4(void);
 
-#define __put_user_nocheck(x,ptr,size)                 \
-({                                                     \
-       long __pu_err;                                  \
-       __put_user_size((x),(ptr),(size),__pu_err);     \
-       __pu_err;                                       \
-})
+#define __put_user_x(size,ret,x,ptr) \
+       __asm__ __volatile__("call __put_user_" #size \
+               :"=a" (ret) \
+               :"0" (ptr),"d" (x) \
+               :"cx")
 
-#define __put_user_check(x,ptr,size)                           \
-({                                                             \
-       long __pu_err = -EFAULT;                                \
-       __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
-       if (access_ok(VERIFY_WRITE,__pu_addr,size))             \
-               __put_user_size((x),__pu_addr,(size),__pu_err); \
-       __pu_err;                                               \
+#define put_user(x,ptr) \
+({     int __ret_pu;    \
+       switch(sizeof (*(ptr))) {     \
+       case 1:  __put_user_x(1,__ret_pu,(char)(x),ptr); break; \
+       case 2:  __put_user_x(2,__ret_pu,(short)(x),ptr); break; \
+       case 4:  __put_user_x(4,__ret_pu,(int)(x),ptr); break; \
+       default: __put_user_x(X,__ret_pu,x,ptr); break; \
+       } \
+       __ret_pu; \
 })
 
-#define __put_user_size(x,ptr,size,retval)                             \
-do {                                                                   \
-       retval = 0;                                                     \
-       switch (size) {                                                 \
-         case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break;     \
-         case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break;     \
-         case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break;      \
-         default: __put_user_bad();                                    \
-       }                                                               \
-} while (0)
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
+#define __get_user(x,ptr) get_user(x,ptr)
+#define __put_user(x,ptr) put_user(x,ptr)
 
 /*
- * Tell gcc we read from memory instead of writing: this is because
- * we do not write to any memory gcc knows about, so there are no
- * aliasing issues.
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
  */
-#define __put_user_asm(x, addr, err, itype, rtype, ltype)      \
-       __asm__ __volatile__(                                   \
-               "1:     mov"itype" %"rtype"1,%2\n"              \
-               "2:\n"                                          \
-               ".section .fixup,\"ax\"\n"                      \
-               "3:     movl %3,%0\n"                           \
-               "       jmp 2b\n"                               \
-               ".previous\n"                                   \
-               ".section __ex_table,\"a\"\n"                   \
-               "       .align 4\n"                             \
-               "       .long 1b,3b\n"                          \
-               ".previous"                                     \
-               : "=r"(err)                                     \
-               : ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
-
-
-#define __get_user_nocheck(x,ptr,size)                         \
-({                                                             \
-       long __gu_err, __gu_val;                                \
-       __get_user_size(__gu_val,(ptr),(size),__gu_err);        \
-       (x) = (__typeof__(*(ptr)))__gu_val;                     \
-       __gu_err;                                               \
-})
 
-#define __get_user_check(x,ptr,size)                                   \
-({                                                                     \
-       long __gu_err = -EFAULT, __gu_val = 0;                          \
-       const __typeof__(*(ptr)) *__gu_addr = (ptr);                    \
-       if (access_ok(VERIFY_READ,__gu_addr,size))                      \
-               __get_user_size(__gu_val,__gu_addr,(size),__gu_err);    \
-       (x) = (__typeof__(*(ptr)))__gu_val;                             \
-       __gu_err;                                                       \
-})
+#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
 
-extern long __get_user_bad(void);
-
-#define __get_user_size(x,ptr,size,retval)                             \
-do {                                                                   \
-       retval = 0;                                                     \
-       switch (size) {                                                 \
-         case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break;     \
-         case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break;     \
-         case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break;      \
-         default: (x) = __get_user_bad();                              \
-       }                                                               \
-} while (0)
+#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
 
-#define __get_user_asm(x, addr, err, itype, rtype, ltype)      \
-       __asm__ __volatile__(                                   \
-               "1:     mov"itype" %2,%"rtype"1\n"              \
-               "2:\n"                                          \
-               ".section .fixup,\"ax\"\n"                      \
-               "3:     movl %3,%0\n"                           \
-               "       xor"itype" %"rtype"1,%"rtype"1\n"       \
-               "       jmp 2b\n"                               \
-               ".previous\n"                                   \
-               ".section __ex_table,\"a\"\n"                   \
-               "       .align 4\n"                             \
-               "       .long 1b,3b\n"                          \
-               ".previous"                                     \
-               : "=r"(err), ltype (x)                          \
-               : "m"(__m(addr)), "i"(-EFAULT), "0"(err))
+#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; })
+
+#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; })
 
 
 /*
@@ -252,6 +181,24 @@ do {                                                                       \
                : "r"(size & 3), "0"(size / 4), "D"(to), "S"(from)      \
                : "di", "si", "memory")
 
+/* We let the __ versions of copy_from/to_user inline, because they're often
+ * used in fast paths and have only a small space overhead.
+ */
+static inline unsigned long
+__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
+{
+       __copy_user(to,from,n);
+       return n;
+}
+
+static inline unsigned long
+__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
+{
+       __copy_user(to,from,n);
+       return n;
+}
+
+
 /* Optimize just a little bit when we know the size of the move. */
 #define __constant_copy_user(to, from, size)                   \
 do {                                                           \
@@ -335,13 +282,8 @@ do {                                                               \
        }                                                       \
 } while (0)
 
-static inline unsigned long
-__generic_copy_to_user(void *to, const void *from, unsigned long n)
-{
-       if (access_ok(VERIFY_WRITE, to, n))
-               __copy_user(to,from,n);
-       return n;
-}
+unsigned long __generic_copy_to_user(void *, const void *, unsigned long);
+unsigned long __generic_copy_from_user(void *, const void *, unsigned long);
 
 static inline unsigned long
 __constant_copy_to_user(void *to, const void *from, unsigned long n)
@@ -351,14 +293,6 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n)
        return n;
 }
 
-static inline unsigned long
-__generic_copy_from_user(void *to, const void *from, unsigned long n)
-{
-       if (access_ok(VERIFY_READ, from, n))
-               __copy_user(to,from,n);
-       return n;
-}
-
 static inline unsigned long
 __constant_copy_from_user(void *to, const void *from, unsigned long n)
 {
@@ -367,13 +301,6 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n)
        return n;
 }
 
-static inline unsigned long
-__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
-{
-       __copy_user(to,from,n);
-       return n;
-}
-
 static inline unsigned long
 __constant_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
 {
@@ -381,13 +308,6 @@ __constant_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
        return n;
 }
 
-static inline unsigned long
-__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
-{
-       __copy_user(to,from,n);
-       return n;
-}
-
 static inline unsigned long
 __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
 {
@@ -405,15 +325,9 @@ __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
         __constant_copy_from_user((to),(from),(n)) :   \
         __generic_copy_from_user((to),(from),(n)))
 
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
-       return retval; \
-})
+#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
 
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
-       return retval; \
-})
+#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
 
 #define __copy_to_user(to,from,n)                      \
        (__builtin_constant_p(n) ?                      \
@@ -425,116 +339,10 @@ if (copy_from_user(to,from,n)) \
         __constant_copy_from_user_nocheck((to),(from),(n)) :   \
         __generic_copy_from_user_nocheck((to),(from),(n)))
 
-
-/*
- * Zero Userspace
- */
-
-#define __do_clear_user(addr,size)                                             \
-       __asm__ __volatile__(                                           \
-               "0:     rep; stosl\n"                                   \
-               "       movl %1,%0\n"                                   \
-               "1:     rep; stosb\n"                                   \
-               "2:\n"                                                  \
-               ".section .fixup,\"ax\"\n"                              \
-               "3:     lea 0(%1,%0,4),%0\n"                            \
-               "       jmp 2b\n"                                       \
-               ".previous\n"                                           \
-               ".section __ex_table,\"a\"\n"                           \
-               "       .align 4\n"                                     \
-               "       .long 0b,3b\n"                                  \
-               "       .long 1b,2b\n"                                  \
-               ".previous"                                             \
-               : "=c"(size)                                            \
-               : "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0)       \
-               : "di")
-
-static inline unsigned long
-clear_user(void *to, unsigned long n)
-{
-       if (access_ok(VERIFY_WRITE, to, n))
-               __do_clear_user(to, n);
-       return n;
-}
-
-static inline unsigned long
-__clear_user(void *to, unsigned long n)
-{
-       __do_clear_user(to, n);
-       return n;
-}
-
-
-/*
- * Copy a null terminated string from userspace.
- */
-
-#define __do_strncpy_from_user(dst,src,count,res)                         \
-       __asm__ __volatile__(                                              \
-               "       testl %1,%1\n"                                     \
-               "       jz 2f\n"                                           \
-               "0:     lodsb\n"                                           \
-               "       stosb\n"                                           \
-               "       testb %%al,%%al\n"                                 \
-               "       jz 1f\n"                                           \
-               "       decl %1\n"                                         \
-               "       jnz 0b\n"                                          \
-               "1:     subl %1,%0\n"                                      \
-               "2:\n"                                                     \
-               ".section .fixup,\"ax\"\n"                                 \
-               "3:     movl %2,%0\n"                                      \
-               "       jmp 2b\n"                                          \
-               ".previous\n"                                              \
-               ".section __ex_table,\"a\"\n"                              \
-               "       .align 4\n"                                        \
-               "       .long 0b,3b\n"                                     \
-               ".previous"                                                \
-               : "=d"(res), "=c"(count)                                   \
-               : "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \
-               : "si", "di", "ax", "memory")
-
-static inline long
-__strncpy_from_user(char *dst, const char *src, long count)
-{
-       long res;
-       __do_strncpy_from_user(dst, src, count, res);
-       return res;
-}
-
-static inline long
-strncpy_from_user(char *dst, const char *src, long count)
-{
-       long res = -EFAULT;
-       if (access_ok(VERIFY_READ, src, 1))
-               __do_strncpy_from_user(dst, src, count, res);
-       return res;
-}
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 for error
- */
-
-extern inline long strlen_user(const char *s)
-{
-       unsigned long res;
-
-       __asm__ __volatile__(
-               "0:     repne; scasb\n"
-               "       notl %0\n"
-               "1:\n"
-               ".section .fixup,\"ax\"\n"
-               "2:     xorl %0,%0\n"
-               "       jmp 1b\n"
-               ".previous\n"
-               ".section __ex_table,\"a\"\n"
-               "       .align 4\n"
-               "       .long 0b,2b\n"
-               ".previous"
-               :"=c" (res), "=D" (s)
-               :"1" (s), "a" (0), "0" (-__addr_ok(s)));
-       return res & -__addr_ok(s);
-}
+long strncpy_from_user(char *dst, const char *src, long count);
+long __strncpy_from_user(char *dst, const char *src, long count);
+long strlen_user(const char *str);
+unsigned long clear_user(void *mem, unsigned long len);
+unsigned long __clear_user(void *mem, unsigned long len);
 
 #endif /* __i386_UACCESS_H */
index ec637973de93138660150da4577421f4fffeaa01..11cbc7e7268e68fd56ec7d048cf440c28f351fca 100644 (file)
@@ -65,7 +65,7 @@ extern int    affs_unlink(struct inode *dir, struct dentry *dentry);
 extern int     affs_create(struct inode *dir, struct dentry *dentry, int mode);
 extern int     affs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
 extern int     affs_rmdir(struct inode *dir, struct dentry *dentry);
-extern int     affs_link(struct inode *oldinode, struct inode *dir,
+extern int     affs_link(struct dentry *olddentry, struct inode *dir,
                          struct dentry *dentry);
 extern int     affs_symlink(struct inode *dir, struct dentry *dentry,
                             const char *symname);
@@ -78,7 +78,7 @@ extern struct buffer_head     *affs_bread(kdev_t dev, int block, int size);
 extern void                     affs_brelse(struct buffer_head *buf);
 extern unsigned long            affs_parent_ino(struct inode *dir);
 extern struct inode            *affs_new_inode(const struct inode *dir);
-extern int                      affs_notify_change(struct inode *inode, struct iattr *attr);
+extern int                      affs_notify_change(struct dentry *dentry, struct iattr *attr);
 extern int                      affs_add_entry(struct inode *dir, struct inode *link,
                                          struct inode *inode, struct dentry *dentry, s32 type);
 extern void                     affs_put_inode(struct inode *inode);
@@ -107,4 +107,7 @@ extern struct inode_operations       affs_symlink_inode_operations;
 extern struct inode_operations  affs_chrdev_inode_operations;
 extern struct inode_operations  affs_blkdev_inode_operations;
 
+extern struct dentry_operations         affs_dentry_operations;
+extern struct dentry_operations         affs_dentry_operations_intl;
+
 #endif
index f0da942911e003c1850fa88369c1978a27514ad2..8a721feea83ad990e39fcdce659eecda444cceba 100644 (file)
 #endif 
 
 #ifdef __linux__
+#define cdev_t u_quad_t
 #if !defined(_UQUAD_T_) && (!defined(__GLIBC__) || __GLIBC__ < 2)
 #define _UQUAD_T_ 1
 typedef unsigned long long u_quad_t;
 #endif 
+#else
+#define cdev_t dev_t
 #endif
 
 
@@ -146,7 +149,7 @@ struct coda_vattr {
        struct timespec va_ctime;       /* time file changed */
        u_long          va_gen;         /* generation number of file */
        u_long          va_flags;       /* flags defined for file */
-       dev_t           va_rdev;        /* device the special file represents */
+       cdev_t          va_rdev;        /* device special file represents */
        u_quad_t        va_bytes;       /* bytes of disk space held by file */
        u_quad_t        va_filerev;     /* file modification number */
 };
@@ -237,7 +240,7 @@ struct cfs_open_in {
 
 struct cfs_open_out {
     struct cfs_out_hdr oh;
-    dev_t      dev;
+    cdev_t     dev;
     ino_t      inode;
 };
 
index 2973be72399905be6a726945512f35d7dbef35b8..626e3d2c412b2dfaf65f4ac7e31346bca80e9fee 100644 (file)
@@ -26,6 +26,7 @@ struct cnode {
         u_short            c_mmcount;   /* count of mmappers */
         struct inode      *c_ovp;       /* open vnode pointer */
         struct list_head   c_cnhead;    /* head of cache entries */
+       struct list_head   c_volrootlist; /* list of volroot cnoddes */
 };
 
 /* flags */
@@ -36,7 +37,6 @@ struct cnode {
 #define C_ZAPDIR      0x10
 
 void coda_cnode_free(struct cnode *);
-struct cnode *coda_cnode_alloc(void);
 int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *);
 int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
 struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb);
index 63ba829de42e524ea8c27b9abe7509ee1beb3b52..400aa283340c05cec63cdbc1967eb4db6c78ef12 100644 (file)
@@ -45,6 +45,7 @@ extern int coda_access_cache;
 /* this file:  heloers */
 char *coda_f2s(ViceFid *f, char *s);
 int coda_isroot(struct inode *i);
+int coda_fid_is_volroot(struct ViceFid *);
 int coda_iscontrol(const char *name, size_t length);
 void coda_load_creds(struct coda_cred *cred);
 int coda_mycred(struct coda_cred *);
index 649234b3be0ad612a870c28a2869e911756d2fe9..3e775425c51e8f012dde3e24967f80c523c10459 100644 (file)
@@ -26,6 +26,7 @@ struct coda_sb_info
        struct vcomm *      sbi_vcomm;
        struct inode *      sbi_root;
        struct list_head    sbi_cchead;
+       struct list_head    sbi_volroothead;
 };
 
 /* communication pending/processing queues queues */
diff --git a/include/linux/fat_cvf.h b/include/linux/fat_cvf.h
new file mode 100644 (file)
index 0000000..1c4df58
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _FAT_CVF
+#define _FAT_CVF
+
+#define CVF_USE_READPAGE  0x0001
+
+struct cvf_format
+{ int cvf_version;
+  char* cvf_version_text;
+  unsigned long flags;
+  int (*detect_cvf) (struct super_block*sb);
+  int (*mount_cvf) (struct super_block*sb,char*options);
+  int (*unmount_cvf) (struct super_block*sb);
+  struct buffer_head* (*cvf_bread) (struct super_block*sb,int block);
+  struct buffer_head* (*cvf_getblk) (struct super_block*sb,int block);
+  void (*cvf_brelse) (struct super_block *sb,struct buffer_head *bh);
+  void (*cvf_mark_buffer_dirty) (struct super_block *sb,
+                              struct buffer_head *bh,
+                              int dirty_val);
+  void (*cvf_set_uptodate) (struct super_block *sb,
+                         struct buffer_head *bh,
+                         int val);
+  int (*cvf_is_uptodate) (struct super_block *sb,struct buffer_head *bh);
+  void (*cvf_ll_rw_block) (struct super_block *sb,
+                        int opr,
+                        int nbreq,
+                        struct buffer_head *bh[32]);
+  int (*fat_access) (struct super_block *sb,int nr,int new_value);
+  int (*cvf_statfs) (struct super_block *sb,struct statfs *buf, int bufsiz);
+  int (*cvf_bmap) (struct inode *inode,int block);
+  int (*cvf_smap) (struct inode *inode,int sector);
+  ssize_t (*cvf_file_read) ( struct file *, char *, size_t, loff_t *);
+  ssize_t (*cvf_file_write) ( struct file *, const char *, size_t, loff_t *);
+  int (*cvf_mmap) (struct file *, struct vm_area_struct *);
+  int (*cvf_readpage) (struct inode *, struct page *);
+  int (*cvf_writepage) (struct inode *, struct page *);
+  int (*cvf_dir_ioctl) (struct inode * inode, struct file * filp,
+                        unsigned int cmd, unsigned long arg);
+  void (*zero_out_cluster) (struct inode*, int clusternr);
+};
+
+int register_cvf_format(struct cvf_format*cvf_format);
+int unregister_cvf_format(struct cvf_format*cvf_format);
+void dec_cvf_format_use_count_by_version(int version);
+int detect_cvf(struct super_block*sb,char*force);
+
+extern struct cvf_format *cvf_formats[];
+extern int cvf_format_use_count[];
+
+#endif
index 35db77dc90a70355198d843a1539c8e4598422c8..9be5bd1b1c61dca02e58c47988e1f3e600a9e246 100644 (file)
 #define WIN_READDMA            0xc8    /* read sectors using DMA transfers */
 #define WIN_WRITEDMA           0xca    /* write sectors using DMA transfers */
 
+#define WIN_SMART              0xb0    /* self-monitoring and reporting */
+
 /* Additional drive command codes used by ATAPI devices. */
 #define WIN_PIDENTIFY          0xA1    /* identify ATAPI device        */
 #define WIN_SRST               0x08    /* ATAPI soft reset command */
 #define WIN_PACKETCMD          0xa0    /* Send a packet command. */
 
+/* WIN_SMART sub-commands */
+
+#define SMART_READ_VALUES      0xd0
+#define SMART_READ_THRESHOLDS  0xd1
+#define SMART_AUTOSAVE         0xd2
+#define SMART_SAVE             0xd3
+#define SMART_IMMEDIATE_OFFLINE        0xd4
+#define SMART_ENABLE           0xd8
+#define SMART_DISABLE          0xd9
+#define SMART_STATUS           0xda
+#define SMART_AUTO_OFFLINE     0xdb
+
 /* Bits for HD_ERROR */
 #define MARK_ERR       0x01    /* Bad address mark */
 #define TRK0_ERR       0x02    /* couldn't find track 0 */
index a725bbe367e8a774ebabafae76e2270c86a7e110..20a8cd66da6f1dfdb0536ad1f37d896005791a9a 100644 (file)
@@ -95,7 +95,7 @@ extern int minix_rmdir(struct inode * dir, struct dentry *dentry);
 extern int minix_unlink(struct inode * dir, struct dentry *dentry);
 extern int minix_symlink(struct inode * inode, struct dentry *dentry,
        const char * symname);
-extern int minix_link(struct inode * oldinode, struct inode * dir, struct dentry *dentry);
+extern int minix_link(struct dentry * old_dentry, struct inode * dir, struct dentry *dentry);
 extern int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev);
 extern int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
                        struct inode * new_dir, struct dentry *new_dentry);
index 3aed2bb1f2b828ae3c63f888c4b2ca36a1b4893f..c245aae26232903b2662249d3639221b4e813a42 100644 (file)
@@ -161,8 +161,9 @@ struct msdos_dir_slot {
        __u8    name11_12[4];   /* last 2 characters in name */
 };
 
-struct slot_info {
+struct vfat_slot_info {
        int is_long;                   /* was the found entry long */
+       int is_alias;                  /* was the found entry an alias */
        int long_slots;                /* number of long slots in filename */
        int total_slots;               /* total slots (long and short) */
        loff_t longname_offset;        /* dir offset for longname start */
@@ -248,12 +249,14 @@ extern int fat_dir_ioctl(struct inode * inode, struct file * filp,
 /* file.c */
 extern struct inode_operations fat_file_inode_operations;
 extern struct inode_operations fat_file_inode_operations_1024;
+extern struct inode_operations fat_file_inode_operations_readpage;
 extern ssize_t fat_file_read(struct file *, char *, size_t, loff_t *);
 extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *);
 extern void fat_truncate(struct inode *inode);
 
 /* mmap.c */
 extern int fat_mmap(struct file *, struct vm_area_struct *);
+extern int fat_readpage(struct inode *, struct page *);
 
 
 /* vfat.c */
index fe584a85b6a0ce79c33824636eee65618144222e..4985eef157f0e669c550ec3eb33e72e48533f003 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _MSDOS_FS_SB
 #define _MSDOS_FS_SB
+#include<linux/fat_cvf.h>
 
 /*
  * MS-DOS file system in-core superblock data
@@ -47,6 +48,8 @@ struct msdos_sb_info {
        struct fat_mount_options options;
        struct nls_table *nls_disk;  /* Codepage used on disk */
        struct nls_table *nls_io;    /* Charset used for input and display */
+       struct cvf_format* cvf_format;
+       void* private_data;     
 };
 
 #endif
index eeaf1b14ee61c00d41b39730a11a513ac688adc6..f0d68f7b1750ce6d528a4e66ceda4b300fd8a256 100644 (file)
@@ -244,6 +244,7 @@ struct proc_dir_entry {
                         int count, int *eof, void *data);
        int (*write_proc)(struct file *file, const char *buffer,
                          unsigned long count, void *data);
+       int (*readlink_proc)(struct proc_dir_entry *de, char *page);
        unsigned int count;     /* use count */
        int deleted;            /* delete flag */
 };
index 32c1949f2b2849476ba2a29c00b1fee04527b5ca..a3d3218c01fe6af3285cdc487b3c8685160f2a5f 100644 (file)
@@ -179,17 +179,18 @@ struct signal_struct {
 struct task_struct {
 /* these are hardcoded - don't touch */
        volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
-       long counter;
-       long priority;
        unsigned long flags;    /* per process flags, defined below */
        int sigpending;
-       long debugreg[8];  /* Hardware debugging registers */
-       struct exec_domain *exec_domain;
-/* various fields */
        mm_segment_t addr_limit;        /* thread address space:
                                                0-0xBFFFFFFF for user-thead
                                                0-0xFFFFFFFF for kernel-thread
                                         */
+       struct exec_domain *exec_domain;
+
+/* various fields */
+       long debugreg[8];  /* Hardware debugging registers */
+       long counter;
+       long priority;
        struct linux_binfmt *binfmt;
        struct task_struct *next_task, *prev_task;
        struct task_struct *next_run,  *prev_run;
@@ -311,10 +312,9 @@ struct task_struct {
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
  */
 #define INIT_TASK \
-/* state etc */        { 0,DEF_PRIORITY,DEF_PRIORITY,0,0, \
+/* state etc */        { 0,0,0,KERNEL_DS,&default_exec_domain, \
 /* debugregs */ { 0, },            \
-/* exec domain */&default_exec_domain, \
-/* mm_seg */   KERNEL_DS, \
+/* counter */  DEF_PRIORITY,DEF_PRIORITY, \
 /* binfmt */   NULL, \
 /* schedlink */        &init_task,&init_task, &init_task, &init_task, \
 /* ec,brk... */        0,0,0,0,0,0, \
index 7c5167fa815d54f8bc64a97391cbb89fd4ad5c2c..00d40adcac62a0e66f44c9ba9d0f3494778aba32 100644 (file)
@@ -367,7 +367,7 @@ extern int sysv_mkdir(struct inode * dir, struct dentry * dentry, int mode);
 extern int sysv_rmdir(struct inode * dir, struct dentry * dentry);
 extern int sysv_unlink(struct inode * dir, struct dentry * dentry);
 extern int sysv_symlink(struct inode * inode, struct dentry * dentry, const char * symname);
-extern int sysv_link(struct inode * oldinode, struct inode * dir, struct dentry * dentry);
+extern int sysv_link(struct dentry * old_dentry, struct inode * dir, struct dentry * dentry);
 extern int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev);
 extern int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
                       struct inode * new_dir, struct dentry * new_dentry);
@@ -390,7 +390,7 @@ extern struct super_block *sysv_read_super(struct super_block *,void *,int);
 extern int init_sysv_fs(void);
 extern void sysv_write_super(struct super_block *);
 extern void sysv_read_inode(struct inode *);
-extern int sysv_notify_change(struct inode *, struct iattr *);
+extern int sysv_notify_change(struct dentry *, struct iattr *);
 extern void sysv_write_inode(struct inode *);
 extern void sysv_put_inode(struct inode *);
 extern int sysv_statfs(struct super_block *, struct statfs *, int);
index b25f0c31e0b2ceaf21a043f034f5ce3174465734..bc08c6cf8da882f066433c4b9f0fec76fb17e0b6 100644 (file)
@@ -135,6 +135,7 @@ extern struct inode_operations umsdos_dir_inode_operations;
 extern struct file_operations  umsdos_file_operations;
 extern struct inode_operations umsdos_file_inode_operations;
 extern struct inode_operations umsdos_file_inode_operations_no_bmap;
+extern struct inode_operations umsdos_file_inode_operations_readpage;
 extern struct inode_operations umsdos_symlink_inode_operations;
 extern int init_umsdos_fs(void);
 
index ae3e60c2d7705dfabd1944acb46c010fbfd2e1e5..6f6441f7c946e6741f4008ac72f0afb14853e72d 100644 (file)
@@ -418,8 +418,7 @@ repeat:
                                if (ru != NULL)
                                        getrusage(p, RUSAGE_BOTH, ru);
                                if (stat_addr)
-                                       __put_user((p->exit_code << 8) | 0x7f,
-                                                  stat_addr);
+                                       __put_user((p->exit_code << 8) | 0x7f, stat_addr);
                                p->exit_code = 0;
                                retval = p->pid;
                                goto end_wait4;
index 6a75e8c97eb43c8b7939ef80563d73a3b3ed0291..920d41c7d1ae446dc789219d20faa6a0b4dd4fec 100644 (file)
@@ -435,12 +435,16 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
        return tmp;
 }
 
-void unregister_sysctl_table(struct ctl_table_header * table)
+/*
+ * Unlink and free a ctl_table.
+ */
+void unregister_sysctl_table(struct ctl_table_header * header)
 {
-       DLIST_DELETE(table, ctl_entry);
+       DLIST_DELETE(header, ctl_entry);
 #ifdef CONFIG_PROC_FS
-       unregister_proc_table(table->ctl_table, &proc_sys_root);
+       unregister_proc_table(header->ctl_table, &proc_sys_root);
 #endif
+       kfree(header);
 }
 
 /*
@@ -457,18 +461,20 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
        mode_t mode;
        
        for (; table->ctl_name; table++) {
-               de = 0;
                /* Can't do anything without a proc name. */
                if (!table->procname)
                        continue;
                /* Maybe we can't do anything with it... */
-               if (!table->proc_handler &&
-                   !table->child)
+               if (!table->proc_handler && !table->child) {
+                       printk(KERN_WARNING "SYSCTL: Can't register %s\n",
+                               table->procname);
                        continue;
+               }
 
                len = strlen(table->procname);
                mode = table->mode;
 
+               de = NULL;
                if (table->proc_handler)
                        mode |= S_IFREG;
                else {
@@ -495,6 +501,9 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
        }
 }
 
+/*
+ * Unregister a /proc sysctl table and any subdirectories.
+ */
 static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
 {
        struct proc_dir_entry *de;
@@ -512,8 +521,11 @@ static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root
                   entries... */
                if (!((de->mode & S_IFDIR) && de->subdir)) {
                        proc_unregister(root, de->low_ino);
+                       table->de = NULL;
                        kfree(de);
-               }
+               } else
+                       printk("unregister_proc_table: %s not empty!\n",
+                               table->procname);
        }
 }
 
index 30df2360d57b294694be57a19239405e4bc91492..fbc2171857bea73fc1802ba7a081b7c5b9d2b624 100644 (file)
@@ -868,6 +868,9 @@ __initfunc(static void ic_bootp_recv(void))
                        }
                }
        }
+
+       if (ic_gateway == INADDR_NONE && b->relay_ip)
+               ic_gateway = b->relay_ip;
 }
 
 #endif