]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.21pre1 2.2.21pre1
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:24:03 +0000 (15:24 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:24:03 +0000 (15:24 -0500)
o Fix potential corruption with vmalloc on (Ralf Baechle)
virtually cached boxes
o Small PPC build fixups (Tom Rini)
o zImage booting fix (Kalev Soikonen)
o EIO on NFS read fixup (Trond Myklebust)
o Update 3ware raid driver (Adam Radford)
o page_alloc race fix (Andrea Arcangeli)
o Update USB maintainers (Greg Kroah-Hartmann)
o bttv clipcount=0 fix (Solar Designer)
o Fix multiple eepro driver bugs (Aris)
o Sym53c8xx queue handling fix (Gerard Roudier)
o Update SubmittingDrivers document (Michal Svec)
o 8139too performance tune (Jens David)
o procfs follow link return fix (Solar Designer)
o Backport SEM_UNDO overflow fix from 2.4 (Leonid Igolnik)
o VM86 fixes (Manfred Spraul)
o Fix alpha build (Kim Heino)

21 files changed:
Documentation/SubmittingDrivers
MAINTAINERS
Makefile
arch/i386/boot/compressed/misc.c
arch/i386/kernel/vm86.c
arch/ppc/kernel/ppc_ksyms.c
drivers/block/ll_rw_blk.c
drivers/char/bttv.c
drivers/net/8139too.c
drivers/net/eepro.c
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/53c7,8xx.c
drivers/scsi/sym53c8xx.c
fs/nfs/read.c
fs/proc/root.c
include/asm-alpha/pci.h
include/linux/sem.h
ipc/sem.c
mm/page_alloc.c
mm/vmalloc.c

index db8540ce121245ded4a81a8136d1202cb1e8ce2d..1b618364f4be850f7117388c178283920bb6550e 100644 (file)
@@ -2,7 +2,7 @@ Submitting Drivers For The Linux Kernel
 ---------------------------------------
 
 This document is intended to explain how to submit device drivers to the
-Linux 2.2 and 2.4test kernel trees. Note that if you are interested in video
+Linux 2.2, 2.4 and 2.5 kernel trees. Note that if you are interested in video
 card drivers you should probably talk to XFree86 (http://wwww.xfree86.org) 
 instead.
 
@@ -10,9 +10,9 @@ Allocating Device Numbers
 -------------------------
 
 Major and minor numbers for devices are allocated by the Linux assigned name
-and number authority (currently better known as H Peter Anvin). The
-site is http://www.lanana.org/. This also deals with allocating numbers for
-devices that are not going to be submitted to the mainstream kernel.
+and number authority (currently better known as H Peter Anvin). The site is
+http://www.lanana.org/. This also deals with allocating numbers for devices
+that are not going to be submitted to the mainstream kernel.
 
 If you don't use assigned numbers then when you device is submitted it will
 get given an assigned number even if that is different from values you may
@@ -22,21 +22,28 @@ Who To Submit Drivers To
 ------------------------
 
 Linux 2.0:
-       No new drivers are accepted for this kernel tree
+       No new drivers are accepted for this kernel tree. If you have any
+       security or other fixes then please contact David Weinehall
+       <tao@acc.umu.se>
 
 Linux 2.2:
        If the code area has a general maintainer then please submit it to
        the maintainer listed in MAINTAINERS in the kernel file. If the
        maintainer does not respond or you cannot find the appropriate
-       maintainer then please contact Alan Cox <alan@lxorguk.ukuu.org.uk>
+       maintainer then please contact Alan Cox <alan@lxorguk.ukuu.org.uk>.
 
-Linux 2.4test:
+Linux 2.4:
+       If the code area has a general maintainer then please submit it to
+       the maintainer listed in MAINTAINERS in the kernel file. If the
+       maintainer does not respond or you cannot find the appropriate
+       maintainer then please contact Marcelo Tosatti
+       <marcelo@conectiva.com.br>.
+
+Linux 2.5:
        This kernel tree is under active development. The same rules apply
-       as 2.2 but you may wish to submit your driver via linux-kernel (see
-       resources) and follow that list to track changes in API's. These
-       should no longer be occurring as we are now in a code freeze.
-       The final contact point for Linux 2.4 submissions is    
-       <torvalds@transmeta.com>.
+       as 2.4 but you may wish to submit your driver via linux-kernel (see
+       resources) and follow that list to track changes in API's. The final
+       contact point for Linux 2.5 submissions is <torvalds@transmeta.com>.
 
 What Criteria Determine Acceptance
 ----------------------------------
index d7b914986999280d552bb8fdcf386b0e4f129068..10e537f5f56cf7fb3b2416e2c139c149b558dc99 100644 (file)
@@ -1000,9 +1000,8 @@ L:        linux-kernel@vger.kernel.org
 S:     Maintained
 
 USB SUBSYSTEM
-P:     Johannes Erdfelt
-M      jerdfelt@valinux.com
-M:     johannes@erdfelt.com
+P:     Greg Kroah-Hartman
+M:     greg@kroah.com
 L:     linux-usb-users@lists.sourceforge.net
 L:     linux-usb-devel@lists.sourceforge.net
 W:     http://www.linux-usb.org
index 54b565991ebcf9d59dcc26cfb8e5a7564bc545d2..462bc7ec8814255e3305bf8a015d6da74a2cd9f2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
-SUBLEVEL = 20
-EXTRAVERSION =
+SUBLEVEL = 21
+EXTRAVERSION = pre1
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index 6279fc726cd9d3ba5903228d4985a700d2e51cf2..547ec8f64c7a3a96af9242b32f2ec8b056f6da84 100644 (file)
@@ -297,6 +297,7 @@ void setup_normal_output_buffer()
        if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n");
 #endif
        output_data = (char *)0x100000; /* Points to 1M */
+       free_mem_end_ptr = (long)real_mode;
 }
 
 struct moveparams {
index 6d1badf75bb8dfd39450412570daba8aaeffa475..eb0799ed03f85319312c14c3b4bff37389ed86ea 100644 (file)
@@ -330,74 +330,176 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
  * Boy are these ugly, but we need to do the correct 16-bit arithmetic.
  * Gcc makes a mess of it, so we do it inline and use non-obvious calling
  * conventions..
+ * FIXME: is VM86_UNKNOWN really the correct return code?
  */
-#define pushb(base, ptr, val) \
-__asm__ __volatile__( \
-       "decw %w0\n\t" \
-       "movb %2,0(%1,%0)" \
-       : "=r" (ptr) \
-       : "r" (base), "q" (val), "0" (ptr))
-
-#define pushw(base, ptr, val) \
-__asm__ __volatile__( \
-       "decw %w0\n\t" \
-       "movb %h2,0(%1,%0)\n\t" \
-       "decw %w0\n\t" \
-       "movb %b2,0(%1,%0)" \
-       : "=r" (ptr) \
-       : "r" (base), "q" (val), "0" (ptr))
-
-#define pushl(base, ptr, val) \
-__asm__ __volatile__( \
-       "decw %w0\n\t" \
-       "rorl $16,%2\n\t" \
-       "movb %h2,0(%1,%0)\n\t" \
-       "decw %w0\n\t" \
-       "movb %b2,0(%1,%0)\n\t" \
-       "decw %w0\n\t" \
-       "rorl $16,%2\n\t" \
-       "movb %h2,0(%1,%0)\n\t" \
-       "decw %w0\n\t" \
-       "movb %b2,0(%1,%0)" \
-       : "=r" (ptr) \
-       : "r" (base), "q" (val), "0" (ptr))
-
-#define popb(base, ptr) \
-({ unsigned long __res; \
-__asm__ __volatile__( \
-       "movb 0(%1,%0),%b2\n\t" \
-       "incw %w0" \
-       : "=r" (ptr), "=r" (base), "=q" (__res) \
-       : "0" (ptr), "1" (base), "2" (0)); \
-__res; })
-
-#define popw(base, ptr) \
-({ unsigned long __res; \
-__asm__ __volatile__( \
-       "movb 0(%1,%0),%b2\n\t" \
-       "incw %w0\n\t" \
-       "movb 0(%1,%0),%h2\n\t" \
-       "incw %w0" \
-       : "=r" (ptr), "=r" (base), "=q" (__res) \
-       : "0" (ptr), "1" (base), "2" (0)); \
-__res; })
-
-#define popl(base, ptr) \
-({ unsigned long __res; \
-__asm__ __volatile__( \
-       "movb 0(%1,%0),%b2\n\t" \
-       "incw %w0\n\t" \
-       "movb 0(%1,%0),%h2\n\t" \
-       "incw %w0\n\t" \
-       "rorl $16,%2\n\t" \
-       "movb 0(%1,%0),%b2\n\t" \
-       "incw %w0\n\t" \
-       "movb 0(%1,%0),%h2\n\t" \
-       "incw %w0\n\t" \
-       "rorl $16,%2" \
-       : "=r" (ptr), "=r" (base), "=q" (__res) \
-       : "0" (ptr), "1" (base)); \
-__res; })
+#define pushb(base, ptr, val, regs) \
+       do { \
+               int err; \
+               __asm__ __volatile__(                           \
+                       "decw %w0\n\t"                          \
+                       "1: movb %3,0(%2,%0)\n\t"               \
+                       "xor %1,%1\n\t"                         \
+                       "2:\n"                                  \
+                       ".section .fixup,\"ax\"\n\t"            \
+                       "3:     movl $1,%1\n\t"                 \
+                       "       jmp 2b\n\t"                     \
+                       ".previous\n"                           \
+                       ".section __ex_table,\"a\"\n"           \
+                       "       .align 4\n"                     \
+                       "       .long 1b,3b\n"                  \
+                       ".previous"                             \
+                       : "=r" (ptr), "=r" (err)                \
+                       : "r" (base), "q" (val), "0" (ptr));    \
+               if (err) \
+                       return_to_32bit(regs, VM86_UNKNOWN); \
+       } while(0)
+
+#define pushw(base, ptr, val, regs) \
+       do { \
+               int err; \
+               __asm__ __volatile__(                           \
+                       "decw %w0\n\t"                          \
+                       "1: movb %h3,0(%2,%0)\n\t"              \
+                       "decw %w0\n\t"                          \
+                       "2: movb %b3,0(%2,%0)\n\t"              \
+                       "xor %1,%1\n\t"                         \
+                       "3:\n"                                  \
+                       ".section .fixup,\"ax\"\n\t"            \
+                       "4:     movl $1,%1\n\t"                 \
+                       "       jmp 3b\n\t"                     \
+                       ".previous\n"                           \
+                       ".section __ex_table,\"a\"\n"           \
+                       "       .align 4\n"                     \
+                       "       .long 1b,4b\n"                  \
+                       "       .long 2b,4b\n"                  \
+                       ".previous"                             \
+                       : "=r" (ptr), "=r" (err)                \
+                       : "r" (base), "q" (val), "0" (ptr));    \
+               if (err) \
+                       return_to_32bit(regs, VM86_UNKNOWN); \
+       } while(0)
+
+#define pushl(base, ptr, val, regs) \
+       do { \
+               int err; \
+               __asm__ __volatile__(                           \
+                       "decw %w0\n\t"                          \
+                       "rorl $16,%3\n\t"                       \
+                       "1: movb %h3,0(%2,%0)\n\t"              \
+                       "decw %w0\n\t"                          \
+                       "2: movb %b3,0(%2,%0)\n\t"              \
+                       "decw %w0\n\t"                          \
+                       "rorl $16,%3\n\t"                       \
+                       "3: movb %h3,0(%2,%0)\n\t"              \
+                       "decw %w0\n\t"                          \
+                       "4: movb %b3,0(%2,%0)\n\t"              \
+                       "xor %1,%1\n\t"                         \
+                       "5:\n"                                  \
+                       ".section .fixup,\"ax\"\n\t"            \
+                       "6:     movl $1,%1\n\t"                 \
+                       "       jmp 5b\n\t"                     \
+                       ".previous\n"                           \
+                       ".section __ex_table,\"a\"\n"           \
+                       "       .align 4\n"                     \
+                       "       .long 1b,6b\n"                  \
+                       "       .long 2b,6b\n"                  \
+                       "       .long 3b,6b\n"                  \
+                       "       .long 4b,6b\n"                  \
+                       ".previous"                             \
+                       : "=r" (ptr), "=r" (err)                \
+                       : "r" (base), "q" (val), "0" (ptr));    \
+               if (err) \
+                       return_to_32bit(regs, VM86_UNKNOWN); \
+       } while(0)
+
+#define popb(base, ptr, regs) \
+       ({ \
+               unsigned long __res; \
+               unsigned int err; \
+               __asm__ __volatile__( \
+                       "1:movb 0(%1,%0),%b2\n\t"               \
+                       "incw %w0\n\t"                          \
+                       "xor %3,%3\n\t"                         \
+                       "2:\n"                                  \
+                       ".section .fixup,\"ax\"\n\t"            \
+                       "3:     movl $1,%1\n\t"                 \
+                       "       jmp 2b\n\t"                     \
+                       ".previous\n"                           \
+                       ".section __ex_table,\"a\"\n"           \
+                       "       .align 4\n"                     \
+                       "       .long 1b,3b\n"                  \
+                       ".previous"                             \
+                       : "=r" (ptr), "=r" (base), "=q" (__res), \
+                               "=r" (err) \
+                       : "0" (ptr), "1" (base), "2" (0)); \
+               if (err) \
+                       return_to_32bit(regs, VM86_UNKNOWN); \
+               __res; \
+       })
+
+#define popw(base, ptr, regs) \
+       ({ \
+               unsigned long __res; \
+               unsigned int err; \
+               __asm__ __volatile__( \
+                       "1:movb 0(%1,%0),%b2\n\t"               \
+                       "incw %w0\n\t"                          \
+                       "2:movb 0(%1,%0),%h2\n\t"               \
+                       "incw %w0\n\t"                          \
+                       "xor %3,%3\n\t"                         \
+                       "3:\n"                                  \
+                       ".section .fixup,\"ax\"\n\t"            \
+                       "4:     movl $1,%1\n\t"                 \
+                       "       jmp 3b\n\t"                     \
+                       ".previous\n"                           \
+                       ".section __ex_table,\"a\"\n"           \
+                       "       .align 4\n"                     \
+                       "       .long 1b,4b\n"                  \
+                       "       .long 2b,4b\n"                  \
+                       ".previous"                             \
+                       : "=r" (ptr), "=r" (base), "=q" (__res), \
+                               "=r" (err) \
+                       : "0" (ptr), "1" (base), "2" (0)); \
+               if (err) \
+                       return_to_32bit(regs, VM86_UNKNOWN); \
+               __res; \
+       })
+
+#define popl(base, ptr, regs) \
+       ({ \
+               unsigned long __res; \
+               unsigned int err; \
+               __asm__ __volatile__( \
+                       "1:movb 0(%1,%0),%b2\n\t"               \
+                       "incw %w0\n\t"                          \
+                       "2:movb 0(%1,%0),%h2\n\t"               \
+                       "incw %w0\n\t"                          \
+                       "rorl $16,%2\n\t"                       \
+                       "3:movb 0(%1,%0),%b2\n\t"               \
+                       "incw %w0\n\t"                          \
+                       "4:movb 0(%1,%0),%h2\n\t"               \
+                       "incw %w0\n\t"                          \
+                       "rorl $16,%2\n\t"                       \
+                       "xor %3,%3\n\t"                         \
+                       "5:\n"                                  \
+                       ".section .fixup,\"ax\"\n\t"            \
+                       "6:     movl $1,%1\n\t"                 \
+                       "       jmp 5b\n\t"                     \
+                       ".previous\n"                           \
+                       ".section __ex_table,\"a\"\n"           \
+                       "       .align 4\n"                     \
+                       "       .long 1b,6b\n"                  \
+                       "       .long 2b,6b\n"                  \
+                       "       .long 3b,6b\n"                  \
+                       "       .long 4b,6b\n"                  \
+                       ".previous"                             \
+                       : "=r" (ptr), "=r" (base), "=q" (__res), \
+                               "=r" (err) \
+                       : "0" (ptr), "1" (base), "2" (0)); \
+               if (err) \
+                       return_to_32bit(regs, VM86_UNKNOWN); \
+               __res; \
+       })
 
 static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, unsigned long sp)
 {
@@ -414,9 +516,9 @@ static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, un
                goto cannot_handle;
        if ((segoffs >> 16) == BIOSSEG)
                goto cannot_handle;
-       pushw(ssp, sp, get_vflags(regs));
-       pushw(ssp, sp, regs->cs);
-       pushw(ssp, sp, IP(regs));
+       pushw(ssp, sp, get_vflags(regs), regs);
+       pushw(ssp, sp, regs->cs, regs);
+       pushw(ssp, sp, IP(regs), regs);
        regs->cs = segoffs >> 16;
        SP(regs) -= 6;
        IP(regs) = segoffs & 0xffff;
@@ -460,7 +562,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
 
 #define CHECK_IF_IN_TRAP \
        if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \
-               pushw(ssp,sp,popw(ssp,sp) | TF_MASK);
+               pushw(ssp,sp,popw(ssp,sp, regs) | TF_MASK, regs);
 #define VM86_FAULT_RETURN \
        if (VMPI.force_return_for_pic  && (VEFLAGS & IF_MASK)) \
                return_to_32bit(regs, VM86_PICRETURN); \
@@ -471,17 +573,17 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
        sp = SP(regs);
        ip = IP(regs);
 
-       switch (popb(csp, ip)) {
+       switch (popb(csp, ip, regs)) {
 
        /* operand size override */
        case 0x66:
-               switch (popb(csp, ip)) {
+               switch (popb(csp, ip, regs)) {
 
                /* pushfd */
                case 0x9c:
                        SP(regs) -= 4;
                        IP(regs) += 2;
-                       pushl(ssp, sp, get_vflags(regs));
+                       pushl(ssp, sp, get_vflags(regs), regs);
                        VM86_FAULT_RETURN;
 
                /* popfd */
@@ -489,16 +591,16 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
                        SP(regs) += 4;
                        IP(regs) += 2;
                        CHECK_IF_IN_TRAP
-                       set_vflags_long(popl(ssp, sp), regs);
+                       set_vflags_long(popl(ssp, sp, regs), regs);
                        VM86_FAULT_RETURN;
 
                /* iretd */
                case 0xcf:
                        SP(regs) += 12;
-                       IP(regs) = (unsigned short)popl(ssp, sp);
-                       regs->cs = (unsigned short)popl(ssp, sp);
+                       IP(regs) = (unsigned short)popl(ssp, sp, regs);
+                       regs->cs = (unsigned short)popl(ssp, sp, regs);
                        CHECK_IF_IN_TRAP
-                       set_vflags_long(popl(ssp, sp), regs);
+                       set_vflags_long(popl(ssp, sp, regs), regs);
                        VM86_FAULT_RETURN;
                /* need this to avoid a fallthrough */
                default:
@@ -509,7 +611,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
        case 0x9c:
                SP(regs) -= 2;
                IP(regs)++;
-               pushw(ssp, sp, get_vflags(regs));
+               pushw(ssp, sp, get_vflags(regs), regs);
                VM86_FAULT_RETURN;
 
        /* popf */
@@ -517,12 +619,12 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
                SP(regs) += 2;
                IP(regs)++;
                CHECK_IF_IN_TRAP
-               set_vflags_short(popw(ssp, sp), regs);
+               set_vflags_short(popw(ssp, sp, regs), regs);
                VM86_FAULT_RETURN;
 
        /* int xx */
        case 0xcd: {
-               int intno=popb(csp, ip);
+               int intno=popb(csp, ip, regs);
                IP(regs) += 2;
                if (VMPI.vm86dbg_active) {
                        if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] )
@@ -535,10 +637,10 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
        /* iret */
        case 0xcf:
                SP(regs) += 6;
-               IP(regs) = popw(ssp, sp);
-               regs->cs = popw(ssp, sp);
+               IP(regs) = popw(ssp, sp, regs);
+               regs->cs = popw(ssp, sp, regs);
                CHECK_IF_IN_TRAP
-               set_vflags_short(popw(ssp, sp), regs);
+               set_vflags_short(popw(ssp, sp, regs), regs);
                VM86_FAULT_RETURN;
 
        /* cli */
index 3619bbd0c3fbcd3761e64d46bcd8e62ae7cf5b88..de4dd194792b7762382ebe5ff1637240ec1e0fb0 100644 (file)
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(isa_io_base);
 EXPORT_SYMBOL(isa_mem_base);
 EXPORT_SYMBOL(pci_dram_offset);
 EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
-EXPORT_SYMBOL(DMA_MODE_READ);
+EXPORT_SYMBOL_NOVERS(DMA_MODE_READ);
 EXPORT_SYMBOL(DMA_MODE_WRITE);
 #if defined(CONFIG_PREP) || defined(CONFIG_ALL_PPC)
 EXPORT_SYMBOL(_prep_type);
index 0eadfefdd8395b59153d7a6c2b27454d70b07d1b..2f80f75a8de6d5885c9d5eb96a4512b800cf01ce 100644 (file)
@@ -975,7 +975,7 @@ __initfunc(int blk_dev_init(void))
        isp16_init();
 #endif CONFIG_ISP16_CDI
 #ifdef CONFIG_BLK_DEV_IDE
-#ifdef CONFIG_POWERMAC
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
        ide_pmac_init();
 #else
        ide_init();             /* this MUST precede hd_init */
index 149077d9897995fd7fd3ecd65c92668794987f46..386e49917c9856717bd8cecbfab9bb675b9315af 100644 (file)
@@ -1981,7 +1981,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                }
                        } else if (vw.clipcount > 2048) 
                                return -ENOMEM;
-                       else {
+                       else if (vw.clipcount) {
                                if((vcp=vmalloc(sizeof(struct video_clip)*
                                        (vw.clipcount))) == NULL)
                                        return -ENOMEM;
index cc38ed091cf7a1a7652aa35042099787da0cb2bc..1193178119be91797d2cdd2388274cab3642aaf7 100644 (file)
@@ -137,7 +137,7 @@ an MMIO register read.
 */
 
 #define DRV_NAME       "8139too"
-#define DRV_VERSION    "0.9.18-pre4"
+#define DRV_VERSION    "0.9.18-2.2"
 
 
 #include <linux/config.h>
@@ -342,7 +342,7 @@ static int multicast_filter_limit = 32;
 #define RX_BUF_PAD 16
 #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
 #define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
-#define RX_EARLY_THRESH 2
+#define RX_EARLY_THRESH 14
 
 /* Number of Tx descriptor registers. */
 #define NUM_TX_DESC    4
index 1167dda7925ef285d6a51fda6d54744fd1e6c81c..120196a6cd7ad6c3968d10a78ad4d04d0f77ba9f 100644 (file)
@@ -23,6 +23,8 @@
        This is a compatibility hardware problem.
 
        Versions:
+       0.13    irq sharing, rewrote probe function, fixed a nasty bug in
+               hardware_send_packet and a major cleanup (aris, 11/08/2001)
        0.12d   tottaly isolated old code to new code (blue cards).
                (aris, 12/27/2000)
        0.12c   fixed other multiple cards bug and other cleanups
 */
 
 static const char *version =
-       "eepro.c: v0.12d 12/27/2000 aris@conectiva.com.br\n";
+       "eepro.c: v0.13 11/08/2001 aris@cathedrallabs.org\n";
 
 #include <linux/module.h>
 
@@ -192,18 +194,22 @@ struct eepro_local {
        unsigned tx_end;        /* end of the transmit chain (plus 1) */
        int eepro;              /* 1 for the EtherExpress Pro/10,
                                 * 2 for the EtherExpress Pro/10+,
-                                * 3 for the blue cards,
+                                * 3 for the EtherExpress 10 (blue cards),
                                 * 0 for other 82595-based lan cards. */
        int version;            /* a flag to indicate if this is a TX or FX
                                 * version of the 82595 chip. */
        int stepping;
        spinlock_t lock;        /* Serializing lock  */ 
-       unsigned rcv_ram;
-       unsigned rcv_start;
-       unsigned xmt_bar;
-       unsigned xmt_lower_limit_reg;
-       unsigned xmt_upper_limit_reg;
-       unsigned eeprom_reg;
+       unsigned rcv_ram;       /* pre-calculated space for rx */
+       unsigned xmt_ram;       /* pre-calculated space for tx */
+       unsigned char xmt_bar;
+       unsigned char xmt_lower_limit_reg;
+       unsigned char xmt_upper_limit_reg;
+       short xmt_lower_limit;
+       short xmt_upper_limit;
+       short rcv_lower_limit;
+       short rcv_upper_limit;
+       unsigned char eeprom_reg;
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
@@ -305,7 +311,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, struct device *dev);
+static int     read_eeprom(int ioaddr, int location, struct device *dev);
 static int     hardware_send_packet(struct device *dev, void *buf, short length);
 static int     eepro_grab_irq(struct device *dev);
 
@@ -339,35 +345,25 @@ it is reset to the default of 24K, and, hence, 8K for the trasnmit
 buffer (transmit-buffer = 32K - receive-buffer).
 
 */
-
-/* now this section could be used by both boards: the oldies and the ee10:
- * ee10 uses tx buffer before of rx buffer and the oldies the inverse.
- * (aris)
- */
 #define        RAM_SIZE        0x8000
 
 #define        RCV_HEADER      8
 #define RCV_DEFAULT_RAM        0x6000
-#define RCV_RAM        lp->rcv_ram
 
 #define XMT_HEADER     8
-#define XMT_RAM                (RAM_SIZE - RCV_RAM)
-
-#define XMT_START      ((lp->rcv_start + RCV_RAM) % RAM_SIZE)
-
-#define RCV_LOWER_LIMIT        (lp->rcv_start >> 8)
-#define RCV_UPPER_LIMIT        (((lp->rcv_start + RCV_RAM) - 2) >> 8)
-#define XMT_LOWER_LIMIT        (XMT_START >> 8)
-#define XMT_UPPER_LIMIT        (((XMT_START + XMT_RAM) - 2) >> 8)
+#define XMT_DEFAULT_RAM        (RAM_SIZE - RCV_DEFAULT_RAM)
 
-#define RCV_START_PRO  0x00
-#define RCV_START_10   XMT_RAM
+#define XMT_START_PRO  RCV_DEFAULT_RAM
+#define XMT_START_10   0x0000
+#define RCV_START_PRO  0x0000
+#define RCV_START_10   XMT_DEFAULT_RAM
 
 #define        RCV_DONE        0x0008
 #define        RX_OK           0x2000
 #define        RX_ERROR        0x0d81
 
 #define        TX_DONE_BIT     0x0080
+#define TX_OK          0x2000
 #define        CHAIN_BIT       0x8000
 #define        XMT_STATUS      0x02
 #define        XMT_CHAIN       0x04
@@ -458,7 +454,7 @@ buffer (transmit-buffer = 32K - receive-buffer).
 #define EEDO 0x08
 
 /* do a full reset */
-#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr); udelay(40);
+#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr)
 
 /* do a nice reset */
 #define eepro_sel_reset(ioaddr)        { \
@@ -515,16 +511,14 @@ buffer (transmit-buffer = 32K - receive-buffer).
 
 /* a complete sel reset */
 #define eepro_complete_selreset(ioaddr) {      \
-                                               /* eepro_dis_int(ioaddr); */ \
                                                lp->stats.tx_errors++;\
                                                eepro_sel_reset(ioaddr);\
                                                lp->tx_end = \
-                                                       (XMT_LOWER_LIMIT << 8);\
+                                                       lp->xmt_lower_limit;\
                                                lp->tx_start = lp->tx_end;\
                                                lp->tx_last = 0;\
                                                dev->tbusy=0;\
                                                dev->trans_start = jiffies;\
-                                               /*eepro_en_int(ioaddr); */ \
                                                eepro_en_rx(ioaddr);\
                                        }
 
@@ -541,7 +535,7 @@ __initfunc(int eepro_probe(struct device *dev)) {
                return eepro_probe1(dev, base_addr);
 
        else if (base_addr != 0)        /* Don't probe at all. */
-               return ENXIO;
+               return -ENXIO;
 
        for (i = 0; eepro_portlist[i]; i++) {
                int ioaddr = eepro_portlist[i];
@@ -552,7 +546,7 @@ __initfunc(int eepro_probe(struct device *dev)) {
                        return 0;
        }
        
-       return ENODEV;
+       return -ENODEV;
 }
 
 static void printEEPROMInfo(short ioaddr, struct device *dev)
@@ -562,7 +556,7 @@ static void printEEPROMInfo(short ioaddr, struct device *dev)
 
        for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
                j+=read_eeprom(ioaddr,i,dev);
-       printk("Checksum: %#x\n",j&0xffff);
+       printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
 
        Word=read_eeprom(ioaddr, 0, dev);
        printk(KERN_DEBUG "Word0:\n");
@@ -588,10 +582,10 @@ static void printEEPROMInfo(short ioaddr, struct device *dev)
        printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
        printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
        printk(KERN_DEBUG " Has ");
-       if (GetBit(Word,ee_PortTPE)) printk("TPE ");
-       if (GetBit(Word,ee_PortBNC)) printk("BNC ");
-       if (GetBit(Word,ee_PortAUI)) printk("AUI ");
-       printk("port(s) \n");
+       if (GetBit(Word,ee_PortTPE)) printk(KERN_DEBUG "TPE ");
+       if (GetBit(Word,ee_PortBNC)) printk(KERN_DEBUG "BNC ");
+       if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
+       printk(KERN_DEBUG "port(s) \n");
 
        Word=read_eeprom(ioaddr, 6, dev);
        printk(KERN_DEBUG "Word6:\n");
@@ -602,209 +596,226 @@ static void printEEPROMInfo(short ioaddr, struct device *dev)
        printk(KERN_DEBUG "Word7:\n");
        printk(KERN_DEBUG " INT to IRQ:\n");
 
-       printk(KERN_DEBUG);
-
        for (i=0, j=0; i<15; i++)
-               if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
+               if (GetBit(Word,i)) printk(KERN_DEBUG " INT%d -> IRQ %d;",j++,i);
 
-       printk("\n");
+       printk(KERN_DEBUG "\n");
 }
 
-/* This is the real probe routine.  Linux has a history of friendly device
-   probes on the ISA bus.  A good device probe avoids doing writes, and
-   verifies that the correct device exists and functions.  */
-
-int eepro_probe1(struct device *dev, short ioaddr)
+/* function to recalculate the limits of buffer based on rcv_ram */
+static void eepro_recalc (struct device *dev)
 {
-       unsigned short station_addr[6], id, counter;
-       int i,j, irqMask;
-       int eepro = 0;
-       struct eepro_local *lp;
-       const char *ifmap[] = {"AUI", "10Base2", "10BaseT"};
-       enum iftype { AUI=0, BNC=1, TPE=2 };
+       struct eepro_local *    lp;
 
-       /* Now, we are going to check for the signature of the
-          ID_REG (register 2 of bank 0) */
-
-       id=inb(ioaddr + ID_REG);
-       if (((id) & ID_REG_MASK) == ID_REG_SIG) {
-
-               /* 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)) {
-
-                       /* Yes, the 82595 has been found */
-                       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;
-
-                       /* default values */
-                       lp->rcv_start = RCV_START_PRO;
-                       lp->xmt_bar = XMT_BAR_PRO;
-                       lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
-                       lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
-                       lp->eeprom_reg = EEPROM_REG_PRO;
-                       lp->rcv_ram = RCV_DEFAULT_RAM;
-
-               /* Now, get the ethernet hardware address from
-                          the EEPROM */
-
-                       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) {
-                               eepro = 3;
-                               lp->eepro = LAN595FX_10ISA;
-                               lp->eeprom_reg = EEPROM_REG_10;
-                               lp->rcv_start = RCV_START_10;
-                               lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
-                               lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
-                               lp->xmt_bar = XMT_BAR_10;
-
-                               station_addr[0] = read_eeprom(ioaddr, 2, dev);
-                       }
+       lp = dev->priv;
+       lp->xmt_ram = RAM_SIZE - lp->rcv_ram;
 
-                       station_addr[1] = read_eeprom(ioaddr, 3, dev);
-                       station_addr[2] = read_eeprom(ioaddr, 4, dev);
-
-                       if (eepro) {
-                               printk("%s: Intel EtherExpress 10 ISA\n at %#x,",
-                                       dev->name, ioaddr);
-                       } 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] == SA_ADDR1)  {
-                               eepro = 1;
-                               printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
-                                       dev->name, ioaddr);
-                       }
-                       else {
-                               eepro = 0;
-                               printk("%s: Intel 82595-based lan card at %#x,", 
-                                       dev->name, ioaddr);
-                       }
+       if (lp->eepro == LAN595FX_10ISA) {
+               lp->xmt_lower_limit = XMT_START_10;
+               lp->xmt_upper_limit = (lp->xmt_ram - 2);
+               lp->rcv_lower_limit = lp->xmt_ram;
+               lp->rcv_upper_limit = (RAM_SIZE - 2);
+       }
+       else {
+               lp->rcv_lower_limit = RCV_START_PRO;
+               lp->rcv_upper_limit = (lp->rcv_ram - 2);
+               lp->xmt_lower_limit = lp->rcv_ram;
+               lp->xmt_upper_limit = (RAM_SIZE - 2);
+       }
+}
 
-                       /* Fill in the 'dev' fields. */
-                       dev->base_addr = ioaddr;
-                       
-                       for (i=0; i < 6; i++) {
-                               dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
-                               printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
-                       }
+/* prints boot-time info */
+static void eepro_print_info (struct device *dev)
+{
+       struct eepro_local *    lp = dev->priv;
+       int                     i;
+       const char *            ifmap[] = {"AUI", "10Base2", "10BaseT"};
+
+       i = inb(dev->base_addr + ID_REG);
+       printk(KERN_DEBUG " id: %#x ",i);
+       printk(KERN_DEBUG " io: %#x ", (unsigned)dev->base_addr);
+
+       switch (lp->eepro) {
+               case LAN595FX_10ISA:
+                       printk(KERN_INFO "%s: Intel EtherExpress 10 ISA\n at %#x,",
+                                       dev->name, (unsigned)dev->base_addr);
+                       break;
+               case LAN595FX:
+                       printk(KERN_INFO "%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 
+                                       dev->name, (unsigned)dev->base_addr);
+                       break;
+               case LAN595TX:
+                       printk(KERN_INFO "%s: Intel EtherExpress Pro/10 ISA at %#x,",
+                                       dev->name, (unsigned)dev->base_addr);
+                       break;
+               case LAN595:
+                       printk(KERN_INFO "%s: Intel 82595-based lan card at %#x,", 
+                                       dev->name, (unsigned)dev->base_addr);
+       }
 
-                       dev->mem_start = (RCV_LOWER_LIMIT << 8);
+       for (i=0; i < 6; i++)
+               printk(KERN_INFO "%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
 
-                       /* received mem_end as argument */
-                       if ((dev->mem_end & 0x3f) < 3 ||        /* RX buffer must be more than 3K */
-                               (dev->mem_end & 0x3f) > 29)     /* and less than 29K */
-                               dev->mem_end = (RCV_UPPER_LIMIT << 8);
-                       else {
-                               dev->mem_end = (dev->mem_end * 1024) +
-                                                       (RCV_LOWER_LIMIT << 8);
-                               lp->rcv_ram = dev->mem_end - (RCV_LOWER_LIMIT << 8);
-                       }
+       if (net_debug > 3)
+               printk(KERN_DEBUG ", %dK RCV buffer",
+                               (int)(lp->rcv_ram)/1024);
 
-                       /* From now on, dev->mem_end - dev->mem_start contains 
-                        * the actual size of rx buffer 
-                        */
-                       
-                       if (net_debug > 3)
-                               printk(", %dK RCV buffer",
-                                               (int)(dev->mem_end - dev->mem_start)/1024);
-                                                               
-                       /* ............... */
+       if (dev->irq > 2)
+               printk(KERN_INFO ", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
+       else 
+               printk(KERN_INFO ", %s.\n", ifmap[dev->if_port]);
 
-                       if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
-                               dev->if_port = BNC;
-                       else dev->if_port = TPE;
+       if (net_debug > 3) {
+               i = read_eeprom(dev->base_addr, 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);
+       }
 
-                       /* ............... */
+       /* Check the station address for the manufacturer's code */
+       if (net_debug>3)
+               printEEPROMInfo(dev->base_addr, dev);
+}
 
+/* This is the real probe routine.  Linux has a history of friendly device
+   probes on the ISA bus.  A good device probe avoids doing writes, and
+   verifies that the correct device exists and functions.  */
 
-                       if ((dev->irq < 2) && (eepro!=0)) {
-                               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++) {
-                                       if ((irqMask & (1<<j))!=0) {
-                                               if (i==0) {
-                                                       dev->irq = j;
-                                                       break; /* found bit corresponding to irq */
-                                               }
-                                               i--; /* count bits set in irqMask */
-                                       }
-                               }
-                               if (dev->irq < 2) {
-                                       printk(" Duh! illegal interrupt vector stored in EEPROM.\n");
-                                               return ENODEV;
-                               } else 
-                               
-                               if (dev->irq==2)
-                                       dev->irq = 9;
-                       }
-                       
-                       if (dev->irq > 2) {
-                               printk(", IRQ %d, %s.\n", dev->irq,
-                                               ifmap[dev->if_port]);
-                       }
-                       else printk(", %s.\n", ifmap[dev->if_port]);
-                       
-                       if (net_debug > 3) {
-                               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);
-                       }
+int eepro_probe1(struct device *dev, short ioaddr)
+{
+       unsigned short          station_addr[6],
+                               id,
+                               counter;
+       int                     i,
+                               j,
+                               irqMask,
+                               retval = 0;
+       struct eepro_local *    lp;
+       enum                    iftype { AUI=0, BNC=1, TPE=2 };
 
-                       if (net_debug) 
-                               printk(version);
+       /* Now, we are going to check for the signature of the
+        * ID_REG (register 2 of bank 0) */
+       id = inb(ioaddr + ID_REG);
+       if (((id) & ID_REG_MASK) != ID_REG_SIG) {
+               if (net_debug > 3)
+                       printk (KERN_DEBUG "EtherExpress Pro probed failed!\n");
+               retval = -ENODEV;
+               goto exit;
+       }
 
-                       /* Grab the region so we can find another board if autoIRQ fails. */
-                       request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
+       /* 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)) {
+               retval = -ENODEV;
+               goto exit;
+       }
 
-                       spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
-                       dev->open               = eepro_open;
-                       dev->stop               = eepro_close;
-                       dev->hard_start_xmit    = eepro_send_packet;
-                       dev->get_stats          = eepro_get_stats;
-                       dev->set_multicast_list = &set_multicast_list;
+       /* Initialize the device structure */
+       dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
+       if (dev->priv == NULL) {
+               retval = -ENOMEM;
+               goto exit;
+       }
+       memset(dev->priv, 0, sizeof(struct eepro_local));
+       lp = (struct eepro_local *)dev->priv;
+
+       /* default values */
+       lp->eepro = 0;
+       lp->xmt_bar = XMT_BAR_PRO;
+       lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
+       lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
+       lp->eeprom_reg = EEPROM_REG_PRO;
+
+       /* Now, get the ethernet hardware address from
+        * the EEPROM */
+       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) {
+               lp->eepro = LAN595FX_10ISA;
+               lp->eeprom_reg = EEPROM_REG_10;
+               lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
+               lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
+               lp->xmt_bar = XMT_BAR_10;
+               station_addr[0] = read_eeprom(ioaddr, 2, dev);
+       }
+       station_addr[1] = read_eeprom(ioaddr, 3, dev);
+       station_addr[2] = read_eeprom(ioaddr, 4, dev);
 
-                       /* Fill in the fields of the device structure with
-                          ethernet generic values */
+       if (!lp->eepro) {
+               if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ)
+                       lp->eepro = 2;
+               else if (station_addr[2] == SA_ADDR1)
+                       lp->eepro = 1;
+       }
 
-                       ether_setup(dev);
+       /* Fill in the 'dev' fields. */
+       dev->base_addr = ioaddr;
+       for (i=0; i < 6; i++)
+               dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
 
-                       /* Check the station address for the manufacturer's code */
-                       if (net_debug>3)
-                               printEEPROMInfo(ioaddr, dev);
+       /* RX buffer must be more than 3K and less than 29K */
+       if (dev->mem_end < 3072 || dev->mem_end > 29696)
+               lp->rcv_ram = RCV_DEFAULT_RAM;
 
-                       /* reset 82595 */
-                       eepro_reset(ioaddr);
+       /* calculate {xmt,rcv}_{lower,upper}_limit */
+       eepro_recalc(dev);
+       
+       if (GetBit(read_eeprom(ioaddr, 5, dev), ee_BNC_TPE))
+               dev->if_port = BNC;
+       else 
+               dev->if_port = TPE;
 
-                       return 0;
+       if ((dev->irq < 2) && (lp->eepro != 0)) {
+               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++) {
+                       if ((irqMask & (1<<j))!=0) {
+                               if (i==0) {
+                                       dev->irq = j;
+                                       /* found bit corresponding to irq */
+                                       break;
+                               }
+                               i--; /* count bits set in irqMask */
                        }
-               else return ENODEV;
                }
-       else if (net_debug > 3)
-               printk ("EtherExpress Pro probed failed!\n");
-       return ENODEV;
+               if (dev->irq < 2) {
+                       printk(KERN_ERR " Duh! illegal interrupt vector stored in "
+                               "EEPROM.\n");
+                               retval = -ENODEV;
+                               goto freeall;
+               } else 
+                       if (dev->irq == 2) dev->irq = 9;
+       }
+       /* Grab the region so we can find another board if autoIRQ fails. */
+       request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
+       spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
+       dev->open               = eepro_open;
+       dev->stop               = eepro_close;
+       dev->hard_start_xmit    = eepro_send_packet;
+       dev->get_stats          = eepro_get_stats;
+       dev->set_multicast_list = &set_multicast_list;
+
+       /* Fill in the fields of the device structure with ethernet generic
+        * values */
+       ether_setup(dev);
+
+       /* print boot time info */
+       eepro_print_info(dev);
+
+       /* reset 82595 */
+       eepro_reset(ioaddr);
+
+exit:
+       return retval;
+freeall:
+       kfree(dev->priv);
+       goto exit;
 }
 
 /* Open/initialize the board.  This is called (in the current kernel)
@@ -842,7 +853,7 @@ static int  eepro_grab_irq(struct device *dev)
 
                eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
 
-               if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) {
+               if (request_irq (*irqp, NULL, SA_SHIRQ, "bogus", dev) != -EBUSY) {
                        /* Twinkle the interrupt, and check if it's seen */
                        autoirq_setup(0);
 
@@ -877,7 +888,6 @@ static int eepro_open(struct device *dev)
        unsigned short temp_reg, old8, old9;
        int irqMask;
        int i, ioaddr = dev->base_addr;
-
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
 
        if (net_debug > 3)
@@ -906,12 +916,12 @@ static int eepro_open(struct device *dev)
 
        /* Get the interrupt vector for the 82595 */    
        if (dev->irq < 2 && eepro_grab_irq(dev) == 0) {
-               printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+               printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
                return -EAGAIN;
        }
                
        if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) {
-               printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+               printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
                return -EAGAIN;
        }
        
@@ -920,6 +930,7 @@ static int eepro_open(struct device *dev)
                || (irq2dev_map[dev->irq] = dev) == 0) && 
                (irq2dev_map[dev->irq]!=dev)) {
                /* printk("%s: IRQ map wrong\n", dev->name); */
+               free_irq(dev->irq, dev);
                return -EAGAIN;
        }
 #endif
@@ -930,7 +941,6 @@ static int eepro_open(struct device *dev)
        temp_reg = inb(ioaddr + lp->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);
@@ -955,12 +965,12 @@ static int eepro_open(struct device *dev)
 
        /* Set the interrupt vector */  
        temp_reg = inb(ioaddr + INT_NO_REG);
-       if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA)
+       if (lp->eepro == LAN595FX || 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 || lp->eepro == LAN595FX_10ISA)
+       if (lp->eepro == LAN595FX || 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);
 
@@ -969,10 +979,10 @@ static int eepro_open(struct device *dev)
 
 
        /* Initialize the RCV and XMT upper and lower limits */
-       outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); 
-       outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); 
-       outb(XMT_LOWER_LIMIT, ioaddr + lp->xmt_lower_limit_reg); 
-       outb(XMT_UPPER_LIMIT, ioaddr + lp->xmt_upper_limit_reg); 
+       outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG); 
+       outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG); 
+       outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg); 
+       outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg); 
 
        /* Enable the interrupt line. */
        eepro_en_intline(ioaddr);
@@ -986,12 +996,14 @@ static int eepro_open(struct device *dev)
        eepro_clear_int(ioaddr);
 
        /* Initialize RCV */
-       outw((RCV_LOWER_LIMIT << 8), ioaddr + RCV_BAR); 
-       lp->rx_start = (RCV_LOWER_LIMIT << 8);
-       outw(((RCV_UPPER_LIMIT << 8) | 0xfe), ioaddr + RCV_STOP); 
+       outw(lp->rcv_lower_limit, ioaddr + RCV_BAR); 
+       outw((lp->rcv_upper_limit | 0xfe), ioaddr + RCV_STOP); 
+       lp->rx_start = lp->rcv_lower_limit;
 
        /* Initialize XMT */
-       outw((XMT_LOWER_LIMIT << 8), ioaddr + lp->xmt_bar); 
+       outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar); 
+       lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
+       lp->tx_last = 0;
 
        /* Check for the i82595TX and i82595FX */
        old8 = inb(ioaddr + 8);
@@ -1034,11 +1046,6 @@ static int eepro_open(struct device *dev)
        }
        
        eepro_sel_reset(ioaddr);
-       SLOW_DOWN;
-       SLOW_DOWN;
-
-       lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8);
-       lp->tx_last = 0;
        
        dev->tbusy = 0;
        dev->interrupt = 0;
@@ -1064,14 +1071,10 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
        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;
+       eepro_dis_int(ioaddr);
+       spin_lock_irqsave(&lp->lock, flags);
 
-               if (tickssofar < 40)
-                       return 1;
-               
+       if (dev->tbusy) {
                /* if (net_debug > 1) */
                printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, 
                        "network cable problem");
@@ -1083,33 +1086,29 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
                /* let's do a complete sel reset */
                eepro_complete_selreset(ioaddr);
        }
-       spin_lock_irqsave(&lp->lock, flags);
 
        /* 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);
-
-               spin_unlock_irqrestore(&lp->lock, flags);
+               lp->stats.tx_aborted_errors++;
        } else {
                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-               unsigned char *buf = skb->data;
-
-               lp->stats.tx_bytes+=skb->len;
-               if (hardware_send_packet(dev, buf, length))
-                       return 1;
-               
-               dev->trans_start = jiffies;
 
+               if (hardware_send_packet(dev, skb->data, length))
+                       /* we won't unset tbusy because we're out of space. */
+                       lp->stats.tx_dropped++;
+               else {
+                       lp->stats.tx_bytes += skb->len;
+                       dev->trans_start = jiffies;
+                       dev->tbusy = 0;
+               }
        }
-
        dev_kfree_skb(skb);
 
-       /* You might need to clean up and record Tx statistics here. */
-       /* lp->stats.tx_aborted_errors++; */
-
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
 
+       eepro_en_int(ioaddr);
        spin_unlock_irqrestore(&lp->lock, flags);
        
        return 0;
@@ -1122,17 +1121,20 @@ static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
 static void
 eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-       struct device *dev =  (struct device *)dev_id;
-                             /* (struct device *)(irq2dev_map[irq]);*/
-       struct eepro_local *lp = (struct eepro_local *)dev->priv;
+       struct device *dev;
+       struct eepro_local *lp;
        int ioaddr, status, boguscount = 20;
 
-       if (dev == NULL) {
+       if (dev_id == NULL) {
                 printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
                 return;
         }
 
-        spin_lock(&lp->lock);
+       dev = (struct device *)dev_id;
+
+       lp = (struct eepro_local *)dev->priv;
+
+       spin_lock(&lp->lock);
 
        if (dev->interrupt) {
                printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
@@ -1150,39 +1152,37 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        
        ioaddr = dev->base_addr;
 
-       while (((status = inb(ioaddr + STATUS_REG)) & 0x06) && (boguscount--)) 
+       eepro_sw2bank0(ioaddr);
+
+       while (((status = inb(ioaddr + STATUS_REG)) & (RX_INT|TX_INT)) && boguscount--) 
        {
-               switch (status & (RX_INT | TX_INT)) {
-#ifdef ANSWER_TX_AND_RX
-                       case (RX_INT | TX_INT):
-                               eepro_ack_rxtx(ioaddr);
-                               break;
-#endif
-                       case RX_INT:
-                               eepro_ack_rx(ioaddr);
-                               break;
-                       case TX_INT:
-                               eepro_ack_tx(ioaddr);
-               }
+
                if (status & RX_INT) {
                        if (net_debug > 4)
                                printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
 
+                       eepro_dis_int(ioaddr);
+
                        /* Get the received packets */
+                       eepro_ack_rx(ioaddr);
                        eepro_rx(dev);
-#ifndef ANSWER_TX_AND_RX
-                       continue;
-#endif
+
+                       eepro_en_int(ioaddr);
                }
                if (status & TX_INT) {
                        if (net_debug > 4)
                                printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
 
+                       eepro_dis_int(ioaddr);
+
                        /* Process the status of transmitted packets */
+                       eepro_ack_tx(ioaddr);
                        eepro_transmit_interrupt(dev);
+
+                       eepro_en_int(ioaddr);
                }
        }
-       
+
        dev->interrupt = 0;
 
        if (net_debug > 5)
@@ -1212,7 +1212,7 @@ static int eepro_close(struct device *dev)
 
        /* Flush the Tx and disable Rx. */
        outb(STOP_RCV_CMD, ioaddr); 
-       lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8);
+       lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
        lp->tx_last = 0;
 
        /* Mask all the interrupts. */
@@ -1273,7 +1273,7 @@ set_multicast_list(struct device *dev)
                mode = inb(ioaddr + REG3);
                outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
                eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
-               printk("%s: promiscuous mode enabled.\n", dev->name);
+               printk(KERN_INFO "%s: promiscuous mode enabled.\n", dev->name);
        }
        
        else if (dev->mc_count==0 ) 
@@ -1352,11 +1352,11 @@ set_multicast_list(struct device *dev)
                                outb(0x08, ioaddr + STATUS_REG);
                                
                                if (i & 0x20) { /* command ABORTed */
-                                       printk("%s: multicast setup failed.\n", 
+                                       printk(KERN_NOTICE "%s: multicast setup failed.\n", 
                                                dev->name);
                                        break;
                                } else if ((i & 0x0f) == 0x03)  { /* MC-Done */
-                                       printk("%s: set Rx mode to %d address%s.\n",
+                                       printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n",
                                                dev->name, dev->mc_count,
                                                dev->mc_count > 1 ? "es":"");
                                        break;
@@ -1392,14 +1392,10 @@ read_eeprom(int ioaddr, int location, struct device *dev)
        int read_cmd = location | EE_READ_CMD;
        short ctrl_val = EECS ;
        
-       /* XXXX - this is not the final version. We must test this on other
-        *        boards other than eepro10. I think that it won't let other
-        *        boards to fail. (aris)
-        */
-       if (lp->eepro == LAN595FX_10ISA) {
-               eepro_sw2bank1(ioaddr);
-               outb(0x00, ioaddr + STATUS_REG);
-       }
+       /* XXXX - black magic */
+       eepro_sw2bank1(ioaddr);
+       outb(0x00, ioaddr + STATUS_REG);
+       /* XXXX - black magic */
                
        eepro_sw2bank2(ioaddr);
        outb(ctrl_val, ee_addr);
@@ -1437,133 +1433,95 @@ 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;
+       unsigned status, tx_available, last, end;
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
 
+       /* determine how much of the transmit buffer space is
+        * available */
+       if (lp->tx_end > lp->tx_start)
+               tx_available = lp->xmt_ram - (lp->tx_end - 
+                                                       lp->tx_start);
+       else if (lp->tx_end < lp->tx_start)
+               tx_available = lp->tx_start - lp->tx_end;
+       else tx_available = lp->xmt_ram;
+
+       if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) {
+               /* No space available ??? */
+               return 1;
+       }
 
-       while (boguscount-- > 0) {
-               /* Disable RX and TX interrupts.  Necessary to avoid
-               corruption of the HOST_ADDRESS_REG by interrupt
-               service routines. */
-               eepro_dis_int(ioaddr);
-
-               if (dev->interrupt == 1) {
-                       /* Enable RX and TX interrupts */
-                       eepro_en_int(ioaddr);
-                       continue;
-               }
-
-               /* determine how much of the transmit buffer space is available */
-               if (lp->tx_end > lp->tx_start)
-                       tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
-               else if (lp->tx_end < lp->tx_start)
-                       tx_available = lp->tx_start - lp->tx_end;
-               else tx_available = XMT_RAM;
-
-               if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) 
-                       >= tx_available)   /* No space available ??? */
-                       {
-                       eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
-
-                       /* Enable RX and TX interrupts */
-                       eepro_en_int(ioaddr);
-                       continue;
-               }
-
-               last = lp->tx_end;
-               end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
-
-               if (end >= (XMT_UPPER_LIMIT << 8)) { /* the transmit buffer is wrapped around */
-                       if (((XMT_UPPER_LIMIT << 8) - last) <= XMT_HEADER) {
-                               /* Arrrr!!!, must keep the xmt header together,
-                               several days were lost to chase this one down. */
-                               
-                               last = (XMT_LOWER_LIMIT << 8);
-                               end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
-                       }
-                       else end = (XMT_LOWER_LIMIT << 8) + (end - 
-                                               (XMT_UPPER_LIMIT << 8));
-               }
-
-               outw(last, ioaddr + HOST_ADDRESS_REG);
-               outw(XMT_CMD, ioaddr + IO_PORT);
-               outw(0, ioaddr + IO_PORT);
-               outw(end, ioaddr + IO_PORT);
-               outw(length, ioaddr + IO_PORT);
-
-               if (lp->version == LAN595)
-                       outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1);
-               else {  /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
-                       unsigned short temp = inb(ioaddr + INT_MASK_REG);
-                       outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
-                       outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2);
-                       outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
-               }
-
-               /* A dummy read to flush the DRAM write pipeline */
-               status = inw(ioaddr + IO_PORT); 
+       last = lp->tx_end;
+       end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 
-               if (lp->tx_start == lp->tx_end) {
-                       outw(last, ioaddr + lp->xmt_bar);
-                       outb(XMT_CMD, ioaddr);                  
-                       lp->tx_start = last;   /* I don't like to change tx_start here */
-               }
-               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); 
-                       }
+       if (end >= lp->xmt_upper_limit + 2) { 
+       /* the transmit buffer is wrapped around */
+               if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
+                       /* Arrrr!!!, must keep the xmt header together,
+                       several days were lost to chase this one down. */
                        
-                       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);
+                       last = lp->xmt_lower_limit;
+                       end = last + (((length + 3) >> 1) << 1) +
+                                                       XMT_HEADER;
                }
+               else end = lp->xmt_lower_limit + (end - 
+                                       lp->xmt_upper_limit + 2);
+       }
 
-               lp->tx_last = last;
-               lp->tx_end = end;
+       outw(last, ioaddr + HOST_ADDRESS_REG);
+       outw(XMT_CMD, ioaddr + IO_PORT);
+       outw(0, ioaddr + IO_PORT);
+       outw(end, ioaddr + IO_PORT);
+       outw(length, ioaddr + IO_PORT);
+
+       if (lp->version == LAN595)
+               outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1);
+       else {  /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
+               unsigned short temp = inb(ioaddr + INT_MASK_REG);
+               outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
+               outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2);
+               outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
+       }
 
-               if (dev->tbusy) {
-                       dev->tbusy = 0;
+       /* A dummy read to flush the DRAM write pipeline */
+       status = inw(ioaddr + IO_PORT); 
+       if (lp->tx_start == lp->tx_end) {
+               outw(last, ioaddr + lp->xmt_bar);
+               outb(XMT_CMD, ioaddr);
+               lp->tx_start = last;   /* I don't like to change tx_start here */
+       }
+       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); 
                }
-               
-               /* now we are serializing tx. tbusy won't come back until
-                * the tx interrupt
-                */
-               if (lp->eepro == LAN595FX_10ISA)
-                       dev->tbusy = 1;
-               
-               /* Enable RX and TX interrupts */
-               eepro_en_int(ioaddr);
-
-               if (net_debug > 5)
-                       printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
 
-               return 0;
+               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);
        }
-       if (lp->eepro == LAN595FX_10ISA)
-               dev->tbusy = 1;
+
+       lp->tx_last = last;
+       lp->tx_end = end;
 
        if (net_debug > 5)
                printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
 
-       return 1;
+       return 0;
 }
 
 static void
 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;
+       short   ioaddr = dev->base_addr,
+               boguscount = 25,
+               rcv_car = lp->rx_start;
        unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
 
        if (net_debug > 5)
@@ -1575,7 +1533,6 @@ eepro_rx(struct device *dev)
        rcv_event = inw(ioaddr + IO_PORT);
 
        while (rcv_event == RCV_DONE) {
-       
                rcv_status = inw(ioaddr + IO_PORT); 
                rcv_next_frame = inw(ioaddr + IO_PORT);
                rcv_size = inw(ioaddr + IO_PORT); 
@@ -1624,24 +1581,26 @@ eepro_rx(struct device *dev)
                        else if (rcv_status & 0x0800)
                                lp->stats.rx_crc_errors++;
                        
-                       printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
+                       printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
                                dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
                }
 
                if (rcv_status & 0x1000)
                        lp->stats.rx_length_errors++;
 
-               if (--boguscount == 0)
-                       break;
 
                rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
                lp->rx_start = rcv_next_frame;
+
+               if (--boguscount == 0)
+                       break;
+
                outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
                rcv_event = inw(ioaddr + IO_PORT);
 
        } 
        if (rcv_car == 0)
-               rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff);
+               rcv_car = lp->rcv_upper_limit | 0xff;
                
        outw(rcv_car - 1, ioaddr + RCV_STOP);
 
@@ -1653,59 +1612,25 @@ static void
 eepro_transmit_interrupt(struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
-       short ioaddr = dev->base_addr;
-       short boguscount = 20; 
-       unsigned xmt_status;
-
-       /*
-       if (dev->tbusy == 0) {
-               printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
-                       dev->name);
-               printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
-                       dev->name);
-       }
-       */
-       while (lp->tx_start != lp->tx_end && boguscount) {
+       short   ioaddr = dev->base_addr,
+               boguscount = 25,
+               xmt_status;
 
+       while ((lp->tx_start != lp->tx_end) && boguscount--) {
                outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
                xmt_status = inw(ioaddr+IO_PORT);
 
-               if ((xmt_status & TX_DONE_BIT) == 0) {
-                       if (lp->eepro == LAN595FX_10ISA) {
-                               udelay(40);
-                               boguscount--;
-                               continue;
-                       }
-                       else
-                               break;
-               }
-
-
-               xmt_status = inw(ioaddr+IO_PORT); 
-               lp->tx_start = inw(ioaddr+IO_PORT);
-
-               if (lp->eepro == LAN595FX_10ISA) {
-                       lp->tx_start = (XMT_LOWER_LIMIT << 8);
-                       lp->tx_end = lp->tx_start;
-       
-                       /* yeah, black magic :( */
-                       eepro_sw2bank0(ioaddr);
-                       eepro_en_int(ioaddr);
+               /* are we trying to get a packet not ready? */
+               if ((xmt_status & TX_DONE_BIT) == 0)
+                       break;
 
-                       /* disabling rx */
-                       eepro_dis_rx(ioaddr);
-                       
-                       /* enabling rx */
-                       eepro_en_rx(ioaddr);
-               }
+               xmt_status = inw(ioaddr+IO_PORT);
+               lp->tx_start = inw(ioaddr + IO_PORT);
 
-               /* here the tbusy comes to 0 for normal and ee10 cards
-                */
                dev->tbusy = 0;
-               
                mark_bh(NET_BH);
-               
-               if (xmt_status & 0x2000) {
+
+               if (xmt_status & TX_OK) {
                        lp->stats.tx_packets++; 
                }
                else {
@@ -1714,45 +1639,17 @@ eepro_transmit_interrupt(struct device *dev)
                                lp->stats.tx_carrier_errors++;
                                printk(KERN_DEBUG "%s: carrier error\n",
                                        dev->name);
-                               printk(KERN_DEBUG "%s: XMT status = %#x\n",
-                                       dev->name, xmt_status);
                        }
-                       else {
-                               printk(KERN_DEBUG "%s: XMT status = %#x\n",
+                       printk(KERN_DEBUG "%s: XMT status = %#x\n",
                                        dev->name, xmt_status);
-                               printk(KERN_DEBUG "%s: XMT status = %#x\n",
-                                       dev->name, xmt_status);
-                       }
-
-                       if (lp->eepro == LAN595FX_10ISA) {                      
-                               /* Try to restart the adaptor. */
-                               /* We are supposed to wait for 2 us after a SEL_RESET */
-                               eepro_sel_reset(ioaddr);
-
-                               /* first enable interrupts */
-                               eepro_sw2bank0(ioaddr);
-                               outb(ALL_MASK & ~(RX_INT | TX_INT), ioaddr + STATUS_REG);
-                       
-                               /* enabling rx */
-                               eepro_en_rx(ioaddr);
-                       }
                }
                
-               if (xmt_status & 0x000f) {
+               if (xmt_status & 0x000f)
                        lp->stats.collisions += (xmt_status & 0x000f);
-               }
                
-               if ((xmt_status & 0x0040) == 0x0) {
+               if (!(xmt_status & 0x0040))
                        lp->stats.tx_heartbeat_errors++;
-               }
-               boguscount--;
        }
-       /* if it reached here then it's probable that the adapter won't
-        * interrupt again for tx. in other words: tx timeout what will take
-        * a lot of time to happen, so we'll do a complete selreset.
-        */
-       if (!boguscount && lp->eepro == LAN595FX_10ISA)
-               eepro_complete_selreset(ioaddr);
 }
 
 #ifdef MODULE
@@ -1781,23 +1678,23 @@ init_module(void)
 {
        int i;
        if (io[0] == 0 && autodetect == 0) {
-               printk("eepro_init_module: Probe is very dangerous in ISA boards!\n");
-               printk("eepro_init_module: Please add \"autodetect=1\" to force probe\n");
+               printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
+               printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
                return 1;
        }
        else if (autodetect) {
                /* if autodetect is set then we must force detection */
                io[0] = 0;
                
-               printk("eepro_init_module: Auto-detecting boards (May God protect us...)\n");
+               printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
        }       
        
        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->base_addr    = io[0];
-               d->irq          = irq[n_eepro];
+               d->mem_end      = mem[i];               
+               d->base_addr    = io[i];
+               d->irq          = irq[i];
                d->init         = eepro_probe;
 
                if (register_netdev(d) == 0)
@@ -1805,7 +1702,10 @@ init_module(void)
                else
                        break;
        }
-       
+
+       if (n_eepro)
+               printk(KERN_INFO "%s", version);
+
        return n_eepro ? 0 : -ENODEV;
 }
 
index 716096e648d3382ddbfcbe7fbfd480f4de821b74..4f5f96a850ca6c69c7347315d27441b9c5144652 100644 (file)
@@ -4,6 +4,7 @@
    Written By: Adam Radford <linux@3ware.com>
    Modifications By: Joel Jacobson <linux@3ware.com>
                     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+                     Brad Strand <linux@3ware.com>
 
    Copyright (C) 1999-2001 3ware Inc.
 
                  Fix possible null pointer dereference in tw_aen_drain_queue()
                  during initialization.
                  Clear pci parity errors during initialization and during io.
+   1.02.00.009 - Remove redundant increment in tw_state_request_start().
+                 Add ioctl support for direct ATA command passthru.
+                 Add entire aen code string list.
+   1.02.00.010 - Cleanup queueing code, fix jbod throughput.
+                 Fix get_param for specific units.
 */
 
 #include <linux/module.h>
@@ -149,7 +155,7 @@ struct proc_dir_entry tw_scsi_proc_entry = {
 };
 
 /* Globals */
-char *tw_driver_version="1.02.00.008";
+char *tw_driver_version="1.02.00.010";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -170,21 +176,17 @@ int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
        dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
 
        /* Print some useful info when certain aen codes come out */
-       switch (aen & 0x0ff) {
-               case TW_AEN_APORT_TIMEOUT:
-                       printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive timeout AEN on port %d, check drive and drive cables.\n", tw_dev->host->host_no, aen >> 8);
-               break;
-               case TW_AEN_DRIVE_ERROR:
-                       printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive error AEN on port %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8);
-                       break;
-               case TW_AEN_SMART_FAIL:
-                       printk(KERN_WARNING "3w-xxxx: scsi%d: Received S.M.A.R.T. threshold AEN on port %d, check drive/cooling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8);
-                       break;
-               case TW_AEN_SBUF_FAIL:
-                       printk(KERN_WARNING "3w-xxxx: scsi%d: Received SBUF integrity check failure AEN, reseat card or bad card.\n", tw_dev->host->host_no);
-                       break;
-               default:
-                       printk(KERN_WARNING "3w-xxxx: Received AEN 0x%x\n", aen);
+       if (aen == 0x0ff) {
+               printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: AEN queue overflow.\n", tw_dev->host->host_no);
+       } else {
+               if ((aen & 0x0ff) < TW_AEN_STRING_MAX) {
+                       if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
+                               printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
+                       } else {
+                               printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
+                       }
+               } else
+                       printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
        }
 
        tw_dev->aen_count++;
@@ -236,7 +238,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
        response_que_addr = tw_dev->registers.response_que_addr;
 
        if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 15)) {
-               printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_device_extension_count);
+               dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_device_extension_count);
                return 1;
        }
 
@@ -292,7 +294,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
                        mdelay(5);
                        status_reg_value = inl(status_reg_addr);
                        if (tw_check_bits(status_reg_value)) {
-                               printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
+                               dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
                                tw_decode_bits(tw_dev, status_reg_value);
                                return 1;
                        }
@@ -309,7 +311,8 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
                                if (command_packet->status != 0) {
                                        if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
                                                /* Bad response */
-                                               printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                                               dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                                               tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
                                                return 1;
                                        } else {
                                                /* We know this is a 3w-1x00, and doesn't support aen's */
@@ -429,7 +432,7 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
 
        status_reg_value = inl(status_reg_addr);
        if (tw_check_bits(status_reg_value)) {
-               printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
+               dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
                tw_decode_bits(tw_dev, status_reg_value);
                return 1;
        }
@@ -527,11 +530,11 @@ int tw_allocate_memory(TW_Device_Extension *tw_dev, int request_id, int size, in
 int tw_check_bits(u32 status_reg_value)
 {
        if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {  
-               printk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
+               dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
                return 1;
        }
        if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
+               dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
                return 1;
        }
 
@@ -635,9 +638,13 @@ void tw_decode_error(TW_Device_Extension *tw_dev, unsigned char status, unsigned
                 case 0x51:
                         printk(KERN_WARNING "3w-xxxx: scsi%d: Unrecoverable drive error on unit %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, unit);
                         break;
-                }
+               default:
+                       printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);
+               }
                 break;
-        }
+       default:
+               printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);
+       }
 } /* End tw_decode_error() */
 
 /* This function will disable interrupts on the controller */  
@@ -662,7 +669,7 @@ int tw_empty_response_que(TW_Device_Extension *tw_dev)
        status_reg_value = inl(status_reg_addr);
 
        if (tw_check_bits(status_reg_value)) {
-               printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
+               dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
                tw_decode_bits(tw_dev, status_reg_value);
                return 1;
        }
@@ -671,7 +678,7 @@ int tw_empty_response_que(TW_Device_Extension *tw_dev)
                response_que_value = inl(response_que_addr);
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
-                       printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
+                       dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
                        tw_decode_bits(tw_dev, status_reg_value);
                        return 1;
                }
@@ -817,9 +824,20 @@ int tw_findcards(Scsi_Host_Template *tw_host)
                                continue;
                        }
 
-                       /* Calculate max cmds per lun */
-                       if (tw_dev->num_units > 0)
-                               tw_host->cmd_per_lun = (TW_Q_LENGTH-2)/tw_dev->num_units;
+                       /* Calculate max cmds per lun, and setup queues */
+                       if (tw_dev->num_units > 0) {
+                               if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
+                                       tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-1)/tw_dev->num_units;
+                                       tw_dev->free_head = TW_Q_START;
+                                       tw_dev->free_tail = TW_MAX_BOUNCEBUF - 1;
+                                       tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1;
+                               } else {
+                                       tw_host->cmd_per_lun = (TW_Q_LENGTH-1)/tw_dev->num_units;
+                                       tw_dev->free_head = TW_Q_START;
+                                       tw_dev->free_tail = TW_Q_LENGTH - 1;
+                                       tw_dev->free_wrap = TW_Q_LENGTH - 1;
+                               }
+                       }
                        
                        /* Register the card with the kernel SCSI layer */
                        host = scsi_register(tw_host, sizeof(TW_Device_Extension));
@@ -890,18 +908,19 @@ int tw_findcards(Scsi_Host_Template *tw_host)
 /* This function will free up device extension resources */
 void tw_free_device_extension(TW_Device_Extension *tw_dev)
 {
-       int i, imax;
-       imax = TW_Q_LENGTH;
+       int i;
 
        dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
        /* Free command packet and generic buffer memory */
-       for (i=0;i<imax;i++) {
+       for (i=0;i<TW_Q_LENGTH;i++) {
                if (tw_dev->command_packet_virtual_address[i]) 
                        kfree(tw_dev->command_packet_virtual_address[i]);
 
                if (tw_dev->alignment_virtual_address[i])
                        kfree(tw_dev->alignment_virtual_address[i]);
 
+       }
+       for (i=0;i<TW_MAX_BOUNCEBUF;i++) {
                if (tw_dev->bounce_buffer[i])
                        kfree(tw_dev->bounce_buffer[i]);
        }
@@ -913,7 +932,7 @@ static int tw_halt(struct notifier_block *nb, ulong event, void *buf)
        int i;
        
        for (i=0;i<tw_device_extension_count;i++) {
-               printk(KERN_NOTICE "3w-xxxx: Notifying card #%d\n", i);
+               printk(KERN_NOTICE "3w-xxxx: Shutting down card %d.\n", i);
                tw_shutdown_device(tw_device_extension_list[i]);
        }
        unregister_reboot_notifier(&tw_notifier);
@@ -972,7 +991,7 @@ int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
                mdelay(5);
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
-                       printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
+                       dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
                        tw_decode_bits(tw_dev, status_reg_value);
                        return 1;
                }
@@ -986,7 +1005,8 @@ int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
                        }
                        if (command_packet->status != 0) {
                                /* bad response */
-                               printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                               dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                               tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
                                return 1;
                        }
                        break;  /* Response was okay, so we exit */
@@ -1034,8 +1054,6 @@ int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
        tw_dev->num_units = 0;
        tw_dev->num_aborts = 0;
        tw_dev->num_resets = 0;
-       tw_dev->free_head = TW_Q_START;
-       tw_dev->free_tail = TW_Q_LENGTH - 1;
        tw_dev->posted_request_count = 0;
        tw_dev->max_posted_request_count = 0;
        tw_dev->max_sgl_entries = 0;
@@ -1125,7 +1143,7 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
                mdelay(5);
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
-                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+                       dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
                        tw_decode_bits(tw_dev, status_reg_value);
                        return 1;
                }
@@ -1139,7 +1157,8 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
                        }
                        if (command_packet->status != 0) {
                                /* bad response */
-                               printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                               dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                               tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
                                return 1;
                        }
                        found = 1;
@@ -1228,7 +1247,7 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
                        mdelay(5);
                        status_reg_value = inl(status_reg_addr);
                        if (tw_check_bits(status_reg_value)) {
-                               printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+                               dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
                                tw_decode_bits(tw_dev, status_reg_value);
                                return 1;
                        }
@@ -1242,7 +1261,8 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
                                }
                                if (command_packet->status != 0) {
                                /* bad response */
-                                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                                       dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                                       tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
                                        return 1;
                                }
                                found = 1;
@@ -1267,13 +1287,13 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
 
        /* Now allocate raid5 bounce buffers */
        if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
-               for (i=0;i<TW_Q_LENGTH;i++) {
-                       tw_allocate_memory(tw_dev, i, sizeof(TW_Sector)*128, 2);
+               for (i=0;i<TW_MAX_BOUNCEBUF;i++) {
+                       tw_allocate_memory(tw_dev, i, sizeof(TW_Sector)*TW_MAX_SECTORS, 2);
                        if (tw_dev->bounce_buffer[i] == NULL) {
                                printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bounce buffer allocation failed.\n");
                                return 1;
                        }
-                       memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*128);
+                       memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*TW_MAX_SECTORS);
                }
        }
   
@@ -1330,7 +1350,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        tw_state_request_start(tw_dev, &request_id);
                        error = tw_aen_read_queue(tw_dev, request_id);
                        if (error) {
-                               printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error reading aen queue.\n");
+                               printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
                                tw_dev->state[request_id] = TW_S_COMPLETED;
                                tw_state_request_finish(tw_dev, request_id);
                        }
@@ -1342,7 +1362,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        while (tw_dev->pending_request_count > 0) {
                                request_id = tw_dev->pending_queue[tw_dev->pending_head];
                                if (tw_dev->state[request_id] != TW_S_PENDING) {
-                                       printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found request id that wasn't pending.\n");
+                                       printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
                                        break;
                                }
                                if (tw_post_command_packet(tw_dev, request_id)==0) {
@@ -1370,12 +1390,12 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
                                error = 0;
                                if (command_packet->status != 0) {
-                                       printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit);
+                                       dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit);
                                        tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
                                        error = 1;
                                }
                                if (tw_dev->state[request_id] != TW_S_POSTED) {
-                                       printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode);
+                                       printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode);
                                        error = 1;
                                }
                                if (TW_STATUS_ERRORS(status_reg_value)) {
@@ -1388,24 +1408,22 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                        dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
                                        error = tw_aen_complete(tw_dev, request_id);
                                        if (error) {
-                                               printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error completing aen.\n");
+                                               printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
                                        }
                                        status_reg_value = inl(status_reg_addr);
                                        if (tw_check_bits(status_reg_value)) {
-                                               printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+                                               dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
                                                tw_decode_bits(tw_dev, status_reg_value);
                                        }
                } else {
                                switch (tw_dev->srb[request_id]->cmnd[0]) {
                                        case READ_10:
-                                               dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10\n");
                                        case READ_6:
-                                               dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_6\n");
+                                               dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
                                                break;
                                        case WRITE_10:
-                                               dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10\n");
                                        case WRITE_6:
-                                               dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_6\n");
+                                               dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
                                                break;
                                        case INQUIRY:
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
@@ -1420,7 +1438,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                                error = tw_ioctl_complete(tw_dev, request_id);
                                                break;
                                        default:
-                                               printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unknown scsi opcode: 0x%x.\n", tw_dev->srb[request_id]->cmnd[0]);
+                                               printk(KERN_WARNING "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x.\n", tw_dev->host->host_no, tw_dev->srb[request_id]->cmnd[0]);
                                                tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
                                                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                                        }
@@ -1438,7 +1456,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                        tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                                        status_reg_value = inl(status_reg_addr);
                                        if (tw_check_bits(status_reg_value)) {
-                                               printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+                                               dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
                                                tw_decode_bits(tw_dev, status_reg_value);
                                        }
                                }
@@ -1458,6 +1476,7 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
        TW_Command *command_packet;
        u32 param_value;
        TW_Ioctl *ioctl = NULL;
+       TW_Passthru *passthru = NULL;
        int tw_aen_code;
 
        ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
@@ -1506,6 +1525,7 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
                case TW_OP_GET_PARAM:
                        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
                        command_packet->byte0.opcode = TW_OP_GET_PARAM;
+                       command_packet->byte3.unit = ioctl->unit_index;
                        param->table_id = ioctl->table_id;
                        param->parameter_id = ioctl->parameter_id;
                        param->parameter_size_bytes = ioctl->parameter_size_bytes;
@@ -1549,6 +1569,25 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
                        tw_dev->srb[request_id]->result = (DID_OK << 16);
                        tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                        return 0;
+               case TW_ATA_PASSTHRU:
+                       if (ioctl->data != NULL) {
+                               memcpy(command_packet, ioctl->data, sizeof(TW_Command));
+                               command_packet->request_id = request_id;
+                       } else {
+                               printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
+                               return 1;
+                       }
+
+                       passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id];
+                       passthru->sg_list[0].length = passthru->sector_count*512;
+                       if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) {
+                               printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%ld) too big.\n", passthru->sg_list[0].length);
+                               return 1;
+                       }
+                       passthru->sg_list[0].address = virt_to_bus(tw_dev->alignment_virtual_address[request_id]);
+                       tw_post_command_packet(tw_dev, request_id);
+                        return 0;
+
                case TW_CMD_PACKET:
                        if (ioctl->data != NULL) {
                                memcpy(command_packet, ioctl->data, sizeof(TW_Command));
@@ -1583,7 +1622,6 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
        command_packet->byte0.sgl_offset = 2;
        command_packet->size = 4;
        command_packet->request_id = request_id;
-       command_packet->byte3.unit = 0;
        command_packet->byte3.host_id = 0;
        command_packet->status = 0;
        command_packet->flags = 0;
@@ -1601,7 +1639,10 @@ int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id)
        unsigned char *param_data;
        unsigned char *buff;
        TW_Param *param;
+       TW_Ioctl *ioctl = NULL;
+       TW_Passthru *passthru = NULL;
 
+       ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
        buff = tw_dev->srb[request_id]->request_buffer;
        if (buff == NULL) {
@@ -1609,16 +1650,23 @@ int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id)
                return 1;
        }
        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);
-       memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
-       param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
-       if (param == NULL) {
-               printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
-               return 1;
-       }
-       param_data = &(param->data[0]);
-
-       memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
 
+       ioctl = (TW_Ioctl *)buff;
+       switch (ioctl->opcode) {
+               case TW_ATA_PASSTHRU:
+                       passthru = (TW_Passthru *)ioctl->data;
+                       memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512);
+                       break;
+               default:
+                       memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+                       param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+                       if (param == NULL) {
+                               printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Bad alignment virtual address.\n");
+                               return 1;
+                       }
+                       param_data = &(param->data[0]);
+                       memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
+       }
        return 0;
 } /* End tw_ioctl_complete() */
 
@@ -1646,7 +1694,7 @@ int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
                status_reg_value = inl(status_reg_addr);
                do_gettimeofday(&timeout);
                if (before.tv_sec + seconds < timeout.tv_sec) { 
-                       printk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
+                       dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
                        return 1;
                }
                mdelay(1);
@@ -1667,7 +1715,7 @@ int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
        status_reg_value = inl(status_reg_addr);
 
        if (tw_check_bits(status_reg_value)) {
-               printk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
+               dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
                tw_decode_bits(tw_dev, status_reg_value);
        }
 
@@ -1711,7 +1759,7 @@ int tw_reset_device_extension(TW_Device_Extension *tw_dev)
        imax = TW_Q_LENGTH;
 
        if (tw_reset_sequence(tw_dev)) {
-               printk(KERN_WARNING "3w-xxxx: tw_reset_device_extension(): Reset sequence failed for card %d.\n", tw_dev->host->host_no);
+               printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
                return 1;
        }
 
@@ -1758,14 +1806,14 @@ int tw_reset_sequence(TW_Device_Extension *tw_dev)
 
                error = tw_aen_drain_queue(tw_dev);
                if (error) {
-                       printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev->host->host_no);
+                       printk(KERN_WARNING "3w-xxxx: scsi%d: Card not responding, retrying.\n", tw_dev->host->host_no);
                        tries++;
                        continue;
                }
 
                /* Check for controller errors */
                if (tw_check_errors(tw_dev)) {
-                       printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller errors found, soft resetting card %d.\n", tw_dev->host->host_no);
+                       printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no);
                        tries++;
                        continue;
                }
@@ -1773,7 +1821,7 @@ int tw_reset_sequence(TW_Device_Extension *tw_dev)
                /* Empty the response queue again */
                error = tw_empty_response_que(tw_dev);
                if (error) {
-                       printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev->host->host_no);
+                       printk(KERN_WARNING "3w-xxxx: scsi%d: Couldn't empty response queue, retrying.\n", tw_dev->host->host_no);
                        tries++;
                        continue;
                }
@@ -1783,13 +1831,13 @@ int tw_reset_sequence(TW_Device_Extension *tw_dev)
        }
 
        if (tries >= TW_MAX_RESET_TRIES) {
-               printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller error or no attention interrupt: giving up for card %d.\n", tw_dev->host->host_no);
+               printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no);
                return 1;
        }
 
        error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
        if (error) {
-               printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+               printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no);
                return 1;
        }
 
@@ -1879,14 +1927,14 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
        for (i=0;i<TW_Q_LENGTH;i++) {
                if (tw_dev->srb[i] == SCpnt) {
                        if (tw_dev->state[i] == TW_S_STARTED) {
-                               printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for started Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+                               printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt);
                                tw_dev->state[i] = TW_S_COMPLETED;
                                tw_state_request_finish(tw_dev, i);
                                spin_unlock(&tw_dev->tw_lock);
                                return (SUCCESS);
                        }
                        if (tw_dev->state[i] == TW_S_PENDING) {
-                               printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for pending Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+                               printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt);
                                if (tw_dev->pending_head == TW_Q_LENGTH-1) {
                                        tw_dev->pending_head = TW_Q_START;
                                } else {
@@ -1902,10 +1950,9 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
        }
 
        /* If the command has already been posted, we have to reset the card */
-       printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort failed for unknown Scsi_Cmnd 0x%x, resetting card %d.\n", (u32)SCpnt, tw_dev->host->host_no);
-
+       printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt);
        if (tw_reset_device_extension(tw_dev)) {
-               printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
+               dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
                spin_unlock(&tw_dev->tw_lock);
                return (FAILED);
        }
@@ -1943,11 +1990,11 @@ int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt)
 
        /* Now reset the card and some of the device extension data */
        if (tw_reset_device_extension(tw_dev)) {
-               printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset failed for card %d.\n", tw_dev->host->host_no);
+               printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
                spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
                return (FAILED);
        }
-       printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset succeeded for card %d.\n", tw_dev->host->host_no);
+       printk(KERN_WARNING "3w-xxxx: scsi%d: Reset succeeded.\n", tw_dev->host->host_no);
        spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
 
        return (SUCCESS);
@@ -2060,13 +2107,10 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 
        switch (*command) {
                case READ_10:
-                       dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_10.\n");
                case READ_6:
-                       dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_6.\n");
                case WRITE_10:
-                       dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n");
                case WRITE_6:
-                       dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n");
+                       dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n");
                        error = tw_scsiop_read_write(tw_dev, request_id);
                        break;
                case TEST_UNIT_READY:
@@ -2090,7 +2134,7 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
                        error = tw_ioctl(tw_dev, request_id);
                        break;
                default:
-                       printk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): Unknown scsi opcode: 0x%x\n", *command);
+                       printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
                        tw_dev->state[request_id] = TW_S_COMPLETED;
                        tw_state_request_finish(tw_dev, request_id);
                        SCpnt->result = (DID_BAD_TARGET << 16);
@@ -2558,7 +2602,7 @@ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
                mdelay(5);
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
-                       printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
+                       dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
                        tw_decode_bits(tw_dev, status_reg_value);
                        return 1;
                }
@@ -2572,7 +2616,8 @@ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
                        }
                        if (command_packet->status != 0) {
                                /* bad response */
-                               printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                               dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                               tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
                                return 1;
                        }
                        break; /* Response was okay, so we exit */
@@ -2592,7 +2637,7 @@ int tw_setup_irq(TW_Device_Extension *tw_dev)
        error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev);
 
        if (error < 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_setup_irq(): Error requesting IRQ: %d for card %d.\n", tw_dev->tw_pci_dev->irq, tw_dev->host->host_no);
+               printk(KERN_WARNING "3w-xxxx: scsi%d: Error requesting IRQ: %d.\n", tw_dev->host->host_no, tw_dev->tw_pci_dev->irq);
                return 1;
        }
        return 0;
@@ -2610,9 +2655,9 @@ int tw_shutdown_device(TW_Device_Extension *tw_dev)
        /* poke the board */
        error = tw_initconnection(tw_dev, 1);
        if (error) {
-               printk(KERN_WARNING "3w-xxxx: tw_shutdown_device(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+               printk(KERN_WARNING "3w-xxxx: scsi%d: Connection shutdown failed.\n", tw_dev->host->host_no);
        } else {
-               printk(KERN_NOTICE "3w-xxxx shutdown succeeded\n");
+               printk(KERN_NOTICE "3w-xxxx: Shutdown complete.\n");
        }
 
        /* Re-enable interrupts */
@@ -2643,7 +2688,7 @@ int tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id)
        dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n");
   
        do {    
-               if (tw_dev->free_tail == TW_Q_LENGTH-1) {
+               if (tw_dev->free_tail == tw_dev->free_wrap) {
                        tw_dev->free_tail = TW_Q_START;
                } else {
                        tw_dev->free_tail = tw_dev->free_tail + 1;
@@ -2667,24 +2712,15 @@ int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
 
        /* Obtain next free request_id */
        do {
-               if (tw_dev->free_head == TW_Q_LENGTH - 1) {
+               if (tw_dev->free_head == tw_dev->free_wrap) {
                        tw_dev->free_head = TW_Q_START;
                } else {
                        tw_dev->free_head = tw_dev->free_head + 1;
                }
-       } while ((tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_STARTED) ||
-                (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_POSTED) ||
-                (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_PENDING) ||
-                (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_COMPLETED));
+       } while (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] & TW_START_MASK);
 
        id = tw_dev->free_queue[tw_dev->free_head];
 
-       if (tw_dev->free_head == TW_Q_LENGTH - 1) {
-               tw_dev->free_head = TW_Q_START;
-       } else {
-               tw_dev->free_head = tw_dev->free_head + 1;
-       }
-
        dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id);
        *request_id = id;
        tw_dev->state[id] = TW_S_STARTED;
index ecba1aeb4d42ee3c292c620fa92c92efb1e23877..655d46ef9b606439c477431c8f84e37e1e43cc29 100644 (file)
@@ -4,6 +4,7 @@
    Written By: Adam Radford <linux@3ware.com>
    Modifications By: Joel Jacobson <linux@3ware.com>
                     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+                     Brad Strand <linux@3ware.com>
 
    Copyright (C) 1999-2001 3ware Inc.
 
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 
+/* AEN strings */
+static char *tw_aen_string[] = {
+       "AEN queue empty",                      // 0x000
+       "Soft reset occurred",                  // 0x001
+       "Mirorr degraded: Unit #",              // 0x002
+       "Controller error",                     // 0x003
+       "Rebuild failed: Unit #",               // 0x004
+       "Rebuild complete: Unit #",             // 0x005
+       "Incomplete unit detected: Unit #",     // 0x006
+       "Initialization complete: Unit #",      // 0x007
+       "Unclean shutdown detected: Unit #",    // 0x008
+       "ATA port timeout: Port #",             // 0x009
+       "Drive error: Port #",                  // 0x00A
+       "Rebuild started: Unit #",              // 0x00B
+       "Initialization started: Unit #",       // 0x00C
+       "Logical unit deleted: Unit #",         // 0x00D
+       NULL,                                   // 0x00E unused
+       "SMART threshold exceeded: Port #",     // 0x00F
+       NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL,                             // 0x010-0x020 unused
+       "ATA UDMA downgrade: Port #",           // 0x021
+       "ATA UDMA upgrade: Port #",             // 0x022
+       "Sector repair occurred: Port #",       // 0x023
+       "SBUF integrity check failure",         // 0x024
+       "Lost cached write: Port #",            // 0x025
+       "Drive ECC error detected: Port #",     // 0x026
+       "DCB checksum error: Port #",           // 0x027
+       "DCB unsupported version: Port #",      // 0x028
+       "Verify started: Unit #",               // 0x029
+       "Verify failed: Port #",                // 0x02A
+       "Verify complete: Unit #"               // 0x02B
+};
+
+#define TW_AEN_STRING_MAX                      0x02C
+
 /* Control register bit definitions */
 #define TW_CONTROL_CLEAR_HOST_INTERRUPT               0x00080000
 #define TW_CONTROL_CLEAR_ATTENTION_INTERRUPT   0x00040000
 #define TW_OP_SECTOR_INFO     0x1a
 #define TW_OP_AEN_LISTEN      0x1c
 #define TW_CMD_PACKET         0x1d
+#define TW_ATA_PASSTHRU       0x1e
 
 /* Asynchronous Event Notification (AEN) Codes */
 #define TW_AEN_QUEUE_EMPTY       0x0000
 #define TW_INIT_COMMAND_PACKET_SIZE          0x3
 #define TW_POLL_MAX_RETRIES                  20000
 #define TW_MAX_SGL_LENGTH                    62
-#define TW_Q_LENGTH                          16
+#define TW_ATA_PASS_SGL_MAX                   60
+#define TW_MAX_PASSTHRU_BYTES                 4096
+#define TW_Q_LENGTH                          256
+#define TW_MAX_BOUNCEBUF                      16
 #define TW_Q_START                           0
 #define TW_MAX_SLOT                          32
 #define TW_MAX_PCI_BUSES                     255
 #define TW_MAX_AEN_TRIES                      100
 #define TW_UNIT_ONLINE                        1
 #define TW_IN_INTR                            1
+#define TW_MAX_SECTORS                        128
 #define TW_AEN_WAIT_TIME                      1000
 
 /* Macros */
@@ -222,6 +265,7 @@ typedef struct TAG_TW_Ioctl {
        unsigned short table_id;
        unsigned char parameter_id;
        unsigned char parameter_size_bytes;
+       unsigned char unit_index;
        unsigned char data[1];
 } TW_Ioctl;
 
@@ -258,14 +302,42 @@ typedef struct TAG_TW_Info {
        int position;
 } TW_Info;
 
-typedef enum TAG_TW_Cmd_State {
-       TW_S_INITIAL,           /* Initial state */
-       TW_S_STARTED,           /* Id in use */
-       TW_S_POSTED,            /* Posted to the controller */
-       TW_S_PENDING,           /* Waiting to be posted in isr */
-       TW_S_COMPLETED,         /* Completed by isr */
-       TW_S_FINISHED,          /* I/O completely done */
-} TW_Cmd_State;
+typedef int TW_Cmd_State;
+
+#define TW_S_INITIAL   0x1  /* Initial state */
+#define TW_S_STARTED   0x2  /* Id in use */
+#define TW_S_POSTED    0x4  /* Posted to the controller */
+#define TW_S_PENDING   0x8  /* Waiting to be posted in isr */
+#define TW_S_COMPLETED 0x10 /* Completed by isr */
+#define TW_S_FINISHED  0x20 /* I/O completely done */
+#define TW_START_MASK (TW_S_STARTED | TW_S_POSTED | TW_S_PENDING | TW_S_COMPLETED)
+
+/* Command header for ATA pass-thru */
+typedef struct TAG_TW_Passthru
+{
+       struct {
+               unsigned char opcode:5;
+               unsigned char sgloff:3;
+       } byte0;
+       unsigned char size;
+       unsigned char request_id;
+       struct {
+               unsigned char aport:4;
+               unsigned char host_id:4;
+       } byte3;
+       unsigned char status;
+       unsigned char flags;
+       unsigned short param;
+       unsigned short features;
+       unsigned short sector_count;
+       unsigned short sector_num;
+       unsigned short cylinder_lo;
+       unsigned short cylinder_hi;
+       unsigned char drive_head;
+       unsigned char command;
+       TW_SG_Entry sg_list[TW_ATA_PASS_SGL_MAX];
+       unsigned char padding[12];
+} TW_Passthru;
 
 typedef struct TAG_TW_Device_Extension {
        TW_Registers            registers;
@@ -283,6 +355,7 @@ typedef struct TAG_TW_Device_Extension {
        unsigned char           free_queue[TW_Q_LENGTH];
        unsigned char           free_head;
        unsigned char           free_tail;
+       unsigned char           free_wrap;
        unsigned char           pending_queue[TW_Q_LENGTH];
        unsigned char           pending_head;
        unsigned char           pending_tail;
index f9259bb761ab7c85de98075ea70be84cf6aef8c4..0c936e2e89fe72bb4e13ac96fae23056cecdf55a 100644 (file)
@@ -239,6 +239,7 @@ typedef unsigned int  u32;
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/processor.h>
 #include <linux/delay.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -1463,7 +1464,7 @@ ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip,
       command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO;
       pci_write_config_word(pdev, PCI_COMMAND, command);
 
-      if (io_port >= 0x10000000 && is_prep ) {
+      if (io_port >= 0x10000000 && (_machine == _MACH_prep)) {
              /* Mapping on PowerPC can't handle this! */
              unsigned long new_io_port;
              new_io_port = (io_port & 0x00FFFFFF) | 0x01000000;
index acecb9b1bbe60b5f7d89910108355e72234da1f1..05736c863d4438310cfb4240c0d5bd5ddf96b256 100644 (file)
@@ -10125,14 +10125,13 @@ static void ncr_sir_task_recovery(ncb_p np, int num)
                                if (i >= MAX_START*2)
                                        i = 0;
                        }
-                       assert(k != -1);
-                       if (k != 1) {
+                       if (k != -1) {
                                np->squeue[k] = np->squeue[i]; /* Idle task */
                                np->squeueput = k; /* Start queue pointer */
-                               cp->host_status = HS_ABORTED;
-                               cp->scsi_status = S_ILLEGAL;
-                               ncr_complete(np, cp);
                        }
+                       cp->host_status = HS_ABORTED;
+                       cp->scsi_status = S_ILLEGAL;
+                       ncr_complete(np, cp);
                }
                break;
        /*
index 71d842c042b61f918c3bab92e38f21bd3dcaf66f..f2ab31cb5a0d28e46d9789468d858c4bc5a94430 100644 (file)
@@ -420,7 +420,7 @@ nfs_readpage_result(struct rpc_task *task)
 {
        struct nfs_read_data    *data = (struct nfs_read_data *) task->tk_calldata;
        struct inode            *inode = data->inode;
-       int                     count = data->res.count;
+       unsigned int            count = data->res.count;
 
        dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
                task->tk_pid, task->tk_status);
@@ -431,10 +431,15 @@ nfs_readpage_result(struct rpc_task *task)
                struct page *page = req->wb_page;
                nfs_list_remove_request(req);
 
-               if (task->tk_status >= 0 && count >= 0) {
+               if (task->tk_status >= 0) {
+                       char *p = page_address(page);
+                       if (count < PAGE_CACHE_SIZE) {
+                               memset(p + count, 0, PAGE_CACHE_SIZE - count);
+                               count = 0;
+                       } else
+                               count -= PAGE_CACHE_SIZE;
                        flush_dcache_page(page_address(page)); /* Is this correct? */
                        set_bit(PG_uptodate, &page->flags);
-                       count -= PAGE_CACHE_SIZE;
                } else
                        set_bit(PG_error, &page->flags);
                nfs_unlock_page(page);
index 2607e06589ac5510855fd29b933c4739e1b13e5b..539a0599388caf5b86f4bdf87b6c4647ebe3fece 100644 (file)
@@ -454,7 +454,7 @@ struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, un
 
        de = (struct proc_dir_entry *) inode->u.generic_ip;
        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        if (de->readlink_proc)
                len = de->readlink_proc(de, page);
index 86e5e74d520f2caebdfcf1c55bbe0762c450e56c..9dd29555d464f3dc72aa66669b34fd7f26ea70ac 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/pci.h>
-
+#include <linux/errno.h>
 
 /*
  * The following structure is used to manage multiple PCI busses.
@@ -59,7 +59,7 @@ static __inline__ int pci_controller_num(struct pci_dev *pdev)
        if (bus2hose[pdev->bus->number] == NULL)
                return -ENXIO;
 
-       return bus2hose[pdev->bus->number]->pci_host_index;
+       return bus2hose[pdev->bus->number]->pci_hose_index;
 }
 
 #endif /* __ALPHA_PCI_H */
index 13c9a8acc6f47249ab4cf4023da039b3e20bc4ed..936c94d51b2249e0497ddb097fdc69624b509a0d 100644 (file)
@@ -65,11 +65,11 @@ struct  seminfo {
 #define SEMMNS  (SEMMNI*SEMMSL) /* ? max # of semaphores in system */
 #define SEMOPM  32             /* ~ 100 max num of ops per semop call */
 #define SEMVMX  32767           /* semaphore maximum value */
+#define SEMAEM  SEMVMX          /* adjust on exit max value */
 
 /* unused */
 #define SEMUME  SEMOPM          /* max num of undo entries per process */
 #define SEMMNU  SEMMNS          /* num of undo structures system wide */
-#define SEMAEM  (SEMVMX >> 1)   /* adjust on exit max value */
 #define SEMMAP  SEMMNS          /* # of entries in semaphore map */
 #define SEMUSZ  20             /* sizeof struct sem_undo */
 
index 9598a1684e1e451b478166a1187d0c36dd7c6926..bbe847899a6c9ad75691051cdcbf5c971c25881a 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -229,7 +229,19 @@ static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,
                curr->sempid = (curr->sempid << 16) | pid;
                curr->semval += sem_op;
                if (sop->sem_flg & SEM_UNDO)
-                       un->semadj[sop->sem_num] -= sem_op;
+               {
+                       int undo = un->semadj[sop->sem_num] - sem_op;
+                       /*
+                       *      Exceeding the undo range is an error.
+                       */
+                       if(undo < (-SEMAEM - 1) || undo > SEMAEM)
+                       {
+                               /* Don't undo the undo */
+                               sop->sem_flg &= ~SEM_UNDO;
+                               goto out_of_range;
+                       }
+                       un->semadj[sop->sem_num] = undo;
+               }
 
                if (curr->semval < 0)
                        goto would_block;
index 533cca3ad461d2c4846b3bb8cc4e4db487bbbdf7..40fa139bdf67e46907f337a6cfcc05603fc34e96 100644 (file)
@@ -149,7 +149,8 @@ static inline void free_pages_ok(unsigned long map_nr, unsigned long order, unsi
         * local since we must deal with fragmentation too and we
         * can't rely on the nr_local_pages information.
         */
-       if (current->nr_local_pages && !current->allocation_order)
+       if ((current->nr_local_pages && !current->allocation_order) ||
+           in_interrupt())
                goto back_local_freelist;
 
        page = mem_map + map_nr;
index a944a13a1d8e4ef644c3790e3b4eef9170091b86..5a32418906dcaa7d08199628ebf023b247a3e93c 100644 (file)
@@ -132,7 +132,6 @@ int vmalloc_area_pages(unsigned long address, unsigned long size)
        unsigned long end = address + size;
 
        dir = pgd_offset_k(address);
-       flush_cache_all();
        while (address >= start && address < end) {
                pmd_t *pmd;
                pgd_t olddir = *dir;
@@ -147,6 +146,7 @@ int vmalloc_area_pages(unsigned long address, unsigned long size)
                address = (address + PGDIR_SIZE) & PGDIR_MASK;
                dir++;
        }
+       flush_cache_all();
        flush_tlb_all();
        return 0;
 }