]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.16pre5 2.2.16pre5
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:21 +0000 (15:21 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:21 +0000 (15:21 -0500)
o Work around the cmpci DMA buf bug (Alan Cox)
o Fix a couple of headers  (Andrew Morgan)
o 2.2 backport of Jeff's via audio code (Marcelo Tosatti)
o Fix the infamous 8K 3c590 stall bug (Anders Pedersen, Don Becker)
| Yay and it only took 3 years to find ;)
o ATAPI probe fix (Geert Van der Plas)
o Fix n_tty.c invalid copyuser (Andrew Morton)
o NLS init cleanups/config docs (Andrzej Krzysztofowicz)
o EEpro support for old ISA cards (Aristeu Filho)
o Export disk_name for other users (Alan Cox)
o Add blkdev.h to sparc64 ioctl32  (Fredrick Koehler)
o Handle thinkpad APM bios bugs (Stephen Rothwell
under threat from Rusty ;))
o FPU, CTC and other bug fixes for S/390 (IBM)
o Fix signal alt stack on exec (Bruno Haible)
o SCSI generic update (Doug Gilbert)
| Roman your sg race patch clashed - can you sort with Doug
o Add TIMEDIA cards to parport (Tim Waugh)

78 files changed:
Documentation/Configure.help
Makefile
arch/alpha/config.in
arch/arm/config.in
arch/i386/config.in
arch/i386/kernel/apm.c
arch/m68k/config.in
arch/mips/config.in
arch/ppc/config.in
arch/s390/config.in
arch/s390/kernel/ptrace.c
arch/s390/kernel/s390io.c
arch/s390/kernel/setup.c
arch/s390/kernel/traps.c
arch/sparc/config.in
arch/sparc64/config.in
arch/sparc64/kernel/ioctl32.c
drivers/block/ide-probe.c
drivers/block/ll_rw_blk.c
drivers/char/n_tty.c
drivers/misc/parport_pc.c
drivers/net/3c59x.c
drivers/net/eepro.c
drivers/pci/oldproc.c
drivers/s390/char/hwc_tty.c
drivers/s390/net/ctc.c
drivers/scsi/sg.c
drivers/sound/Makefile
drivers/sound/cmpci.c
drivers/sound/via82cxxx.c [deleted file]
drivers/sound/via82cxxx_audio.c [new file with mode: 0644]
fs/exec.c
fs/nls/nls_base.c
fs/nls/nls_cp437.c
fs/nls/nls_cp737.c
fs/nls/nls_cp775.c
fs/nls/nls_cp850.c
fs/nls/nls_cp852.c
fs/nls/nls_cp855.c
fs/nls/nls_cp857.c
fs/nls/nls_cp860.c
fs/nls/nls_cp861.c
fs/nls/nls_cp862.c
fs/nls/nls_cp863.c
fs/nls/nls_cp864.c
fs/nls/nls_cp865.c
fs/nls/nls_cp866.c
fs/nls/nls_cp869.c
fs/nls/nls_cp874.c
fs/nls/nls_cp932.c
fs/nls/nls_cp936.c
fs/nls/nls_cp949.c
fs/nls/nls_cp950.c
fs/nls/nls_iso8859-1.c
fs/nls/nls_iso8859-14.c
fs/nls/nls_iso8859-15.c
fs/nls/nls_iso8859-2.c
fs/nls/nls_iso8859-3.c
fs/nls/nls_iso8859-4.c
fs/nls/nls_iso8859-5.c
fs/nls/nls_iso8859-6.c
fs/nls/nls_iso8859-7.c
fs/nls/nls_iso8859-8.c
fs/nls/nls_iso8859-9.c
fs/nls/nls_koi8-r.c
fs/proc/array.c
include/asm-s390/irq.h
include/asm-s390/pgtable.h
include/asm-s390/ptrace.h
include/asm-s390/s390-regs-common.h
include/asm-s390/s390io.h
include/linux/capability.h
include/linux/nls.h
include/linux/pci.h
include/linux/timex.h
include/scsi/sg.h
kernel/ksyms.c
p_sg2136_sg2137 [new file with mode: 0644]

index 9710a8dfb60d58334381c669ab94afa7e5d8b039..780ba39ce2bae6edcbd788e3b30aa0b6e9e47798 100644 (file)
@@ -9305,14 +9305,6 @@ CONFIG_APM_DISPLAY_BLANK
   backlight at all, or it might print a lot of errors to the console,
   especially if you are using gpm.
 
-Ignore multiple suspend/standby events
-CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-  This option is necessary on the IBM Thinkpad 560, but should work on
-  all other laptops. When the APM BIOS returns multiple suspend or
-  standby events while one is already being processed they will be
-  ignored. Without this the Thinkpad 560 has troubles with the user
-  level daemon apmd, and with the PCMCIA package pcmcia-cs.
-
 Ignore multiple suspend/resume cycles
 CONFIG_APM_IGNORE_SUSPEND_BOUNCE
   This option is necessary on the Dell Inspiron 3200 and others, but
index b5cac6cd63a06b7994ed77af727e4d760b68823a..8f662659e7a5461dc4b986a3ec9d6a4a75802da6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 16
-EXTRAVERSION = pre4
+EXTRAVERSION = pre5
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index fdfab4aef937bd2f80c56eb3feb41d8d4d737ba2..72f8eb345c2f2a80fcfd6a4ad22e5db629d21126 100644 (file)
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Kernel configuration of Linux for Alpha machines"
 
index 467218db714ed13d12f2bbafaa051d9216c7b018..332239262d1be0d0819d28be549c7885fde9ecaf 100644 (file)
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux Kernel Configuration"
 
index 2e8a9bc5c58ed0cf6b1ae747fa6be89f472da58c..d903b40abb59326cd7a218e2e86b766fcd9990a7 100644 (file)
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux Kernel Configuration"
 
@@ -109,7 +109,6 @@ if [ "$CONFIG_APM" != "n" ]; then
   bool '   Enable PM at boot time' CONFIG_APM_DO_ENABLE
   bool '   Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
   bool '   Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
-  bool '   Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
   bool '   Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
   bool '   RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
   bool '   Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
index d161b93c0b66d89b7f74f27fb83abb7454709f21..6723c98f2a400aa6415a6f881c7890c5487fe9c7 100644 (file)
  *         Register the /proc/apm entry even on SMP so that
  *         scripts that check for it before doing power off
  *         work (Jim Avera <jima@hal.com>).
+ *   1.13: Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
+ *         is now the way life works). 
+ *         Fix thinko in suspend() (wrong return).
  *
  * APM 1.1 Reference:
  *
@@ -318,9 +321,7 @@ static int                  clock_slowed = 0;
 #endif
 static int                     suspends_pending = 0;
 static int                     standbys_pending = 0;
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 static int                     waiting_for_resume = 0;
-#endif
 
 #ifdef CONFIG_APM_RTC_IS_GMT
 #      define  clock_cmos_diff 0
@@ -343,7 +344,7 @@ static struct apm_user *    user_list = NULL;
 
 static struct timer_list       apm_timer;
 
-static char                    driver_version[] = "1.12";      /* no spaces */
+static char                    driver_version[] = "1.13";      /* no spaces */
 
 static char *  apm_event_name[] = {
        "system standby",
@@ -883,19 +884,19 @@ static void reinit_timer(void)
 static int suspend(void)
 {
        int             err;
-       int             ret;
        struct apm_user *as;
 
        get_time_diff();
        err = apm_set_power_state(APM_STATE_SUSPEND);
        reinit_timer();
        set_time();
-       ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
-       if (!ret)
+       if (err == APM_NO_ERROR)
+               err = APM_SUCCESS;
+       if (err != APM_SUCCESS)
                apm_error("suspend", err);
        for (as = user_list; as != NULL; as = as->next) {
                as->suspend_wait = 0;
-               as->suspend_result = (ret ? 0 : -EIO);
+               as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
        }
        wake_up_interruptible(&apm_suspend_waitqueue);
        return err;
@@ -975,14 +976,7 @@ static void check_events(void)
                switch (event) {
                case APM_SYS_STANDBY:
                case APM_USER_STANDBY:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-                       if (waiting_for_resume)
-                               break;
-#endif
                        if (send_event(event, APM_STANDBY_RESUME, NULL)) {
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-                               waiting_for_resume = 1;
-#endif
                                if (standbys_pending <= 0)
                                        standby();
                        }
@@ -999,14 +993,18 @@ static void check_events(void)
                        if (ignore_bounce)
                                break;
 #endif
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+                       /*
+                        * If we are already processing a SUSPEND,
+                        * then further SUSPEND events from the BIOS
+                        * will be ignored.  We also return here to
+                        * cope with the fact that the Thinkpads keep
+                        * sending a SUSPEND event until something else
+                        * happens!
+                        */
                        if (waiting_for_resume)
-                               break;
-#endif
+                               return;
                        if (send_event(event, APM_NORMAL_RESUME, NULL)) {
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
                                waiting_for_resume = 1;
-#endif
                                if (suspends_pending <= 0)
                                        (void) suspend();
                        }
@@ -1015,9 +1013,7 @@ static void check_events(void)
                case APM_NORMAL_RESUME:
                case APM_CRITICAL_RESUME:
                case APM_STANDBY_RESUME:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
                        waiting_for_resume = 0;
-#endif
 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
                        last_resume = jiffies;
                        ignore_bounce = 1;
@@ -1049,8 +1045,10 @@ static void apm_event_handler(unsigned long unused)
        int             err;
 
        if ((standbys_pending > 0) || (suspends_pending > 0)) {
-               if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) {
+               if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
                        pending_count = 4;
+                       if (debug)
+                               printk(KERN_DEBUG "apm: setting state busy\n");
                        err = apm_set_power_state(APM_STATE_BUSY);
                        if (err)
                                apm_error("busy", err);
@@ -1066,7 +1064,7 @@ static void apm_event_handler(unsigned long unused)
 static int check_apm_user(struct apm_user *as, const char *func)
 {
        if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-               printk(KERN_ERR "apm: %s passed bad filp", func);
+               printk(KERN_ERR "apm: %s passed bad filp\n", func);
                return 1;
        }
        return 0;
@@ -1169,7 +1167,7 @@ static int do_ioctl(struct inode * inode, struct file *filp,
                } else if (!send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as))
                        return -EAGAIN;
                if (suspends_pending <= 0) {
-                       if (!suspend())
+                       if (suspend() != APM_SUCCESS)
                                return -EIO;
                } else {
                        as->suspend_wait = 1;
@@ -1220,7 +1218,7 @@ static int do_release(struct inode * inode, struct file * filp)
                     as1 = as1->next)
                        ;
                if (as1 == NULL)
-                       printk(KERN_ERR "apm: filp not in user list");
+                       printk(KERN_ERR "apm: filp not in user list\n");
                else
                        as1->next = as->next;
        }
@@ -1234,7 +1232,7 @@ static int do_open(struct inode * inode, struct file * filp)
 
        as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
        if (as == NULL) {
-               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
+               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
                       sizeof(*as));
                return -ENOMEM;
        }
index a8dacc904c557bf33d097ea58b78f5dea43d5d4b..4207efcdb33bc51142092ba0d00be4f1336e1a11 100644 (file)
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux/68k Kernel Configuration"
 
index aa1aba32f0252c0b2591a72a8aaf94ea30f7b6cd..b4c92b40b84a6863c49ad9826fb73734da4f8f98 100644 (file)
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux Kernel Configuration"
 
index f653a4e7edb49859f85cdafd8f8a4cd1350e7d65..97cf3a68d20094716a5a8804d1748f13cef23e94 100644 (file)
@@ -1,6 +1,6 @@
 # $Id: config.in,v 1.92.2.4 1999/09/10 01:23:40 paulus Exp $
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
index cf6f4e937fb7b06719d267b272f2b84e85865b7c..b6c5787f0bd76734a781e29e1276ecb017616807 100644 (file)
@@ -1,6 +1,6 @@
-
+#
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux Kernel Configuration"
 define_bool CONFIG_ARCH_S390 y
index 0938e5c0c482dbe15477b66d7e5629c9f1d1b066..896631756bd3d8cc56d1453547521ca45b0c1387 100644 (file)
@@ -474,6 +474,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        }
        ret = -ESRCH;
        // printk("child=%lX child->flags=%lX",child,child->flags);
+       /* I added child!=current line so we can get the */
+       /* ieee_instruction_pointer from the user structure DJB */
+       if(child!=current)
+       {
        if (!(child->flags & PF_PTRACED))
                goto out;
        if (child->state != TASK_STOPPED) 
@@ -483,7 +487,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        }
        if (child->p_pptr != current)
                goto out;
-
+       }
        switch (request) 
        {
                /* If I and D space are separate, these will need to be fixed. */
index 87facae69714f6f271cd5c66535bd7bde1ba748e..e80b1d05465da6b71ed2bfddfc9a29329fc785d6 100644 (file)
@@ -437,8 +437,17 @@ static int enable_subchannel( unsigned int irq)
       else
       {
                        ioinfo[irq]->schib.pmcw.ena = 1;
+
+                       if ( irq == cons_dev )
+                       {
+                               ioinfo[irq]->schib.pmcw.isc = 7;
+                       }
+                       else    
+                       {
                        ioinfo[irq]->schib.pmcw.isc = 3;
 
+                       } /* endif */
+
          do
          {
                                ccode = msch( irq, &(ioinfo[irq]->schib) );
@@ -776,7 +785,7 @@ int s390_start_IO( int            irq,      /* IRQ */
        ioinfo[irq]->orb.fmt     = 1;
 
        ioinfo[irq]->orb.pfch = !(flag & DOIO_DENY_PREFETCH);
-       ioinfo[irq]->orb.spnd =  (flag & DOIO_ALLOW_SUSPEND);
+       ioinfo[irq]->orb.spnd =  (flag & DOIO_ALLOW_SUSPEND ? TRUE : FALSE);
        ioinfo[irq]->orb.ssic =  (    (flag & DOIO_ALLOW_SUSPEND )
                                  && (flag & DOIO_SUPPRESS_INTER) );
 
@@ -2092,7 +2101,7 @@ int s390_process_IRQ( unsigned int irq )
        ccode = tsch( irq, &(ioinfo[irq]->devstat.ii.irb) );
 
        //
-       // We must only accumulate the status if initiated by do_IO() or halt_IO()
+       // We must only accumulate the status if the device is busy already
        //
        if ( ioinfo[irq]->ui.flags.busy )
                                {
@@ -2130,9 +2139,11 @@ int s390_process_IRQ( unsigned int irq )
         * Save residual count and CCW information in case primary and
         *  secondary status are presented with different interrupts.
                         */
-       if ( ioinfo[irq]->devstat.ii.irb.scsw.stctl & SCSW_STCTL_PRIM_STATUS )
+       if ( ioinfo[irq]->devstat.ii.irb.scsw.stctl
+                  & (   SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_INTER_STATUS ) )
                        {
                ioinfo[irq]->devstat.rescnt = ioinfo[irq]->devstat.ii.irb.scsw.count;
+               ioinfo[irq]->devstat.cpa    = ioinfo[irq]->devstat.ii.irb.scsw.cpa;
 
 #ifdef CONFIG_DEBUG_IO
       if ( irq != cons_dev )
@@ -2140,11 +2151,6 @@ int s390_process_IRQ( unsigned int irq )
                  "residual count from irb after tsch() %d\n",
                  irq, ioinfo[irq]->devstat.rescnt );
 #endif
-       } /* endif */
-
-       if ( ioinfo[irq]->devstat.ii.irb.scsw.cpa != 0 )
-       {
-               ioinfo[irq]->devstat.cpa = ioinfo[irq]->devstat.ii.irb.scsw.cpa;
 
        } /* endif */
 
@@ -2305,7 +2311,7 @@ int s390_process_IRQ( unsigned int irq )
                                        sizeof( devstat_t) );
 
                                s_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
-                               s_ccw->cda      = (char *)virt_to_phys( ioinfo[irq]->devstat.ii.sense.data);
+                               s_ccw->cda      = (char *)virt_to_phys( ioinfo[irq]->sense_data);
                                s_ccw->count    = SENSE_MAX_COUNT;
                                s_ccw->flags    = CCW_FLAG_SLI;
 
@@ -2373,7 +2379,7 @@ int s390_process_IRQ( unsigned int irq )
                 * we allow for the device action handler if .
                 *  - we received ending status
                 *  - the action handler requested to see all interrupts
-                *  - we received a PCI
+                *  - we received an intermediate status
                 *  - fast notification was requested (primary status)
                 *  - unsollicited interrupts
                 *
@@ -2382,7 +2388,7 @@ int s390_process_IRQ( unsigned int irq )
                {
                        allow4handler =    ending_status
                           || ( ioinfo[irq]->ui.flags.repall                                      )
-                          || ( ioinfo[irq]->devstat.ii.irb.scsw.cstat & SCHN_STAT_PCI            )
+                          || ( stctl & SCSW_STCTL_INTER_STATUS                                   )
                                || ( (ioinfo[irq]->ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) )
                                || ( ioinfo[irq]->ui.flags.oper == 0                                   );
 
@@ -2421,7 +2427,7 @@ int s390_process_IRQ( unsigned int irq )
                                if ( sense_count >= 0 )
                                {
                                        memcpy( ((devstat_t *)(action->dev_id))->ii.sense.data,
-                                               &(ioinfo[irq]->devstat.ii.sense.data),
+                                               &(ioinfo[irq]->sense_data),
                                                sense_count);
                                }
                                else
@@ -2557,13 +2563,31 @@ int s390_process_IRQ( unsigned int irq )
                        {
                                ioinfo[irq]->ui.flags.w4final = 1;
 
+                               /*
+                                * Eventually reset subchannel PCI status and
+                                *  set the PCI or SUSPENDED flag in the user
+                                *  device status block if appropriate.
+                                */
+                               if ( ioinfo[irq]->devstat.cstat & SCHN_STAT_PCI )
+                               {
+                                       ((devstat_t *)(action->dev_id))->flag |= DEVSTAT_PCI;
+                                       ioinfo[irq]->devstat.cstat &= ~SCHN_STAT_PCI;
+                               }
+                               else if ( actl & SCSW_ACTL_SUSPENDED )
+                               {
+                                       ((devstat_t *)(action->dev_id))->flag |= DEVSTAT_SUSPENDED;
+
+                               } /* endif */
+
                                if ( ioinfo[irq]->ui.flags.newreq )
                                {
                                        action->handler( irq, ioinfo[irq]->u_intparm );
                                }
                                else
                                {
-                                       ((io_handler_func1_t)action->handler)( irq, action->dev_id, &regs );
+                                       ((io_handler_func1_t)action->handler)( irq,
+                                                                              action->dev_id,
+                                                                              &regs );
 
                                } /* endif */
 
@@ -4549,7 +4573,7 @@ int s390_SenseID( int irq, senseid_t *sid, __u8 lpm )
                                                                        ioinfo[irq]->schib.pmcw.dev,
                                                                        irq);
 #endif
-                                                               io_retry = 0;
+                                                               io_retry = 1;
                }
 #ifdef CONFIG_DEBUG_IO
                else
@@ -4579,7 +4603,7 @@ int s390_SenseID( int irq, senseid_t *sid, __u8 lpm )
 #endif
        }
                                                else if (    ( pdevstat->flag & DEVSTAT_NOT_OPER )
-                                                    || ( irq_ret        != -ENODEV         ) )
+                                                    || ( irq_ret        == -ENODEV         ) )
        {
 #ifdef CONFIG_DEBUG_IO
                                                        printk( "SenseID : path %02X for "
index 2a0952be41b2cf06e64e6b334c76cbf846a02cb2..2fecb21e1308b711201d66afae15b44bdb2987e4 100644 (file)
@@ -211,6 +211,13 @@ __initfunc(void setup_arch(char **cmdline_p,
 #endif
         memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
        memory_end = MEMORY_SIZE;
+        /*
+         * We need some free virtual space to be able to do vmalloc.
+         * On a machine with 2GB memory we make sure that we have at
+         * least 128 MB free space for vmalloc.
+         */
+        if (memory_end > 1920*1024*1024)
+                memory_end = 1920*1024*1024;
         init_task.mm->start_code = PAGE_OFFSET;
         init_task.mm->end_code = (unsigned long) &_etext;
         init_task.mm->end_data = (unsigned long) &_edata;
index a2127494aa2aefd4322e281175a75d007ae6dfa8..3afac79365f4c19c182b3a72f990eb50257eaf09 100644 (file)
@@ -359,8 +359,23 @@ asmlinkage void data_exception(struct pt_regs * regs, long error_code)
        int do_sig = 0;
 
         lock_kernel();
-        if (regs->psw.mask & 0x00010000L) {
                location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+       if(MACHINE_HAS_IEEE)
+       {
+               __asm__ volatile ("stfpc %0\n\t" 
+                                 : "=m" (current->tss.fp_regs.fpc));
+               
+       }
+       /* Same code should work when we implement fpu emulation */
+       /* provided we call data exception from the fpu emulator */
+       if(current->tss.fp_regs.fpc&FPC_DXC_MASK)
+       {
+               current->tss.ieee_instruction_pointer=
+                       (addr_t)ADDR_BITS_REMOVE((addr_t)location);
+               force_sig(SIGFPE, current);
+       }
+        else if ((regs->psw.mask & 0x00010000L)) 
+       {
                get_user(*((__u16 *) opcode), location);
                switch (opcode[0]) {
                case 0x28: /* LDR Rx,Ry   */
@@ -411,7 +426,8 @@ asmlinkage void data_exception(struct pt_regs * regs, long error_code)
                        do_sig = 1;
                        break;
                 }
-        } else
+        } 
+       else
                do_sig = 1;
        if (do_sig) {
                 if (check_for_fixup(regs) == 0) {
index a34e80ebec27bffe929c8af8a0d83142a609ce5e..f58277be09e18d7536936437a0feacf895c3bb05 100644 (file)
@@ -1,6 +1,6 @@
 # $Id: config.in,v 1.68.2.1 1999/09/22 11:37:34 jj Exp $
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux/SPARC Kernel Configuration"
 
index f666634046aa11782f06a4426a03028706685f09..5036f3dac5450ac7a0e90826991cea19c7b60de5 100644 (file)
@@ -1,6 +1,6 @@
 # $Id: config.in,v 1.67.2.5 1999/10/19 16:49:37 davem Exp $
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/config-language.txt.
 #
 mainmenu_name "Linux/UltraSPARC Kernel Configuration"
 
index c29edba0fe97c2547874e44120853c0b821c0073..13110a0e57e20ba9f160b8201aba73e64fc5a1cf 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/videodev.h>
 #include <linux/netdevice.h>
 #include <linux/smb_fs.h>
+#include <linux/blkdev.h>
 
 #include <scsi/scsi.h>
 /* Ugly hack. */
index 243ba23a78586eb4c34fd56f1690da951ce9da05..0af96fedb80078d947b31b0c044e9dde7bb8bca4 100644 (file)
@@ -191,6 +191,10 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
        } else
                hd_status = IDE_ALTSTATUS_REG;  /* use non-intrusive polling */
 
+       /* set features register for atapi identify command */
+       if((cmd == WIN_PIDENTIFY))
+               OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap mode */
+
 #if CONFIG_BLK_DEV_PDC4030
        if (IS_PDC4030_DRIVE) {
                extern int pdc4030_cmd(ide_drive_t *, byte);
index a60dc9dffa7c5f1d1b8181cc8be9b0d39727434c..f918e56ea4167043da78f8724ff9c304316f8c37 100644 (file)
@@ -359,6 +359,7 @@ int blkelv_ioctl(kdev_t dev, unsigned long cmd, unsigned long arg)
        case BLKELVSET:
                return blkelvset_ioctl(elevator, __arg);
        }
+       return -EINVAL;
 }
 
 static inline int seek_to_not_starving_chunk(struct request ** req, int * lat)
index 80763b17f7e068dc9d7a22dc2d7e72c8d7158cb9..416b0604c588f55d488f375125c117fa69de4f3c 100644 (file)
@@ -228,9 +228,9 @@ static ssize_t opost_block(struct tty_struct * tty,
                nr = space;
        if (nr > sizeof(buf))
            nr = sizeof(buf);
-       nr -= copy_from_user(buf, inbuf, nr);
-       if (!nr)
-               return 0;
+
+       if (copy_from_user(buf, inbuf, nr))
+               return -EFAULT;
        
        for (i = 0, cp = buf; i < nr; i++, cp++) {
                switch (*cp) {
index 82af953522e67df4e6969dc1cf4efe961ee7348c..71fffaffd2cc660a08c01fb37d67c39d818cfeba 100644 (file)
@@ -906,6 +906,8 @@ static int parport_pc_init_pci (int irq, int dma)
                  { { 0, 1 }, } },
                { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, 1,
                  { { 2, -1 }, } },
+               { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_4008A, 1,
+                 { { 0, 1 }, } },
                { 0, }
        };
 
index 1f4ea7b3a2069dfb1cd7f1b3e11c49ae72bf69c6..58ea3207097a16f9a37cb1eb1f60adefe0f5c511 100644 (file)
@@ -1394,8 +1394,10 @@ static void vortex_tx_timeout(struct device *dev)
                }
                outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
                outw(DownUnstall, ioaddr + EL3_CMD);
-       } else
+       } else {
                vp->stats.tx_dropped++;
+               clear_bit(0, (void *)&dev->tbusy);
+       }
        
        /* Issue Tx Enable */
        outw(TxEnable, ioaddr + EL3_CMD);
index 02ea165f3ce85e3a15b383d70ffd85e482098bb7..22c74f93be633ce4ffefe0fa07f0e896ad9ba8cd 100644 (file)
@@ -23,6 +23,8 @@
        This is a compatibility hardware problem.
 
        Versions:
+       0.12a   fixed bug that would make impossible have ee10 boards and
+               other previous supported boards. (aris, 05/19/2000)
        0.12    added support to 82595FX etherexpress 10 based cards
                 (aris <aris@conectiva.com.br>), 04/26/2000)
        0.11e   some tweaks about multiple cards support (PdP, jul/aug 1999)
@@ -95,7 +97,7 @@
 */
 
 static const char *version =
-       "eepro.c: v0.12 04/26/2000 aris@conectiva.com.br\n";
+       "eepro.c: v0.12a 04/26/2000 aris@conectiva.com.br\n";
 
 #include <linux/module.h>
 
@@ -142,11 +144,6 @@ static const char *version =
 #include <linux/skbuff.h>
 
 
-/* need to remove these asap      */
-/* 2.1.xx compatibility macros... */
-/*                                */
-
-
 #include <linux/version.h>
 
 /* For linux 2.1.xx */
@@ -178,20 +175,10 @@ static const char *version =
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int eepro_portlist[] compat_init_data =
-#ifdef PnPWakeup
-   { 0x210, 0x300,
-#else
-   { 0x300, 0x210, 
-#endif
-   0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
+       { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
 /* note: 0x300 is default, the 595FX supports ALL IO Ports 
   from 0x000 to 0x3F0, some of which are reserved in PCs */
 
-/* To try the (not-really PnP Wakeup: */
-/*
-#define PnPWakeup
-*/
-
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
 #define NET_DEBUG 0
@@ -205,9 +192,7 @@ static unsigned int net_debug = NET_DEBUG;
 #define        LAN595          0
 #define        LAN595TX        1
 #define        LAN595FX        2
-
-/* global to recall the read_eepro */
-static unsigned char etherexpress10 = 0;
+#define        LAN595FX_10ISA  3
 
 /* Information that need to be kept for each board. */
 struct eepro_local {
@@ -222,9 +207,7 @@ struct eepro_local {
        int version;    /* a flag to indicate if this is a TX or FX
                                   version of the 82595 chip. */
        int stepping;
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
        spinlock_t lock; /* Serializing lock  */ 
-#endif
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
@@ -326,7 +309,7 @@ static int  eepro_close(struct device *dev);
 static struct enet_statistics *eepro_get_stats(struct device *dev);
 static void     set_multicast_list(struct device *dev);
 
-static int read_eeprom(int ioaddr, int location);
+static int read_eeprom(int ioaddr, int location, struct device *dev);
 static void hardware_send_packet(struct device *dev, void *buf, short length);
 static int     eepro_grab_irq(struct device *dev);
 
@@ -486,6 +469,59 @@ static unsigned eeprom_reg = EEPROM_REG_PRO;
 #define EEDI 0x04
 #define EEDO 0x08
 
+/* do a full reset */
+#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr)
+
+/* do a nice reset */
+#define eepro_sel_reset(ioaddr)        { \
+                                       outb(SEL_RESET_CMD, ioaddr); \
+                                       SLOW_DOWN; \
+                                       SLOW_DOWN; \
+                                       }
+
+/* disable all interrupts */
+#define eepro_dis_int(ioaddr) outb(ALL_MASK, ioaddr + INT_MASK_REG)
+
+/* clear all interrupts */
+#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG)
+
+/* enable tx/rx */
+#define eepro_en_int(ioaddr) outb(ALL_MASK & ~(RX_MASK | TX_MASK), \
+                                                       ioaddr + INT_MASK_REG)
+
+/* enable exec event interrupt */
+#define eepro_en_intexec(ioaddr) outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG)
+
+/* enable rx */
+#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr)
+
+/* disable rx */
+#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr)
+
+/* switch bank */
+#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr)
+#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr)
+#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr)
+
+/* enable interrupt line */
+#define eepro_en_intline(ioaddr) outb(inb(ioaddr + REG1) | INT_ENABLE,\
+                               ioaddr + REG1)
+
+/* disable interrupt line */
+#define eepro_dis_intline(ioaddr) outb(inb(ioaddr + REG1) & 0x7f, \
+                               ioaddr + REG1);
+
+/* set diagnose flag */
+#define eepro_diag(ioaddr) outb(DIAGNOSE_CMD, ioaddr)
+
+/* ack for rx/tx int */
+#define eepro_ack_rxtx(ioaddr) outb (RX_INT | TX_INT, ioaddr + STATUS_REG)
+
+/* ack for rx int */
+#define eepro_ack_rx(ioaddr) outb (RX_INT, ioaddr + STATUS_REG)
+
+/* ack for tx int */
+#define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG)
 
 /* Check for a network adaptor of this type, and return '0' if one exists.
    If dev->base_addr == 0, probe all likely locations.
@@ -503,44 +539,12 @@ compat_init_func(int eepro_probe(struct device *dev))
 {
        int i;
        int base_addr = dev ? dev->base_addr : 0;
-
-
-#ifdef PnPWakeup
-       /* XXXX for multiple cards should this only be run once? */
-       
-       /* Wakeup: */
-       #define WakeupPort 0x279
-       #define WakeupSeq    {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
-                             0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
-                             0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
-                             0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
-
-       {
-               unsigned short int WS[32]=WakeupSeq;
-
-               if (check_region(WakeupPort, 2)==0) {
-
-                       if (net_debug>5)
-                               printk(KERN_DEBUG "Waking UP\n");
-
-                       outb_p(0,WakeupPort);
-                       outb_p(0,WakeupPort);
-                       for (i=0; i<32; i++) {
-                               outb_p(WS[i],WakeupPort);
-                               if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
-                       }
-               } else printk(KERN_WARNING "Checkregion Failed!\n");
-       }
-#endif
-
-
        if (base_addr > 0x1ff)          /* Check a single specified location. */
                return eepro_probe1(dev, base_addr);
 
        else if (base_addr != 0)        /* Don't probe at all. */
                return ENXIO;
 
-
        for (i = 0; eepro_portlist[i]; i++) {
                int ioaddr = eepro_portlist[i];
 
@@ -549,21 +553,21 @@ compat_init_func(int eepro_probe(struct device *dev))
                if (eepro_probe1(dev, ioaddr) == 0)
                        return 0;
        }
-
+       
        return ENODEV;
 }
 #endif
 
-static void printEEPROMInfo(short ioaddr)
+static void printEEPROMInfo(short ioaddr, struct device *dev)
 {
        unsigned short Word;
        int i,j;
 
        for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
-               j+=read_eeprom(ioaddr,i);
+               j+=read_eeprom(ioaddr,i,dev);
        printk("Checksum: %#x\n",j&0xffff);
 
-       Word=read_eeprom(ioaddr, 0);
+       Word=read_eeprom(ioaddr, 0, dev);
        printk(KERN_DEBUG "Word0:\n");
        printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
        printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
@@ -571,7 +575,7 @@ static void printEEPROMInfo(short ioaddr)
        printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
 
        if (net_debug>4)  {
-               Word=read_eeprom(ioaddr, 1);
+               Word=read_eeprom(ioaddr, 1, dev);
                printk(KERN_DEBUG "Word1:\n");
                printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
                printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
@@ -582,7 +586,7 @@ static void printEEPROMInfo(short ioaddr)
                printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
        }
 
-       Word=read_eeprom(ioaddr, 5);
+       Word=read_eeprom(ioaddr, 5, dev);
        printk(KERN_DEBUG "Word5:\n");
        printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
        printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
@@ -592,12 +596,12 @@ static void printEEPROMInfo(short ioaddr)
        if (GetBit(Word,ee_PortAUI)) printk("AUI ");
        printk("port(s) \n");
 
-       Word=read_eeprom(ioaddr, 6);
+       Word=read_eeprom(ioaddr, 6, dev);
        printk(KERN_DEBUG "Word6:\n");
        printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
        printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
 
-       Word=read_eeprom(ioaddr, 7);
+       Word=read_eeprom(ioaddr, 7, dev);
        printk(KERN_DEBUG "Word7:\n");
        printk(KERN_DEBUG " INT to IRQ:\n");
 
@@ -617,7 +621,8 @@ int eepro_probe1(struct device *dev, short ioaddr)
 {
        unsigned short station_addr[6], id, counter;
        int i,j, irqMask;
-       int eepro;
+       int eepro = 0;
+       struct eepro_local *lp;
        const char *ifmap[] = {"AUI", "10Base2", "10BaseT"};
        enum iftype { AUI=0, BNC=1, TPE=2 };
 
@@ -631,7 +636,6 @@ int eepro_probe1(struct device *dev, short ioaddr)
                /* We seem to have the 82595 signature, let's
                   play with its counter (last 2 bits of
                   register 2 of bank 0) to be sure. */
-
                counter = (id & R_ROBIN_BITS);  
                if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == 
                        (counter + 0x40)) {
@@ -640,43 +644,47 @@ int eepro_probe1(struct device *dev, short ioaddr)
                        printk(KERN_DEBUG " id: %#x ",id);
                        printk(" io: %#x ",ioaddr);
 
+                       /* Initialize the device structure */
+                       dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
+                       if (dev->priv == NULL)
+                               return -ENOMEM;
+                       memset(dev->priv, 0, sizeof(struct eepro_local));
+
+                       lp = (struct eepro_local *)dev->priv;
+
                        /* Now, get the ethernet hardware address from
                           the EEPROM */
 
-                       station_addr[0] = read_eeprom(ioaddr, 2);
+                       station_addr[0] = read_eeprom(ioaddr, 2, dev);
 
                        /* FIXME - find another way to know that we've found
                         * a Etherexpress 10
                         */
                        if (station_addr[0] == 0x0000 ||
                            station_addr[0] == 0xffff) {
-                               etherexpress10 = 1;
+                               eepro = 3;
+                               lp->eepro = LAN595FX_10ISA;
                                eeprom_reg = EEPROM_REG_10;
                                rcv_start = RCV_START_10;
                                xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
                                xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
 
-                               station_addr[0] = read_eeprom(ioaddr, 2);
+                               station_addr[0] = read_eeprom(ioaddr, 2, dev);
                        }
                        
-                       station_addr[1] = read_eeprom(ioaddr, 3);
-                       station_addr[2] = read_eeprom(ioaddr, 4);
+                       station_addr[1] = read_eeprom(ioaddr, 3, dev);
+                       station_addr[2] = read_eeprom(ioaddr, 4, dev);
 
-                       /* Check the station address for the manufacturer's code */
-                       if (net_debug>3)
-                               printEEPROMInfo(ioaddr);
 
-                       if (etherexpress10) {
-                               eepro = 2;
+                       if (eepro) {
                                printk("%s: Intel EtherExpress 10 ISA\n at %#x,",
                                        dev->name, ioaddr);
-                       } else if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) {
+                       } else if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ) {
                                                 /* int to IRQ Mask */
                                eepro = 2;
                                printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 
                                        dev->name, ioaddr);
-                       } else
-                       if (station_addr[2] == 0x00aa)  {
+                       } else if (station_addr[2] == SA_ADDR1)  {
                                eepro = 1;
                                printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
                                        dev->name, ioaddr);
@@ -694,7 +702,7 @@ int eepro_probe1(struct device *dev, short ioaddr)
                                dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
                                printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
                        }
-                       
+
                        dev->mem_start = (RCV_LOWER_LIMIT << 8);
 
                        if ((dev->mem_end & 0x3f) < 3 ||        /* RX buffer must be more than 3K */
@@ -716,7 +724,7 @@ int eepro_probe1(struct device *dev, short ioaddr)
                                                                
                        /* ............... */
 
-                       if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE))
+                       if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
                                dev->if_port = BNC;
                        else dev->if_port = TPE;
 
@@ -724,8 +732,8 @@ int eepro_probe1(struct device *dev, short ioaddr)
 
 
                        if ((dev->irq < 2) && (eepro!=0)) {
-                               i = read_eeprom(ioaddr, 1);
-                               irqMask = read_eeprom(ioaddr, 7);
+                               i = read_eeprom(ioaddr, 1, dev);
+                               irqMask = read_eeprom(ioaddr, 7, dev);
                                i &= 0x07; /* Mask off INT number */
                                
                                for (j=0; ((j<16) && (i>=0)); j++) {
@@ -737,7 +745,7 @@ int eepro_probe1(struct device *dev, short ioaddr)
                                                i--; /* count bits set in irqMask */
                                        }
                                }
-                               if (dev -> irq<2) {
+                               if (dev->irq < 2) {
                                        printk(" Duh! illegal interrupt vector stored in EEPROM.\n");
                                                return ENODEV;
                                } else 
@@ -753,7 +761,7 @@ int eepro_probe1(struct device *dev, short ioaddr)
                        else printk(", %s.\n", ifmap[dev->if_port]);
                        
                        if (net_debug > 3) {
-                               i = read_eeprom(ioaddr, 5);
+                               i = read_eeprom(ioaddr, 5, dev);
                                if (i & 0x2000) /* bit 13 of EEPROM word 5 */
                                        printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
                                                dev->name);
@@ -765,15 +773,7 @@ int eepro_probe1(struct device *dev, short ioaddr)
                        /* Grab the region so we can find another board if autoIRQ fails. */
                        request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
 
-                       /* Initialize the device structure */
-                       dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
-                       if (dev->priv == NULL)
-                               return -ENOMEM;
-                       memset(dev->priv, 0, sizeof(struct eepro_local));
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
                        spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
-#endif
                        dev->open               = eepro_open;
                        dev->stop               = eepro_close;
                        dev->hard_start_xmit    = eepro_send_packet;
@@ -785,7 +785,12 @@ int eepro_probe1(struct device *dev, short ioaddr)
 
                        ether_setup(dev);
 
-                       outb(RESET_CMD, ioaddr); /* RESET the 82595 */
+                       /* Check the station address for the manufacturer's code */
+                       if (net_debug>3)
+                               printEEPROMInfo(ioaddr, dev);
+
+                       /* reset 82595 */
+                       eepro_reset(ioaddr);
 
                        return 0;
                        }
@@ -811,55 +816,52 @@ static int        eepro_grab_irq(struct device *dev)
        int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 };
        int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
        
-       outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
+       eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
 
        /* Enable the interrupt line. */
-       temp_reg = inb(ioaddr + REG1);
-       outb(temp_reg | INT_ENABLE, ioaddr + REG1);
+       eepro_en_intline(ioaddr);
        
-       outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
+       eepro_sw2bank0(ioaddr); /* be CAREFUL, BANK 0 now */
 
        /* clear all interrupts */
-       outb(ALL_MASK, ioaddr + STATUS_REG);
+       eepro_clear_int(ioaddr);
 
        /* Let EXEC event to interrupt */
-       outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG);
+       eepro_en_intexec(ioaddr);
 
        do {
-               outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
-
+               eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
                temp_reg = inb(ioaddr + INT_NO_REG);
                outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG);
 
-               outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
+               eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
 
                if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) {
                        /* Twinkle the interrupt, and check if it's seen */
                        autoirq_setup(0);
 
-                       outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
+                       eepro_diag(ioaddr); /* RESET the 82595 */
                                
                        if (*irqp == autoirq_report(2))  /* It's a good IRQ line */
                                break;
 
                        /* clear all interrupts */
-                       outb(ALL_MASK, ioaddr + STATUS_REG); 
+                       eepro_clear_int(ioaddr);
                }
        } while (*++irqp);
 
-       outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */
+       eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */
 
        /* Disable the physical interrupt line. */
-       temp_reg = inb(ioaddr + REG1);
-       outb(temp_reg & 0x7f, ioaddr + REG1); 
+       eepro_dis_intline(ioaddr);
 
-       outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
+       eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
 
        /* Mask all the interrupts. */
-       outb(ALL_MASK, ioaddr + INT_MASK_REG); 
+       eepro_dis_int(ioaddr);
 
        /* clear all interrupts */
-       outb(ALL_MASK, ioaddr + STATUS_REG); 
+       eepro_clear_int(ioaddr);
 
        return dev->irq;
 }
@@ -875,7 +877,12 @@ static int eepro_open(struct device *dev)
        if (net_debug > 3)
                printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
 
-       if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */
+       irqMask = read_eeprom(ioaddr,7,dev);
+
+       if (lp->eepro == LAN595FX_10ISA) {
+               if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n"); 
+       }
+       else if (irqMask == ee_FX_INT2IRQ) /* INT to IRQ Mask */
                {
                        lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
                        if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); 
@@ -913,18 +920,19 @@ static int eepro_open(struct device *dev)
 
        /* Initialize the 82595. */
 
-       outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
+       eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
        temp_reg = inb(ioaddr + eeprom_reg);
 
        lp->stepping = temp_reg >> 5;   /* Get the stepping number of the 595 */
-       
+       /* Get the stepping number of the 595 */
+
        if (net_debug > 3)
                printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping);
 
        if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
                outb(temp_reg & 0xef, ioaddr + eeprom_reg);
-       for (i=0; i < 6; i++)
-               outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); 
+       for (i=0; i < 6; i++) /* Fill the mac address */
+               outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i);
                        
        temp_reg = inb(ioaddr + REG1);    /* Setup Transmit Chaining */
        outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */
@@ -937,17 +945,16 @@ static int eepro_open(struct device *dev)
        outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */
 
        /* Set the receiving mode */
-       outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
+       eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
 
        /* Set the interrupt vector */  
        temp_reg = inb(ioaddr + INT_NO_REG);
-       if (lp->eepro == 2)
+       if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA)
                outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);
        else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); 
 
-
        temp_reg = inb(ioaddr + INT_NO_REG);
-       if (lp->eepro == 2)
+       if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA)
                outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
        else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
 
@@ -962,16 +969,15 @@ static int eepro_open(struct device *dev)
        outb(XMT_UPPER_LIMIT, ioaddr + xmt_upper_limit_reg); 
 
        /* Enable the interrupt line. */
-       temp_reg = inb(ioaddr + REG1);
-       outb(temp_reg | INT_ENABLE, ioaddr + REG1); 
+       eepro_en_intline(ioaddr);
 
-       outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
+       eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
 
        /* Let RX and TX events to interrupt */
-       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+       eepro_en_int(ioaddr);
 
        /* clear all interrupts */
-       outb(ALL_MASK, ioaddr + STATUS_REG); 
+       eepro_clear_int(ioaddr);
 
        /* Initialize RCV */
        outw((RCV_LOWER_LIMIT << 8), ioaddr + RCV_BAR); 
@@ -994,8 +1000,6 @@ static int eepro_open(struct device *dev)
                lp->version = LAN595TX;
                outb(old8, ioaddr + 8);
                old9 = inb(ioaddr + 9);
-               /*outb(~old9, ioaddr + 9);
-               if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) {*/
                
                if (irqMask==ee_FX_INT2IRQ) {
                        enum iftype { AUI=0, BNC=1, TPE=2 };
@@ -1009,12 +1013,12 @@ static int eepro_open(struct device *dev)
                        if (dev->if_port != TPE) {      /* Hopefully, this will fix the
                                                        problem of using Pentiums and
                                                        pro/10 w/ BNC. */
-                               outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
+                               eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
                                temp_reg = inb(ioaddr + REG13);
                                /* disable the full duplex mode since it is not
                                applicable with the 10Base2 cable. */
                                outb(temp_reg & ~(FDX | A_N_ENABLE), REG13);
-                               outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
+                               eepro_sw2bank0(ioaddr); /* be CAREFUL, BANK 0 now */
                        }
                }
                else if (net_debug > 3) {
@@ -1023,11 +1027,7 @@ static int eepro_open(struct device *dev)
                }
        }
        
-       outb(SEL_RESET_CMD, ioaddr);
-
-       /* We are supposed to wait for 2 us after a SEL_RESET */
-       SLOW_DOWN;
-       SLOW_DOWN;
+       eepro_sel_reset(ioaddr);
 
        lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8);
        lp->tx_last = 0;
@@ -1039,7 +1039,8 @@ static int eepro_open(struct device *dev)
        if (net_debug > 3)
                printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
 
-       outb(RCV_ENABLE_CMD, ioaddr);
+       /* enabling rx */
+       eepro_en_rx(ioaddr);
 
        MOD_INC_USE_COUNT;
        return 0;
@@ -1050,23 +1051,22 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        int ioaddr = dev->base_addr;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
        unsigned long flags;
-#endif
-       
+
        if (net_debug > 5)
                printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
-       
+
        if (dev->tbusy) {
                /* If we get here, some higher level has decided we are broken.
                   There should really be a "kick me" function call instead. */
                int tickssofar = jiffies - dev->trans_start;
+
                if (tickssofar < 40)
                        return 1;
-       
+               
                /* let's disable interrupts so we can avoid confusion on SMP
                 */
-               outb(ALL_MASK, ioaddr + INT_MASK_REG);
+               eepro_dis_int(ioaddr);
                
                /* if (net_debug > 1) */
                printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, 
@@ -1078,10 +1078,8 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
                lp->stats.tx_errors++;
 
                /* Try to restart the adaptor. */
-               outb(SEL_RESET_CMD, ioaddr); 
                /* We are supposed to wait for 2 us after a SEL_RESET */
-               SLOW_DOWN;
-               SLOW_DOWN;
+               eepro_sel_reset(ioaddr);
 
                /* Do I also need to flush the transmit buffers here? YES? */
                lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8); 
@@ -1092,31 +1090,24 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
 
 
                /* re-enabling all interrupts */
-               outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
-               
-               outb(RCV_ENABLE_CMD, ioaddr);
-       }
+               eepro_en_int(ioaddr);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+               /* enable rx */
+               eepro_en_rx(ioaddr);
+       }
        spin_lock_irqsave(&lp->lock, flags);
-#endif
 
        /* Block a timer-based transmit from overlapping. */
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
                printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
                spin_unlock_irqrestore(&lp->lock, flags);
-#endif
        } else {
                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
                unsigned char *buf = skb->data;
                int discard = lp->stats.tx_dropped;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
                lp->stats.tx_bytes+=skb->len;
-#endif
-
                hardware_send_packet(dev, buf, length);
 
                if (lp->stats.tx_dropped != discard)
@@ -1134,9 +1125,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
        spin_unlock_irqrestore(&lp->lock, flags);
-#endif
        
        return 0;
 }
@@ -1158,20 +1147,17 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                 return;
         }
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
         spin_lock(&lp->lock);
-#endif
 
        if (dev->interrupt) {
                printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
                spin_unlock(&lp->lock);
                /* FIXME : with the lock, could this ever happen ? */
-#endif
 
                return;
        }
+
        dev->interrupt = 1;
 
        if (net_debug > 5)
@@ -1183,13 +1169,13 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        {
                switch (status & (RX_INT | TX_INT)) {
                        case (RX_INT | TX_INT):
-                               outb (RX_INT | TX_INT, ioaddr + STATUS_REG);
+                               eepro_ack_rxtx(ioaddr);
                                break;
                        case RX_INT:
-                               outb (RX_INT, ioaddr + STATUS_REG);
+                               eepro_ack_rx(ioaddr);
                                break;
                        case TX_INT:
-                               outb (TX_INT, ioaddr + STATUS_REG);
+                               eepro_ack_tx(ioaddr);
                                break;
                }
                if (status & RX_INT) {
@@ -1201,7 +1187,7 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                }
                if (status & TX_INT) {
                        if (net_debug > 4)
-                               printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
+                               printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
 
                        /* Process the status of transmitted packets */
                        eepro_transmit_interrupt(dev);
@@ -1213,9 +1199,8 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
        spin_unlock(&lp->lock);
-#endif
+
        return;
 }
 
@@ -1228,13 +1213,13 @@ static int eepro_close(struct device *dev)
        dev->tbusy = 1;
        dev->start = 0;
 
-       outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */
+       eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */
 
        /* Disable the physical interrupt line. */
        temp_reg = inb(ioaddr + REG1);
        outb(temp_reg & 0x7f, ioaddr + REG1); 
 
-       outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
+       eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
 
        /* Flush the Tx and disable Rx. */
        outb(STOP_RCV_CMD, ioaddr); 
@@ -1242,13 +1227,13 @@ static int eepro_close(struct device *dev)
        lp->tx_last = 0;
 
        /* Mask all the interrupts. */
-       outb(ALL_MASK, ioaddr + INT_MASK_REG); 
+       eepro_dis_int(ioaddr);
 
        /* clear all interrupts */
-       outb(ALL_MASK, ioaddr + STATUS_REG); 
+       eepro_clear_int(ioaddr);
 
        /* Reset the 82595 */
-       outb(RESET_CMD, ioaddr); 
+       eepro_reset(ioaddr);
 
        /* release the interrupt */
        free_irq(dev->irq, dev);
@@ -1259,10 +1244,6 @@ static int eepro_close(struct device *dev)
 
        /* Update the statistics here. What statistics? */
 
-       /* We are supposed to wait for 200 us after a RESET */
-       SLOW_DOWN;
-       SLOW_DOWN; /* May not be enough? */
-
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -1297,23 +1278,23 @@ set_multicast_list(struct device *dev)
                 */
                dev->flags|=IFF_PROMISC;                
 
-               outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
+               eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
                mode = inb(ioaddr + REG2);
                outb(mode | PRMSC_Mode, ioaddr + REG2); 
                mode = inb(ioaddr + REG3);
                outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
-               outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
+               eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
                printk("%s: promiscuous mode enabled.\n", dev->name);
        }
        
        else if (dev->mc_count==0 ) 
        {
-               outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
+               eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
                mode = inb(ioaddr + REG2);
                outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */
                mode = inb(ioaddr + REG3);
                outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
-               outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
+               eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
        }
        
        else 
@@ -1324,14 +1305,14 @@ set_multicast_list(struct device *dev)
                /* Disable RX and TX interrupts.  Necessary to avoid
                   corruption of the HOST_ADDRESS_REG by interrupt
                   service routines. */
-               outb(ALL_MASK, ioaddr + INT_MASK_REG);
+               eepro_dis_int(ioaddr);
 
-               outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
+               eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
                mode = inb(ioaddr + REG2);
                outb(mode | Multi_IA, ioaddr + REG2);   
                mode = inb(ioaddr + REG3);
                outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
-               outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
+               eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
                outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG);
                outw(MC_SETUP, ioaddr + IO_PORT);
                outw(0, ioaddr + IO_PORT);
@@ -1395,10 +1376,11 @@ set_multicast_list(struct device *dev)
                } while (++boguscount < 100);
 
                /* Re-enable RX and TX interrupts */
-               outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+               eepro_en_int(ioaddr);
        
        }
-       outb(RCV_ENABLE_CMD, ioaddr);
+       /* enabling rx */
+       eepro_en_rx(ioaddr);
 }
 
 /* The horrible routine to read a word from the serial EEPROM. */
@@ -1409,11 +1391,12 @@ set_multicast_list(struct device *dev)
 #define EE_READ_CMD (6 << 6)
 
 int
-read_eeprom(int ioaddr, int location)
+read_eeprom(int ioaddr, int location, struct device *dev)
 {
        int i;
        unsigned short retval = 0;
        short ee_addr = ioaddr + eeprom_reg;
+       struct eepro_local *lp = (struct eepro_local *)dev->priv;
        int read_cmd = location | EE_READ_CMD;
        short ctrl_val = EECS ;
        
@@ -1421,12 +1404,12 @@ read_eeprom(int ioaddr, int location)
         *        boards other than eepro10. I think that it won't let other
         *        boards to fail. (aris)
         */
-       if (etherexpress10) {
-               outb(BANK1_SELECT, ioaddr);
+       if (lp->eepro == LAN595FX_10ISA) {
+               eepro_sw2bank1(ioaddr);
                outb(0x00, ioaddr + STATUS_REG);
        }
                
-       outb(BANK2_SELECT, ioaddr);
+       eepro_sw2bank2(ioaddr);
        outb(ctrl_val, ee_addr);
        
        /* Shift the read command bits out. */
@@ -1453,7 +1436,7 @@ read_eeprom(int ioaddr, int location)
        eeprom_delay();
        outb(ctrl_val, ee_addr);
        eeprom_delay();
-       outb(BANK0_SELECT, ioaddr);
+       eepro_sw2bank0(ioaddr);
        return retval;
 }
 
@@ -1462,21 +1445,22 @@ hardware_send_packet(struct device *dev, void *buf, short length)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        short ioaddr = dev->base_addr;
+
        unsigned status, tx_available, last, end, boguscount = 100;
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
 
-       while (boguscount-- > 0) {
 
+       while (boguscount-- > 0) {
                /* Disable RX and TX interrupts.  Necessary to avoid
                corruption of the HOST_ADDRESS_REG by interrupt
                service routines. */
-               outb(ALL_MASK, ioaddr + INT_MASK_REG);
+               eepro_dis_int(ioaddr);
 
                if (dev->interrupt == 1) {
                        /* Enable RX and TX interrupts */
-                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+                       eepro_en_int(ioaddr);
                        continue;
                }
 
@@ -1493,7 +1477,7 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                        eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
 
                        /* Enable RX and TX interrupts */
-                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+                       eepro_en_int(ioaddr);
                        continue;
                }
 
@@ -1537,7 +1521,6 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                else {
                        /* update the next address and the chain bit in the 
                        last packet */
-                       
                        if (lp->tx_end != last) {
                                outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
                                outw(last, ioaddr + IO_PORT); 
@@ -1546,7 +1529,6 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                        outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
                        status = inw(ioaddr + IO_PORT); 
                        outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-
                        /* Continue the transmit command */
                        outb(RESUME_XMT_CMD, ioaddr);
                }
@@ -1561,18 +1543,18 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                /* now we are serializing tx. tbusy won't come back until
                 * the tx interrupt
                 */
-               if (etherexpress10)
+               if (lp->eepro == LAN595FX_10ISA)
                        dev->tbusy = 1;
                
                /* Enable RX and TX interrupts */
-               outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+               eepro_en_int(ioaddr);
 
                if (net_debug > 5)
                        printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
                return;
        }
 
-       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+       eepro_en_int(ioaddr);
        dev->tbusy = 1;
 
        if (net_debug > 5)
@@ -1584,15 +1566,16 @@ eepro_rx(struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        short ioaddr = dev->base_addr;
+               
        short boguscount = 20;
        unsigned rcv_car = lp->rx_start;
        unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
-       
-       /* disabling all interrupts */
-       outb(ALL_MASK, ioaddr + STATUS_REG);
+
+       /* clear all interrupts */
+       eepro_clear_int(ioaddr);
        
        /* Set the read pointer to the start of the RCV */
        outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
@@ -1610,9 +1593,7 @@ eepro_rx(struct device *dev)
                        /* Malloc up new buffer. */
                        struct sk_buff *skb;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
                        lp->stats.rx_bytes+=rcv_size;
-#endif
                        rcv_size &= 0x3fff;
                        skb = dev_alloc_skb(rcv_size+5);
                        if (skb == NULL) {
@@ -1675,7 +1656,8 @@ eepro_rx(struct device *dev)
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
 
-       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+       /* enable tx/rx interrupts */
+       eepro_en_int(ioaddr);
 }
 
 static void
@@ -1685,7 +1667,7 @@ eepro_transmit_interrupt(struct device *dev)
        short ioaddr = dev->base_addr;
        short boguscount = 20; 
        unsigned xmt_status;
-       
+
        /*
        if (dev->tbusy == 0) {
                printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
@@ -1705,19 +1687,23 @@ eepro_transmit_interrupt(struct device *dev)
                        continue;
                }
 
+
                xmt_status = inw(ioaddr+IO_PORT); 
                lp->tx_start = inw(ioaddr+IO_PORT);
 
-               if (etherexpress10) {
+               if (lp->eepro == LAN595FX_10ISA) {
                        lp->tx_start = (XMT_LOWER_LIMIT << 8);
                        lp->tx_end = lp->tx_start;
        
                        /* yeah, black magic :( */
-                       outb(BANK0_SELECT, ioaddr);
-                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
-               
-                       outb(RCV_DISABLE_CMD, ioaddr);
-                       outb(RCV_ENABLE_CMD, ioaddr);
+                       eepro_sw2bank0(ioaddr);
+                       eepro_en_int(ioaddr);
+
+                       /* disabling rx */
+                       eepro_dis_rx(ioaddr);
+                       
+                       /* enabling rx */
+                       eepro_en_rx(ioaddr);
                }
 
                /* here the tbusy comes to 0 for normal and ee10 cards
@@ -1744,20 +1730,18 @@ eepro_transmit_interrupt(struct device *dev)
                                printk(KERN_DEBUG "%s: XMT status = %#x\n",
                                        dev->name, xmt_status);
                        }
-                       
-                       if (etherexpress10) {
+
+                       if (lp->eepro == LAN595FX_10ISA) {                      
                                /* Try to restart the adaptor. */
-                               outb(SEL_RESET_CMD, ioaddr); 
-                       
                                /* We are supposed to wait for 2 us after a SEL_RESET */
-                               SLOW_DOWN;
-                               SLOW_DOWN;
+                               eepro_sel_reset(ioaddr);
 
                                /* first enable interrupts */
-                               outb(BANK0_SELECT, ioaddr);
+                               eepro_sw2bank0(ioaddr);
                                outb(ALL_MASK & ~(RX_INT | TX_INT), ioaddr + STATUS_REG);
                        
-                               outb(RCV_ENABLE_CMD, ioaddr);
+                               /* enabling rx */
+                               eepro_en_rx(ioaddr);
                        }
                }
                
@@ -1786,15 +1770,12 @@ static int mem[MAX_EEPRO] = {   /* Size of the rx buffer in KB */
 static int autodetect;
 
 static int n_eepro = 0;
-/* For linux 2.1.xx */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 MODULE_AUTHOR("Pascal Dupuis <dupuis@lei.ucl.ac.be> for the 2.1 stuff (locking,...)");
 MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i");
 MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i");
 MODULE_PARM(autodetect, "1-" __MODULE_STRING(1) "i");
-#endif 
 
 int 
 init_module(void)
@@ -1815,13 +1796,15 @@ init_module(void)
        for (i = 0; i < MAX_EEPRO; i++) {
                struct device *d = &dev_eepro[n_eepro];
                d->name         = devicename[n_eepro]; /* inserted by drivers/net/net_init.c */
-               d->mem_end      = mem[n_eepro];
+               d->mem_end      = mem[n_eepro];         
                d->base_addr    = io[0];
                d->irq          = irq[n_eepro];
                d->init         = eepro_probe;
 
                if (register_netdev(d) == 0)
                        n_eepro++;
+               else
+                       break;
        }
        
        return n_eepro ? 0 : -ENODEV;
index d79c09b2292aefa30c9ee33f28d8bbeca82be6c2..c0aec40fe4cb2ad6a95ce62e914bc0d89347e5c3 100644 (file)
@@ -483,6 +483,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( NVIDIA_SGS,     NVIDIA_SGS_RIVA128,     "Riva 128"),
        DEVICE( CBOARDS,        CBOARDS_DAS1602_16,"DAS1602/16"),
        DEVICE( MOTOROLA_OOPS,  MOTOROLA_FALCON,"Falcon"),
+       DEVICE( TIMEDIA,        TIMEDIA_4008A, "Noname 4008A"),
        DEVICE( SYMPHONY,       SYMPHONY_101,   "82C101"),
        DEVICE( TEKRAM,         TEKRAM_DC290,   "DC-290"),
        DEVICE( 3DLABS,         3DLABS_300SX,   "GLINT 300SX"),
@@ -846,6 +847,7 @@ static const char *pci_strvendor(unsigned int vendor)
              case PCI_VENDOR_ID_PICTUREL:      return "Picture Elements";
              case PCI_VENDOR_ID_NVIDIA_SGS:    return "NVidia/SGS Thomson";
              case PCI_VENDOR_ID_CBOARDS:       return "ComputerBoards";
+             case PCI_VENDOR_ID_TIMEDIA:       return "Timedia Technology";
              case PCI_VENDOR_ID_SYMPHONY:      return "Symphony";
              case PCI_VENDOR_ID_COMPUTONE:     return "Computone Corporation";
              case PCI_VENDOR_ID_TEKRAM:        return "Tekram";
index 25a1cea5f8e35ebcbc69d669c79cde3a7d5e7f47..5e3944c4ba7f1f15d312316893dc7e3f0dbaca51 100644 (file)
@@ -207,8 +207,6 @@ hwc_tty_input (unsigned char *buf, unsigned int count)
 {
        struct tty_struct *tty = hwc_tty_data.tty;
 
-#if 0
-
        if (tty != NULL) {
 
                if (count == 2 && (
@@ -249,7 +247,7 @@ hwc_tty_input (unsigned char *buf, unsigned int count)
                tty_flip_buffer_push (tty);
                hwc_tty_wake_up ();
        }
-#endif
+#if 0
 
        if (tty != NULL) {
 
@@ -289,6 +287,7 @@ hwc_tty_input (unsigned char *buf, unsigned int count)
                tty_flip_buffer_push(tty);
                hwc_tty_wake_up ();
        }
+#endif
 }
 
 void 
index 2ea8e3f276a82bb20843c61e5e827161df489766..dbe3cf2c96410307a75896f55ec2e84b93d1e49e 100644 (file)
@@ -42,6 +42,9 @@
  *            IFCONFIG dev DOWN and IFCONFIG dev UP 
  *          - Possibility to switch the automatic selection off
  *          - Minor bug fixes 
+ *    0.52  Bug fixes 
+ *          - Subchannel check message enhanced 
+ *          - Read / Write retry routine check for CTC_STOP added  
  */
 #include <linux/version.h>
 #include <linux/init.h>
@@ -80,7 +83,7 @@
         #define KERN_WARNING KERN_EMERG
         #define KERN_DEBUG   KERN_EMERG
 #endif  
-//#undef DEBUG
+
 
 #define CCW_CMD_WRITE           0x01
 #define CCW_CMD_READ            0x02
@@ -914,10 +917,10 @@ static void ctc_irq_handler (int irq, void *initparm, struct pt_regs *regs)
 
         devstat_t *devstat = ((devstat_t *)initparm);
 
-        /* Bypass all 'unsolited interrupts' */
+        /* Bypass all 'unsolicited interrupts' */
         if (devstat->intparm == 0) {
 #ifdef DEBUG
-                printk(KERN_DEBUG "ctc: unsolited interrupt for device: %04x received c-%02x d-%02x f-%02x\n",
+                printk(KERN_DEBUG "ctc: unsolicited interrupt for device: %04x received c-%02x d-%02x f-%02x\n",
                     devstat->devno, devstat->cstat, devstat->dstat, devstat->flag);
 #endif 
                 /* FIXME - find the related intparm!!! No IO outstanding!!!! */
@@ -935,8 +938,8 @@ static void ctc_irq_handler (int irq, void *initparm, struct pt_regs *regs)
 
         /* Check for good subchannel return code, otherwise error message */
         if (devstat->cstat) {
-                printk(KERN_WARNING "%s: subchannel check for device: %04x - %02x\n", 
-                    dev->name, ctc->devno, devstat->cstat);
+                printk(KERN_WARNING "%s: subchannel check for device: %04x - %02x %02x %02x\n", 
+                    dev->name, ctc->devno, devstat->cstat, devstat->dstat, devstat->flag);
                 return;
         }
 
@@ -1245,6 +1248,8 @@ static void ctc_read_retry (struct channel *ctc)
 #ifdef DEBUG
         printk(KERN_DEBUG "%s: read retry - state-%02x\n" ,dev->name, ctc->state);
 #endif 
+        if (ctc->state == CTC_STOP)
+                return;
         s390irq_spin_lock_irqsave(ctc->irq, saveflags);
         ctc->ccw[1].cda  = (char *)virt_to_phys(ctc->free_anchor->block);
         parm = (__u32) ctc; 
@@ -1269,6 +1274,8 @@ static void ctc_write_retry (struct channel *ctc)
 #ifdef DEBUG
         printk(KERN_DEBUG "%s: write retry - state-%02x\n" ,dev->name, ctc->state);
 #endif 
+        if (ctc->state == CTC_STOP)
+                return;
         s390irq_spin_lock_irqsave(ctc->irq, saveflags);
         ctc->ccw[1].count = 0;
         ctc->ccw[1].cda  = (char *)virt_to_phys(ctc->proc_anchor->block);
@@ -1414,6 +1421,7 @@ static void ctc_timer (struct channel *ctc)
 static int ctc_release(net_device *dev)
 {   
         int                rc;
+        int                x; 
         int                i;
         int                j;
         __u8               flags = 0x00;
@@ -1429,6 +1437,7 @@ static int ctc_release(net_device *dev)
        ctc_unprotect_busy_irqrestore(dev,flags);
         for (i = 0; i < 2;  i++) {
                 s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags);
+                del_timer(&privptr->channel[READ].timer);  
                 privptr->channel[i].state = CTC_STOP;
                 parm = (__u32) &privptr->channel[i]; 
                 rc = halt_IO (privptr->channel[i].irq, parm, flags );
index 1930d896a4934d2dd47b1405b3f3df45520bff61..dff3e5b96f92d40881110e57b815da65932fe7ab 100644 (file)
@@ -7,7 +7,7 @@
  * Original driver (sg.c):
  *        Copyright (C) 1992 Lawrence Foard
  * 2.x extensions to driver:
- *        Copyright (C) 1998, 1999 Douglas Gilbert
+ *        Copyright (C) 1998 - 2000 Douglas Gilbert
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,8 +16,8 @@
  *
  *  Borrows code from st driver. Thanks to Alessandro Rubini's "dd" book.
  */
- static char * sg_version_str = "Version: 2.1.36 (991218)";
- static int sg_version_num = 20136; /* 2 digits for each component */
+ static char * sg_version_str = "Version: 2.1.37 (20000504)";
+ static int sg_version_num = 20137; /* 2 digits for each component */
 /*
  *  D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
  *      - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
@@ -100,7 +100,7 @@ static int sg_detect(Scsi_Device *);
 static void sg_detach(Scsi_Device *);
 
 
-struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff,
+struct Scsi_Device_Template sg_template = {NULL, "generic", "sg", NULL, 0xff,
                                            SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
                                            sg_detect, sg_init,
                                            sg_finish, sg_attach, sg_detach};
@@ -609,8 +609,29 @@ static int sg_ioctl(struct inode * inode, struct file * filp,
             return -EBUSY;
         result = get_user(val, (int *)arg);
         if (result) return result;
-        /* Don't do anything till scsi mod level visibility */
-        return 0;
+        if (SG_SCSI_RESET_NOTHING == val)
+            return 0;
+#ifdef SCSI_TRY_RESET_DEVICE
+        switch (val)
+        {
+        case SG_SCSI_RESET_DEVICE:
+            val = SCSI_TRY_RESET_DEVICE;
+            break;
+        case SG_SCSI_RESET_BUS:
+            val = SCSI_TRY_RESET_BUS;
+            break;
+        case SG_SCSI_RESET_HOST:
+            val = SCSI_TRY_RESET_HOST;
+            break;
+        default:
+            return -EINVAL;
+        }
+        if(! capable(CAP_SYS_ADMIN))  return -EACCES;
+        return (scsi_reset_provider(sdp->device, val) == SUCCESS) ? 0 : -EIO;
+#else
+        SCSI_LOG_TIMEOUT(1, printk("sg_ioctl: SG_RESET_SCSI not supported\n"));
+        result = -EINVAL;
+#endif
     case SCSI_IOCTL_SEND_COMMAND:
         /* Allow SCSI_IOCTL_SEND_COMMAND without checking suser() since the
            user already has read/write access to the generic device and so
@@ -1124,6 +1145,8 @@ static int sg_start_req(Sg_request * srp, int max_buff_size,
 
     SCSI_LOG_TIMEOUT(4, printk("sg_start_req: max_buff_size=%d\n", 
                                max_buff_size)); 
+    if (max_buff_size <= 0)
+        return 0;
     if ((! sg_res_in_use(sfp)) && (max_buff_size <= rsv_schp->bufflen)) {
         sg_link_reserve(sfp, srp, max_buff_size);
         sg_write_xfer(req_schp, inp, num_write_xfer);
@@ -1351,6 +1374,8 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
     Sg_scatter_hold * rsv_schp = &sfp->reserve;
 
     SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); 
+    /* round request up to next highest SG_SECTOR_SZ byte boundary */
+    size = (size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
     if (rsv_schp->use_sg > 0) {
         int k, num;
         int rem = size;
@@ -1431,12 +1456,12 @@ static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id)
 static Sg_request * sg_add_request(Sg_fd * sfp)
 {
     int k;
-    Sg_request * resp = NULL;
-    Sg_request * rp;
+    Sg_request * resp = sfp->headrp;
+    Sg_request * rp = sfp->req_arr;
 
-    resp = sfp->headrp;
-    rp = sfp->req_arr;
     if (! resp) {
+        memset(rp, 0, sizeof(Sg_request));
+        rp->parentfp = sfp;
         resp = rp;
         sfp->headrp = resp;
     }
@@ -1444,12 +1469,15 @@ static Sg_request * sg_add_request(Sg_fd * sfp)
         if (0 == sfp->cmd_q)
             resp = NULL;   /* command queuing disallowed */
         else {
-            for (k = 0, rp; k < SG_MAX_QUEUE; ++k, ++rp) {
+            for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
                 if (! rp->parentfp)
                     break;
             }
             if (k < SG_MAX_QUEUE) {
-                while (resp->nextrp) resp = resp->nextrp;
+                memset(rp, 0, sizeof(Sg_request));
+                rp->parentfp = sfp;
+                while (resp->nextrp) 
+                    resp = resp->nextrp;
                 resp->nextrp = rp;
                 resp = rp;
             }
@@ -1458,11 +1486,7 @@ static Sg_request * sg_add_request(Sg_fd * sfp)
         }
     }
     if (resp) {
-        resp->parentfp = sfp;
         resp->nextrp = NULL;
-        resp->res_used = 0;
-        memset(&resp->data, 0, sizeof(Sg_scatter_hold));
-        memset(&resp->header, 0, sizeof(struct sg_header));
         resp->my_cmdp = NULL;
     }
     return resp;
@@ -1478,14 +1502,14 @@ static int sg_remove_request(Sg_fd * sfp, const Sg_request * srp)
         return 0;
     prev_rp = sfp->headrp;
     if (srp == prev_rp) {
-        prev_rp->parentfp = NULL;
         sfp->headrp = prev_rp->nextrp;
+        prev_rp->parentfp = NULL;
         return 1;
     }
     while ((rp = prev_rp->nextrp)) {
         if (srp == rp) {
-            rp->parentfp = NULL;
             prev_rp->nextrp = rp->nextrp;
+            rp->parentfp = NULL;
             return 1;
         }
         prev_rp = rp;
index 8dc6774279f9e35561f2e8a13654db8a24723fb7..c3f1f34b64f34329e41599a94823e560db29d261 100644 (file)
@@ -53,7 +53,7 @@ obj-$(CONFIG_SOUND_CS4232)    += cs4232.o ad1848.o
 obj-$(CONFIG_SOUND_CS4232)     += uart401.o
 obj-$(CONFIG_SOUND_GUS)                += gus.o ad1848.o
 obj-$(CONFIG_SOUND_MAD16)      += mad16.o ad1848.o sb.o uart401.o
-obj-$(CONFIG_SOUND_VIA82CXXX)  += via82cxxx.o sb.o uart401.o
+obj-$(CONFIG_SOUND_VIA82CXXX)  += via82cxxx.o sb.o uart401.o 
 obj-$(CONFIG_SOUND_MAUI)       += maui.o mpu401.o
 obj-$(CONFIG_SOUND_MPU401)     += mpu401.o
 obj-$(CONFIG_SOUND_MSNDCLAS)   += msnd.o msnd_classic.o
@@ -90,7 +90,7 @@ obj-$(CONFIG_SOUND_SONICVIBES)        += sonicvibes.o
 # Declare multi-part drivers.
 
 list-multi     := sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
-    soundcore.o wavefront.o nm256.o
+    soundcore.o wavefront.o nm256.o via82cxxx.o \
 
 sound-objs     :=                                                      \
     dev_table.o soundcard.o sound_syms.o               \
@@ -108,6 +108,7 @@ softoss2-objs       := softoss.o softoss_rs.o
 vidc_mod-objs  := vidc.o vidc_audio.o vidc_fill.o vidc_mixer.o vidc_synth.o
 wavefront-objs  := wavfront.o wf_midi.o yss225.o
 nm256-objs     := nm256_audio.o ac97.o
+via82cxxx-objs := via82cxxx_audio.o ac97.o
 
 
 # Extract lists of the multi-part drivers.
@@ -196,6 +197,9 @@ wavefront.o: $(wavefront-objs)
 nm256.o: $(nm256-objs)
        $(LD) -r -o $@ $(nm256-objs)
 
+via82cxxx.o: $(via82cxxx-objs)
+       $(LD) -r -o $@ $(via82cxxx-objs)
+
 # Firmware files that need translation
 #
 # The translated files are protected by a file that keeps track
index 4462b74e89e806c8ab230326ad7fdb008b8841fa..23c6e77ecd65885f29013211e17ea497fa20b25b 100644 (file)
@@ -588,7 +588,7 @@ static void start_adc(struct cm_state *s)
 
 /* --------------------------------------------------------------------- */
 
-#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
+#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
 static void dealloc_dmabuf(struct dmabuf *db)
diff --git a/drivers/sound/via82cxxx.c b/drivers/sound/via82cxxx.c
deleted file mode 100644 (file)
index b5ad6a9..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
- *
- * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
- * See the "COPYING" file distributed with this software for more info.
- *
- ********************************************************************
- *
- * TODO:
- *
- *     - Integrate AC'97 support, when AC'97 interface released
- *
- */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#include "sound_config.h"
-#include "soundmodule.h"
-#include "sb.h"
-
-#ifndef SOUND_LOCK
-#define SOUND_LOCK do {} while (0)
-#define SOUND_LOCK_END do {} while (0)
-#endif
-
-#define MAX_CARDS      2
-
-#define PFX            "via82cxxx: "
-
-#define VIA_VERSION    "1.0.0"
-#define VIA_CARD_NAME  "VIA 82Cxxx Audio driver " VIA_VERSION
-
-#define VIA_FUNC_ENABLE                0x42
-#define VIA_PNP_CONTROL                0x43
-
-#define VIA_CR42_SB_ENABLE     0x01
-#define VIA_CR42_MIDI_ENABLE   0x02
-#define VIA_CR42_FM_ENABLE     0x04
-
-#define via_probe_midi probe_uart401
-#define via_attach_midi attach_uart401
-#define via_unload_midi unload_uart401
-
-static struct address_info     sb_data[MAX_CARDS];
-static struct address_info     opl3_data[MAX_CARDS];
-static unsigned                        cards = 0;
-
-
-static void __init via_attach_sb(struct address_info *hw_config)
-{
-       if(!sb_dsp_init(hw_config))
-               hw_config->slots[0] = -1;
-}
-
-
-static int __init via_probe_sb(struct address_info *hw_config)
-{
-       if (check_region(hw_config->io_base, 16))
-       {
-               printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
-                      hw_config->io_base);
-               return 0;
-       }
-       return sb_dsp_detect(hw_config, 0, 0);
-}
-
-
-static void via_unload_sb(struct address_info *hw_config, int unload_mpu)
-{
-       if(hw_config->slots[0]!=-1)
-               sb_dsp_unload(hw_config, unload_mpu);
-}
-
-
-static int __init via82cxxx_install (struct pci_dev *pcidev)
-{
-       int sb_io_base = 0;
-       int sb_irq = 0;
-       int sb_dma = 0;
-       int midi_base = 0;
-       u8 tmp8;
-       
-       memset (&sb_data[cards], 0, sizeof (struct address_info));
-       memset (&opl3_data[cards], 0, sizeof (struct address_info));
-
-       sb_data[cards].name = opl3_data[cards].name = VIA_CARD_NAME;
-       opl3_data[cards].irq = -1;
-
-       /* turn on features, if not already */
-       pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
-       tmp8 |= VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
-               VIA_CR42_FM_ENABLE;
-       pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
-
-       /* read legacy PNP info byte */
-       pci_read_config_byte (pcidev, VIA_PNP_CONTROL, &tmp8);
-       pci_write_config_byte (pcidev, VIA_PNP_CONTROL, tmp8);
-       
-       switch ((tmp8 >> 6) & 0x03) {
-               case 0: sb_irq = 5; break;
-               case 1: sb_irq = 7; break;
-               case 2: sb_irq = 9; break;
-               case 3: sb_irq = 10; break;
-               default: /* do nothing */ break;
-       }
-       switch ((tmp8 >> 4) & 0x03) {
-               case 0: sb_dma = 0; break;
-               case 1: sb_dma = 1; break;
-               case 2: sb_dma = 2; break;
-               case 3: sb_dma = 3; break;
-               default: /* do nothing */ break;
-       }
-       switch ((tmp8 >> 2) & 0x03) {
-               case 0: midi_base = 0x300; break;
-               case 1: midi_base = 0x310; break;
-               case 2: midi_base = 0x320; break;
-               case 3: midi_base = 0x330; break;
-               default: /* do nothing */ break;
-       }
-       switch (tmp8 & 0x03) {
-               case 0: sb_io_base = 0x220; break;
-               case 1: sb_io_base = 0x240; break;
-               case 2: sb_io_base = 0x260; break;
-               case 3: sb_io_base = 0x280; break;
-               default: /* do nothing */ break;
-       }
-
-       udelay(100);
-       
-       printk(KERN_INFO PFX "legacy "
-              "MIDI: 0x%X, SB: 0x%X / %d IRQ / %d DMA\n",
-               midi_base, sb_io_base, sb_irq, sb_dma);
-               
-       sb_data[cards].card_subtype = MDL_SBPRO;
-       sb_data[cards].io_base = sb_io_base;
-       sb_data[cards].irq = sb_irq;
-       sb_data[cards].dma = sb_dma;
-       
-       opl3_data[cards].io_base = midi_base;
-       
-       /* register legacy SoundBlaster Pro */
-       if (!via_probe_sb (&sb_data[cards])) {
-               printk (KERN_ERR PFX
-                       "SB probe @ 0x%X failed, aborting\n",
-                       sb_io_base);
-               return -1;
-       }
-       via_attach_sb (&sb_data[cards]);
-
-       /* register legacy MIDI */
-       if (!via_probe_midi (&opl3_data[cards])) {
-               printk (KERN_ERR PFX
-                       "MIDI probe @ 0x%X failed, aborting\n",
-                       midi_base);
-               via_unload_sb (&sb_data[cards], 0);
-               return -1;
-       }
-       via_attach_midi (&opl3_data[cards]);
-
-       cards++;        
-       return 0;
-}
-
-
-/*
- *     This loop walks the PCI configuration database and finds where
- *     the sound cards are.
- */
-static int __init probe_via82cxxx (void)
-{
-       struct pci_dev *pcidev = NULL;
-
-       while ((pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
-                                         PCI_DEVICE_ID_VIA_82C686_5,
-                                         pcidev)) != NULL) {
-
-                 if (via82cxxx_install (pcidev) != 0) {
-                         printk (KERN_ERR PFX "audio init failed\n");
-                         return -1;
-                 }
-
-                 if (cards == MAX_CARDS) {
-                         printk (KERN_DEBUG PFX "maximum number of cards reached\n");
-                         break;
-                 }
-       }
-
-       return 0;
-}
-
-
-/*
- *     This function is called when the user or kernel loads the 
- *     module into memory.
- */
-
-
-static int __init init_via82cxxx_module(void)
-{
-       if (!pci_present ()) {
-               printk (KERN_DEBUG PFX "PCI not present, exiting\n");
-               return -ENODEV;
-       }
-
-       if (probe_via82cxxx() != 0) {
-               printk(KERN_ERR PFX "probe failed, aborting\n");
-               /* XXX unload cards registered so far, if any */
-               return -ENODEV;
-       }
-
-       if (cards == 0) {
-               printk(KERN_DEBUG PFX "No chips found, aborting\n");
-               return -ENODEV;
-       }
-
-       printk (KERN_INFO PFX VIA_CARD_NAME " loaded\n");
-       
-       /*
-        *      Binds us to the sound subsystem 
-        */
-       SOUND_LOCK;
-       return 0;
-}
-
-/*
- *     This is called when it is removed. It will only be removed 
- *     when its use count is 0. For sound the SOUND_LOCK/SOUND_UNLOCK
- *     macros hide the entire work for this.
- */
-static void cleanup_via82cxxx_module(void)
-{
-       int i;
-       
-       for (i = 0; i < cards; i++)
-               via_unload_sb (&sb_data[i], 1);
-
-       /*
-        *      Final clean up with the sound layer
-        */
-       SOUND_LOCK_END;
-}
-
-#ifdef MODULE
-
-int init_module(void)
-{
-       return init_via82cxxx_module();
-}
-
-void cleanup_module(void)
-{
-       cleanup_via82cxxx_module();
-}
-
-#endif
diff --git a/drivers/sound/via82cxxx_audio.c b/drivers/sound/via82cxxx_audio.c
new file mode 100644 (file)
index 0000000..0af24cb
--- /dev/null
@@ -0,0 +1,729 @@
+/*
+ * Support for VIA 82Cxxx Audio Codecs
+ * Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ *
+ * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
+ * See the "COPYING" file distributed with this software for more info.
+ *
+ * Documentation for this driver available as
+ * linux/Documentation/sound/via82cxxx.txt.
+ *
+ * Since the mixer is called from the OSS glue the kernel lock is always held
+ * on our AC97 mixing
+ */
+
+#define VIA_VERSION    "1.1.2.1"
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+
+#include <asm/io.h>
+
+#include "sound_config.h"
+#include "soundmodule.h"
+#include "sb.h"
+#include "ac97.h"
+
+#ifndef SOUND_LOCK
+#define SOUND_LOCK do {} while (0)
+#define SOUND_LOCK_END do {} while (0)
+#endif
+
+#define VIA_DEBUG 0    /* define to 1 to enable debugging output and checks */
+#if VIA_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define VIA_NDEBUG 0   /* define to 1 to disable lightweight runtime checks */
+#if VIA_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+        if(!(expr)) {                                  \
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",        \
+        #expr,__FILE__,__FUNCTION__,__LINE__);         \
+        }
+#endif
+
+#define arraysize(x)            (sizeof(x)/sizeof(*(x)))
+
+#define MAX_CARDS      2
+
+#define        LINE_SIZE       10
+
+#define VIA_CARD_NAME  "VIA 82Cxxx Audio driver " VIA_VERSION
+#define VIA_MODULE_NAME "via_audio"
+#define PFX            VIA_MODULE_NAME ": "
+
+#define VIA_COUNTER_LIMIT      100000
+
+/* 82C686 function 5 (audio codec) PCI configuration registers */
+#define VIA_FUNC_ENABLE                0x42
+#define VIA_PNP_CONTROL                0x43
+#define VIA_AC97_CTRL          0x80
+
+/* PCI configuration register bits and masks */
+#define VIA_CR40_AC97_READY    0x01
+#define VIA_CR40_AC97_LOW_POWER        0x02
+#define VIA_CR40_SECONDARY_READY 0x04
+
+#define VIA_CR41_ACLINK_ENABLE 0x80
+
+#define VIA_CR42_SB_ENABLE     0x01
+#define VIA_CR42_MIDI_ENABLE   0x02
+#define VIA_CR42_FM_ENABLE     0x04
+#define VIA_CR42_GAME_ENABLE   0x08
+
+#define VIA_CR44_SECOND_CODEC_SUPPORT  (1 << 6)
+#define VIA_CR44_AC_LINK_ACCESS                (1 << 7)
+
+#define VIA_CR80_FIRST_CODEC           0
+#define VIA_CR80_SECOND_CODEC          (1 << 30)
+#define VIA_CR80_FIRST_CODEC_VALID     (1 << 25)
+#define VIA_CR80_SECOND_CODEC_VALID    (1 << 27)
+#define VIA_CR80_BUSY                  (1 << 24)
+#define VIA_CR80_READ_MODE             (1 << 23)
+#define VIA_CR80_WRITE_MODE            0
+#define VIA_CR80_REG_IDX(idx)          (((idx) & 0x7E) << 16)
+
+struct via_info {
+       struct address_info sb_data;
+       struct address_info opl3_data;
+       struct pci_dev *pdev;
+       struct ac97_hwint ac97;
+       int mixer_oss_dev;
+       int have_ac97;
+};
+static struct via_info         cards [MAX_CARDS];
+static unsigned                        num_cards = 0;
+
+
+static const struct {
+       int revision;
+       const char *rev_name;
+} via_chip_revs[] __initdata = {
+       { 0x10, "A" },
+       { 0x11, "B" },
+       { 0x12, "C" },
+       { 0x13, "D" },
+       { 0x14, "E" },
+       { 0x20, "H" },
+};
+
+static inline void via_ac97_write32 (struct pci_dev *pdev, int port, u32 data)
+{
+
+       int iobase = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+       
+       outw ((u16)data,iobase+port);   
+       outw ((u16)(data>>16),iobase+port+2);   
+}
+
+static inline u32 via_ac97_read32 (struct pci_dev *pdev, int port)
+{
+       int iobase = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+
+       return
+               ((u32)inw (iobase+port)) |
+               (((u32)inw (iobase+port+2)) << 16);
+}
+
+/****************************************************************
+ *
+ * Intel Audio Codec '97 interface
+ *
+ *
+ */
+static inline void via_ac97_wait_idle (struct pci_dev *pdev)
+{
+       u32 tmp;
+       int counter = VIA_COUNTER_LIMIT;
+       
+       DPRINTK ("ENTER\n");
+
+       assert (pdev != NULL);
+       
+       do {
+               tmp = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+       } while ((tmp & VIA_CR80_BUSY) && (counter-- > 0));
+
+       DPRINTK ("EXIT%s\n", counter > 0 ? "" : ", counter limit reached");
+}
+
+
+static int via_ac97_read_reg (struct ac97_hwint *dev, u8 reg)
+{
+       u32 data;
+       struct via_info *card;
+       struct pci_dev *pdev;
+       
+       DPRINTK ("ENTER\n");
+
+       assert (dev != NULL);
+       assert (dev->driver_private != NULL);
+
+       card = (struct via_info *) dev->driver_private;
+       pdev = card->pdev;
+       assert (pdev != NULL);
+
+       via_ac97_wait_idle (pdev);
+       data =  VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+               VIA_CR80_READ_MODE | VIA_CR80_REG_IDX(reg);
+       via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+       via_ac97_wait_idle (pdev);
+       data = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+
+#if 0
+       if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+               DPRINTK ("EXIT, first codec not valid, returning -1\n");
+               return -1;
+       }
+#endif
+
+       DPRINTK ("EXIT, returning %d\n", data & 0xFFFF);
+       return data & 0xFFFF;
+}
+
+
+static int via_ac97_write_reg (struct ac97_hwint *dev, u8 reg, u16 value)
+{
+       u32 data;
+       struct via_info *card;
+       struct pci_dev *pdev;
+       
+       DPRINTK ("ENTER\n");
+
+       assert (dev != NULL);
+       assert (dev->driver_private != NULL);
+
+       card = (struct via_info *) dev->driver_private;
+       pdev = card->pdev;
+       assert (pdev != NULL);
+
+       via_ac97_wait_idle (pdev);
+       data =  VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+               VIA_CR80_WRITE_MODE | VIA_CR80_REG_IDX(reg) | value;
+       via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+
+#if 0
+       if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+               DPRINTK ("EXIT, first codec invalid, returning -1\n");
+               return -1;
+       }
+#endif
+
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+}
+
+
+static int via_ac97_reset (struct ac97_hwint *dev)
+{
+       struct via_info *card;
+       struct pci_dev *pdev;
+       
+       DPRINTK ("ENTER\n");
+
+       assert (dev != NULL);
+       assert (dev->driver_private != NULL);
+
+       card = (struct via_info *) dev->driver_private;
+       pdev = card->pdev;
+       assert (pdev != NULL);
+       
+       pci_write_config_word (pdev, PCI_COMMAND, PCI_COMMAND_IO);
+
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+}
+
+
+static struct via_info *via_ac97_find_card_for_mixer (int dev)
+{
+       int x;
+
+       DPRINTK ("ENTER\n");
+
+       for (x = 0; x < num_cards; x++)
+               if (cards[x].mixer_oss_dev == dev) {
+                       DPRINTK ("EXIT, returning %p\n", cards + x);
+                       return cards + x;
+               }
+
+       DPRINTK ("EXIT, returning 0\n");
+       return NULL;
+}
+
+
+static int
+via_ac97_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+       int rc;
+       struct via_info *card = via_ac97_find_card_for_mixer (dev);
+
+       DPRINTK ("ENTER\n");
+
+       if (card != NULL) {
+               rc = ac97_mixer_ioctl (&card->ac97, cmd, arg);
+               DPRINTK ("EXIT, returning %d\n", rc);
+               return rc;
+       }
+       
+       DPRINTK ("EXIT, returning -ENODEV\n");
+       return -ENODEV;
+
+}
+
+static struct mixer_operations via_ac97_mixer_operations =
+{
+       "VIA82Cxxx",
+       "via82cxxxAC97Mixer",
+       via_ac97_default_mixer_ioctl
+};
+
+static int __init via_attach_ac97 (struct via_info *card)
+{
+       int mixer;
+       struct ac97_hwint *mdev;
+
+       DPRINTK ("ENTER\n");
+
+       assert (card != NULL);
+
+       mdev = &card->ac97;
+
+       memset (mdev, 0, sizeof (*mdev));
+       mdev->reset_device = via_ac97_reset;
+       mdev->read_reg = via_ac97_read_reg;
+       mdev->write_reg = via_ac97_write_reg;
+       mdev->driver_private = (void *) card;
+
+       if (ac97_init (mdev)) {
+               printk (KERN_ERR PFX "Unable to init AC97\n");
+               DPRINTK ("EXIT, returning -1\n");
+               return -1;
+       }
+       mixer = sound_alloc_mixerdev ();
+       if (mixer < 0 || num_mixers >= MAX_MIXER_DEV) {
+               printk (KERN_ERR PFX "Unable to alloc mixerdev\n");
+               DPRINTK ("EXIT, returning -1\n");
+               return -1;
+       }
+       mixer_devs[mixer] = &via_ac97_mixer_operations;
+       card->mixer_oss_dev = mixer;
+
+       /* Some reasonable default values.  */
+       ac97_set_mixer (mdev, SOUND_MIXER_VOLUME, (85 << 8) | 85);
+       ac97_set_mixer (mdev, SOUND_MIXER_SPEAKER, 100);
+       ac97_set_mixer (mdev, SOUND_MIXER_PCM, (65 << 8) | 65);
+       ac97_set_mixer (mdev, SOUND_MIXER_CD, (65 << 8) | 65);
+
+       printk (KERN_INFO PFX "Initialized AC97 mixer\n");
+       
+       card->have_ac97 = mixer;
+       
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+}
+
+
+static void via_unload_ac97 (struct via_info *card)
+{
+       DPRINTK ("ENTER\n");
+
+       assert (card != NULL);
+
+       if (card->have_ac97 >= 0)
+               sound_unload_mixerdev (card->have_ac97);
+
+       DPRINTK ("EXIT\n");
+}
+
+#if 0
+#ifdef CONFIG_PROC_FS
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx/info
+ *
+ *
+ */
+static int via_info_read_proc (char *page, char **start, off_t off,
+                              int count, int *eof, void *data)
+{
+#define YN(val,bit) (((val) & (bit)) ? "yes" : "no")
+
+       int len = 0, i;
+       u8 r40, r41, r42, r44;
+       
+       DPRINTK ("ENTER\n");
+
+       len += sprintf (page+len, VIA_CARD_NAME "\n\n");
+       
+       for (i = 0; i < num_cards; i++) {
+               pci_read_config_byte (cards[i].pdev, 0x40, &r40);
+               pci_read_config_byte (cards[i].pdev, 0x42, &r41);
+               pci_read_config_byte (cards[i].pdev, 0x42, &r42);
+               pci_read_config_byte (cards[i].pdev, 0x44, &r44);
+       
+               len += sprintf (page+len,
+                       "40  AC97 Codec Ready: %s\n"
+                       "    AC97 Codec Low-power: %s\n"
+                       "    Secondary Codec Ready: %s\n"
+
+                       "41  AC-Link Interface Enable: %s\n"
+
+                       "42  Game port enabled: %s\n"
+                       "    SoundBlaster enabled: %s\n"
+                       "    FM enabled: %s\n"
+                       "    MIDI enabled: %s\n"
+                       
+                       "44  AC-Link Interface Access: %s\n"
+                       "    Secondary Codec Support: %s\n"
+                       
+                       "\n",
+                       
+                       YN (r40, VIA_CR40_AC97_READY),
+                       YN (r40, VIA_CR40_AC97_LOW_POWER),
+                       YN (r40, VIA_CR40_SECONDARY_READY),
+
+                       YN (r41, VIA_CR41_ACLINK_ENABLE),
+
+                       YN (r42, VIA_CR42_GAME_ENABLE),
+                       YN (r42, VIA_CR42_SB_ENABLE),
+                       YN (r42, VIA_CR42_FM_ENABLE),
+                       YN (r42, VIA_CR42_MIDI_ENABLE),
+
+                       YN (r44, VIA_CR44_AC_LINK_ACCESS),
+                       YN (r44, VIA_CR44_SECOND_CODEC_SUPPORT)
+                       
+                       );
+       }
+       
+       DPRINTK("EXIT, returning %d\n", len);
+       return len;
+
+#undef YN
+}
+
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx
+ *
+ *
+ */
+
+static int __init via_init_proc (void)
+{
+       DPRINTK ("ENTER\n");
+
+
+       proc_mkdir ("driver/via_audio", 0);
+       create_proc_read_entry ("driver/via_audio/info", 0, 0, via_info_read_proc, NULL);
+       
+       DPRINTK("EXIT\n");
+       return 0;
+}
+
+
+
+static void __exit via_cleanup_proc (void)
+{
+       DPRINTK ("ENTER\n");
+       remove_proc_entry ("driver/via_audio/info", NULL);
+       remove_proc_entry ("driver/via_audio", NULL);
+       DPRINTK("EXIT\n");
+}
+
+
+#else
+#endif /* CONFIG_PROC_FS */
+
+#endif /* if 0 */
+
+static inline int via_init_proc (void) { return 0; }
+static inline void via_cleanup_proc (void) {}
+
+
+
+/****************************************************************
+ *
+ * Legacy SoundBlaster Pro, FM support via OSS
+ *
+ *
+ */
+
+static void via_attach_sb(struct address_info *hw_config)
+{
+       DPRINTK ("ENTER\n");
+
+       if(!sb_dsp_init(hw_config))
+               hw_config->slots[0] = -1;
+
+       DPRINTK("EXIT\n");
+}
+
+
+static int via_probe_sb(struct address_info *hw_config)
+{
+       DPRINTK ("ENTER\n");
+
+       if (check_region(hw_config->io_base, 16))
+       {
+               printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
+                      hw_config->io_base);
+               return 0;
+       }
+       DPRINTK("EXIT after sb_dsp_detect\n");
+       return sb_dsp_detect(hw_config, 0, 0);
+}
+
+
+static void via_unload_sb(struct address_info *hw_config)
+{
+       DPRINTK ("ENTER\n");
+
+       if(hw_config->slots[0] != -1)
+               sb_dsp_unload(hw_config, 1);
+
+       DPRINTK("EXIT\n");
+}
+
+
+static const struct {
+       int sb_irq,
+           sb_dma,
+           midi_base,
+           sb_io_base;
+} via_pnp_data[] __initdata = {
+       { 5, 0, 0x300, 0x220 },
+       { 7, 1, 0x310, 0x240 },
+       { 9, 2, 0x320, 0x260 },
+       { 10,3, 0x330, 0x280 },
+};
+
+
+/****************************************************************
+ *
+ * Chip setup and kernel registration
+ *
+ *
+ */
+
+static int __init via82cxxx_install (struct pci_dev *pcidev)
+{
+       int sb_io_base;
+       int sb_irq;
+       int sb_dma;
+       int midi_base, rc;
+       u8 tmp8;
+       struct via_info *card = &cards[num_cards];
+       
+       DPRINTK ("ENTER\n");
+
+       card->pdev = pcidev;
+       card->have_ac97 = -1;
+       
+       /* turn off legacy features, if not already */
+       pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
+       tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
+                 VIA_CR42_FM_ENABLE);
+       pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
+
+       /* 
+        * try to init AC97 mixer device
+        */
+       rc = via_attach_ac97 (card);
+       if (rc) {
+               printk (KERN_WARNING PFX
+                       "AC97 init failed, SB legacy mode only\n");
+       }
+       
+       /* turn on legacy features */
+       pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
+       tmp8 |= VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
+               VIA_CR42_FM_ENABLE;
+       pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
+
+       /* read legacy PNP info byte */
+       pci_read_config_byte (pcidev, VIA_PNP_CONTROL, &tmp8);
+       pci_write_config_byte (pcidev, VIA_PNP_CONTROL, tmp8);
+       
+       sb_irq = via_pnp_data[((tmp8 >> 6) & 0x03)].sb_irq;
+       sb_dma = via_pnp_data[((tmp8 >> 4) & 0x03)].sb_dma;
+       midi_base = via_pnp_data[((tmp8 >> 2) & 0x03)].midi_base;
+       sb_io_base = via_pnp_data[(tmp8 & 0x03)].sb_io_base;
+
+       udelay(100);
+       
+       printk(KERN_INFO PFX "legacy "
+              "MIDI: 0x%X, SB: 0x%X / %d IRQ / %d DMA\n",
+               midi_base, sb_io_base, sb_irq, sb_dma);
+               
+       card->sb_data.name = VIA_CARD_NAME;
+       card->sb_data.card_subtype = MDL_SBPRO;
+       card->sb_data.io_base = sb_io_base;
+       card->sb_data.irq = sb_irq;
+       card->sb_data.dma = sb_dma;
+       
+       /* register legacy SoundBlaster Pro */
+       if (!via_probe_sb (&card->sb_data)) {
+               printk (KERN_ERR PFX
+                       "SB probe @ 0x%X failed, aborting\n",
+                       sb_io_base);
+               DPRINTK ("EXIT, returning -1\n");
+               return -1;
+       }
+       via_attach_sb (&card->sb_data);
+
+       card->opl3_data.name = card->sb_data.name;
+       card->opl3_data.io_base = midi_base;
+       card->opl3_data.irq = -1;
+       
+       /* register legacy MIDI */
+       if (!probe_uart401 (&card->opl3_data)) {
+               printk (KERN_WARNING PFX
+                       "MIDI probe @ 0x%X failed, continuing\n",
+                       midi_base);
+               card->opl3_data.io_base = 0;
+       } else {
+               attach_uart401 (&card->opl3_data);
+       }
+
+       num_cards++;    
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+}
+
+
+/*
+ *     This loop walks the PCI configuration database and finds where
+ *     the sound cards are.
+ *
+ *     Note - only a single PCI scan occurs, eliminating possibility
+ *     of multiple audio chips
+ *
+ */
+static int __init probe_via82cxxx (void)
+{
+       struct pci_dev *pcidev = NULL;
+
+       DPRINTK ("ENTER\n");
+
+       pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
+                                 PCI_DEVICE_ID_VIA_82C686_5, NULL);
+
+       if (!pcidev || via82cxxx_install (pcidev) != 0) {
+               printk (KERN_ERR PFX "audio init failed\n");
+               DPRINTK ("EXIT, returning -1\n");
+               return -1;
+       }
+
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+}
+
+
+/*
+ *     This function is called when the user or kernel loads the 
+ *     module into memory.
+ */
+
+
+static int init_via82cxxx_module(void)
+{
+       u8 tmp;
+       int i;
+       const char *rev = "unknown!";
+       
+       memset (cards, 0, sizeof (cards));
+       
+       DPRINTK ("ENTER\n");
+
+       if (!pci_present ()) {
+               printk (KERN_DEBUG PFX "PCI not present, exiting\n");
+               DPRINTK ("EXIT, returning -ENODEV\n");
+               return -ENODEV;
+       }
+
+       if (probe_via82cxxx() != 0) {
+               printk(KERN_ERR PFX "probe failed, aborting\n");
+               /* XXX unload cards registered so far, if any */
+               DPRINTK ("EXIT, returning -ENODEV\n");
+               return -ENODEV;
+       }
+
+       pci_read_config_byte (cards[0].pdev, PCI_REVISION_ID, &tmp);
+       for (i = 0; i < arraysize(via_chip_revs); i++)
+               if (via_chip_revs[i].revision == tmp) {
+                       rev = via_chip_revs[i].rev_name;
+                       break;
+               }
+       printk (KERN_INFO PFX VIA_CARD_NAME " loaded\n");
+       printk (KERN_INFO PFX "Chip rev %s.  Features: SBPro compat%s%s\n",
+               rev,
+               cards[0].opl3_data.io_base == 0 ? "" : ", MPU-401 MIDI",
+               cards[0].have_ac97 == -1 ? "" : ", AC97 mixer");
+       
+       if (via_init_proc () != 0) {
+               printk (KERN_WARNING PFX
+                       "Unable to init experimental /proc, ignoring\n");
+       }
+
+       /*
+        *      Binds us to the sound subsystem 
+        */
+       SOUND_LOCK;
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+}
+
+int init_module(void) {
+       return init_via82cxxx_module();
+}
+
+/*
+ *     This is called when it is removed. It will only be removed 
+ *     when its use count is 0. For sound the SOUND_LOCK/SOUND_UNLOCK
+ *     macros hide the entire work for this.
+ */
+static void cleanup_via82cxxx_module(void)
+{
+       DPRINTK("ENTER\n");
+       
+       if (cards[0].opl3_data.io_base)
+               unload_uart401 (&cards[0].opl3_data);
+
+       via_unload_sb (&cards[0].sb_data);
+       
+       via_unload_ac97 (&cards[0]);
+
+       via_cleanup_proc ();
+       
+       /*
+        *      Final clean up with the sound layer
+        */
+       SOUND_LOCK_END;
+
+       DPRINTK("EXIT\n");
+}
+
+void cleanup_module(void) {
+       cleanup_via82cxxx_module();
+}
+
index 81a4be6a08dc616dc3889862a8e142d22fbdeaeb..d5ce75e61a9333807c66ccea6bfdd98156d5bff3 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -515,6 +515,8 @@ int flush_old_exec(struct linux_binprm * bprm)
        /* This is the point of no return */
        release_old_signals(oldsig);
 
+       current->sas_ss_sp = current->sas_ss_size = 0;
+
        if (current->euid == current->uid && current->egid == current->gid)
                current->dumpable = 1;
        name = bprm->filename;
index f44887f9936a5a11e6db85aac57fece257c0fcd9..1823b805356e843b3035baf18a869a40afb897d2 100644 (file)
@@ -15,6 +15,7 @@
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
+#include <linux/init.h>
 #include <asm/byteorder.h>
 
 static struct nls_table *tables = (struct nls_table *) NULL;
@@ -429,7 +430,7 @@ EXPORT_SYMBOL(utf8_mbstowcs);
 EXPORT_SYMBOL(utf8_wctomb);
 EXPORT_SYMBOL(utf8_wcstombs);
 
-int init_nls(void)
+int __init init_nls(void)
 {
 #ifdef CONFIG_NLS_ISO8859_1
        init_nls_iso8859_1();
index 7d52ccd5002db75309d718d0a4a1300d2a4ecbb9..7a8dddafa5fef73e0770d0942cbc3a8c7f1eadfc 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -435,7 +436,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp437(void)
+int __init init_nls_cp437(void)
 {
        return register_nls(&table);
 }
index 025ddd61fe984a76340151fe4a9c25e54cd92d21..5987de7425da4fc46453631f4feeadbbe57fef69 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -364,7 +365,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp737(void)
+int __init init_nls_cp737(void)
 {
        return register_nls(&table);
 }
index 255c858be4bbf413ac083fc7948ec19f0e3ff6c2..4418dc577fbebc934ce5336027fb8e7ee80a63ac 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -363,7 +364,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp775(void)
+int __init init_nls_cp775(void)
 {
        return register_nls(&table);
 }
index 8468b42ed9efcb97ab87655148aa010dedc5eae7..4f389544ff79994087a8cbfa55c2c9095dedb797 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -327,7 +328,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp850(void)
+int __init init_nls_cp850(void)
 {
        return register_nls(&table);
 }
index 8d5330cce9e4fb6eb8c9c4b6c50c88fd4467b173..e0c2930acf126e6fb3dd6a1bf361f2b0044a51c3 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -327,7 +328,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp852(void)
+int __init init_nls_cp852(void)
 {
        return register_nls(&table);
 }
index dba571e8ac06ccd51ff9abbc5337ea4636eb5e57..59e24c9a78d1f94486999e387560bc1019e7d565 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -327,7 +328,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp855(void)
+int __init init_nls_cp855(void)
 {
        return register_nls(&table);
 }
index 43f53c7bd3c34f09ce43c8a99743dca036e36ed4..ffff1a97d3aab02c5ae460c319ab949b54f34b5d 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -291,7 +292,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp857(void)
+int __init init_nls_cp857(void)
 {
        return register_nls(&table);
 }
index 89d5b7096cad0a8cdf7afd891d8de0df2ffdc760..f0fecce3401545ffc084d6455105df880c0b66ee 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -399,7 +400,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp860(void)
+int __init init_nls_cp860(void)
 {
        return register_nls(&table);
 }
index ca6ea5b19cc87806f61e9d75e0455613dd3f2290..c7a8a9e17a986579611a1f1f33d009fda324dfe7 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -435,7 +436,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp861(void)
+int __init init_nls_cp861(void)
 {
        return register_nls(&table);
 }
index 77775ecfe225f755eada1f83b91be8120123e69a..c59d81748c5949d2b305ad2a8fbd81b95ba5d64e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -471,7 +472,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp862(void)
+int __init init_nls_cp862(void)
 {
        return register_nls(&table);
 }
index 505f3e6481d8e5e47b13c23fae0fa6cf9ecfc698..db86fd52975cb2c0b435a71f065129d5170971c1 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -435,7 +436,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp863(void)
+int __init init_nls_cp863(void)
 {
        return register_nls(&table);
 }
index 4da15290066b659a7f6f76a261cd116b8d76fd9e..01cbf3cd5648ca09d8fc7c6e785e90188afd9b02 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -426,7 +427,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp864(void)
+int __init init_nls_cp864(void)
 {
        return register_nls(&table);
 }
index 47bdbac7915ba9d56f988d3c422a694d6b888a7c..a303205ebd1eb96f56b21febe214c0417ad1c879 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -435,7 +436,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp865(void)
+int __init init_nls_cp865(void)
 {
        return register_nls(&table);
 }
index 9b5d4aab40f84c83f2fae3394e57ad726842590e..2218ced401b6039777cb2dd719d93f2949d7aa6e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -363,7 +364,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp866(void)
+int __init init_nls_cp866(void)
 {
        return register_nls(&table);
 }
index 5680b93a71e25fdeb3a99febbadb6170c598bd1a..968d2f34d3198f5d38e8833b991772843f0aad55 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -327,7 +328,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp869(void)
+int __init init_nls_cp869(void)
 {
        return register_nls(&table);
 }
index d161855b9bb807ac332da10ef73a4bfb39634b81..71b69aa29ac6ba0a5c1d265a0c6283cd3a0b600b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -291,7 +292,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp874(void)
+int __init init_nls_cp874(void)
 {
        return register_nls(&table);
 }
index da972ea1d9ce736113d295fe092dead722fa88d9..8821e0067bb530459626c8f163d7455fd465a68a 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode c2u_81[256] = {
        {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, /* 0x00-0x03 */
@@ -9809,7 +9810,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp932(void)
+int __init init_nls_cp932(void)
 {
        return register_nls(&table);
 }
index 94b44e2164e76499af443aff4d9005d0ed43426f..c1a5f102bc23ac639342b47e6715aea53b3596f5 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode c2u_81[256] = {
        {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, /* 0x00-0x03 */
@@ -15576,7 +15577,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp936(void)
+int __init init_nls_cp936(void)
 {
        return register_nls(&table);
 }
index 9867df78b2e8550895a20c4fa186e9fb86d735ab..ac575f1569a1960be659238a88af57c1ad31b233 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode c2u_81[256] = {
        {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, /* 0x00-0x03 */
@@ -18364,7 +18365,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp949(void)
+int __init init_nls_cp949(void)
 {
        return register_nls(&table);
 }
index 0f880755dce8e1eac8b1f74742563dca3e096ab9..5bdcaced047673bff3622c973adf53016ed32124 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode c2u_A1[256] = {
        {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, {0x00, 0x3F}, /* 0x00-0x03 */
@@ -12584,7 +12585,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_cp950(void)
+int __init init_nls_cp950(void)
 {
        return register_nls(&table);
 }
index d5b614c1605860615e726eae50f03fd2e9df21f3..bb86de370c19156c1b68c82192fa2192abf0dd4a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -215,7 +216,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_1(void)
+int __init init_nls_iso8859_1(void)
 {
        return register_nls(&table);
 }
index b466a65604759a92e6d006013855dc31c93ef877..538ce8bcb2910cf9a0f83a272ce27cbc6317c22c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -219,6 +220,30 @@ static unsigned char *page_uni2charset[256] = {
        NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
 };
 
+static void uni2char(unsigned char ch, unsigned char cl, unsigned char *out, int boundlen, int *outlen)
+{
+       unsigned char *uni2charset;
+
+       if (boundlen <= 0)
+               return;
+
+       uni2charset = page_uni2charset[ch];
+       if (uni2charset && uni2charset[cl])
+               out[0] = uni2charset[cl];
+       else
+               out[0] = '?';
+       *outlen = 1;
+       return;
+}
+
+static void char2uni(unsigned char *rawstring, int *offset, unsigned char *uni1, unsigned char *uni2)
+{
+       *uni1 = charset2uni[*rawstring].uni1;
+       *uni2 = charset2uni[*rawstring].uni2;
+       *offset = 1;
+       return;
+}
+
 static void inc_use_count(void)
 {
        MOD_INC_USE_COUNT;
@@ -231,14 +256,14 @@ static void dec_use_count(void)
 
 static struct nls_table table = {
        "iso8859-14",
-       page_uni2charset,
-       charset2uni,
+       uni2char,
+       char2uni,
        inc_use_count,
        dec_use_count,
        NULL
 };
 
-int init_nls_iso8859_14(void)
+int __init init_nls_iso8859_14(void)
 {
        return register_nls(&table);
 }
index 2a4829ea3264525293c20e4fa5d2a2658c8d37d1..9a0ae2ede432ba8c1e6b0ac9ab27d01cc1f6e566 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -255,7 +256,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_15(void)
+int __init init_nls_iso8859_15(void)
 {
        return register_nls(&table);
 }
index b6491b2663707734794bbe90e5448fb30dbaf3c4..6baddfc4859662e2d62650bb05a1ff2263b69f90 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -287,7 +288,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_2(void)
+int __init init_nls_iso8859_2(void)
 {
        return register_nls(&table);
 }
index f3d8b23d9450241ece7de4356ac6682af4f87e45..1576aeac4e782cfcfbf1f9109478f08cb788bf01 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -287,7 +288,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_3(void)
+int __init init_nls_iso8859_3(void)
 {
        return register_nls(&table);
 }
index fd746f29eaf44976237804d4d610e8a4fba31d18..7d79070bc8c535819c2a0f391652e2d3af4aadbe 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -287,7 +288,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_4(void)
+int __init init_nls_iso8859_4(void)
 {
        return register_nls(&table);
 }
index 963fdc79f692b461def43adddb26aa250c8c29a6..724149fa1e0d88ccc5c2b3300ed18dc61ca27145 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -291,7 +292,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_5(void)
+int __init init_nls_iso8859_5(void)
 {
        return register_nls(&table);
 }
index 20d80a1a33f735d5281b90289c7b3a4de00cc9ed..f4800a924eddf2872765775eea7f373c696dfb81 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -251,7 +252,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_6(void)
+int __init init_nls_iso8859_6(void)
 {
        return register_nls(&table);
 }
index bb1b64912b692614a883271cf3a04b382279677b..f5f66c008437cb5f0f77e34506073ed308cd8f33 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -327,7 +328,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_7(void)
+int __init init_nls_iso8859_7(void)
 {
        return register_nls(&table);
 }
index 031b9a2a41f766fc4c422c71ddbd89afcdd62355..987e719370ffd03dc2b00b4ff1d8fc4632840cfb 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -291,7 +292,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_8(void)
+int __init init_nls_iso8859_8(void)
 {
        return register_nls(&table);
 }
index f4c1cf13132b9e9563fdbd2cc025107386b72455..eecc051b64311a8e4927206521a1918d6ea9a39a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -251,7 +252,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_iso8859_9(void)
+int __init init_nls_iso8859_9(void)
 {
        return register_nls(&table);
 }
index 71ef8506852d57c881ed354434ed52b4025d230d..1cff830db1d5bee5abc3fa614bc12cc566b91cfd 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/nls.h>
+#include <linux/init.h>
 
 static struct nls_unicode charset2uni[256] = {
        /* 0x00*/
@@ -363,7 +364,7 @@ static struct nls_table table = {
        NULL
 };
 
-int init_nls_koi8_r(void)
+int __init init_nls_koi8_r(void)
 {
        return register_nls(&table);
 }
index 4e38c0a2f75bb57d3eaeb4e9cf4ca38ed4b85107..750443e1f8063f835a7fe84249f8eb512b36130d 100644 (file)
@@ -651,6 +651,26 @@ static unsigned long get_wchan(struct task_struct *p)
                        fp = rw->ins[6] + bias;
                } while (++count < 16);
        }
+#elif defined (__s390__)
+        {
+                unsigned long ksp, backchain, ip;
+                unsigned long stack_page;
+                int count = 0;
+
+                stack_page = (unsigned long)p;
+                ksp = p->tss.ksp;
+                if (!stack_page || ksp < stack_page || ksp >= 8188+stack_page)
+                        return 0;
+                backchain = (*(unsigned long *) ksp) & 0x7fffffff;
+                do {
+                        if (backchain < stack_page || backchain >= 8188+stack_page)
+                                return 0;
+                        ip = (*(unsigned long *) (backchain+56)) & 0x7fffffff;
+                        if (ip < first_sched || ip >= last_sched)
+                                return ip;
+                        backchain = (*(unsigned long *) backchain) & 0x7fffffff;
+                } while (count++ < 16);
+        }
 #endif
 
        return 0;
index 5fe340a5e7ea51ce7cdc251b5f45e6094899536a..782166d168303541fdad9bb8080af1dbed8c61a6 100644 (file)
@@ -365,6 +365,8 @@ typedef struct {
 #define DEVSTAT_DEVICE_GONE        0x00000040
 #define DEVSTAT_DEVICE_OWNED       0x00000080
 #define DEVSTAT_CLEAR_FUNCTION     0x00000100
+#define DEVSTAT_PCI                0x00000200
+#define DEVSTAT_SUSPENDED          0x00000400
 #define DEVSTAT_FINAL_STATUS       0x80000000
 
 #define INTPARM_STATUS_PENDING     0xFFFFFFFF
index 3bedc4fdbdaebcd1a1981856d2a874f9cecce6dc..8b1100290ec1cb1402264375108932a0f2ec3d86 100644 (file)
@@ -630,22 +630,27 @@ extern void __bad_pte_kernel(pmd_t *pmd);
 extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
 {
         address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-        if (pmd_none(*pmd)) {
-                pte_t * page = (pte_t *) get_pte_fast();
-
-                if (!page)
-                        return get_pte_kernel_slow(pmd, address);
-                pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(page);
-                pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(page+1024);
-                pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(page+2048);
-                pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(page+3072);
-                return page + address;
-        }
-        if (pmd_bad(*pmd)) {
-                __bad_pte_kernel(pmd);
-                return NULL;
-        }
+
+        if (pmd_none(*pmd))
+                goto getnew;
+        if (pmd_bad(*pmd))
+                goto fix;
         return (pte_t *) pmd_page(*pmd) + address;
+getnew:
+{
+        unsigned long page = (unsigned long) get_pte_fast();
+
+        if (!page)
+                return get_pte_kernel_slow(pmd, address);
+        pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(page);
+        pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(page+1024);
+        pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(page+2048);
+        pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(page+3072);
+        return (pte_t *) page + address;
+}
+fix:
+        __bad_pte_kernel(pmd);
+        return NULL;
 }
 
 extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
index 9089d34be1368319782737df72928e7e68441f60..5a07956651d13224f28a31627489172415375c5d 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  *  include/asm-s390/ptrace.h
  *
@@ -133,6 +134,8 @@ struct user_regs_struct
  * this is the way intel does it
  */
        per_struct per_info;
+       addr_t  ieee_instruction_pointer; 
+       /* Used to give failing instruction back to user for ieee exceptions */
 };
 
 typedef struct user_regs_struct user_regs_struct;
@@ -269,8 +272,9 @@ enum
        PT_CR_9=pt_off(per_info.control_regs.words.cr[0]),
        PT_CR_10=pt_off(per_info.control_regs.words.cr[1]),
        PT_CR_11=pt_off(per_info.control_regs.words.cr[2]),
-       PT_LASTOFF=PT_CR_11,
-       PT_ENDREGS=offsetof(user_regs_struct,per_info.lowcore.words.perc_atmid)
+       PT_IEEE_IP=pt_off(ieee_instruction_pointer),
+       PT_LASTOFF=PT_IEEE_IP,
+       PT_ENDREGS=sizeof(user_regs_struct)-1
 };
 
 #define PTRACE_AREA \
index 586d92cae86aa67ad5c8b6c19ff75b3fcce3bbcd..aabd220725bcff11041af7c48416d995d93b646e 100644 (file)
@@ -69,6 +69,12 @@ typedef struct
        freg_t  fprs[NUM_FPRS];              
 } s390_fp_regs;
 
+#define FPC_DXC_MASK            0x0000FF00
+#define FPC_EXCEPTION_MASK      0xF8000000
+#define FPC_FLAGS_MASK          0x00F80000
+#define FPC_RM_MASK             0x00000003
+
+
 /*
   gdb structures & the kernel have this much always in common
  */
index 1531db729d9acbf4cb707b3f6b73e6e5d41db831..e63f73be15d3f936e640776c1f6033313f125f2b 100644 (file)
@@ -69,6 +69,7 @@ typedef struct _ioinfo {
      devstat_t     devstat;       /* device status */
      ccw1_t       *qcpa;          /* queued channel program */
      ccw1_t        senseccw;      /* ccw for sense command */
+     __u8          sense_data[32];/* buffer for basic sense */
      unsigned int  stctl;         /* accumulated status control from irb */
      unsigned long qintparm;      /* queued interruption parameter  */
      unsigned long qflag;         /* queued flags */
index 03c93dadde0e391491c553247bc3ceef83f93b22..cb82da06265a895c6a41e7fce037d7951ba496c8 100644 (file)
@@ -10,7 +10,6 @@
 #define _LINUX_CAPABILITY_H
 
 #include <linux/types.h>
-#include <linux/fs.h>
 
 /* User-level do most of the mapping between kernel and user
    capabilities based on the version tag given by the kernel. The
index 0867c8a9d0e215c1c65bdc48af99758f9250fe4b..5b361a617e0c3762b9e8c0824eddcee5ca6acc1a 100644 (file)
@@ -36,6 +36,7 @@ extern int init_nls_iso8859_6(void);
 extern int init_nls_iso8859_7(void);
 extern int init_nls_iso8859_8(void);
 extern int init_nls_iso8859_9(void);
+extern int init_nls_iso8859_14(void);
 extern int init_nls_iso8859_15(void);
 extern int init_nls_cp437(void);
 extern int init_nls_cp737(void);
index cbafb4d78bf3d5d2c8a53320f04e772add630ad7..aa972681fa8d7f6cfb748c6f808136f0e26eb80d 100644 (file)
 #define PCI_VENDOR_ID_AFAVLAB          0x14db
 #define PCI_DEVICE_ID_AFAVLAB_TK9902   0x2120
 
+#define PCI_VENDOR_ID_TIMEDIA          0x1409
+#define PCI_DEVICE_ID_TIMEDIA_4008A    0x7268
+
 #define PCI_VENDOR_ID_SYMPHONY         0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101     0x0001
 
index 653009adf15e27f791c05a34745ba64e7e63ee16..1842222be21e8f1664e3753b13b3d7385beccdaa 100644 (file)
  * Pick up the architecture specific timex specifications
  */
 #include <asm/timex.h>
+/*
+ * Pick up the definition of timeval
+ */
+#include <linux/time.h>
 
 /* LATCH is used in the interval timer and ftape setup. */
 #define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
index 67320db695cdc68be025724de2e75f2c848714f0..fb0472333aea4d4fcd30d6e14fbe6750e0d4d76d 100644 (file)
@@ -9,13 +9,15 @@
 Original driver (sg.h):
 *       Copyright (C) 1992 Lawrence Foard
 2.x extensions to driver:
-*       Copyright (C) 1998, 1999 Douglas Gilbert
+*       Copyright (C) 1998 - 2000 Douglas Gilbert
 
-
-    Version: 2.1.36 (991008)
+    Version: 2.1.37 (20000504)
     This version for 2.2.x series kernels
     D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au)
 
+    Changes since 2.1.36 (991008)
+        - fix 0 length scatter gather requests + alignment
+        - activate SG_SCSI_RESET ioctl() [to work needs mid level changes]
     Changes since 2.1.34 (990603)
         - skipped 2.1.35 (never fully released)
         - add queuing info into struct sg_scsi_id
@@ -35,19 +37,24 @@ Original driver (sg.h):
         - clean up logging of pointers to use %p (for 64 bit architectures)
         - rework usage of get_user/copy_to_user family of kernel calls
         - "disown" scsi_command blocks before releasing them
-    Changes since 2.1.30 (990320)
-        - memory tweaks: change flags on kmalloc (GFP_KERNEL to GFP_ATOMIC)
-        -                increase max allowable mid-level pool usage
 
+Map of SG verions to the Linux kernels in which they appear:
+       ----------        ----------------------------------
+       original          all kernels < 2.2.6
+       2.1.31            2.2.6 and 2.2.7
+       2.1.32            2.2.8 and 2.2.9
+       2.1.34            2.2.10 to 2.2.13
+       2.1.36            2.2.14 and 2.2.15
+       2.1.37            2.2.16
+       3.0.13            optional version 3 sg driver for 2.2 series
+       3.1.13            2.3.99-pre5, version 3 sg driver for 2.3 series
 
     New features and changes:
-        - per file descriptor (fd) write-read sequencing and command queues.
-        - command queuing supported (SG_MAX_QUEUE is maximum per fd).
+        - per file descriptor (fd) write-read sequencing
+        - command queuing supported
         - scatter-gather supported (allowing potentially megabyte transfers).
-        - the SCSI target, host and driver status are returned
-          in unused fields of sg_header (maintaining its original size).
-        - asynchronous notification support added (SIGPOLL, SIGIO) for
-          read()s (write()s should never block).
+        - more SCSI status information returned
+        - asynchronous notification support added (SIGPOLL, SIGIO)
         - pack_id logic added so read() can wait for a specific pack_id. 
         - uses memory > ISA_DMA_THRESHOLD if adapter allows it (e.g. a
           pci scsi adapter).
@@ -68,61 +75,21 @@ Original driver (sg.h):
           calling the ioctl of the same name is a more flexible and
           safer approach.
         - adds several ioctl calls, see ioctl section below.
- Good documentation on the original "sg" device interface and usage can be
- found in the Linux HOWTO document: "SCSI Programming HOWTO" (version 0.5)
- by Heiko Eissfeldt; last updated 7 May 1996. Here is a quick summary of
- sg basics:
- An SG device is accessed by writing SCSI commands plus any associated 
- outgoing data to it; the resulting status codes and any incoming data
- are then obtained by a read call. The device can be opened O_NONBLOCK
- (non-blocking) and poll() used to monitor its progress. The device may be
- opened O_EXCL which excludes other "sg" users from this device (but not 
- "sd", "st" or "sr" users). The buffer given to the write() call is made
- up as follows:
-        - struct sg_header image (see below)
-        - scsi command (6, 10 or 12 bytes long)
-        - data to be written to the device (if any)
-
- The buffer received from the corresponding read() call contains:
-        - struct sg_header image (check results + sense_buffer)
-        - data read back from device (if any)
-
- The given SCSI command has its LUN field overwritten internally by the
- value associated with the device that has been opened.
-
- This device currently uses "indirect IO" in the sense that data is
- DMAed into kernel buffers from the hardware and afterwards is
- transferred into the user space (or vice versa if you are writing).
- Transfer speeds or up to 20 to 30MBytes/sec have been measured using
- indirect IO. For faster throughputs "direct IO" which cuts out the
- double handling of data is required. This will also need a new interface.
-
- Grabbing memory for those kernel buffers used in this driver for DMA may
- cause the dreaded ENOMEM error. This error seems to be more prevalent 
- under early 2.2.x kernels than under the 2.0.x kernel series. For a given 
- (large) transfer the memory obtained by this driver must be contiguous or
- scatter-gather must be used (if supported by the adapter). [Furthermore, 
- ISA SCSI adapters can only use memory below the 16MB level on a i386.]
-
- When a "sg" device is open()ed O_RDWR then this driver will attempt to
- reserve a buffer of SG_DEF_RESERVED_SIZE that will be used by subsequent
- write()s on this file descriptor as long as:
-    -  it is not already in use (eg when command queuing is in use)
-    -  the write() does not call for a buffer size larger than the
-       reserved size.
- In these cases the write() will attempt to find the memory it needs for
- DMA buffers dynamically and in the worst case will fail with ENOMEM.
- The amount of memory actually reserved depends on various dynamic factors
- and can be checked with the SG_GET_RESERVED_SIZE ioctl(). [In a very
- tight memory situation it may yield 0!] The size of the reserved buffer
- can be changed with the SG_SET_RESERVED_SIZE ioctl(). It should be
- followed with a call to the SG_GET_RESERVED_SIZE ioctl() to find out how
- much was actually reserved.
-
- More documentation plus test and utility programs can be found at 
- http://www.torque.net/sg
+
+ Documentation
+ =============
+ A web site for SG device drivers can be found at:
+        http://www.torque.net/sg  [alternatively check the MAINTAINERS file]
+ The main documents are still based on 2.x versions:
+        http://www.torque.net/sg/p/scsi-generic.txt
+        http://www.torque.net/sg/p/scsi-generic_long.txt
+ The first document can also be found in the kernel source tree, probably at:
+        /usr/src/linux/Documentation/scsi-generic.txt .
+ Documentation on the changes and additions in 3.x version of the sg driver
+ can be found at: http://www.torque.net/sg/p/scsi-generic_v3.txt
+ Utility and test programs are also available at that web site.
 */
 
 #define SG_MAX_SENSE 16   /* too little, unlikely to change in 2.2.x */
 
@@ -213,9 +180,13 @@ typedef struct sg_scsi_id {
 #define SG_NEXT_CMD_LEN 0x2283  /* override SCSI command length with given
                    number on the next write() on this file descriptor */
 
-/* Returns -EBUSY if occupied else takes as input: 0 -> do nothing,
-   1 -> device reset or  2 -> bus reset (not operational yet) */
+/* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */
 #define SG_SCSI_RESET 0x2284
+/* Associated values that can be given to SG_SCSI_RESET follow */
+#define         SG_SCSI_RESET_NOTHING   0
+#define         SG_SCSI_RESET_DEVICE    1
+#define         SG_SCSI_RESET_BUS       2
+#define         SG_SCSI_RESET_HOST      3
 
 
 #define SG_SCATTER_SZ (8 * 4096)  /* PAGE_SIZE not available to user */
index 74fbb38405e56e4774dc68737c7fab089edd986f..8980bc39778bfd22f9f50b9eb5eca72e5ee737c8 100644 (file)
@@ -405,9 +405,7 @@ EXPORT_SYMBOL(brw_page);
 EXPORT_SYMBOL(add_mouse_randomness);
 EXPORT_SYMBOL(fasync_helper);
 
-#ifdef CONFIG_BLK_DEV_MD
-EXPORT_SYMBOL(disk_name);      /* for md.c */
-#endif
+EXPORT_SYMBOL(disk_name);      /* for md.c and others */
 
 /* binfmt_aout */
 EXPORT_SYMBOL(get_write_access);
diff --git a/p_sg2136_sg2137 b/p_sg2136_sg2137
new file mode 100644 (file)
index 0000000..623f167
--- /dev/null
@@ -0,0 +1,291 @@
+--- linux/include/scsi/sg.h    Thu Jan 13 20:40:36 2000
++++ linux/include/scsi/sg.h2137        Thu May  4 01:25:19 2000
+@@ -9,13 +9,15 @@
+ Original driver (sg.h):
+ *       Copyright (C) 1992 Lawrence Foard
+ 2.x extensions to driver:
+-*       Copyright (C) 1998, 1999 Douglas Gilbert
+-
++*       Copyright (C) 1998 - 2000 Douglas Gilbert
+-    Version: 2.1.36 (991008)
++    Version: 2.1.37 (20000504)
+     This version for 2.2.x series kernels
+     D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au)
++    Changes since 2.1.36 (991008)
++        - fix 0 length scatter gather requests + alignment
++        - activate SG_SCSI_RESET ioctl() [to work needs mid level changes]
+     Changes since 2.1.34 (990603)
+         - skipped 2.1.35 (never fully released)
+         - add queuing info into struct sg_scsi_id
+@@ -35,19 +37,24 @@
+         - clean up logging of pointers to use %p (for 64 bit architectures)
+         - rework usage of get_user/copy_to_user family of kernel calls
+         - "disown" scsi_command blocks before releasing them
+-    Changes since 2.1.30 (990320)
+-        - memory tweaks: change flags on kmalloc (GFP_KERNEL to GFP_ATOMIC)
+-        -                increase max allowable mid-level pool usage
++Map of SG verions to the Linux kernels in which they appear:
++       ----------        ----------------------------------
++       original          all kernels < 2.2.6
++       2.1.31            2.2.6 and 2.2.7
++       2.1.32            2.2.8 and 2.2.9
++       2.1.34            2.2.10 to 2.2.13
++       2.1.36            2.2.14 and 2.2.15
++       2.1.37            2.2.16
++       3.0.13            optional version 3 sg driver for 2.2 series
++       3.1.13            2.3.99-pre5, version 3 sg driver for 2.3 series
+     New features and changes:
+-        - per file descriptor (fd) write-read sequencing and command queues.
+-        - command queuing supported (SG_MAX_QUEUE is maximum per fd).
++        - per file descriptor (fd) write-read sequencing
++        - command queuing supported
+         - scatter-gather supported (allowing potentially megabyte transfers).
+-        - the SCSI target, host and driver status are returned
+-          in unused fields of sg_header (maintaining its original size).
+-        - asynchronous notification support added (SIGPOLL, SIGIO) for
+-          read()s (write()s should never block).
++        - more SCSI status information returned
++        - asynchronous notification support added (SIGPOLL, SIGIO)
+         - pack_id logic added so read() can wait for a specific pack_id. 
+         - uses memory > ISA_DMA_THRESHOLD if adapter allows it (e.g. a
+           pci scsi adapter).
+@@ -68,61 +75,21 @@
+           calling the ioctl of the same name is a more flexible and
+           safer approach.
+         - adds several ioctl calls, see ioctl section below.
+- 
+- Good documentation on the original "sg" device interface and usage can be
+- found in the Linux HOWTO document: "SCSI Programming HOWTO" (version 0.5)
+- by Heiko Eissfeldt; last updated 7 May 1996. Here is a quick summary of
+- sg basics:
+- An SG device is accessed by writing SCSI commands plus any associated 
+- outgoing data to it; the resulting status codes and any incoming data
+- are then obtained by a read call. The device can be opened O_NONBLOCK
+- (non-blocking) and poll() used to monitor its progress. The device may be
+- opened O_EXCL which excludes other "sg" users from this device (but not 
+- "sd", "st" or "sr" users). The buffer given to the write() call is made
+- up as follows:
+-        - struct sg_header image (see below)
+-        - scsi command (6, 10 or 12 bytes long)
+-        - data to be written to the device (if any)
+-
+- The buffer received from the corresponding read() call contains:
+-        - struct sg_header image (check results + sense_buffer)
+-        - data read back from device (if any)
+-
+- The given SCSI command has its LUN field overwritten internally by the
+- value associated with the device that has been opened.
+- This device currently uses "indirect IO" in the sense that data is
+- DMAed into kernel buffers from the hardware and afterwards is
+- transferred into the user space (or vice versa if you are writing).
+- Transfer speeds or up to 20 to 30MBytes/sec have been measured using
+- indirect IO. For faster throughputs "direct IO" which cuts out the
+- double handling of data is required. This will also need a new interface.
+-
+- Grabbing memory for those kernel buffers used in this driver for DMA may
+- cause the dreaded ENOMEM error. This error seems to be more prevalent 
+- under early 2.2.x kernels than under the 2.0.x kernel series. For a given 
+- (large) transfer the memory obtained by this driver must be contiguous or
+- scatter-gather must be used (if supported by the adapter). [Furthermore, 
+- ISA SCSI adapters can only use memory below the 16MB level on a i386.]
+-
+- When a "sg" device is open()ed O_RDWR then this driver will attempt to
+- reserve a buffer of SG_DEF_RESERVED_SIZE that will be used by subsequent
+- write()s on this file descriptor as long as:
+-    -  it is not already in use (eg when command queuing is in use)
+-    -  the write() does not call for a buffer size larger than the
+-       reserved size.
+- In these cases the write() will attempt to find the memory it needs for
+- DMA buffers dynamically and in the worst case will fail with ENOMEM.
+- The amount of memory actually reserved depends on various dynamic factors
+- and can be checked with the SG_GET_RESERVED_SIZE ioctl(). [In a very
+- tight memory situation it may yield 0!] The size of the reserved buffer
+- can be changed with the SG_SET_RESERVED_SIZE ioctl(). It should be
+- followed with a call to the SG_GET_RESERVED_SIZE ioctl() to find out how
+- much was actually reserved.
+-
+- More documentation plus test and utility programs can be found at 
+- http://www.torque.net/sg
++ Documentation
++ =============
++ A web site for SG device drivers can be found at:
++        http://www.torque.net/sg  [alternatively check the MAINTAINERS file]
++ The main documents are still based on 2.x versions:
++        http://www.torque.net/sg/p/scsi-generic.txt
++        http://www.torque.net/sg/p/scsi-generic_long.txt
++ The first document can also be found in the kernel source tree, probably at:
++        /usr/src/linux/Documentation/scsi-generic.txt .
++ Documentation on the changes and additions in 3.x version of the sg driver
++ can be found at: http://www.torque.net/sg/p/scsi-generic_v3.txt
++ Utility and test programs are also available at that web site.
+ */
++ 
+ #define SG_MAX_SENSE 16   /* too little, unlikely to change in 2.2.x */
+@@ -213,9 +180,13 @@
+ #define SG_NEXT_CMD_LEN 0x2283  /* override SCSI command length with given
+                    number on the next write() on this file descriptor */
+-/* Returns -EBUSY if occupied else takes as input: 0 -> do nothing,
+-   1 -> device reset or  2 -> bus reset (not operational yet) */
++/* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */
+ #define SG_SCSI_RESET 0x2284
++/* Associated values that can be given to SG_SCSI_RESET follow */
++#define         SG_SCSI_RESET_NOTHING   0
++#define         SG_SCSI_RESET_DEVICE    1
++#define         SG_SCSI_RESET_BUS       2
++#define         SG_SCSI_RESET_HOST      3
+ #define SG_SCATTER_SZ (8 * 4096)  /* PAGE_SIZE not available to user */
+--- linux/drivers/scsi/sg.c    Thu Jan 13 20:40:23 2000
++++ linux/drivers/scsi/sg.c2137        Thu May  4 01:24:01 2000
+@@ -7,7 +7,7 @@
+  * Original driver (sg.c):
+  *        Copyright (C) 1992 Lawrence Foard
+  * 2.x extensions to driver:
+- *        Copyright (C) 1998, 1999 Douglas Gilbert
++ *        Copyright (C) 1998 - 2000 Douglas Gilbert
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -16,8 +16,8 @@
+  *
+  *  Borrows code from st driver. Thanks to Alessandro Rubini's "dd" book.
+  */
+- static char * sg_version_str = "Version: 2.1.36 (991218)";
+- static int sg_version_num = 20136; /* 2 digits for each component */
++ static char * sg_version_str = "Version: 2.1.37 (20000504)";
++ static int sg_version_num = 20137; /* 2 digits for each component */
+ /*
+  *  D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
+  *      - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
+@@ -100,7 +100,7 @@
+ static void sg_detach(Scsi_Device *);
+-struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff,
++struct Scsi_Device_Template sg_template = {NULL, "generic", "sg", NULL, 0xff,
+                                            SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
+                                            sg_detect, sg_init,
+                                            sg_finish, sg_attach, sg_detach};
+@@ -609,8 +609,29 @@
+             return -EBUSY;
+         result = get_user(val, (int *)arg);
+         if (result) return result;
+-        /* Don't do anything till scsi mod level visibility */
+-        return 0;
++        if (SG_SCSI_RESET_NOTHING == val)
++            return 0;
++#ifdef SCSI_TRY_RESET_DEVICE
++        switch (val)
++        {
++        case SG_SCSI_RESET_DEVICE:
++            val = SCSI_TRY_RESET_DEVICE;
++            break;
++        case SG_SCSI_RESET_BUS:
++            val = SCSI_TRY_RESET_BUS;
++            break;
++        case SG_SCSI_RESET_HOST:
++            val = SCSI_TRY_RESET_HOST;
++            break;
++        default:
++            return -EINVAL;
++        }
++        if(! capable(CAP_SYS_ADMIN))  return -EACCES;
++        return (scsi_reset_provider(sdp->device, val) == SUCCESS) ? 0 : -EIO;
++#else
++        SCSI_LOG_TIMEOUT(1, printk("sg_ioctl: SG_RESET_SCSI not supported\n"));
++        result = -EINVAL;
++#endif
+     case SCSI_IOCTL_SEND_COMMAND:
+         /* Allow SCSI_IOCTL_SEND_COMMAND without checking suser() since the
+            user already has read/write access to the generic device and so
+@@ -1124,6 +1145,8 @@
+     SCSI_LOG_TIMEOUT(4, printk("sg_start_req: max_buff_size=%d\n", 
+                                max_buff_size)); 
++    if (max_buff_size <= 0)
++        return 0;
+     if ((! sg_res_in_use(sfp)) && (max_buff_size <= rsv_schp->bufflen)) {
+         sg_link_reserve(sfp, srp, max_buff_size);
+         sg_write_xfer(req_schp, inp, num_write_xfer);
+@@ -1351,6 +1374,8 @@
+     Sg_scatter_hold * rsv_schp = &sfp->reserve;
+     SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); 
++    /* round request up to next highest SG_SECTOR_SZ byte boundary */
++    size = (size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
+     if (rsv_schp->use_sg > 0) {
+         int k, num;
+         int rem = size;
+@@ -1431,12 +1456,12 @@
+ static Sg_request * sg_add_request(Sg_fd * sfp)
+ {
+     int k;
+-    Sg_request * resp = NULL;
+-    Sg_request * rp;
++    Sg_request * resp = sfp->headrp;
++    Sg_request * rp = sfp->req_arr;
+-    resp = sfp->headrp;
+-    rp = sfp->req_arr;
+     if (! resp) {
++        memset(rp, 0, sizeof(Sg_request));
++        rp->parentfp = sfp;
+         resp = rp;
+         sfp->headrp = resp;
+     }
+@@ -1444,12 +1469,15 @@
+         if (0 == sfp->cmd_q)
+             resp = NULL;   /* command queuing disallowed */
+         else {
+-            for (k = 0, rp; k < SG_MAX_QUEUE; ++k, ++rp) {
++            for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
+                 if (! rp->parentfp)
+                     break;
+             }
+             if (k < SG_MAX_QUEUE) {
+-                while (resp->nextrp) resp = resp->nextrp;
++                memset(rp, 0, sizeof(Sg_request));
++                rp->parentfp = sfp;
++                while (resp->nextrp) 
++                    resp = resp->nextrp;
+                 resp->nextrp = rp;
+                 resp = rp;
+             }
+@@ -1458,11 +1486,7 @@
+         }
+     }
+     if (resp) {
+-        resp->parentfp = sfp;
+         resp->nextrp = NULL;
+-        resp->res_used = 0;
+-        memset(&resp->data, 0, sizeof(Sg_scatter_hold));
+-        memset(&resp->header, 0, sizeof(struct sg_header));
+         resp->my_cmdp = NULL;
+     }
+     return resp;
+@@ -1478,14 +1502,14 @@
+         return 0;
+     prev_rp = sfp->headrp;
+     if (srp == prev_rp) {
+-        prev_rp->parentfp = NULL;
+         sfp->headrp = prev_rp->nextrp;
++        prev_rp->parentfp = NULL;
+         return 1;
+     }
+     while ((rp = prev_rp->nextrp)) {
+         if (srp == rp) {
+-            rp->parentfp = NULL;
+             prev_rp->nextrp = rp->nextrp;
++            rp->parentfp = NULL;
+             return 1;
+         }
+         prev_rp = rp;