]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.15pre14 2.2.15pre14
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:01 +0000 (15:21 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:01 +0000 (15:21 -0500)
o Revert megaraid driver to 1.04 due to apparent (Alan Cox)
        corruption problems some firmware shows.
| This is a temporary state of affairs I hope,
| once Dell/AMI have a handle on which firmware
| and how to either fix it or refuse to boot
| on those firmwares then we can go back.
o Acard scsi shared IRQ fix (hopefully) (Acard, ported
| Folks with Acard stuff please test this  into newer driver
| one hard  by Alan Cox)
o Fix assorted network driver ioctl checks (Mitchell Blank Jr)
o Two small updates to the telephony API needed (Alan Cox)
by other vendors
o Fix bit masking error on IO port in I2O (Deepak Saxena)
o Work around spitfire errata 32 and 54 on (Dave Miller)
Ultrasparc
o Work around Sparcstation 5 Swift MMU (Dave Miller)
o Fix SunQE problem with 32bit sparc (Dave Miller)
o Fix breakage of ISA support in SX driver
and add EISA support (Rogier Wolff)
o Arlan fixes (but not 4500 for 2.2.15) (Elmer Joandi)
o Fix EXPERIMENTAL checking in 2.2.15pre (Paul Vojta)
o Update AIC7xxx driver to rev 5.1.28 (Doug Ledford)
o Simple (ie not strictly correct) fix for the
cisco 3600 syncppp problem (Madarasz Gergely)
[Proper fix for 2.2.16 I think]
o Zero the sin_zero part of sockaddr_in (Frank van Maarseveen)
o Correct erase handling in 16 colour text (Jon Mitchell)
o Fix typo in videodev.h (fjolliton)
o Another small ultrasparc errata fix (Dave Miller)
o Semaphore deadlock fix (Christoph Rohland)
o Further SX fixes (Rogier Wolff)
o SKTR driver fixes (Christoph Goos)
o Further small 3ware fix (Adam Radford)
o Up the default number of module loadable  (Alan Cox)
scsi disks to 16
o Wan config typo fix (Dave Jones)
o Sparc blackbird errata fixes (Dave Miller)
o Wanpipe needs inet (Arjan van de Ven)
o Revert cursor/bh lock patch (breaks Alpha) (Alan Cox)
o Fix ext2 dir race (Al Viro)

54 files changed:
Documentation/Configure.help
Documentation/networking/sktr.txt
Makefile
arch/sparc/mm/srmmu.c
arch/sparc/mm/swift.S
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/head.S
arch/sparc64/kernel/setup.c
arch/sparc64/kernel/smp.c
arch/sparc64/lib/blockops.S
arch/sparc64/mm/init.c
arch/sparc64/mm/ultra.S
drivers/char/console.c
drivers/char/generic_serial.c
drivers/char/sx.c
drivers/char/sx.h
drivers/char/sxboards.h
drivers/i2o/i2o_pci.c
drivers/net/Config.in
drivers/net/arlan-proc.c
drivers/net/arlan.c
drivers/net/arlan.h
drivers/net/comx.c
drivers/net/dgrs.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/plip.c
drivers/net/rcpci45.c
drivers/net/sbni.c
drivers/net/sktr.c
drivers/net/sktr.h
drivers/net/syncppp.c
drivers/scsi/3w-xxxx.c
drivers/scsi/53c8xx_d.h
drivers/scsi/README.aic7xxx
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx/aic7xxx.reg
drivers/scsi/aic7xxx/aic7xxx.seq
drivers/scsi/aic7xxx_proc.c
drivers/scsi/aic7xxx_reg.h
drivers/scsi/aic7xxx_seq.c
drivers/scsi/atp870u.c
drivers/scsi/hosts.h
drivers/scsi/megaraid.c
drivers/scsi/megaraid.h
drivers/telephony/ixj.c
drivers/video/fbcon.c
fs/ext2/dir.c
include/asm-sparc/vaddrs.h
include/asm-sparc64/system.h
include/linux/telephony.h
include/linux/videodev.h
ipc/sem.c
net/ipv4/udp.c

index 2d60f93179bbf4477ca2ff3cefadf26c4d792c86..b47f9b92c1f316d7513061e044db98d26cd7feca 100644 (file)
@@ -6785,6 +6785,8 @@ CONFIG_SKTR
   This is support for all SysKonnect Token Ring cards, specifically
   SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect TR4/16(+) PCI
   (SK-4590), SysKonnect TR4/16 PCI (SK-4591) adapters.
+  It also supports Compaq PCI Token Ring adapters and Proteon ISA
+  Token Ring adapters (1392 and 1392+).
 
   If you have such an adapter and would like to use it, say Y or M and
   read the Token-Ring mini-HOWTO, available via FTP (user: anonymous)
index a35332af14c9391fca1d64bd699f8b50d97c7a48..5caa202eec32ee5b7ba59e26e6edb79d3cfe289e 100644 (file)
@@ -46,6 +46,11 @@ tr2: SK NET TR 4/16 ISA found at 0xa20, using IRQ 10 and DMA 5.
 Now just setup the device via ifconfig and set and routes you may have. After
 this you are ready to start sending some tokens.
 
+Parameters:
+The driver supports the usual parameters irq and dma (for ISA-adapters only).
+Additional, there is a parameter for setting the connection speed (4 MBits/sec
+or 16 MBit/sec). Default is 16, use "rate=4" to force 4 MBit.
+
 Errata:
 For anyone wondering where to pick up the SysKonnect adapters please browse
 to http://www.syskonnect.com
index 777f7d061b2e6552c61b2b7fe922a5038b0e7e09..3b3279d4e4025c7cc297adc60b63700011d353e2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 15
-EXTRAVERSION = pre13
+EXTRAVERSION = pre14
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index b2e9441424b1373866908646b3e6bdba91858b1b..1e94af359244a45375d6abf8917409f4814c0720 100644 (file)
@@ -2424,7 +2424,15 @@ __initfunc(static void init_swift(void))
        BTFIXUPSET_CALL(set_pte, srmmu_set_pte_nocache_swift, BTFIXUPCALL_NORM);
        BTFIXUPSET_CALL(init_new_context, swift_init_new_context, BTFIXUPCALL_NORM);
 
+#if 1
+       /* If granular flushes are ever cured and reenabled in
+        * swift.S, revert this setting back to non-global iommu
+        * cache flushes. -DaveM
+        */
+       flush_page_for_dma_global = 1;
+#else
        flush_page_for_dma_global = 0;
+#endif
 
        /* Are you now convinced that the Swift is one of the
         * biggest VLSI abortions of all time?  Bravo Fujitsu!
index c570f555123878a8cf4db7d539beba7355e627fa..1e67635720e210a9fac9cf5c013f410a8e12075a 100644 (file)
@@ -41,10 +41,10 @@ swift_flush_chunk:
 swift_flush_page_to_ram:
        sethi   %hi(0x2000), %o0
 1:     subcc   %o0, 0x10, %o0
-       sta     %g0, [%o0] ASI_M_TXTC_TAG
+       add     %o0, %o0, %o1
        sta     %g0, [%o0] ASI_M_DATAC_TAG
        bne     1b
-        nop
+        sta    %g0, [%o1] ASI_M_TXTC_TAG
        retl
         nop
 #else
index 47cdfc9bcce247f2b2810c01e5eeb0d7050ec21f..cab4ecc74a6945366b2002ab397feb193edc93bc 100644 (file)
@@ -945,7 +945,17 @@ ret_from_syscall:
                 nop
                ldx             [%g6 + AOFF_task_tss + AOFF_thread_pcr_reg], %o7
                wr              %g0, %o7, %pcr
-               wr              %g0, %g0, %pic
+
+               /* Blackbird errata workaround.  See commentary in
+                * smp.c:smp_percpu_timer_interrupt() for more
+                * information.
+                */
+               ba,pt           %xcc, 99f
+                nop
+               .align          64
+99:            wr              %g0, %g0, %pic
+               rd              %pic, %g0
+
 1:             b,pt            %xcc, ret_sys_call
                 ldx            [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
 sparc_exit:    rdpr            %otherwin, %g1
index 2bb3d81460ab132ff17124ee10567e942489e136..8bbb6417976b7f81ca0f60e74d37e33a57705bca 100644 (file)
@@ -262,7 +262,16 @@ sun4u_init:
 
        /* Setup "Linux Current Register", thanks Sun 8-) */
        wr      %g0, 0x1, %pcr
-       wr      %g6, 0x0, %pic
+
+       /* Blackbird errata workaround.  See commentary in
+        * smp.c:smp_percpu_timer_interrupt() for more
+        * information.
+        */
+       ba,pt   %xcc, 99f
+        nop
+       .align  64
+99:    wr      %g6, %g0, %pic
+       rd      %pic, %g0
 #endif
 
        mov     1, %g5
index 1c2e67bd05c6d142034273db70a1d54c9a20d696..a2ad607c4655fe3728e7593d8c7eef35f055cb5f 100644 (file)
@@ -160,9 +160,17 @@ int prom_callback(long *args)
                }
 
                if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
+                       /* Spitfire Errata #32 workaround */
+                       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                            "flush     %%g6"
+                                            : /* No outputs */
+                                            : "r" (0),
+                                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
                        /*
                         * Locked down tlb entry 63.
                         */
+
                        tte = spitfire_get_dtlb_data(63);
                        res = PROM_TRUE;
                        goto done;
index a8e74d94cecf21ed7fc8de0e0546d761cb5e427a..cfb1749774ac2e7e75c50578758b31e08927df90 100644 (file)
@@ -301,6 +301,13 @@ static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, un
               smp_processor_id(), data0, data1, data2, target);
 #endif
 again:
+       /* Ok, this is the real Spitfire Errata #54.
+        * One must read back from a UDB internal register
+        * after writes to the UDB interrupt dispatch, but
+        * before the membar Sync for that write.
+        * So we use the high UDB control register (ASI 0x7f,
+        * ADDR 0x20) for the dummy read. -DaveM
+        */
        __asm__ __volatile__("
        wrpr    %0, %1, %%pstate
        wr      %%g0, %2, %%asi
@@ -309,10 +316,14 @@ again:
        stxa    %5, [0x60] %%asi
        membar  #Sync
        stxa    %%g0, [%6] %%asi
+       membar  #Sync
+       mov     0x20, %%g1
+       ldxa    [%%g1] 0x7f, %%g0
        membar  #Sync"
        : /* No outputs */
        : "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
-         "r" (data0), "r" (data1), "r" (data2), "r" (target));
+         "r" (data0), "r" (data1), "r" (data2), "r" (target)
+       : "g1");
 
        /* NOTE: PSTATE_IE is still clear. */
        stuck = 100000;
index c850247cafcb2e227999867d3829b63fc01dce8d..7a5bcad0e6f8c8f00fcbb46f251f05f8b9a7a9c1 100644 (file)
@@ -46,13 +46,37 @@ copy_page: /* %o0=dest, %o1=src */
        sethi           %hi(TLBTEMP_ENT1), %o3
        rdpr            %pstate, %g3
        wrpr            %g3, PSTATE_IE, %pstate
+
+       /* Spitfire Errata #32 workaround */
+       mov             0x8, %o4
+       stxa            %g0, [%o4] ASI_DMMU
+       flush           %g6
+
        ldxa            [%o3] ASI_DTLB_TAG_READ, %o4
+
+       /* Spitfire Errata #32 workaround */
+       mov             0x8, %o5
+       stxa            %g0, [%o5] ASI_DMMU
+       flush           %g6
+
        ldxa            [%o3] ASI_DTLB_DATA_ACCESS, %o5
        stxa            %o0, [%o2] ASI_DMMU
        stxa            %g1, [%o3] ASI_DTLB_DATA_ACCESS
        membar          #Sync
        add             %o3, (TLBTEMP_ENTSZ), %o3
+
+       /* Spitfire Errata #32 workaround */
+       mov             0x8, %g5
+       stxa            %g0, [%g5] ASI_DMMU
+       flush           %g6
+
        ldxa            [%o3] ASI_DTLB_TAG_READ, %g5
+
+       /* Spitfire Errata #32 workaround */
+       mov             0x8, %g7
+       stxa            %g0, [%g7] ASI_DMMU
+       flush           %g6
+
        ldxa            [%o3] ASI_DTLB_DATA_ACCESS, %g7
        stxa            %o1, [%o2] ASI_DMMU
        stxa            %g2, [%o3] ASI_DTLB_DATA_ACCESS
@@ -120,7 +144,19 @@ clear_page:                /* %o0=dest */
        sethi           %hi(TLBTEMP_ENT2), %o3
        rdpr            %pstate, %g3
        wrpr            %g3, PSTATE_IE, %pstate
+
+       /* Spitfire Errata #32 workaround */
+       mov             0x8, %g5
+       stxa            %g0, [%g5] ASI_DMMU
+       flush           %g6
+
        ldxa            [%o3] ASI_DTLB_TAG_READ, %g5
+
+       /* Spitfire Errata #32 workaround */
+       mov             0x8, %g7
+       stxa            %g0, [%g7] ASI_DMMU
+       flush           %g6
+
        ldxa            [%o3] ASI_DTLB_DATA_ACCESS, %g7
        stxa            %o0, [%o2] ASI_DMMU
        stxa            %g1, [%o3] ASI_DTLB_DATA_ACCESS
index 6a85988a598a71466eddf246a1d4e06937ba764d..55b3e3a954449e9a972b0700ab62cde86564b8cd 100644 (file)
@@ -709,6 +709,14 @@ static void inherit_prom_mappings(void)
 
        /* Now fixup OBP's idea about where we really are mapped. */
        prom_printf("Remapping the kernel... ");
+
+       /* Spitfire Errata #32 workaround */
+       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                            "flush     %%g6"
+                            : /* No outputs */
+                            : "r" (0),
+                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
        phys_page = spitfire_get_dtlb_data(63) & _PAGE_PADDR;
        phys_page += ((unsigned long)&prom_boot_page -
                      (unsigned long)&empty_zero_page);
@@ -731,11 +739,27 @@ static void inherit_prom_mappings(void)
                : "memory");
 
        tte_vaddr = (unsigned long) &empty_zero_page;
+
+       /* Spitfire Errata #32 workaround */
+       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                            "flush     %%g6"
+                            : /* No outputs */
+                            : "r" (0),
+                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
        kern_locked_tte_data = tte_data = spitfire_get_dtlb_data(63);
 
        remap_func = (void *)  ((unsigned long) &prom_remap -
                                (unsigned long) &prom_boot_page);
 
+
+       /* Spitfire Errata #32 workaround */
+       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                            "flush     %%g6"
+                            : /* No outputs */
+                            : "r" (0),
+                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
        remap_func(spitfire_get_dtlb_data(63) & _PAGE_PADDR,
                   (unsigned long) &empty_zero_page,
                   prom_get_mmu_ihandle());
@@ -798,8 +822,16 @@ static void __flush_nucleus_vptes(void)
 
        /* Only DTLB must be checked for VPTE entries. */
        for(i = 0; i < 63; i++) {
-               unsigned long tag = spitfire_get_dtlb_tag(i);
+               unsigned long tag;
 
+               /* Spitfire Errata #32 workaround */
+               __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                    "flush     %%g6"
+                                    : /* No outputs */
+                                    : "r" (0),
+                                    "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
+               tag = spitfire_get_dtlb_tag(i);
                if(((tag & ~(PAGE_MASK)) == 0) &&
                   ((tag &  (PAGE_MASK)) >= prom_reserved_base)) {
                        __asm__ __volatile__("stxa %%g0, [%0] %1"
@@ -912,10 +944,26 @@ void inherit_locked_prom_mappings(int save_p)
        for(i = 0; i < 63; i++) {
                unsigned long data;
 
+
+               /* Spitfire Errata #32 workaround */
+               __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                    "flush     %%g6"
+                                    : /* No outputs */
+                                    : "r" (0),
+                                    "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
                data = spitfire_get_dtlb_data(i);
                if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
-                       unsigned long tag = spitfire_get_dtlb_tag(i);
+                       unsigned long tag;
+
+                       /* Spitfire Errata #32 workaround */
+                       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                            "flush     %%g6"
+                                            : /* No outputs */
+                                            : "r" (0),
+                                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 
+                       tag = spitfire_get_dtlb_tag(i);
                        if(save_p) {
                                prom_dtlb[dtlb_seen].tlb_ent = i;
                                prom_dtlb[dtlb_seen].tlb_tag = tag;
@@ -935,10 +983,25 @@ void inherit_locked_prom_mappings(int save_p)
        for(i = 0; i < 63; i++) {
                unsigned long data;
 
+               /* Spitfire Errata #32 workaround */
+               __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                    "flush     %%g6"
+                                    : /* No outputs */
+                                    : "r" (0),
+                                    "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
                data = spitfire_get_itlb_data(i);
                if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
-                       unsigned long tag = spitfire_get_itlb_tag(i);
+                       unsigned long tag;
+
+                       /* Spitfire Errata #32 workaround */
+                       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                            "flush     %%g6"
+                                            : /* No outputs */
+                                            : "r" (0),
+                                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 
+                       tag = spitfire_get_itlb_tag(i);
                        if(save_p) {
                                prom_itlb[itlb_seen].tlb_ent = i;
                                prom_itlb[itlb_seen].tlb_tag = tag;
@@ -1018,6 +1081,13 @@ void __flush_tlb_all(void)
                             : "=r" (pstate)
                             : "i" (PSTATE_IE));
        for(i = 0; i < 64; i++) {
+               /* Spitfire Errata #32 workaround */
+               __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                    "flush     %%g6"
+                                    : /* No outputs */
+                                    : "r" (0),
+                                    "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
                if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) {
                        __asm__ __volatile__("stxa %%g0, [%0] %1"
                                             : /* no outputs */
@@ -1026,6 +1096,14 @@ void __flush_tlb_all(void)
                        spitfire_put_dtlb_data(i, 0x0UL);
                        membar("#Sync");
                }
+
+               /* Spitfire Errata #32 workaround */
+               __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
+                                    "flush     %%g6"
+                                    : /* No outputs */
+                                    : "r" (0),
+                                    "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
                if(!(spitfire_get_itlb_data(i) & _PAGE_L)) {
                        __asm__ __volatile__("stxa %%g0, [%0] %1"
                                             : /* no outputs */
index 26240eb73ae0a57ab7ddb32541f385b65840fdec..9c4ac94410effd924e7e151633044e0eb6074515 100644 (file)
@@ -35,7 +35,7 @@ __flush_tlb_mm: /* %o0=(ctx & 0x3ff), %o1=SECONDARY_CONTEXT */
 __flush_tlb_range: /* %o0=(ctx&0x3ff), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT,
                    * %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start)
                    */
-#define TLB_MAGIC      206 /* Students, do you know how I calculated this?  -DaveM */
+#define TLB_MAGIC      207 /* Students, do you know how I calculated this?  -DaveM */
 /*IC3*/        cmp             %o5, %o4
        be,pt           %xcc, __flush_tlb_page
         srlx           %o5, 13, %g5
@@ -58,6 +58,12 @@ __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
        wrpr            %g1, PSTATE_IE, %pstate
        mov             TLB_TAG_ACCESS, %g3
        mov             (62 << 3), %g2
+
+       /* Spitfire Errata #32 workaround. */
+       mov             0x8, %o4
+       stxa            %g0, [%o4] ASI_DMMU
+       flush           %g6
+
 1:     ldxa            [%g2] ASI_ITLB_TAG_READ, %o4
        and             %o4, 0x3ff, %o5
        cmp             %o5, %o0
@@ -83,12 +89,27 @@ __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
         wrpr           %g1, 0x0, %pstate
 4:     stxa            %g0, [%g3] ASI_IMMU
        stxa            %g0, [%g2] ASI_ITLB_DATA_ACCESS
+       flush           %g6
+
+       /* Spitfire Errata #32 workaround. */
+       mov             0x8, %o4
+       stxa            %g0, [%o4] ASI_DMMU
+       flush           %g6
+
        ba,pt           %xcc, 2b
-        flush          %g6
+        nop
+
 5:     stxa            %g0, [%g3] ASI_DMMU
 /*IC9*/        stxa            %g0, [%g2] ASI_DTLB_DATA_ACCESS
+       flush           %g6
+
+       /* Spitfire Errata #32 workaround. */
+       mov             0x8, %o4
+       stxa            %g0, [%o4] ASI_DMMU
+       flush           %g6
+
        ba,pt           %xcc, 3b
-        flush          %g6
+        nop
 
        .align          32
 __flush_tlb_mm_slow:
@@ -315,28 +336,51 @@ xcall_receive_signal:
         clr            %l6
 99:    retry
 
+       .data
+
+errata32_hwbug:
+       .xword  0
+
+       .text
+
        /* These two are not performance critical... */
        .globl          xcall_flush_tlb_all
 xcall_flush_tlb_all:
+
+       /* Spitfire Errata #32 workaround. */
+       sethi           %hi(errata32_hwbug), %g4
+       stx             %g0, [%g4 + %lo(errata32_hwbug)]
+
        clr             %g2
        clr             %g3
 1:     ldxa            [%g3] ASI_DTLB_DATA_ACCESS, %g4
        and             %g4, _PAGE_L, %g5
        brnz,pn         %g5, 2f
         mov            TLB_TAG_ACCESS, %g7
+
        stxa            %g0, [%g7] ASI_DMMU
        membar          #Sync
-
        stxa            %g0, [%g3] ASI_DTLB_DATA_ACCESS
        membar          #Sync
+
+       /* Spitfire Errata #32 workaround. */
+       sethi           %hi(errata32_hwbug), %g4
+       stx             %g0, [%g4 + %lo(errata32_hwbug)]
+
 2:     ldxa            [%g3] ASI_ITLB_DATA_ACCESS, %g4
        and             %g4, _PAGE_L, %g5
        brnz,pn         %g5, 2f
         mov            TLB_TAG_ACCESS, %g7
+
        stxa            %g0, [%g7] ASI_IMMU
        membar          #Sync
-
        stxa            %g0, [%g3] ASI_ITLB_DATA_ACCESS
+       membar          #Sync
+
+       /* Spitfire Errata #32 workaround. */
+       sethi           %hi(errata32_hwbug), %g4
+       stx             %g0, [%g4 + %lo(errata32_hwbug)]
+
 2:     add             %g2, 1, %g2
        cmp             %g2, 63
        ble,pt          %icc, 1b
index 5dfb1c48df4f0e658a31d8d080bbcb782fb587ad..691ff1e6005f9eadf5dc3447880064e5406eac53 100644 (file)
@@ -358,7 +358,7 @@ static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _unde
 static void update_attr(int currcons)
 {
        attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
-       video_erase_char = (build_attr(currcons, color, 1, 0, 0, decscnm) << 8) | ' ';
+       video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
 }
 
 /* Note: inverting the screen twice should revert to the original state */
@@ -506,9 +506,6 @@ static void set_cursor(int currcons)
 {
     if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
        return;
-       
-    disable_bh(CONSOLE_BH);
-    
     if (deccm) {
        if (currcons == sel_cons)
                clear_selection();
@@ -517,8 +514,6 @@ static void set_cursor(int currcons)
            sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
     } else
        hide_cursor(currcons);
-       
-    enable_bh(CONSOLE_BH);
 }
 
 static void set_origin(int currcons)
@@ -1817,12 +1812,11 @@ static int do_con_write(struct tty_struct * tty, int from_user,
        himask = hi_font_mask;
        charmask = himask ? 0x1ff : 0xff;
 
-       disable_bh(CONSOLE_BH);
-
        /* undraw cursor first */
        if (IS_FG)
                hide_cursor(currcons);
 
+       disable_bh(CONSOLE_BH);
        while (!tty->stopped && count) {
                enable_bh(CONSOLE_BH);
                if (from_user)
index eeeab0a71ad015bcdc187654ebf8b137eb7a7c06..a4c3251aaed886a94d7e591290726a0cca3635e8 100644 (file)
@@ -491,7 +491,7 @@ void gs_start(struct tty_struct * tty)
 void gs_shutdown_port (struct gs_port *port)
 {
        long flags;
-
+       func_enter();
        if (!(port->flags & ASYNC_INITIALIZED))
                return;
 
@@ -510,6 +510,7 @@ void gs_shutdown_port (struct gs_port *port)
 
        port->flags &= ~ASYNC_INITIALIZED;
        restore_flags (flags);
+       func_exit();
 }
 
 
index 29e4e4eaf11c7adb9090dc6e72559f9a7852bbd5..515bf0a41c66f5a344bae3364b5ea64a53c5a428 100644 (file)
  *
  * Revision history:
  * $Log: sx.c,v $
+ * Revision 1.32  2000/03/07 90:00:00  wolff,pvdl
+ * - Fixed some sx_dprintk typos
+ * - added detection for an invalid board/module configuration
+ *
+ * Revision 1.31  2000/03/06 12:00:00  wolff,pvdl
+ * - Added support for EISA
+ *
  * Revision 1.30  2000/01/21 17:43:06  wolff
  * - Added support for SX+
  *
  * */
 
 
-#define RCS_ID "$Id: sx.c,v 1.30 2000/01/21 17:43:06 wolff Exp $"
-#define RCS_REV "$Revision: 1.30 $"
+#define RCS_ID "$Id: sx.c,v 1.32 2000/03/07 17:01:02 wolff, pvdl Exp $"
+#define RCS_REV "$Revision: 1.32 $"
 
 
 #include <linux/module.h>
@@ -291,7 +298,7 @@ static int sx_chars_in_buffer (void * ptr);
 static int sx_init_board (struct sx_board *board);
 static int sx_init_portstructs (int nboards, int nports);
 static int sx_fw_ioctl (struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
+                        unsigned int cmd, unsigned long arg);
 static int sx_fw_open(struct inode *inode, struct file *filp);
 static INT sx_fw_release(struct inode *inode, struct file *filp);
 static int sx_init_drivers(void);
@@ -330,11 +337,13 @@ int sx_slowpoll = 0;
 int sx_maxints = 100;
 
 /* These are the only open spaces in my computer. Yours may have more
-   or less.... */
+   or less.... -- REW 
+   duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
+*/
 int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
                        0xc8000, 0xd8000, 0xe8000};
 int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
-                       0xc8000, 0xd8000, 0xe8000};
+                       0xc8000, 0xd8000, 0xe8000, 0xa0000};
 
 #define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
 #define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
@@ -346,6 +355,8 @@ int sx_irqmask = -1;
 
 #ifndef TWO_ZERO
 #ifdef MODULE
+MODULE_PARM(sx_probe_addrs, "i");
+MODULE_PARM(si_probe_addrs, "i");
 MODULE_PARM(sx_poll, "i");
 MODULE_PARM(sx_slowpoll, "i");
 MODULE_PARM(sx_maxints, "i");
@@ -581,6 +592,8 @@ int sx_reset (struct sx_board *board)
                        printk (KERN_INFO "sx: Card doesn't respond to reset....\n");
                        return 0;
                }
+       } else if (IS_EISA_BOARD(board)) {
+               outb(board->irq<<4, board->eisa_base+0xc02);
        } else {
                /* Gory details of the SI/ISA board */
                write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_SET);
@@ -652,6 +665,9 @@ int sx_start_board (struct sx_board *board)
 {
        if (IS_SX_BOARD (board)) {
                write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
+       } else if (IS_EISA_BOARD(board)) {
+               write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
+               outb((board->irq<<4)|4, board->eisa_base+0xc02);
        } else {
                /* Don't bug me about the clear_set. 
                   I haven't the foggiest idea what it's about -- REW */
@@ -675,6 +691,8 @@ int sx_start_interrupts (struct sx_board *board)
                write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) | 
                                                 SX_CONF_BUSEN | 
                                                 SX_CONF_HOSTIRQ);
+       } else if (IS_EISA_BOARD(board)) {
+               inb(board->eisa_base+0xc03);  
        } else {
                switch (board->irq) {
                case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break;
@@ -740,6 +758,18 @@ int mod_compat_type (int module_type)
        return module_type >> 4;
 }
 
+static void sx_reconfigure_port(struct sx_port *port)
+{
+       if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
+               if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
+                       printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
+               }
+       } else {
+               sx_dprintk (SX_DEBUG_TERMIOS, 
+                           "sx: Not sending reconfigure: port isn't open (%02x).\n", 
+                           sx_read_channel_byte (port, hi_hstat));
+       }       
+}
 
 static void sx_setsignals (struct sx_port *port, int dtr, int rts)
 {
@@ -914,16 +944,7 @@ static int sx_set_real_termios (void *ptr)
        sx_write_channel_byte (port, hi_txoff, STOP_CHAR  (port->gs.tty));
        sx_write_channel_byte (port, hi_rxoff, STOP_CHAR  (port->gs.tty));
 
-       if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
-               if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
-                       printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
-               }
-       } else {
-               sx_dprintk (SX_DEBUG_TERMIOS, 
-                           "sx: Not sending reconfigure: port isn't open (%02x).\n", 
-                           sx_read_channel_byte (port, hi_hstat));
-       }
-
+       sx_reconfigure_port(port);
 
        /* Tell line discipline whether we will do input cooking */
        if(I_OTHER(port->gs.tty)) {
@@ -1238,6 +1259,9 @@ static void sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
                sx_write_board_word (board, cc_int_pending, 0);
                if (IS_SX_BOARD (board)) {
                        write_sx_byte (board, SX_RESET_IRQ, 1);
+               } else if (IS_EISA_BOARD(board)) {
+                       inb(board->eisa_base+0xc03);
+                       write_sx_word(board, 8, 0); 
                } else {
                        write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
                        write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
@@ -1381,6 +1405,7 @@ static void sx_shutdown_port (void * ptr)
        port->gs.flags &= ~ GS_ACTIVE;
        if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
                sx_setsignals (port, 0, 0);
+               sx_reconfigure_port(port);
        }
 
        func_exit();
@@ -1661,10 +1686,11 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
                board = &boards[arg];
                break;
        case SXIO_GET_TYPE:
-               rc = -1; /* If we manage to miss one, return error. */
+               rc = -ENOENT; /* If we manage to miss one, return error. */
                if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
                if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
                if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
+               if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI;
                sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
                break;
        case SXIO_DO_RAMTEST:
@@ -1799,6 +1825,7 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
                        Get_user(ival, (unsigned int *) arg);
                        sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
                                             ((ival & TIOCM_RTS) ? 1 : -1));
+                       sx_reconfigure_port(port);
                }
                break;
        case TIOCMBIC:
@@ -1807,6 +1834,7 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
                        Get_user(ival, (unsigned int *) arg);
                        sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
                                             ((ival & TIOCM_RTS) ? 0 : -1));
+                       sx_reconfigure_port(port);
                }
                break;
        case TIOCMSET:
@@ -1815,6 +1843,7 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
                        Get_user(ival, (unsigned int *) arg);
                        sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
                                             ((ival & TIOCM_RTS) ? 1 : 0));
+                       sx_reconfigure_port(port);
                }
                break;
 
@@ -1967,7 +1996,8 @@ static int sx_init_board (struct sx_board *board)
                        chans=0;
                        break;
                }
-               if (IS_SI_BOARD(board) && (mod_compat_type(type) == 4)) {
+               if ((IS_EISA_BOARD(board) || 
+                    IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) {
                        printk (KERN_ERR "sx: This is an invalid configuration.\n"
                                "Don't use SXDCs on an SI/XIO adapter.\n");
                        chans=0;
@@ -2146,9 +2176,11 @@ int probe_si (struct sx_board *board)
        if (sx_debug & SX_DEBUG_PROBE)
                my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8);
 
-       for (i=0;i<8;i++) {
-               if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
-                       return 0;
+       if (!IS_EISA_BOARD(board)) {
+               for (i=0;i<8;i++) {
+                       if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+                               return 0;
+                       }
                }
        }
 
@@ -2370,7 +2402,7 @@ void fix_sx_pci (PDEV, struct sx_board *board)
        unsigned int t;
 
 #define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x00260000
+#define CNTRL_REG_GOODVALUE     0x18260000
 
        pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
        hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
@@ -2393,6 +2425,7 @@ int sx_init(void)
 {
        int i;
        int found = 0;
+       int eisa_slot;
        struct sx_board *board;
 
 #ifdef CONFIG_PCI
@@ -2481,6 +2514,7 @@ int sx_init(void)
        for (i=0;i<NR_SX_ADDRS;i++) {
                board = &boards[found];
                board->hw_base = sx_probe_addrs[i];
+               board->base2 =
                board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN);
                board->flags &= ~SX_BOARD_TYPE;
                board->flags |= SX_ISA_BOARD;
@@ -2496,6 +2530,7 @@ int sx_init(void)
        for (i=0;i<NR_SI_ADDRS;i++) {
                board = &boards[found];
                board->hw_base = si_probe_addrs[i];
+               board->base2 =
                board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
                board->flags &= ~SX_BOARD_TYPE;
                board->flags |=  SI_ISA_BOARD;
@@ -2508,6 +2543,34 @@ int sx_init(void)
                }
        }
 
+        sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n");
+        for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000)
+        {
+                if((inb(eisa_slot+0xc80)==0x4d) &&
+                   (inb(eisa_slot+0xc81)==0x98))
+                {
+                       sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n",
+                                               "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83));
+
+                       board = &boards[found];
+                       board->eisa_base = eisa_slot;
+                       board->flags &= ~SX_BOARD_TYPE;
+                       board->flags |= SI_EISA_BOARD;
+
+                       board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16);
+                       board->base2 =
+                       board->base = (ulong) ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+
+                       sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %x\n", board->hw_base);
+                       sx_dprintk(SX_DEBUG_PROBE, "base: %x\n", board->base);
+                       board->irq = inb(board->eisa_base+0xc02)>>4; 
+                       sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
+                       
+                       probe_si(board);
+
+                       found++;
+               }
+       }
        if (found) {
                printk (KERN_INFO "sx: total of %d boards detected.\n", found);
 
@@ -2557,27 +2620,3 @@ void cleanup_module(void)
        func_exit();
 }
 #endif
-
-
-
-
-/*
- * Anybody who knows why this doesn't work for me, please tell me -- REW.
- * Snatched from scsi.c (fixed one spelling error):
- * Overrides for Emacs so that we follow Linus' tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
index 3f483622a062e9e5c1e495194ec998b934a0817a..662b27ca2aa630186011270fa3627c4f7f86643b 100644 (file)
@@ -39,6 +39,7 @@ struct sx_board {
   unsigned int base;
   unsigned int base2;
   unsigned int hw_base;
+  int eisa_base;
   int port_base; /* Number of the first port */
   struct sx_port *ports;
   int nports;
@@ -71,6 +72,7 @@ struct vpd_prom {
 #define SX_PCI_BOARD         0x00000004
 #define SX_CFPCI_BOARD       0x00000008
 #define SX_CFISA_BOARD       0x00000010
+#define SI_EISA_BOARD        0x00000020
 
 #define SX_BOARD_PRESENT     0x00001000
 #define SX_BOARD_INITIALIZED 0x00002000
@@ -83,6 +85,8 @@ struct vpd_prom {
 
 #define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
 
+#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
+
 #define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
 
 #define SERIAL_TYPE_NORMAL 1
index 45636c9e9058fb6401d51b2c1932b78e04cf5422..2f0f5428e680bc0a9c56cb6797ff24618868046a 100644 (file)
 
 #define                SI2_EISA_OFF            0x42
 #define                SI2_EISA_VAL            0x01
+#define                SI2_EISA_WINDOW_LEN     0x10000
 
 /*****************************************************************************
 ***********************************         **********************************
index 98bf4c2f0c0e6ba9893fc690bd20beac77096f4a..e768ea34ea6311d136fb1778b2a5e89248dd805e 100644 (file)
@@ -131,7 +131,7 @@ int __init i2o_pci_install(struct pci_dev *dev)
                /* Skip I/O spaces */
                if(!(dev->base_address[i]&PCI_BASE_ADDRESS_SPACE))
                {
-                       memptr=dev->base_address[i]&~3;
+                       memptr=dev->base_address[i]&~15;
                        break;
                }
        }
index 58ffe70f7a6681245cff01591b35a5e08131838f..a064cb146e9dd3489d9f0602911e858ed38c6f73 100644 (file)
@@ -129,7 +129,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
     fi
     tristate 'Apricot Xen-II on board Ethernet' CONFIG_APRICOT
     tristate 'CS89x0 support' CONFIG_CS89x0
-    tristate 'DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      tristate 'DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+    fi
     tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
     tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
     if [ "$CONFIG_DEC_ELCP" != "y" ]; then
@@ -318,14 +320,16 @@ fi
 if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
   bool 'WAN drivers' CONFIG_WAN_DRIVERS 
   if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then
-    dep_tristate 'Sangoma WANPIPE(tm) multi-prot cards: (select M not Y !)' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS 
+    dep_tristate 'Sangoma WANPIPE(tm) multi-port cards: (select M not Y !)' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS 
+    if [ "$CONFIG_INET" != "n" ]; then
     if [ "$CONFIG_VENDOR_SANGOMA" != "n" ]; then
-      int  '  Maximum number of cards' CONFIG_WANPIPE_CARDS 1
-      #bool '  WANPIPE X.25 support' CONFIG_WANPIPE_X25
-      bool '  WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
-      bool '  WANPIPE PPP support' CONFIG_WANPIPE_PPP
-      bool '  WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC
-    fi
+        int  '  Maximum number of cards' CONFIG_WANPIPE_CARDS 1
+        #bool '  WANPIPE X.25 support' CONFIG_WANPIPE_X25
+        bool '  WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
+        bool '  WANPIPE PPP support' CONFIG_WANPIPE_PPP
+        bool '  WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC
+      fi
+    fi 
   fi
 fi
 
index fedeb277924e8f4288dad8b36586cf85f2f2e8cc..7e12a53e06a7fa233c19b35c193193139a82b99c 100644 (file)
@@ -10,7 +10,6 @@
 /* void enableReceive(struct device* dev);
 */
 
-static  int    arlan_command(struct device * dev, int command);
 
 
 #define ARLAN_STR_SIZE         0x2ff0
@@ -185,6 +184,7 @@ static const char *arlan_hardware_type_string(struct device *dev)
                        return "type A672T";
        }
 }
+#ifdef ARLAN_DEBUGING
 
 static void arlan_print_diagnostic_info(struct device *dev)
 {
@@ -396,6 +396,7 @@ static int arlan_setup_card_by_book(struct device *dev)
        return 0;               /* no errors */
 }
 
+#endif
 
 #ifdef ARLAN_PROC_INTERFACE
 #ifdef ARLAN_PROC_SHM_DUMP
@@ -820,6 +821,16 @@ int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp,
         {num , #nam, &(arlan_conf[card].nam), \
          sizeof(int), 0600, NULL, &proc_dointvec}
 
+#ifdef ARLAN_DEBUGING
+  
+#define ARLAN_PROC_DEBUG_ENTRIES       {48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
+                 sizeof(int), 0600, NULL, &proc_dointvec},\
+       {49, "debug", &arlan_debug, \
+                 sizeof(int), 0600, NULL, &proc_dointvec},
+#else 
+#define ARLAN_PROC_DEBUG_ENTRIES
+#endif
+
 
 #define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\
        CTBLN(1,cardNo,spreadingCode),\
@@ -870,10 +881,7 @@ int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp,
        CTBLN(45,cardNo,radioType),\
        CTBLN(46,cardNo,writeEEPROM),\
        CTBLN(47,cardNo,writeRadioType),\
-       {48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
-                sizeof(int), 0600, NULL, &proc_dointvec},\
-       {49, "debug", &arlan_debug, \
-                sizeof(int), 0600, NULL, &proc_dointvec},\
+       ARLAN_PROC_DEBUG_ENTRIES\
        CTBLN(50,cardNo,in_speed),\
        CTBLN(51,cardNo,out_speed),\
        CTBLN(52,cardNo,in_speed10),\
@@ -1008,7 +1016,8 @@ static ctl_table arlan_table[MAX_ARLANS + 1] =
 };
 #endif
 
-static int mmtu = 1234;
+
+// static int mmtu = 1234;
 
 static ctl_table arlan_root_table[] =
 {
@@ -1017,11 +1026,11 @@ static ctl_table arlan_root_table[] =
 };
 
 /* Make sure that /proc/sys/dev is there */
-static ctl_table arlan_device_root_table[] =
-{
-       {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
-       {0}
-};
+//static ctl_table arlan_device_root_table[] =
+//{
+//     {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
+//     {0}
+//};
 
 
 
index cd828bcdc8883b831ef819455adf58f99691bfac..a7f9ac4064f3784c832de4cac3e4271957365df3 100644 (file)
@@ -18,28 +18,32 @@ static int SID = SIDUNKNOWN;
 static int radioNodeId = radioNodeIdUNKNOWN;
 static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
 static char *siteName = siteNameUNKNOWN;
-static int irq = irqUNKNOWN;
 static int mem = memUNKNOWN;
-static int arlan_debug = debugUNKNOWN;
+int arlan_debug = debugUNKNOWN;
 static int probe = probeUNKNOWN;
 static int numDevices = numDevicesUNKNOWN;
-static int testMemory = testMemoryUNKNOWN;
 static int spreadingCode = spreadingCodeUNKNOWN;
 static int channelNumber = channelNumberUNKNOWN;
 static int channelSet = channelSetUNKNOWN;
 static int systemId = systemIdUNKNOWN;
 static int registrationMode = registrationModeUNKNOWN;
-static int txScrambled = 1;
 static int keyStart = 0;
-static int mdebug = 0;
 static int tx_delay_ms = 0;
 static int retries = 5;
 static int async = 1;
 static int tx_queue_len = 1;
+static int arlan_EEPROM_bad = 0;
+int arlan_entry_and_exit_debug = 0;
+
+#ifdef ARLAN_DEBUGING
+
 static int arlan_entry_debug = 0;
 static int arlan_exit_debug = 0;
-static int arlan_entry_and_exit_debug = 0;
-static int arlan_EEPROM_bad = 0;
+static int testMemory = testMemoryUNKNOWN;
+static int irq = irqUNKNOWN;
+static int txScrambled = 1;
+static int mdebug = 0;
+#endif
 
 #if LINUX_VERSION_CODE > 0x20100
 MODULE_PARM(irq, "i");
@@ -339,11 +343,15 @@ int arlan_command(struct device *dev, int command_p)
        }
        else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
        {
+               priv->under_reset=1;
+               dev->tbusy = 1;
+
                arlan_drop_tx(dev);
                if (priv->tx_command_given || priv->rx_command_given)
                {
                        printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);
                };
+               dev->tbusy = 1;
                if (arlan_debug & ARLAN_DEBUG_RESET)
                        printk(KERN_ERR "%s: Doing chip reset\n", dev->name);
                priv->lastReset = jiffies;
@@ -401,15 +409,10 @@ int arlan_command(struct device *dev, int command_p)
                {
                        priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT;
                        priv->waiting_command_mask |= ARLAN_COMMAND_RX;
+                       priv->waiting_command_mask |= ARLAN_COMMAND_TBUSY_CLEAR;
                        priv->card_polling_interval = HZ / 10;
                        priv->tx_command_given = 0;
                        priv->under_config = 0;
-                       if (dev->tbusy || !dev->start)
-                       {
-                               dev->tbusy = 0;
-                               dev->start = 1;
-                               mark_bh(NET_BH);
-                       };
                }
                else
                {
@@ -427,7 +430,7 @@ int arlan_command(struct device *dev, int command_p)
                        WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE);
                        WRITESHMB(arlan->commandParameter[0], conf->rxParameter);
                        arlan_interrupt_lancpu(dev);
-                       priv->rx_command_given;
+                       priv->rx_command_given = 0; // mnjah, bad
                        priv->last_rx_time = arlan_time();
                        priv->waiting_command_mask &= ~ARLAN_COMMAND_RX;
                        priv->card_polling_interval = 1;
@@ -435,6 +438,17 @@ int arlan_command(struct device *dev, int command_p)
                else
                        priv->card_polling_interval = 2;
        }
+       else if (priv->waiting_command_mask & ARLAN_COMMAND_TBUSY_CLEAR)
+       {
+               if ( !registrationBad(dev) && (dev->tbusy || !dev->start) )
+                       {
+                               priv->waiting_command_mask &= ~ARLAN_COMMAND_TBUSY_CLEAR;
+
+                               dev->tbusy = 0;
+                               dev->start = 1;
+                               mark_bh(NET_BH);
+                       };
+       }
        else if (priv->waiting_command_mask & ARLAN_COMMAND_TX)
        {
                if (!test_and_set_bit(0, (void *) &priv->tx_command_given))
@@ -694,7 +708,7 @@ static void arlan_registration_timer(unsigned long data)
        add_timer(&priv->timer);
 }
 
-
+#ifdef ARLAN_DEBUGING
 
 
 static void arlan_print_registers(struct device *dev, int line)
@@ -721,6 +735,7 @@ static void arlan_print_registers(struct device *dev, int line)
 
        ARLAN_DEBUG_EXIT("arlan_print_registers");
 }
+#endif
 
 
 static int arlan_hw_tx(struct device *dev, char *buf, int length)
@@ -1042,12 +1057,18 @@ __initfunctio(static int arlan_check_fingerprint(int memaddr))
        volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr;
 
        ARLAN_DEBUG_ENTRY("arlan_check_fingerprint");
+//     if (check_mem_region(virt_to_phys((void *)memaddr),0x2000 )){
+//             // printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",virt_to_phys((void*)memaddr));
+//             return -ENODEV;
+//     };
        memcpy_fromio(tempBuf, arlan->textRegion, 29);
        tempBuf[30] = 0;
 
        /* check for card at this address */
-       if (0 != strncmp(tempBuf, probeText, 29))
+       if (0 != strncmp(tempBuf, probeText, 29)){
+// not                 release_mem_region(virt_to_phys((void*)memaddr),0x2000);
                return -ENODEV;
+       }
 
 //   printk(KERN_INFO "arlan found at 0x%x \n",memaddr);
        ARLAN_DEBUG_EXIT("arlan_check_fingerprint");
@@ -1066,17 +1087,17 @@ __initfunctio(int arlan_probe_everywhere(struct device *dev))
        ARLAN_DEBUG_ENTRY("arlan_probe_everywhere");
        if (mem != 0 && numDevices == 1)        /* Check a single specified location. */
        {
-               if (arlan_probe_here(dev, mem) == 0)
+               if (arlan_probe_here(dev, (int) phys_to_virt(  mem) ) == 0)
                        return 0;
                else
                        return -ENODEV;
        }
-       for (m = lastFoundAt + 0x2000; m <= 0xDE000; m += 0x2000)
+       for (m = (int)phys_to_virt(lastFoundAt) + 0x2000; m <= (int)phys_to_virt(0xDE000); m += 0x2000)
        {
                if (arlan_probe_here(dev, m) == 0)
                {
                        found++;
-                       lastFoundAt = m;
+                       lastFoundAt = (int)virt_to_phys((void*)m);
                        break;
                }
                probed++;
@@ -1103,7 +1124,7 @@ __initfunctio(int arlan_find_devices(void))
        ARLAN_DEBUG_ENTRY("arlan_find_devices");
        if (mem != 0 && numDevices == 1)        /* Check a single specified location. */
                return 1;
-       for (m = 0xc000; m <= 0xDE000; m += 0x2000)
+       for (m =(int) phys_to_virt(0xc0000); m <=(int) phys_to_virt(0xDE000); m += 0x2000)
        {
                if (arlan_check_fingerprint(m) == 0)
                        found++;
@@ -1175,6 +1196,9 @@ __initfunctio(static int
                printk(KERN_CRIT "init_etherdev failed ");
                return 0;
        }
+
+       memset(dev->priv,0,sizeof(struct arlan_private));
+
        ((struct arlan_private *) dev->priv)->conf =
            kmalloc(sizeof(struct arlan_shmem), GFP_KERNEL);
 
@@ -1202,6 +1226,9 @@ __initfunctio(static int
        dev->set_multicast_list = arlan_set_multicast;
        dev->change_mtu = arlan_change_mtu;
        dev->set_mac_address = arlan_mac_addr;
+       dev->tbusy = 1;
+       dev->start = 0;
+       
        ((struct arlan_private *) dev->priv)->irq_test_done = 0;
        arlan_device[num] = dev;
        ((struct arlan_private *) arlan_device[num]->priv)->Conf = &(arlan_conf[num]);
@@ -1224,7 +1251,7 @@ __initfunctio(int arlan_probe_here(struct device *dev, int memaddr))
        if (arlan_check_fingerprint(memaddr))
                return -ENODEV;
 
-       printk(KERN_NOTICE "%s: Arlan found at %#5x, \n ", dev->name, memaddr);
+       printk(KERN_NOTICE "%s: Arlan found at %x, \n ", dev->name, (int) virt_to_phys((void*)memaddr));
 
        if (!arlan_allocate_device(arlans_found, dev))
                return -1;
@@ -1264,14 +1291,13 @@ static int arlan_open(struct device *dev)
                return ret;
 
        arlan = ((struct arlan_private *) dev->priv)->card;
-
        if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev))
        {
                printk(KERN_ERR "%s: unable to get IRQ %d .\n",
                        dev->name, dev->irq);
                return -EAGAIN;
        }
-       arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+
 
        priv->bad = 0;
        priv->lastReset = 0;
@@ -1282,15 +1308,10 @@ static int arlan_open(struct device *dev)
        dev->tbusy = 1;
        priv->txOffset = 0;
        dev->interrupt = 0;
-       dev->start = 1;
+       dev->start = 0;
        dev->tx_queue_len = tx_queue_len;
-       init_timer(&priv->timer);
-       priv->timer.expires = jiffies + HZ / 10;
-       priv->timer.data = (unsigned long) dev;
-       priv->timer.function = &arlan_registration_timer;       /* timer handler */
        priv->interrupt_processing_active = 0;
        priv->command_lock = 0;
-       add_timer(&priv->timer);
 
        priv->card_lock = MUTEX;
        myATOMIC_INIT(priv->card_users, 1);     /* damn 2.0.33 */
@@ -1298,7 +1319,8 @@ static int arlan_open(struct device *dev)
        priv->registrationLastSeen = jiffies;
        priv->txLast = 0;
        priv->tx_command_given = 0;
-
+       priv->rx_command_given = 0;
+       
        priv->reRegisterExp = 1;
        priv->nof_tx = 0;
        priv->nof_tx_ack = 0;
@@ -1309,6 +1331,16 @@ static int arlan_open(struct device *dev)
        priv->Conf->registrationInterrupts = 1;
 
        dev->tbusy = 0;
+       init_timer(&priv->timer);
+       priv->timer.expires = jiffies + HZ / 10;
+       priv->timer.data = (unsigned long) dev;
+       priv->timer.function = &arlan_registration_timer;       /* timer handler */
+
+       arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+       udelay(200000);
+       dev->tbusy = 0;
+       dev->start = 1;
+       add_timer(&priv->timer);
 
        MOD_INC_USE_COUNT;
 #ifdef CONFIG_PROC_FS
@@ -1901,29 +1933,31 @@ static int arlan_close(struct device *dev)
        }
        ARLAN_DEBUG_ENTRY("arlan_close");
 
+       del_timer(&priv->timer);
+
+       arlan_command(dev, ARLAN_COMMAND_POWERDOWN);
+
        IFDEBUG(ARLAN_DEBUG_STARTUP)
                printk(KERN_NOTICE "%s: Closing device\n", dev->name);
 
        priv->open_time = 0;
        dev->tbusy = 1;
        dev->start = 0;
-       del_timer(&priv->timer);
        free_irq(dev->irq, dev);
-
        MOD_DEC_USE_COUNT;
 
        ARLAN_DEBUG_EXIT("arlan_close");
        return 0;
 }
 
-
+#ifdef ARLAN_DEBUGING
 static long alignLong(volatile u_char * ptr)
 {
        long ret;
        memcpy_fromio(&ret, (void *) ptr, 4);
        return ret;
 }
-
+#endif
 
 /*
  * Get the current statistics.
@@ -2044,6 +2078,7 @@ int init_module(void)
                }
                if (probe)
                        arlan_probe_everywhere(arlan_device[i]);
+//             arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN );
        }
        printk(KERN_INFO "Arlan driver %s\n", arlan_version);
        ARLAN_DEBUG_EXIT("init_module");
@@ -2063,6 +2098,9 @@ void cleanup_module(void)
        {
                if (arlan_device[i])
                {
+                       arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN );
+
+//                     release_mem_region(virt_to_phys(arlan_device[i]->mem_start), 0x2000 );
                        unregister_netdev(arlan_device[i]);
                        if (arlan_device[i]->priv)
                        {
index 7074335eac35ba70e481a4f31ed7a26bebfb02e5..9bf12d744400e586769bbc0e46d03f170c3a3645 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/etherdevice.h>
 
 
-#define DEBUG 1
+//#define ARLAN_DEBUGING 1
 
 #define ARLAN_PROC_INTERFACE
 #define MAX_ARLANS 4 /* not more than 4 ! */
@@ -46,13 +46,14 @@ extern int  init_arlan_proc(void);
 #endif
 
 extern struct device *arlan_device[MAX_ARLANS];
-static int     arlan_debug;
-static char *  siteName;
-static int     arlan_entry_debug;
-static int     arlan_exit_debug;
-static int     arlan_entry_and_exit_debug;
-static int     testMemory;
-static const char* arlan_version;
+extern int     arlan_debug;
+extern char *  siteName;
+extern int     arlan_entry_debug;
+extern int     arlan_exit_debug;
+extern int     arlan_entry_and_exit_debug;
+extern int     testMemory;
+extern const char* arlan_version;
+extern  int    arlan_command(struct device * dev, int command);
  
 #define SIDUNKNOWN -1
 #define radioNodeIdUNKNOWN -1
@@ -75,7 +76,8 @@ static const char* arlan_version;
 #define IFDEBUG( L ) if ( (L) & arlan_debug ) 
 #define ARLAN_FAKE_HDR_LEN 12 
 
-#ifdef DEBUG
+#ifdef ARLAN_DEBUGING
+       #define DEBUG 1
        #define ARLAN_ENTRY_EXIT_DEBUGING 1
        #define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b)
 #else
@@ -532,26 +534,27 @@ struct arlan_private {
 
 
 
-#define ARLAN_COMMAND_RX               0x00001
-#define ARLAN_COMMAND_NOOP             0x00002
-#define ARLAN_COMMAND_NOOPINT          0x00004
-#define ARLAN_COMMAND_TX               0x00008
-#define ARLAN_COMMAND_CONF             0x00010
-#define ARLAN_COMMAND_RESET            0x00020
-#define ARLAN_COMMAND_TX_ABORT         0x00040
-#define ARLAN_COMMAND_RX_ABORT         0x00080
-#define ARLAN_COMMAND_POWERDOWN                0x00100
-#define ARLAN_COMMAND_POWERUP          0x00200
-#define ARLAN_COMMAND_SLOW_POLL        0x00400
-#define ARLAN_COMMAND_ACTIVATE                 0x00800
-#define ARLAN_COMMAND_INT_ACK          0x01000
-#define ARLAN_COMMAND_INT_ENABLE       0x02000
-#define ARLAN_COMMAND_WAIT_NOW         0x04000
-#define ARLAN_COMMAND_LONG_WAIT_NOW    0x08000
-#define ARLAN_COMMAND_STANDBY          0x10000
-#define ARLAN_COMMAND_INT_RACK         0x20000
-#define ARLAN_COMMAND_INT_RENABLE      0x40000
-#define ARLAN_COMMAND_CONF_WAIT                0x80000
+#define ARLAN_COMMAND_RX               0x000001
+#define ARLAN_COMMAND_NOOP             0x000002
+#define ARLAN_COMMAND_NOOPINT          0x000004
+#define ARLAN_COMMAND_TX               0x000008
+#define ARLAN_COMMAND_CONF             0x000010
+#define ARLAN_COMMAND_RESET            0x000020
+#define ARLAN_COMMAND_TX_ABORT         0x000040
+#define ARLAN_COMMAND_RX_ABORT         0x000080
+#define ARLAN_COMMAND_POWERDOWN                0x000100
+#define ARLAN_COMMAND_POWERUP          0x000200
+#define ARLAN_COMMAND_SLOW_POLL        0x000400
+#define ARLAN_COMMAND_ACTIVATE                 0x000800
+#define ARLAN_COMMAND_INT_ACK          0x001000
+#define ARLAN_COMMAND_INT_ENABLE       0x002000
+#define ARLAN_COMMAND_WAIT_NOW         0x004000
+#define ARLAN_COMMAND_LONG_WAIT_NOW    0x008000
+#define ARLAN_COMMAND_STANDBY          0x010000
+#define ARLAN_COMMAND_INT_RACK         0x020000
+#define ARLAN_COMMAND_INT_RENABLE      0x040000
+#define ARLAN_COMMAND_CONF_WAIT                0x080000
+#define ARLAN_COMMAND_TBUSY_CLEAR      0x100000
 #define ARLAN_COMMAND_CLEAN_AND_CONF   (ARLAN_COMMAND_TX_ABORT\
                                        | ARLAN_COMMAND_RX_ABORT\
                                        | ARLAN_COMMAND_CONF)
index 83a376ecf129fcbd28e849ae48a6086145c138d2..3d3a980553a0b331b6a56e3785b4cb72ed8f8a38 100644 (file)
 #include <linux/kmod.h>
 #endif
 
+#ifndef CONFIG_PROC_FS
+#error For now, COMX really needs the /proc filesystem
+#endif
+
 #include "comx.h"
 #include "syncppp.h"
 
index e4c3b920dcba55a095d711404c2239658af4d9b5..5227b3956390d2d370f1d1b66ecf25928f451fe6 100644 (file)
@@ -861,6 +861,8 @@ static int dgrs_ioctl(struct device *devN, struct ifreq *ifr, int cmd)
                                return -EFAULT;
                        return (0);
                case DGRS_SETFILTER:
+                       if (!suser())
+                               return -EPERM;
                        if (ioc.port > privN->bcomm->bc_nports)
                                return -EINVAL;
                        if (ioc.filter >= NFILTERS)
@@ -1198,7 +1200,7 @@ dgrs_probe1(struct device *dev))
        priv->intrcnt = 0;
        for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); )
        {
-               rmb();          /* gcc 2.95 needs this */
+               barrier();              /* gcc 2.95 needs this */
                if (priv->intrcnt >= 2)
                        break;
        }
index d72719e5c0558a1d47fd72f9a45a421ec716f079..e14fb89304c7484c15c6612e3d060bc8f486a79f 100644 (file)
@@ -1308,6 +1308,8 @@ static int baycom_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
                break;          
 
        case HDLCDRVCTL_CALIBRATE:
+               if (!suser())
+                       return -EACCES;
                bc->hdlctx.calibrate = hi.data.calibrate * bc->bitrate / 8;
                return 0;
 
index 5fb420e2e3a79615d5a36dca3fa050e8532286bd..c8e814313988095d96627275f496c6f4fcdbf2d3 100644 (file)
@@ -701,6 +701,8 @@ static int hdlcdrv_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
                break;          
 
        case HDLCDRVCTL_CALIBRATE:
+               if(!suser())
+                       return -EPERM;
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
                return 0;
 
index 15b2e6ebca7b78f2be7736c47ef38a52c8bd6147..77e7aa9058444c9f1e41fd103ad684441c890bd4 100644 (file)
@@ -1198,6 +1198,8 @@ plip_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                pc->nibble  = nl->nibble;
                break;
        case PLIP_SET_TIMEOUT:
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
                nl->trigger = pc->trigger;
                nl->nibble  = pc->nibble;
                break;
index 0aa979bc1648e43f395c79476265530750d8b6f8..fc7644a118bdc4018d6ca22133fcf24869f04ad9 100644 (file)
@@ -1152,6 +1152,9 @@ static int RCioctl(struct device *dev, struct ifreq *rq, int cmd)
     printk("RCioctl: cmd = 0x%x\n", cmd);
 #endif
  
+    if(!capable(CAP_NET_ADMIN))
+       return -EPERM;
+       
     switch (cmd)  {
  
     case RCU_PROTOCOL_REV:
@@ -1165,17 +1168,8 @@ static int RCioctl(struct device *dev, struct ifreq *rq, int cmd)
 
     case RCU_COMMAND:
     {
-#ifdef LINUX_2_1
         if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
              return -EFAULT;
-#else
-        int error;
-        error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser));
-        if (error)  {
-            return error;
-        }
-        memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser));
-#endif
         
 #ifdef RCDEBUG
         printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
@@ -1284,11 +1278,8 @@ static int RCioctl(struct device *dev, struct ifreq *rq, int cmd)
             RCUD_DEFAULT -> rc = 0x11223344;
             break;
         }
-#ifdef LINUX_2_1
-        copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
-#else
-        memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser));
-#endif
+        if(copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser)))
+               return -EFAULT;
         break;
     }   /* RCU_COMMAND */ 
 
index 5ae5902088319fbcc3cb237638ca0508f17d964f..cfe0439192124e643d9dd17953a40bbd5a6876e9 100644 (file)
@@ -1223,6 +1223,8 @@ static int sbni_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
                }
                case SIOCDEVRESINSTATS:
                {
+                       if(!capable(CAP_NET_ADMIN))
+                               return -EPERM;
                        DP( printk("%s: SIOCDEVRESINSTATS\n",dev->name); )
                        lp->in_stats.all_rx_number = 0;
                        lp->in_stats.bad_rx_number = 0;
index d6225c3e2b6bbba313c6631a0189c0766d326685..b9ab897d99e123b9e4fad0ad3891505e0682572c 100644 (file)
@@ -13,6 +13,8 @@
  *     - SysKonnect TR4/16(+) ISA      (SK-4190)
  *     - SysKonnect TR4/16(+) PCI      (SK-4590)
  *     - SysKonnect TR4/16 PCI         (SK-4591)
+ *     - Compact TR PCI adapters
+ *     - Proteon TR ISA adapters       (1392, 1392+)
  *
  *  Sources:
  *     - The hardware related parts of this driver are take from
  *       as samples for some tasks.
  *
  *  Maintainer(s):
- *    JS        Jay Schulist            jschlst@samba.anu.edu.au
+ *    retired: JS        Jay Schulist            jschlst@samba.anu.edu.au
  *    CG       Christoph Goos          cgoos@syskonnect.de
  *    AF       Adam Fritzler           mid@auk.cx
  *
+ *  Contributor(s):
+ *    AB       Alexander Bech          Initiated Proteon works
+ *
  *  Modification History:
  *     29-Aug-97       CG      Created
  *     04-Apr-98       CG      Fixed problems caused by tok_timer_check
  *     21-Sep-99       AF      Added multicast changes recommended by 
  *                               Jochen Friedrich <jochen@nwe.de> (untested)
  *                             Added detection of compatible Compaq PCI card  
+ *     04-Jan-2000     CG      Fixed tx-send/release synchronization
+ *     04-Mar-2000     CG      Added detection/init of Proteon ISA card
+ *     05-Mar-2000     CG      Added line speed setting (parameter "rate")
  *
  *  To do:
- *    1. Selectable 16 Mbps or 4Mbps
+ *    1. Selectable 16 Mbps or 4Mbps (CG: done)
  *    2. Multi/Broadcast packet handling (might be done)
  *
  */
 
-static const char *version = "sktr.c: v1.01 08/29/97 by Christoph Goos\n";
+static const char *version = "sktr.c: v1.02 08/29/97 by Christoph Goos\n";
 
 #ifdef MODULE
 #include <linux/module.h>
@@ -71,6 +79,7 @@ static const char *version = "sktr.c: v1.01 08/29/97 by Christoph Goos\n";
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -82,7 +91,11 @@ static const char *version = "sktr.c: v1.01 08/29/97 by Christoph Goos\n";
 
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int sktr_portlist[] __initdata = {
-       0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,
+       0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK
+       0x0A20, 0x0E20, 0x1A20, 0x1E20, 0x2A20, 0x2E20, 0x3A20, 0x3E20,// Prot.
+       0x4A20, 0x4E20, 0x5A20, 0x5E20, 0x6A20, 0x6E20, 0x7A20, 0x7E20,// Prot.
+       0x8A20, 0x8E20, 0x9A20, 0x9E20, 0xAA20, 0xAE20, 0xBA20, 0xBE20,// Prot.
+       0xCA20, 0xCE20, 0xDA20, 0xDE20, 0xEA20, 0xEE20, 0xFA20, 0xFE20,// Prot.
        0
 };
 
@@ -100,11 +113,28 @@ static int sktr_dmalist[] __initdata = {
        0
 };
 
+static unsigned short proteon_irqlist[] = {
+       7, 6, 5, 4, 3, 12, 11, 10, 9,
+       0
+};
+static int proteon_dmalist[] __initdata = {
+       5, 6, 7,
+       0
+};
+
+
 /* Card names */
 static char *pci_cardname = "SK NET TR 4/16 PCI\0";
 static char *isa_cardname = "SK NET TR 4/16 ISA\0";
+static char *proteon_cardname = "Proteon 1392\0";
 static char *AdapterName;
 
+static int AdapterNum = 0;
+
+#ifdef MODULE
+static int rate[SKTR_MAX_ADAPTERS]     = { SPEED_16,  };
+#endif
+
 /* Use 0 for production, 1 for verification, 2 for debug, and
  * 3 for very verbose debug.
  */
@@ -152,8 +182,10 @@ static void        sktr_init_ipb(struct net_local *tp);
 static void    sktr_init_net_local(struct device *dev);
 static void    sktr_init_opb(struct net_local *tp);
 static void    sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int     sktr_isa_chk_card(struct device *dev, int ioaddr);
+static int     sktr_isa_chk_card(struct device *dev, int ioaddr,
+                       int *cardtype);
 static int      sktr_isa_chk_ioaddr(int ioaddr);
+static int      prot_isa_chk_ioaddr(int ioaddr);
 /* "O" */
 static int     sktr_open(struct device *dev);
 static void    sktr_open_adapter(struct device *dev);
@@ -170,6 +202,8 @@ static void         sktr_read_ram(struct device *dev, unsigned char *Data,
 static int     sktr_reset_adapter(struct device *dev);
 static void    sktr_reset_interrupt(struct device *dev);
 static void    sktr_ring_status_irq(struct device *dev);
+static void    sktr_reg_setup(struct device *dev);
+static void    prot_reg_setup(struct device *dev);
 /* "S" */
 static int     sktr_send_packet(struct sk_buff *skb, struct device *dev);
 static void    sktr_set_multicast_list(struct device *dev);
@@ -304,16 +338,32 @@ __initfunc(static int sktr_pci_chk_card(struct device *dev))
 }
 
 /*
- * Detect and setup the ISA SysKonnect TR cards.
+ * Detect and setup the ISA Proteon and SysKonnect TR cards.
  */
-__initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
+__initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr,
+int *cardtype))
 {
        int i, err;
        unsigned long flags;
+       unsigned short *irqlist;
+       int *dmalist;
+
+       err = prot_isa_chk_ioaddr(ioaddr);
+       if (err < 0) {
+               err = sktr_isa_chk_ioaddr(ioaddr);
+               if(err < 0)
+                       return (-ENODEV);
+               AdapterName = isa_cardname;
+               *cardtype = SK_ISA;
+               irqlist = sktr_irqlist;
+               dmalist = sktr_dmalist;
+       } else {
+               AdapterName = proteon_cardname;
+               *cardtype = PROT_ISA;
+               irqlist = proteon_irqlist;
+               dmalist = proteon_dmalist;
+       }
 
-       err = sktr_isa_chk_ioaddr(ioaddr);
-       if(err < 0)
-               return (-ENODEV);
 
         if(virt_to_bus((void*)((unsigned long)dev->priv+sizeof(struct net_local)))
                > ISA_MAX_ADDRESS)
@@ -323,8 +373,6 @@ __initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
                 return (-EAGAIN);
         }
 
-       AdapterName = isa_cardname;
-
         /* Grab the region so that no one else tries to probe our ioports. */
         request_region(ioaddr, SKTR_IO_EXTENT, AdapterName);
         dev->base_addr = ioaddr;
@@ -332,15 +380,15 @@ __initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
         /* Autoselect IRQ and DMA if dev->irq == 0 */
         if(dev->irq == 0)
         {
-                for(i = 0; sktr_irqlist[i] != 0; i++)
+                for(i = 0; irqlist[i] != 0; i++)
                 {
-                        dev->irq = sktr_irqlist[i];
+                        dev->irq = irqlist[i];
                         err = request_irq(dev->irq, &sktr_interrupt, 0, AdapterName, dev);
                         if(!err)
                                break;
                 }
 
-                if(sktr_irqlist[i] == 0)
+                if(irqlist[i] == 0)
                 {
                         printk("%s: AutoSelect no IRQ available\n", dev->name);
                         return (-EAGAIN);
@@ -359,9 +407,9 @@ __initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
         /* Always allocate the DMA channel after IRQ and clean up on failure */
         if(dev->dma == 0)
         {
-                for(i = 0; sktr_dmalist[i] != 0; i++)
+                for(i = 0; dmalist[i] != 0; i++)
                 {
-                       dev->dma = sktr_dmalist[i];
+                       dev->dma = dmalist[i];
                         err = request_dma(dev->dma, AdapterName);
                         if(!err)
                                 break;
@@ -416,10 +464,9 @@ __initfunc(static int sktr_probe1(struct device *dev, int ioaddr))
        err = sktr_pci_chk_card(dev);
        if(err < 0)
        {
-               err = sktr_isa_chk_card(dev, ioaddr);
+               err = sktr_isa_chk_card(dev, ioaddr, &DeviceType);
                if(err < 0)
                        return (-ENODEV);
-               DeviceType = SK_ISA;
        }
 
        /* Setup this devices private information structure */
@@ -428,6 +475,12 @@ __initfunc(static int sktr_probe1(struct device *dev, int ioaddr))
                return (-ENOMEM);
        memset(tp, 0, sizeof(struct net_local));
        tp->DeviceType = DeviceType;
+       if(DeviceType == SK_ISA || DeviceType == PROT_ISA)
+               tp->BusType = BUS_TYPE_ISA;
+       else
+               tp->BusType = BUS_TYPE_PCI;
+       tp->DataRate = rate[AdapterNum];
+       AdapterNum++;
 
        dev->priv               = tp;
        dev->init               = sktr_init_card;
@@ -485,6 +538,28 @@ __initfunc(static int sktr_isa_chk_ioaddr(int ioaddr))
        return (0);
 }
 
+/*
+ * This function tests if a proteon adapter is really installed at the
+ * given I/O address. Return negative if no adapter at IO addr.
+ */
+__initfunc(static int prot_isa_chk_ioaddr(int ioaddr))
+{
+       unsigned char chk1, chk2;
+       int i;
+
+       chk1 = inb(ioaddr + 0x1f);      /* Get Proteon ID reg 1 */
+       if (chk1 != 0x1f)
+               return (-1);
+       chk1 = inb(ioaddr + 0x1e) & 0x07;       /* Get Proteon ID reg 0 */
+       for (i=0; i<16; i++) {
+               chk2 = inb(ioaddr + 0x1e) & 0x07;
+               if (((chk1 + 1) & 0x07) != chk2)
+                       return (-1);
+               chk1 = chk2;
+       }
+       return (0);
+}
+
 /*
  * Open/initialize the board. This is called sometime after
  * booting when the 'ifconfig' program is run.
@@ -502,7 +577,7 @@ static int sktr_open(struct device *dev)
        err = sktr_chipset_init(dev);
        if(err)
        {
-               printk(KERN_INFO "%s: Chipset initialization error\n", 
+               printk("%s: Chipset initialization error\n", 
                        dev->name);
                return (-1);
        }
@@ -574,14 +649,90 @@ static void sktr_timer_end_wait(unsigned long data)
        return;
 }
 
+/* setup non-standard registers for SK ISA adapters */
+static void sktr_reg_setup(struct device *dev)
+{
+       struct net_local *tp = (struct net_local *)dev->priv;
+       unsigned char PosReg, Tmp;
+       int i;
+       unsigned short *irqlist;
+
+       irqlist = sktr_irqlist;
+       PosReg = 0;
+       for(i = 0; irqlist[i] != 0; i++)
+       {
+               if(irqlist[i] == dev->irq)
+                       break;
+       }
+
+       /* Choose default cycle time, 500 nsec   */
+       PosReg |= CYCLE_TIME << 2;
+       PosReg |= i << 4;
+       i = dev->dma - 5;
+       PosReg |= i;
+
+       if(tp->DataRate == SPEED_4)
+               PosReg |= LINE_SPEED_BIT;
+       else
+               PosReg &= ~LINE_SPEED_BIT;
+
+       outb(PosReg, dev->base_addr + POSREG);
+       Tmp = inb(dev->base_addr + POSREG);
+       if((Tmp & ~CYCLE_TIME) != (PosReg & ~CYCLE_TIME))
+               printk("%s: POSREG error\n", dev->name);
+
+       return;
+}
+
+/* setup non-standard registers for Proteon ISA adapters */
+static void prot_reg_setup(struct device *dev)
+{
+       struct net_local *tp = (struct net_local *)dev->priv;
+       unsigned char PosReg;
+       int i;
+       unsigned short *irqlist;
+
+       /* Proteon reset sequence */
+       outb(0, dev->base_addr + 0x11);
+       mdelay(20);
+       outb(0x04, dev->base_addr + 0x11);
+       mdelay(20);
+       outb(0, dev->base_addr + 0x11);
+       mdelay(100);
+
+       /* set control/status reg */
+       PosReg = inb(dev->base_addr + 0x11);
+       PosReg |= 0x78;
+       PosReg &= 0xf9;
+       if(tp->DataRate == SPEED_4)
+               PosReg |= 0x20;
+       else
+               PosReg &= ~0x20;
+
+       outb(PosReg, dev->base_addr + 0x11);
+       outb(0xff, dev->base_addr + 0x12);
+       irqlist = proteon_irqlist;
+       for(i = 0; irqlist[i] != 0; i++)
+       {
+               if(irqlist[i] == dev->irq)
+                       break;
+       }
+
+       PosReg = i;
+       i = (7 - dev->dma) << 4;
+       PosReg |= i;
+       outb(PosReg, dev->base_addr + 0x13);
+
+       return;
+}
+
 /*
  * Initialize the chipset
  */
 static int sktr_chipset_init(struct device *dev)
 {
        struct net_local *tp = (struct net_local *)dev->priv;
-       unsigned char PosReg, Tmp;
-       int i, err;
+       int err;
 
        sktr_init_ipb(tp);
        sktr_init_opb(tp);
@@ -590,43 +741,28 @@ static int sktr_chipset_init(struct device *dev)
        /* Set pos register: selects irq and dma channel.
         * Only for ISA bus adapters.
         */
-       if(dev->dma > 0)
-       {
-               PosReg = 0;
-               for(i = 0; sktr_irqlist[i] != 0; i++)
-               {
-                       if(sktr_irqlist[i] == dev->irq)
-                               break;
-               }
-
-               /* Choose default cycle time, 500 nsec   */
-               PosReg |= CYCLE_TIME << 2;
-               PosReg |= i << 4;
-               i = dev->dma - 5;
-               PosReg |= i;
-
-               if(tp->DataRate == SPEED_4)
-                       PosReg |= LINE_SPEED_BIT;
-               else
-                       PosReg &= ~LINE_SPEED_BIT;
-
-               outb(PosReg, dev->base_addr + POSREG);
-               Tmp = inb(dev->base_addr + POSREG);
-               if((Tmp & ~CYCLE_TIME) != (PosReg & ~CYCLE_TIME))
-                       printk(KERN_INFO "%s: POSREG error\n", dev->name);
-       }
+       if (tp->DeviceType == SK_ISA)
+               sktr_reg_setup(dev);
+       else if (tp->DeviceType == PROT_ISA)
+               prot_reg_setup(dev);
 
        err = sktr_reset_adapter(dev);
-       if(err < 0)
+       if(err < 0) {
+               printk("sktr_reset_adapter failed\n");
                return (-1);
+       }
 
        err = sktr_bringup_diags(dev);
-       if(err < 0)
+       if(err < 0) {
+               printk("sktr_bringup_diag failed\n");
                return (-1);
+       }
 
        err = sktr_init_adapter(dev);
-       if(err < 0)
+       if(err < 0) {
+               printk("sktr_init_adapter failed\n");
                return (-1);
+       }
 
        return (0);
 }
@@ -660,9 +796,10 @@ static void sktr_init_net_local(struct device *dev)
        tp->LobeWireFaultLogged = 0;
        tp->LastOpenStatus      = 0;
        tp->MaxPacketSize       = DEFAULT_PACKET_SIZE;
+       tp->Sending             = 0;
 
        skb_queue_head_init(&tp->SendSkbQueue);
-       tp->QueueSkb = MAX_TX_QUEUE;
+       atomic_set(&tp->QueueSkb, MAX_TX_QUEUE);
 
        /* Create circular chain of transmit lists */
        for (i = 0; i < TPL_NUM; i++)
@@ -704,12 +841,14 @@ static void sktr_init_net_local(struct device *dev)
                        skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
 
                        /* data unreachable for DMA ? then use local buffer */
-                       if(tp->DeviceType == SK_ISA &&
+                       if(tp->BusType == BUS_TYPE_ISA &&
                                virt_to_bus(tp->Rpl[i].Skb->data) +
                                tp->MaxPacketSize > ISA_MAX_ADDRESS)
                        {
                                tp->Rpl[i].SkbStat = SKB_DATA_COPY;
-                               tp->Rpl[i].FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[i]));
+                               tp->Rpl[i].FragList[0].DataAddr =
+                                       htonl(virt_to_bus(
+                                       tp->LocalRxBuffers[i]));
                                tp->Rpl[i].MData = tp->LocalRxBuffers[i];
                        }
                        else    /* DMA directly in skb->data */
@@ -880,13 +1019,13 @@ static int sktr_send_packet(struct sk_buff *skb, struct device *dev)
                return (1);
        }
 
-       if(tp->QueueSkb == 0)
+       if(atomic_read(&tp->QueueSkb) == 0)
                return (1);     /* Return with tbusy set: queue full */
 
-       tp->QueueSkb--;
+       atomic_dec(&tp->QueueSkb);
        skb_queue_tail(&tp->SendSkbQueue, skb);
        sktr_hardware_send_packet(dev, tp);
-       if(tp->QueueSkb > 0)
+       if(atomic_read(&tp->QueueSkb) > 0)
                dev->tbusy = 0;
 
        return (0);
@@ -903,6 +1042,7 @@ static void sktr_hardware_send_packet(struct device *dev, struct net_local* tp)
        struct sk_buff *skb;
        int i;
     
+       tp->Sending = 1;
        for(;;)
        {
                /* Try to get a free TPL from the chain.
@@ -912,18 +1052,21 @@ static void sktr_hardware_send_packet(struct device *dev, struct net_local* tp)
                 */
                if(tp->TplFree->NextTPLPtr->BusyFlag)   /* No free TPL */
                {
-                       printk(KERN_INFO "%s: No free TPL\n", dev->name);
+                       // printk("%s: No free TPL\n", dev->name);
+                       tp->Sending = 0;
                        return;
                }
 
                /* Send first buffer from queue */
                skb = skb_dequeue(&tp->SendSkbQueue);
-               if(skb == NULL)
+               if(skb == NULL) {
+                       tp->Sending = 0;
                        return;
+               }
 
-               tp->QueueSkb++;
+               atomic_inc(&tp->QueueSkb);
                /* Is buffer reachable for Busmaster-DMA? */
-               if(tp->DeviceType == SK_ISA && 
+               if(tp->BusType == BUS_TYPE_ISA && 
                        virt_to_bus((void*)(((long) skb->data) + skb->len))
                        > ISA_MAX_ADDRESS)
                {
@@ -946,6 +1089,7 @@ static void sktr_hardware_send_packet(struct device *dev, struct net_local* tp)
 
                tp->LastSendTime        = jiffies;
                tpl                     = tp->TplFree;  /* Get the "free" TPL */
+               tpl->Status             = 0;            /* set to INVALID */
                tpl->BusyFlag           = 1;            /* Mark TPL as busy */
                tp->TplFree             = tpl->NextTPLPtr;
     
@@ -967,6 +1111,7 @@ static void sktr_hardware_send_packet(struct device *dev, struct net_local* tp)
                sktr_exec_sifcmd(dev, CMD_TX_VALID);
        }
 
+       tp->Sending = 0;
        return;
 }
 
@@ -1012,7 +1157,8 @@ static void sktr_timer_chk(unsigned long data)
 
        sktr_chk_outstanding_cmds(dev);
        if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies)
-               && (tp->QueueSkb < MAX_TX_QUEUE || tp->TplFree != tp->TplBusy))
+               && (atomic_read(&tp->QueueSkb) < MAX_TX_QUEUE ||
+               tp->TplFree != tp->TplBusy))
        {
                /* Anything to send, but stalled to long */
                tp->LastSendTime = jiffies;
@@ -1059,7 +1205,8 @@ static void sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
                if(!sktr_chk_ssb(tp, irq_type))
                {
-                       printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);
+                       printk(KERN_DEBUG "%s: DATA LATE occurred\n",
+                               dev->name);
                        break;
                }
 
@@ -1107,7 +1254,7 @@ static void sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                break;
 
                        default:
-                               printk(KERN_INFO "Unknown Token Ring IRQ\n");
+                               printk(KERN_DEBUG "Unknown Token Ring IRQ\n");
                                break;
                }
 
@@ -1255,19 +1402,19 @@ static void sktr_cmd_status_irq(struct device *dev)
                else    /* The adapter did not open. */
                {
                        if(ssb_parm_0 & NODE_ADDR_ERROR)
-                               printk(KERN_INFO "%s: Node address error\n",
+                               printk("%s: Node address error\n",
                                        dev->name);
                        if(ssb_parm_0 & LIST_SIZE_ERROR)
-                               printk(KERN_INFO "%s: List size error\n",
+                               printk("%s: List size error\n",
                                        dev->name);
                        if(ssb_parm_0 & BUF_SIZE_ERROR)
-                               printk(KERN_INFO "%s: Buffer size error\n",
+                               printk("%s: Buffer size error\n",
                                        dev->name);
                        if(ssb_parm_0 & TX_BUF_COUNT_ERROR)
-                               printk(KERN_INFO "%s: Tx buffer count error\n",
+                               printk("%s: Tx buffer count error\n",
                                        dev->name);
                        if(ssb_parm_0 & INVALID_OPEN_OPTION)
-                               printk(KERN_INFO "%s: Invalid open option\n",
+                               printk("%s: Invalid open option\n",
                                        dev->name);
                        if(ssb_parm_0 & OPEN_ERROR)
                        {
@@ -1278,7 +1425,7 @@ static void sktr_cmd_status_irq(struct device *dev)
                                                if(!tp->LobeWireFaultLogged)
                                                {
                                                        tp->LobeWireFaultLogged = 1;
-                                                       printk(KERN_INFO "%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);
+                                                       printk("%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);
                                                }
                                                tp->ReOpenInProgress    = 1;
                                                tp->AdapterOpenFlag     = 0;
@@ -1287,27 +1434,27 @@ static void sktr_cmd_status_irq(struct device *dev)
                                                return;
 
                                        case PHYSICAL_INSERTION:
-                                               printk(KERN_INFO "%s: %s Physical insertion.\n", dev->name, open_err);
+                                               printk("%s: %s Physical insertion.\n", dev->name, open_err);
                                                break;
 
                                        case ADDRESS_VERIFICATION:
-                                               printk(KERN_INFO "%s: %s Address verification.\n", dev->name, open_err);
+                                               printk("%s: %s Address verification.\n", dev->name, open_err);
                                                break;
 
                                        case PARTICIPATION_IN_RING_POLL:
-                                               printk(KERN_INFO "%s: %s Participation in ring poll.\n", dev->name, open_err);
+                                               printk("%s: %s Participation in ring poll.\n", dev->name, open_err);
                                                break;
 
                                        case REQUEST_INITIALISATION:
-                                               printk(KERN_INFO "%s: %s Request initialisation.\n", dev->name, open_err);
+                                               printk("%s: %s Request initialisation.\n", dev->name, open_err);
                                                break;
 
                                        case FULLDUPLEX_CHECK:
-                                               printk(KERN_INFO "%s: %s Full duplex check.\n", dev->name, open_err);
+                                               printk("%s: %s Full duplex check.\n", dev->name, open_err);
                                                break;
 
                                        default:
-                                               printk(KERN_INFO "%s: %s Unknown open phase\n", dev->name, open_err);
+                                               printk("%s: %s Unknown open phase\n", dev->name, open_err);
                                                break;
                                }
 
@@ -1315,61 +1462,61 @@ static void sktr_cmd_status_irq(struct device *dev)
                                switch(ssb_parm_0 & OPEN_ERROR_CODES_MASK)
                                {
                                        case OPEN_FUNCTION_FAILURE:
-                                               printk(KERN_INFO "%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);
+                                               printk("%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_FUNCTION_FAILURE;
                                                break;
 
                                        case OPEN_SIGNAL_LOSS:
-                                               printk(KERN_INFO "%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);
+                                               printk("%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_SIGNAL_LOSS;
                                                break;
 
                                        case OPEN_TIMEOUT:
-                                               printk(KERN_INFO "%s: %s OPEN_TIMEOUT\n", dev->name, code_err);
+                                               printk("%s: %s OPEN_TIMEOUT\n", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_TIMEOUT;
                                                break;
 
                                        case OPEN_RING_FAILURE:
-                                               printk(KERN_INFO "%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);
+                                               printk("%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_RING_FAILURE;
                                                break;
 
                                        case OPEN_RING_BEACONING:
-                                               printk(KERN_INFO "%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);
+                                               printk("%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_RING_BEACONING;
                                                break;
 
                                        case OPEN_DUPLICATE_NODEADDR:
-                                               printk(KERN_INFO "%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);
+                                               printk("%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_DUPLICATE_NODEADDR;
                                                break;
 
                                        case OPEN_REQUEST_INIT:
-                                               printk(KERN_INFO "%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);
+                                               printk("%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_REQUEST_INIT;
                                                break;
 
                                        case OPEN_REMOVE_RECEIVED:
-                                               printk(KERN_INFO "%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);
+                                               printk("%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_REMOVE_RECEIVED;
                                                break;
 
                                        case OPEN_FULLDUPLEX_SET:
-                                               printk(KERN_INFO "%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);
+                                               printk("%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_FULLDUPLEX_SET;
                                                break;
 
                                        default:
-                                               printk(KERN_INFO "%s: %s Unknown open err code", dev->name, code_err);
+                                               printk("%s: %s Unknown open err code", dev->name, code_err);
                                                tp->LastOpenStatus =
                                                        OPEN_FUNCTION_FAILURE;
                                                break;
@@ -1646,7 +1793,7 @@ static int sktr_bringup_diags(struct device *dev)
        do {
                retry_cnt--;
                if(sktr_debug > 3)
-                       printk(KERN_INFO "BUD-Status: \n");
+                       printk("BUD-Status: \n");
                loop_cnt = BUD_MAX_LOOPCNT;     /* maximum: three seconds*/
                do {                    /* Inspect BUD results */
                        loop_cnt--;
@@ -1655,7 +1802,7 @@ static int sktr_bringup_diags(struct device *dev)
                        Status &= STS_MASK;
 
                        if(sktr_debug > 3)
-                               printk(KERN_INFO " %04X \n", Status);
+                               printk(" %04X \n", Status);
                        /* BUD successfully completed */
                        if(Status == STS_INITIALIZE)
                                return (1);
@@ -1666,7 +1813,7 @@ static int sktr_bringup_diags(struct device *dev)
                /* Error preventing completion of BUD */
                if(retry_cnt > 0)
                {
-                       printk(KERN_INFO "%s: Adapter Software Reset.\n", 
+                       printk("%s: Adapter Software Reset.\n", 
                                dev->name);
                        sktr_exec_sifcmd(dev, EXEC_SOFT_RESET);
                        sktr_wait(HALF_SECOND);
@@ -1676,7 +1823,7 @@ static int sktr_bringup_diags(struct device *dev)
        Status = inw(ioaddr + SIFSTS);
        Status &= STS_ERROR_MASK;       /* Hardware error occurred! */
 
-       printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",
+       printk("%s: Bring Up Diagnostics Error (%04X) occurred\n",
                dev->name, Status);
 
        return (-1);
@@ -1977,56 +2124,57 @@ static void sktr_ring_status_irq(struct device *dev)
        /* First: fill up statistics */
        if(tp->ssb.Parm[0] & SIGNAL_LOSS)
        {
-               printk(KERN_INFO "%s: Signal Loss\n", dev->name);
+               printk("%s: Signal Loss\n", dev->name);
                tp->MacStat.line_errors++;
        }
 
        /* Adapter is closed, but initialized */
        if(tp->ssb.Parm[0] & LOBE_WIRE_FAULT)
        {
-               printk(KERN_INFO "%s: Lobe Wire Fault, Reopen Adapter\n", 
+               printk("%s: Lobe Wire Fault, Reopen Adapter\n", 
                        dev->name);
                tp->MacStat.line_errors++;
        }
 
        if(tp->ssb.Parm[0] & RING_RECOVERY)
-               printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
+               printk("%s: Ring Recovery\n", dev->name);
 
        /* Counter overflow: read error log */
        if(tp->ssb.Parm[0] & COUNTER_OVERFLOW)
        {
-               printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
+               printk("%s: Counter Overflow\n", dev->name);
                sktr_exec_cmd(dev, OC_READ_ERROR_LOG);
        }
 
        /* Adapter is closed, but initialized */
        if(tp->ssb.Parm[0] & REMOVE_RECEIVED)
-               printk(KERN_INFO "%s: Remove Received, Reopen Adapter\n", 
+               printk("%s: Remove Received, Reopen Adapter\n", 
                        dev->name);
 
        /* Adapter is closed, but initialized */
        if(tp->ssb.Parm[0] & AUTO_REMOVAL_ERROR)
-               printk(KERN_INFO "%s: Auto Removal Error, Reopen Adapter\n", 
+               printk("%s: Auto Removal Error, Reopen Adapter\n", 
                        dev->name);
 
        if(tp->ssb.Parm[0] & HARD_ERROR)
-               printk(KERN_INFO "%s: Hard Error\n", dev->name);
+               printk("%s: Hard Error\n", dev->name);
 
        if(tp->ssb.Parm[0] & SOFT_ERROR)
-               printk(KERN_INFO "%s: Soft Error\n", dev->name);
+               printk("%s: Soft Error\n", dev->name);
 
        if(tp->ssb.Parm[0] & TRANSMIT_BEACON)
-               printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
+               printk("%s: Transmit Beacon\n", dev->name);
 
        if(tp->ssb.Parm[0] & SINGLE_STATION)
-               printk(KERN_INFO "%s: Single Station\n", dev->name);
+               printk("%s: Single Station\n", dev->name);
 
        /* Check if adapter has been closed */
        if(tp->ssb.Parm[0] & ADAPTER_CLOSED)
        {
-               printk(KERN_INFO "%s: Adapter closed (Reopening)," 
+               printk("%s: Adapter closed (Reopening)," 
                        "QueueSkb %d, CurrentRingStat %x\n",
-                       dev->name, tp->QueueSkb, tp->CurrentRingStatus);
+                       dev->name, atomic_read(&tp->QueueSkb),
+                       tp->CurrentRingStatus);
                tp->AdapterOpenFlag = 0;
                sktr_open_adapter(dev);
        }
@@ -2067,69 +2215,69 @@ static void sktr_chk_irq(struct device *dev)
        switch(AdapterCheckBlock[0])
        {
                case DIO_PARITY:
-                       printk(KERN_INFO "%s: DIO parity error\n", dev->name);
+                       printk("%s: DIO parity error\n", dev->name);
                        break;
 
                case DMA_READ_ABORT:
-                       printk(KERN_INFO "%s DMA read operation aborted:\n",
+                       printk("%s DMA read operation aborted:\n",
                                dev->name);
                        switch (AdapterCheckBlock[1])
                        {
                                case 0:
-                                       printk(KERN_INFO "Timeout\n");
-                                       printk(KERN_INFO "Address: %04X %04X\n",
+                                       printk("Timeout\n");
+                                       printk("Address: %04X %04X\n",
                                                AdapterCheckBlock[2],
                                                AdapterCheckBlock[3]);
                                        break;
 
                                case 1:
-                                       printk(KERN_INFO "Parity error\n");
-                                       printk(KERN_INFO "Address: %04X %04X\n",
+                                       printk("Parity error\n");
+                                       printk("Address: %04X %04X\n",
                                                AdapterCheckBlock[2], 
                                                AdapterCheckBlock[3]);
                                        break;
 
                                case 2: 
-                                       printk(KERN_INFO "Bus error\n");
-                                       printk(KERN_INFO "Address: %04X %04X\n",
+                                       printk("Bus error\n");
+                                       printk("Address: %04X %04X\n",
                                                AdapterCheckBlock[2], 
                                                AdapterCheckBlock[3]);
                                        break;
 
                                default:
-                                       printk(KERN_INFO "Unknown error.\n");
+                                       printk("Unknown error.\n");
                                        break;
                        }
                        break;
 
                case DMA_WRITE_ABORT:
-                       printk(KERN_INFO "%s: DMA write operation aborted: \n",
+                       printk("%s: DMA write operation aborted: \n",
                                dev->name);
                        switch (AdapterCheckBlock[1])
                        {
                                case 0: 
-                                       printk(KERN_INFO "Timeout\n");
-                                       printk(KERN_INFO "Address: %04X %04X\n",
+                                       printk("Timeout\n");
+                                       printk("Address: %04X %04X\n",
                                                AdapterCheckBlock[2], 
                                                AdapterCheckBlock[3]);
                                        break;
 
                                case 1: 
-                                       printk(KERN_INFO "Parity error\n");
-                                       printk(KERN_INFO "Address: %04X %04X\n",
+                                       printk("Parity error\n");
+                                       printk("Address: %04X %04X\n",
                                                AdapterCheckBlock[2], 
                                                AdapterCheckBlock[3]);
                                        break;
 
                                case 2: 
-                                       printk(KERN_INFO "Bus error\n");
-                                       printk(KERN_INFO "Address: %04X %04X\n",
+                                       printk("Bus error\n");
+                                       printk("Address: %04X %04X\n",
                                                AdapterCheckBlock[2], 
                                                AdapterCheckBlock[3]);
                                        break;
 
                                default:
-                                       printk(KERN_INFO "Unknown error.\n");
+                                       printk("Unknown error.\n");
                                        break;
                        }
                        break;
@@ -2207,7 +2355,7 @@ static void sktr_read_ptr(struct device *dev)
        sktr_read_ram(dev, (unsigned char *)&adapterram,
                        (unsigned short)SWAPB(tp->intptrs.AdapterRAMPtr), 2);
 
-       printk(KERN_INFO "%s: Adapter RAM size: %d K\n", 
+       printk("%s: Adapter RAM size: %d K\n", 
                dev->name, SWAPB(adapterram));
 
        return;
@@ -2301,7 +2449,7 @@ static void sktr_cancel_tx_queue(struct net_local* tp)
                sktr_write_tpl_status(tpl, 0);  /* Clear VALID bit */
                tpl->BusyFlag = 0;              /* "free" TPL */
 
-               printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
+               printk("Cancel tx (%08lXh).\n", (unsigned long)tpl);
 
                dev_kfree_skb(tpl->Skb);
        }
@@ -2311,7 +2459,7 @@ static void sktr_cancel_tx_queue(struct net_local* tp)
                skb = skb_dequeue(&tp->SendSkbQueue);
                if(skb == NULL)
                        break;
-               tp->QueueSkb++;
+               atomic_inc(&tp->QueueSkb);
                dev_kfree_skb(skb);
        }
 
@@ -2360,7 +2508,7 @@ static void sktr_tx_status_irq(struct device *dev)
 
                        if((HighAc != LowAc) || (HighAc == AC_NOT_RECOGNIZED))
                        {
-                               printk(KERN_INFO "%s: (DA=%08lX not recognized)",
+                               printk("%s: (DA=%08lX not recognized)",
                                        dev->name,
                                        *(unsigned long *)&tpl->MData[2+2]);
                        }
@@ -2387,7 +2535,7 @@ static void sktr_tx_status_irq(struct device *dev)
        }
 
        dev->tbusy = 0;
-       if(tp->QueueSkb < MAX_TX_QUEUE)
+       if(atomic_read(&tp->QueueSkb) < MAX_TX_QUEUE && !tp->Sending)
                sktr_hardware_send_packet(dev, tp);
 
        return;
@@ -2529,12 +2677,14 @@ static void sktr_rcv_status_irq(struct device *dev)
                        skb_put(rpl->Skb, tp->MaxPacketSize);
 
                        /* Data unreachable for DMA ? then use local buffer */
-                       if(tp->DeviceType == SK_ISA &&
+                       if(tp->BusType == BUS_TYPE_ISA &&
                                virt_to_bus(rpl->Skb->data) + tp->MaxPacketSize
                                > ISA_MAX_ADDRESS)
                        {
                                rpl->SkbStat = SKB_DATA_COPY;
-                               rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex]));
+                               rpl->FragList[0].DataAddr = 
+                                       htonl(virt_to_bus(
+                                       tp->LocalRxBuffers[rpl->RPLIndex]));
                                rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];
                        }
                        else
@@ -2637,13 +2787,14 @@ static void sktr_dump(unsigned char *Data, int length)
 #ifdef MODULE
 
 static struct device* dev_sktr[SKTR_MAX_ADAPTERS];
-static int io[SKTR_MAX_ADAPTERS]       = { 0, 0 };
-static int irq[SKTR_MAX_ADAPTERS]      = { 0, 0 };
-static int mem[SKTR_MAX_ADAPTERS]      = { 0, 0 };
+static int io[SKTR_MAX_ADAPTERS]       = { 0,  };
+static int irq[SKTR_MAX_ADAPTERS]      = { 0,  };
+static int dma[SKTR_MAX_ADAPTERS]      = { 0,  };
 
 MODULE_PARM(io,  "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
+MODULE_PARM(rate, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
 
 int init_module(void)
 {
@@ -2651,8 +2802,6 @@ int init_module(void)
 
        for(i = 0; i < SKTR_MAX_ADAPTERS; i++)
        {
-                irq[i] = 0;
-                mem[i] = 0;
                 dev_sktr[i] = NULL;
                 dev_sktr[i] = init_trdev(dev_sktr[i], 0);
                 if(dev_sktr[i] == NULL)
@@ -2660,7 +2809,7 @@ int init_module(void)
 
                dev_sktr[i]->base_addr = io[i];
                 dev_sktr[i]->irq       = irq[i];
-                dev_sktr[i]->mem_start = mem[i];
+                dev_sktr[i]->dma       = dma[i];
                 dev_sktr[i]->init      = &sktr_probe;
 
                 if(register_trdev(dev_sktr[i]) != 0)
index 6d888aad2f283e27984605e30d9464cc2b6e19ad..af724402fbb6c474eaa812d6cb28adb1533c1b57 100644 (file)
 #define TR_RCF_LONGEST_FRAME_MASK 0x0070
 #define TR_RCF_FRAME4K 0x0030
 
+/* DeviceType values */
 #define SK_ISA 0
 #define SK_PCI 1
+#define PROT_ISA 2
+
+/* BusType values */
+#define BUS_TYPE_PCI   0
+#define BUS_TYPE_ISA   1
 
 /*------------------------------------------------------------------*/
 /*  Bit order for adapter communication with DMA                   */
@@ -1067,6 +1073,7 @@ typedef struct net_local {
        unsigned short CMDqueue;
 
        unsigned int DeviceType;
+       unsigned int BusType;
 
        unsigned long AdapterOpenFlag:1;
        unsigned long AdapterVirtOpenFlag:1;
@@ -1077,6 +1084,7 @@ typedef struct net_local {
        unsigned long LobeWireFaultLogged:1;
        unsigned long ReOpenInProgress:1;
        unsigned long Sleeping:1;
+       unsigned long Sending:1;
 
        unsigned long LastOpenStatus;
        unsigned short CurrentRingStatus;
@@ -1086,7 +1094,7 @@ typedef struct net_local {
        unsigned long LastSendTime;
 
        struct sk_buff_head SendSkbQueue;
-       unsigned short QueueSkb;
+       atomic_t QueueSkb;
 
        struct tr_statistics MacStat;   /* MAC statistics structure */
 
index 06ab0406e10d22f54ea2c24f1bf9b59f3b5efadc..189c6803d006689756893d9f7333cfeeed732230 100644 (file)
@@ -326,7 +326,7 @@ static int sppp_hard_header(struct sk_buff *skb, struct device *dev, __u16 type,
        h=(struct ppp_header *)skb->data;
        if(sp->pp_flags&PP_CISCO)
        {
-               h->address = CISCO_MULTICAST;
+               h->address = CISCO_UNICAST;
                h->control = 0;
        }
        else
index 8b13508090db1ddf105f0c8500e0797a75503dc8..88fdfd6bd1224e7730e17224e12be519fd28dded 100644 (file)
@@ -91,7 +91,7 @@ struct proc_dir_entry tw_scsi_proc_entry = {
 };
 
 /* Globals */
-char *tw_driver_version="1.0.000";
+char *tw_driver_version="1.1.000";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -2053,7 +2053,7 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
        command_packet->status = 0;
        command_packet->flags = 0;
 
-        if ((srb->cmnd[0] == WRITE_6) || (srb->cmnd[0] == WRITE_10)) {
+        if (srb->cmnd[0] == WRITE_10) {
          if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
            command_packet->flags = 1;
         }
index b586340693ab2aeac13829b4f27f92f5aca75d73..a3c81ffc22555b6fd45182895b7e8cea3dd2f35c 100644 (file)
@@ -1,4 +1,4 @@
-u32 SCRIPT[] = {
+static u32 SCRIPT[] = {
 /*
 
 
@@ -2179,40 +2179,40 @@ at 0x00000270 : */      0x90080000,0x00000000,
 };
 
 #define A_NCR53c7xx_msg_abort  0x00000000
-u32 A_NCR53c7xx_msg_abort_used[] = {
+static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
        0x00000249,
 };
 
 #define A_NCR53c7xx_msg_reject 0x00000000
-u32 A_NCR53c7xx_msg_reject_used[] = {
+static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
        0x00000172,
 };
 
 #define A_NCR53c7xx_sink       0x00000000
-u32 A_NCR53c7xx_sink_used[] = {
+static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
        0x00000233,
        0x00000239,
        0x0000023f,
 };
 
 #define A_NCR53c7xx_zero       0x00000000
-u32 A_NCR53c7xx_zero_used[] = {
+static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
        0x0000022f,
        0x00000245,
 };
 
 #define A_NOP_insn     0x00000000
-u32 A_NOP_insn_used[] = {
+static u32 A_NOP_insn_used[] __attribute((unused)) = {
        0x00000010,
 };
 
 #define A_addr_reconnect_dsa_head      0x00000000
-u32 A_addr_reconnect_dsa_head_used[] = {
+static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
        0x000001a7,
 };
 
 #define A_addr_scratch 0x00000000
-u32 A_addr_scratch_used[] = {
+static u32 A_addr_scratch_used[] __attribute((unused)) = {
        0x00000004,
        0x0000001b,
        0x00000046,
@@ -2227,13 +2227,13 @@ u32 A_addr_scratch_used[] = {
 };
 
 #define A_addr_temp    0x00000000
-u32 A_addr_temp_used[] = {
+static u32 A_addr_temp_used[] __attribute((unused)) = {
        0x00000025,
        0x00000034,
 };
 
 #define A_dmode_memory_to_memory       0x00000000
-u32 A_dmode_memory_to_memory_used[] = {
+static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
        0x00000005,
        0x0000001c,
        0x00000027,
@@ -2251,7 +2251,7 @@ u32 A_dmode_memory_to_memory_used[] = {
 };
 
 #define A_dmode_memory_to_ncr  0x00000000
-u32 A_dmode_memory_to_ncr_used[] = {
+static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
        0x00000000,
        0x00000017,
        0x00000030,
@@ -2260,7 +2260,7 @@ u32 A_dmode_memory_to_ncr_used[] = {
 };
 
 #define A_dmode_ncr_to_memory  0x00000000
-u32 A_dmode_ncr_to_memory_used[] = {
+static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
        0x00000022,
        0x00000064,
        0x00000070,
@@ -2272,161 +2272,161 @@ u32 A_dmode_ncr_to_memory_used[] = {
 };
 
 #define A_dsa_check_reselect   0x00000000
-u32 A_dsa_check_reselect_used[] = {
+static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
        0x000001bd,
 };
 
 #define A_dsa_cmdout   0x00000048
-u32 A_dsa_cmdout_used[] = {
+static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
        0x00000094,
 };
 
 #define A_dsa_cmnd     0x00000038
-u32 A_dsa_cmnd_used[] = {
+static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_datain   0x00000054
-u32 A_dsa_datain_used[] = {
+static u32 A_dsa_datain_used[] __attribute((unused)) = {
        0x000000bb,
 };
 
 #define A_dsa_dataout  0x00000050
-u32 A_dsa_dataout_used[] = {
+static u32 A_dsa_dataout_used[] __attribute((unused)) = {
        0x000000a5,
 };
 
 #define A_dsa_end      0x00000070
-u32 A_dsa_end_used[] = {
+static u32 A_dsa_end_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_fields_start     0x00000000
-u32 A_dsa_fields_start_used[] = {
+static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_msgin    0x00000058
-u32 A_dsa_msgin_used[] = {
+static u32 A_dsa_msgin_used[] __attribute((unused)) = {
        0x00000188,
 };
 
 #define A_dsa_msgout   0x00000040
-u32 A_dsa_msgout_used[] = {
+static u32 A_dsa_msgout_used[] __attribute((unused)) = {
        0x00000086,
 };
 
 #define A_dsa_msgout_other     0x00000068
-u32 A_dsa_msgout_other_used[] = {
+static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
        0x00000180,
 };
 
 #define A_dsa_next     0x00000030
-u32 A_dsa_next_used[] = {
+static u32 A_dsa_next_used[] __attribute((unused)) = {
        0x0000005c,
 };
 
 #define A_dsa_restore_pointers 0x00000000
-u32 A_dsa_restore_pointers_used[] = {
+static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
        0x0000012e,
 };
 
 #define A_dsa_save_data_pointer        0x00000000
-u32 A_dsa_save_data_pointer_used[] = {
+static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
        0x00000115,
 };
 
 #define A_dsa_select   0x0000003c
-u32 A_dsa_select_used[] = {
+static u32 A_dsa_select_used[] __attribute((unused)) = {
        0x00000081,
 };
 
 #define A_dsa_status   0x00000060
-u32 A_dsa_status_used[] = {
+static u32 A_dsa_status_used[] __attribute((unused)) = {
        0x00000184,
 };
 
 #define A_dsa_temp_addr_array_value    0x00000000
-u32 A_dsa_temp_addr_array_value_used[] = {
+static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_temp_addr_dsa_value      0x00000000
-u32 A_dsa_temp_addr_dsa_value_used[] = {
+static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
        0x00000003,
 };
 
 #define A_dsa_temp_addr_new_value      0x00000000
-u32 A_dsa_temp_addr_new_value_used[] = {
+static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_temp_addr_next   0x00000000
-u32 A_dsa_temp_addr_next_used[] = {
+static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
        0x00000015,
        0x0000004e,
 };
 
 #define A_dsa_temp_addr_residual       0x00000000
-u32 A_dsa_temp_addr_residual_used[] = {
+static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
        0x0000002a,
        0x00000039,
 };
 
 #define A_dsa_temp_addr_saved_pointer  0x00000000
-u32 A_dsa_temp_addr_saved_pointer_used[] = {
+static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
        0x00000026,
        0x00000033,
 };
 
 #define A_dsa_temp_addr_saved_residual 0x00000000
-u32 A_dsa_temp_addr_saved_residual_used[] = {
+static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
        0x0000002b,
        0x00000038,
 };
 
 #define A_dsa_temp_lun 0x00000000
-u32 A_dsa_temp_lun_used[] = {
+static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
        0x0000004b,
 };
 
 #define A_dsa_temp_next        0x00000000
-u32 A_dsa_temp_next_used[] = {
+static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
        0x0000001a,
 };
 
 #define A_dsa_temp_sync        0x00000000
-u32 A_dsa_temp_sync_used[] = {
+static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
        0x00000053,
 };
 
 #define A_dsa_temp_target      0x00000000
-u32 A_dsa_temp_target_used[] = {
+static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
        0x00000040,
 };
 
 #define A_int_debug_break      0x03000000
-u32 A_int_debug_break_used[] = {
+static u32 A_int_debug_break_used[] __attribute((unused)) = {
        0x00000217,
 };
 
 #define A_int_debug_panic      0x030b0000
-u32 A_int_debug_panic_used[] = {
+static u32 A_int_debug_panic_used[] __attribute((unused)) = {
        0x000001e8,
        0x000001f8,
 };
 
 #define A_int_err_check_condition      0x00030000
-u32 A_int_err_check_condition_used[] = {
+static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
        0x00000194,
 };
 
 #define A_int_err_no_phase     0x00040000
-u32 A_int_err_no_phase_used[] = {
+static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
 };
 
 #define A_int_err_selected     0x00010000
-u32 A_int_err_selected_used[] = {
+static u32 A_int_err_selected_used[] __attribute((unused)) = {
        0x000001da,
 };
 
 #define A_int_err_unexpected_phase     0x00000000
-u32 A_int_err_unexpected_phase_used[] = {
+static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
        0x0000008c,
        0x00000092,
        0x0000009a,
@@ -2444,67 +2444,67 @@ u32 A_int_err_unexpected_phase_used[] = {
 };
 
 #define A_int_err_unexpected_reselect  0x00020000
-u32 A_int_err_unexpected_reselect_used[] = {
+static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
        0x000001ba,
 };
 
 #define A_int_msg_1    0x01020000
-u32 A_int_msg_1_used[] = {
+static u32 A_int_msg_1_used[] __attribute((unused)) = {
        0x0000010e,
        0x00000110,
 };
 
 #define A_int_msg_sdtr 0x01010000
-u32 A_int_msg_sdtr_used[] = {
+static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
        0x0000016c,
 };
 
 #define A_int_msg_wdtr 0x01000000
-u32 A_int_msg_wdtr_used[] = {
+static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
        0x00000160,
 };
 
 #define A_int_norm_aborted     0x02040000
-u32 A_int_norm_aborted_used[] = {
+static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
        0x0000024d,
 };
 
 #define A_int_norm_command_complete    0x02020000
-u32 A_int_norm_command_complete_used[] = {
+static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_disconnected        0x02030000
-u32 A_int_norm_disconnected_used[] = {
+static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_reselect_complete   0x02010000
-u32 A_int_norm_reselect_complete_used[] = {
+static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_reset       0x02050000
-u32 A_int_norm_reset_used[] = {
+static u32 A_int_norm_reset_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_select_complete     0x02000000
-u32 A_int_norm_select_complete_used[] = {
+static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_test_1   0x04000000
-u32 A_int_test_1_used[] = {
+static u32 A_int_test_1_used[] __attribute((unused)) = {
        0x000001fd,
 };
 
 #define A_int_test_2   0x04010000
-u32 A_int_test_2_used[] = {
+static u32 A_int_test_2_used[] __attribute((unused)) = {
        0x00000215,
 };
 
 #define A_int_test_3   0x04020000
-u32 A_int_test_3_used[] = {
+static u32 A_int_test_3_used[] __attribute((unused)) = {
 };
 
 #define A_msg_buf      0x00000000
-u32 A_msg_buf_used[] = {
+static u32 A_msg_buf_used[] __attribute((unused)) = {
        0x00000102,
        0x0000014e,
        0x00000158,
@@ -2514,24 +2514,24 @@ u32 A_msg_buf_used[] = {
 };
 
 #define A_reconnect_dsa_head   0x00000000
-u32 A_reconnect_dsa_head_used[] = {
+static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
        0x0000006c,
        0x00000074,
        0x000001a0,
 };
 
 #define A_reselected_identify  0x00000000
-u32 A_reselected_identify_used[] = {
+static u32 A_reselected_identify_used[] __attribute((unused)) = {
        0x00000045,
        0x0000019c,
 };
 
 #define A_reselected_tag       0x00000000
-u32 A_reselected_tag_used[] = {
+static u32 A_reselected_tag_used[] __attribute((unused)) = {
 };
 
 #define A_schedule     0x00000000
-u32 A_schedule_used[] = {
+static u32 A_schedule_used[] __attribute((unused)) = {
        0x0000007e,
        0x00000192,
        0x000001e2,
@@ -2539,12 +2539,12 @@ u32 A_schedule_used[] = {
 };
 
 #define A_test_dest    0x00000000
-u32 A_test_dest_used[] = {
+static u32 A_test_dest_used[] __attribute((unused)) = {
        0x000001fb,
 };
 
 #define A_test_src     0x00000000
-u32 A_test_src_used[] = {
+static u32 A_test_src_used[] __attribute((unused)) = {
        0x000001fa,
 };
 
@@ -2582,7 +2582,7 @@ u32 A_test_src_used[] = {
 #define Ent_test_2     0x000007f8
 #define Ent_test_2_msgout      0x00000810
 #define Ent_wait_reselect      0x00000654
-u32 LABELPATCHES[] = {
+static u32 LABELPATCHES[] __attribute((unused)) = {
        0x00000008,
        0x0000000a,
        0x00000013,
@@ -2666,12 +2666,12 @@ u32 LABELPATCHES[] = {
        0x00000243,
 };
 
-struct {
+static struct {
        u32     offset;
        void            *address;
-} EXTERNAL_PATCHES[] = {
+} EXTERNAL_PATCHES[] __attribute((unused)) = {
 };
 
-u32 INSTRUCTIONS       = 301;
-u32 PATCHES    = 81;
-u32 EXTERNAL_PATCHES_LEN       = 0;
+static u32 INSTRUCTIONS __attribute((unused))  = 301;
+static u32 PATCHES __attribute((unused))       = 81;
+static u32 EXTERNAL_PATCHES_LEN __attribute((unused))  = 0;
index 100f9ff959b4dfe2191010dea9e7d7814a83ba92..70ef93d9261b36a1f52052993938d5b1757d3529 100644 (file)
@@ -208,6 +208,19 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
        will often result in the machine crashing or spontaneously rebooting
        during startup.  Examples of machines that need this are the
        Dell PowerEdge 6300 machines.
+
+    "aic7xxx=seltime:2" - This option controls how long the card waits
+        during a device selection sequence for the device to respond.
+       The original SCSI spec says that this "should be" 256ms.  This
+       is generally not required with modern devices.  However, some
+       very old SCSI I devices need the full 256ms.  Most modern devices
+       can run fine with only 64ms.  The default for this option is
+       64ms.  If you need to change this option, then use the following
+       table to set the proper value in the example above:
+         0  -  256ms
+         1  -  128ms
+         2  -   64ms
+         3  -   32ms
        
     "aic7xxx=panic_on_abort" - This option is for debugging and will cause
         the driver to panic the linux kernel and freeze the system the first
@@ -485,12 +498,14 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
 
   Web sites
   ------------------------------
-    http://people.redhat.com/dledford/aic7xxx.html
-      - Primary web site maintained by Doug Ledford.
+    http://people.redhat.com/dledford/
+      - My web site, also the primary aic7xxx site with several related
+        pages.
 
 Dean W. Gehnert
 deang@teleport.com
 
 $Revision: 3.0 $
 
-Modified by Doug Ledford 1998-9
+Modified by Doug Ledford 1998-2000
+
index 8e712af0e20db71e9f64eaf614e830bf2eaa6c9a..6ecde9a1524ef7669dde5b3c8cdddf77e8500082 100644 (file)
@@ -270,7 +270,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.23"
+#define AIC7XXX_C_VERSION  "5.1.28"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -519,6 +519,7 @@ static const char *board_names[] = {
   "Adaptec AHA-394X Ultra SCSI host adapter",           /* AIC_7882 */
   "Adaptec AHA-398X Ultra SCSI host adapter",           /* AIC_7883 */
   "Adaptec AHA-2944 Ultra SCSI host adapter",           /* AIC_7884 */
+  "Adaptec AHA-2940UW Pro Ultra SCSI host adapter",     /* AIC_7887 */
   "Adaptec AIC-7895 Ultra SCSI host adapter",           /* AIC_7895 */
   "Adaptec AIC-7890/1 Ultra2 SCSI host adapter",        /* AIC_7890 */
   "Adaptec AHA-293X Ultra2 SCSI host adapter",          /* AIC_7890 */
@@ -833,6 +834,8 @@ typedef enum {
   *  and what flags weren't.  This way, I could clean up the flag usage on
   *  a use by use basis.  Doug Ledford
   */
+        AHC_MOTHERBOARD           = 0x00020000,
+        AHC_NO_STPWEN             = 0x00040000,
         AHC_RESET_DELAY           = 0x00080000,
         AHC_A_SCANNED             = 0x00100000,
         AHC_B_SCANNED             = 0x00200000,
@@ -1364,10 +1367,10 @@ static int aic7xxx_scbram = 0;
 /*
  * So that we can set how long each device is given as a selection timeout.
  * The table of values goes like this:
- *     0 - 256ms
- *     1 - 128ms
- *     2 - 64ms
- *     3 - 32ms
+ *   0 - 256ms
+ *   1 - 128ms
+ *   2 - 64ms
+ *   3 - 32ms
  * We default to 64ms because it's fast.  Some old SCSI-I devices need a
  * longer time.  The final value has to be left shifted by 3, hence 0x10
  * is the final value.
@@ -1439,15 +1442,6 @@ static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer);
  ***************************************************************************/
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-static inline void
-mdelay(int milliseconds)
-{
-  int i;
-
-  for(i=0; i<milliseconds; i++)
-    udelay(1000);
-}
-
 static inline int
 time_after_eq(unsigned long a, unsigned long b)
 {
@@ -1490,12 +1484,15 @@ aic_outb(struct aic7xxx_host *p, unsigned char val, long port)
   if(p->maddr)
   {
     writeb(val, p->maddr + port);
+    mb(); /* locked operation in order to force ordering */
+    readb(p->maddr + HCNTRL); /* dummy read to flush the write */
   }
   else
   {
     outb(val, p->base + port);
+    mb(); /* locked operation in order to force ordering */
+    inb(p->base + HCNTRL); /* dummy read to flush the write */
   }
-  mb();
 #else
   outb(val, p->base + port);
 #endif
@@ -1878,13 +1875,10 @@ aic7xxx_download_instr(struct aic7xxx_host *p, int instrptr,
         }
       }
       aic_outb(p, (instr.integer & 0xff), SEQRAM);
-      udelay(50);
       aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM);
-      udelay(50);
       aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM);
-      udelay(50);
       aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM);
-      udelay(50);
+      udelay(10);
       break;
 
     default:
@@ -1996,21 +1990,6 @@ aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded)
   printk("\n");
 }
 
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_delay
- *
- * Description:
- *   Delay for specified amount of time.  We use mdelay because the timer
- *   interrupt is not guaranteed to be enabled.  This will cause an
- *   infinite loop since jiffies (clock ticks) is not updated.
- *-F*************************************************************************/
-static void
-aic7xxx_delay(int seconds)
-{
-  mdelay(seconds * 1000);
-}
-
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_info
@@ -2982,6 +2961,19 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
         p->needwdtr_copy &= ~(1<<tindex);
         p->needsdtr &= ~(1<<tindex);
         p->needsdtr_copy &= ~(1<<tindex);
+        /*
+         * This is needed to work around a sequencer bug for now.  Regardless
+         * of the controller in use, if we have a Quantum drive, we need to
+         * limit the speed to 80MByte/sec.  As soon as I get a fixed version
+         * of the sequencer, this code will get yanked.
+         */
+        if(!strncmp(buffer + 8, "QUANTUM", 7) &&
+           p->transinfo[tindex].goal_options )
+        {
+          p->transinfo[tindex].goal_period = 
+            MAX(p->transinfo[tindex].goal_period, 10);
+          p->transinfo[tindex].goal_options = 0;
+        }
       }
       /*
        * Get the INQUIRY checksum.  We use this on Ultra 160/m
@@ -3896,11 +3888,19 @@ aic7xxx_reset_current_bus(struct aic7xxx_host *p)
   while ( (aic_inb(p, SCSISEQ) & SCSIRSTO) == 0)
     mdelay(5);
 
-  mdelay(10);
+  /*
+   * Some of the new Ultra2 chipsets need a longer delay after a chip
+   * reset than just the init setup creates, so we have to delay here
+   * before we go into a reset in order to make the chips happy.
+   */
+  if (p->features & AHC_ULTRA2)
+    mdelay(250);
+  else
+    mdelay(50);
 
   /* Turn off the bus reset. */
   aic_outb(p, 0, SCSISEQ);
-  mdelay(5);
+  mdelay(10);
 
   aic7xxx_clear_intstat(p);
   /* Re-enable reset interrupts. */
@@ -4779,11 +4779,6 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
             case CHECK_CONDITION:
               if ( !(scb->flags & SCB_SENSE) )
               {
-                /*
-                 * XXX - How do we save the residual (if there is one).
-                 */
-                if ( hscb->residual_SG_segment_count != 0 )
-                  aic7xxx_calculate_residual(p, scb);
 
                 /*
                    * Send a sense command to the requesting target.
@@ -5304,6 +5299,188 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
       }
       break;
 
+    case WIDE_RESIDUE:
+      {
+        unsigned char resid_sgcnt, index;
+        unsigned char scb_index = aic_inb(p, SCB_TAG);
+        unsigned int cur_addr, resid_dcnt;
+        unsigned int native_addr, native_length;
+        int i;
+
+        if(scb_index > p->scb_data->numscbs)
+        {
+          printk(WARN_LEAD "invalid scb_index during WIDE_RESIDUE.\n",
+            p->host_no, -1, -1, -1);
+          /*
+           * XXX: Add error handling here
+           */
+          break;
+        }
+        scb = p->scb_data->scb_array[scb_index];
+        if(!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
+        {
+          printk(WARN_LEAD "invalid scb during WIDE_RESIDUE flags:0x%x "
+                 "scb->cmd:0x%x\n", p->host_no, CTL_OF_SCB(scb),
+                 scb->flags, (unsigned int)scb->cmd);
+          break;
+        }
+
+        /*
+         * We have a valid scb to use on this WIDE_RESIDUE message, so
+         * we need to walk the sg list looking for this particular sg
+         * segment, then see if we happen to be at the very beginning of
+         * the segment.  If we are, then we have to back things up to
+         * the previous segment.  If not, then we simply need to remove
+         * one byte from this segments address and add one to the byte
+         * count.
+         */
+        cur_addr = aic_inb(p, SHADDR) | (aic_inb(p, SHADDR + 1) << 8) |
+          (aic_inb(p, SHADDR + 2) << 16) | (aic_inb(p, SHADDR + 3) << 24);
+        resid_sgcnt = aic_inb(p, SCB_RESID_SGCNT);
+        resid_dcnt = aic_inb(p, SCB_RESID_DCNT) |
+          (aic_inb(p, SCB_RESID_DCNT + 1) << 8) |
+          (aic_inb(p, SCB_RESID_DCNT + 2) << 24);
+        index = scb->sg_count - (resid_sgcnt + 1);
+        native_addr = le32_to_cpu(scb->sg_list[index].address);
+        native_length = le32_to_cpu(scb->sg_list[index].length);
+        /*
+         * Make sure this is a valid sg_seg for the given pointer
+         */
+        if(cur_addr < native_addr ||
+           cur_addr > (native_addr + native_length))
+        {
+          printk(WARN_LEAD "invalid cur_addr:0x%x during WIDE_RESIDUE\n",
+                 p->host_no, CTL_OF_SCB(scb), cur_addr);
+          if(index > 0)
+            printk(WARN_LEAD "  sg_address[-1]:0x%x sg_length[-1]:%d\n",
+                   p->host_no, CTL_OF_SCB(scb),
+                   le32_to_cpu(scb->sg_list[index - 1].address),
+                   le32_to_cpu(scb->sg_list[index - 1].length));
+          printk(WARN_LEAD "  sg_address:0x%x sg_length:%d\n",
+                 p->host_no, CTL_OF_SCB(scb),
+                 native_addr, native_length);
+          if(resid_sgcnt > 1)
+            printk(WARN_LEAD "  sg_address[1]:0x%x sg_length[1]:%d\n",
+                   p->host_no, CTL_OF_SCB(scb),
+                   le32_to_cpu(scb->sg_list[index + 1].address),
+                   le32_to_cpu(scb->sg_list[index + 1].length));
+          break;
+        }
+
+        /*
+         * If our current address matches the sg_seg->address then we
+         * have to back up the sg array to the previous segment and set
+         * it up to have only one byte of transfer left to go.
+         */
+        if(cur_addr == native_addr)
+        {
+          if(index == 0)
+          {
+            printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been "
+                   "transferred.\n", p->host_no, CTL_OF_SCB(scb));
+            break;
+          }
+          resid_sgcnt++;
+          index--;
+          cur_addr = le32_to_cpu(scb->sg_list[index].address) + 
+            le32_to_cpu(scb->sg_list[index].length) - 1;
+          native_addr = aic_inb(p, SG_NEXT) | (aic_inb(p, SG_NEXT + 1) << 8)
+            | (aic_inb(p, SG_NEXT + 2) << 16) | (aic_inb(p, SG_NEXT + 3) << 24);
+          native_addr -= SG_SIZEOF;
+          aic_outb(p, resid_sgcnt, SG_COUNT);
+          aic_outb(p, resid_sgcnt, SCB_RESID_SGCNT);
+          aic_outb(p, native_addr & 0xff, SG_NEXT);
+          aic_outb(p, (native_addr >> 8) & 0xff, SG_NEXT + 1);
+          aic_outb(p, (native_addr >> 16) & 0xff, SG_NEXT + 2);
+          aic_outb(p, (native_addr >> 24) & 0xff, SG_NEXT + 3);
+          aic_outb(p, 1, SCB_RESID_DCNT); 
+          aic_outb(p, 0, SCB_RESID_DCNT + 1); 
+          aic_outb(p, 0, SCB_RESID_DCNT + 2); 
+          aic_outb(p, 1, HCNT); 
+          aic_outb(p, 0, HCNT + 1); 
+          aic_outb(p, 0, HCNT + 2); 
+          aic_outb(p, cur_addr & 0xff, HADDR);
+          aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
+          aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
+          aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
+          /*
+           * The sequencer actually wants to find the new address and byte
+           * count in the SHCNT and SHADDR register sets.  These registers
+           * are a shadow of the regular HCNT and HADDR registers.  On the
+           * Ultra2 controllers, these registers are read only and the way
+           * we have to set their values is to put the values we want into
+           * the HCNT and HADDR registers and then output PRELOADEN into
+           * the DFCNTRL register which causes the card to latch the current
+           * values in the HADDR and HCNT registers and drop it through to
+           * the shadow registers.  On older cards we copy them directly
+           * across by hand.
+           */
+          if(p->features & AHC_ULTRA2)
+          {
+            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+            i=0;
+            udelay(1);
+            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
+            {
+              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+              udelay(1);
+            }
+          }
+          else
+          {
+            aic_outb(p, 1, STCNT); 
+            aic_outb(p, 0, STCNT + 1); 
+            aic_outb(p, 0, STCNT + 2); 
+            aic_outb(p, cur_addr & 0xff, SHADDR);
+            aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
+            aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
+            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+          }
+        }
+        else
+        {
+          /*
+           * Back the data pointer up by one and add one to the remaining
+           * byte count.  Then store that in the HCNT and HADDR registers.
+           */
+          cur_addr--;
+          resid_dcnt++;
+          aic_outb(p, resid_dcnt & 0xff, SCB_RESID_DCNT); 
+          aic_outb(p, (resid_dcnt >> 8) & 0xff, SCB_RESID_DCNT + 1); 
+          aic_outb(p, (resid_dcnt >> 16) & 0xff, SCB_RESID_DCNT + 2); 
+          aic_outb(p, resid_dcnt & 0xff, HCNT); 
+          aic_outb(p, (resid_dcnt >> 8) & 0xff, HCNT + 1); 
+          aic_outb(p, (resid_dcnt >> 16) & 0xff, HCNT + 2); 
+          aic_outb(p, cur_addr & 0xff, HADDR);
+          aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
+          aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
+          aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
+          if(p->features & AHC_ULTRA2)
+          {
+            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+            i=0;
+            udelay(1);
+            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
+            {
+              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+              udelay(1);
+            }
+          }
+          else
+          {
+            aic_outb(p, resid_dcnt & 0xff, STCNT); 
+            aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); 
+            aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); 
+            aic_outb(p, cur_addr & 0xff, SHADDR);
+            aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
+            aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
+            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+          }
+        }
+      }
+      break;
+
+        
 #if AIC7XXX_NOT_YET 
     case TRACEPOINT:
       {
@@ -6232,15 +6409,39 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat)
       }
     }
     /*
-     * Restarting the sequencer will stop the selection and make sure devices
-     * are allowed to reselect in.
+     * Keep the sequencer from trying to restart any selections
      */
     aic_outb(p, 0, SCSISEQ);
+    /*
+     * Make sure the data bits on the bus are released
+     */
+    if(p->features & AHC_WIDE)
+      aic_outb(p, 0, SCSIBUSH);
+    aic_outb(p, 0, SCSIBUSL);
+    /*
+     * Clear the target id bit from the SCSI bus
+     */
+    if(p->features & AHC_ULTRA2)
+      aic_outb(p, aic_inb(p, SCSIID_ULTRA2) & 0x0f, SCSIID_ULTRA2);
+    else
+      aic_outb(p, aic_inb(p, SCSIID) & 0x0f, SCSIID);
+
+    /*
+     * Delay for the selection timeout delay period then stop the selection
+     */
+    udelay(301);
     aic_outb(p, CLRSELINGO, CLRSINT0);
+    /*
+     * Clear out all the interrupt status bits
+     */
     aic_outb(p, aic_inb(p, SIMODE1) & ~(ENREQINIT|ENBUSFREE), SIMODE1);
     p->flags &= ~AHC_HANDLING_REQINITS;
     aic_outb(p, CLRSELTIMEO | CLRBUSFREE, CLRSINT1);
     aic_outb(p, CLRSCSIINT, CLRINT);
+    /*
+     * Restarting the sequencer will stop the selection and make sure devices
+     * are allowed to reselect in.
+     */
     restart_sequencer(p);
     unpause_sequencer(p, TRUE);
   }
@@ -6807,11 +7008,11 @@ do_aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
   if(!p)
     return;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
-  spin_lock_irqsave(&io_request_lock, cpu_flags);
   if(test_and_set_bit(AHC_IN_ISR_BIT, &p->flags))
   {
     return;
   }
+  spin_lock_irqsave(&io_request_lock, cpu_flags);
   do
   {
     aic7xxx_isr(irq, dev_id, regs);
@@ -7210,6 +7411,21 @@ read_284x_seeprom(struct aic7xxx_host *p, struct seeprom_config *sc)
 #undef CLOCK_PULSE
 }
 
+#define CLOCK_PULSE(p)                                               \
+  do {                                                               \
+    int limit = 0;                                                   \
+    do {                                                             \
+      mb();                                                          \
+      pause_sequencer(p);  /* This is just to generate some PCI */   \
+                           /* traffic so the PCI read is flushed */  \
+                           /* it shouldn't be needed, but some */    \
+                           /* chipsets do indeed appear to need */   \
+                           /* something to force PCI reads to get */ \
+                           /* flushed */                             \
+      udelay(1);           /* Do nothing */                          \
+    } while (((aic_inb(p, SEECTL) & SEERDY) == 0) && (++limit < 1000)); \
+  } while(0)
+
 /*+F*************************************************************************
  * Function:
  *   acquire_seeprom
@@ -7220,7 +7436,6 @@ read_284x_seeprom(struct aic7xxx_host *p, struct seeprom_config *sc)
 static int
 acquire_seeprom(struct aic7xxx_host *p)
 {
-  int wait;
 
   /*
    * Request access of the memory port.  When access is
@@ -7230,12 +7445,7 @@ acquire_seeprom(struct aic7xxx_host *p)
    * should be no contention.
    */
   aic_outb(p, SEEMS, SEECTL);
-  wait = 1000;  /* 1000 msec = 1 second */
-  while ((wait > 0) && ((aic_inb(p, SEECTL) & SEERDY) == 0))
-  {
-    wait--;
-    mdelay(1);  /* 1 msec */
-  }
+  CLOCK_PULSE(p);
   if ((aic_inb(p, SEECTL) & SEERDY) == 0)
   {
     aic_outb(p, 0, SEECTL);
@@ -7254,6 +7464,10 @@ acquire_seeprom(struct aic7xxx_host *p)
 static void
 release_seeprom(struct aic7xxx_host *p)
 {
+  /*
+   * Make sure the SEEPROM is ready before we release it.
+   */
+  CLOCK_PULSE(p);
   aic_outb(p, 0, SEECTL);
 }
 
@@ -7320,18 +7534,6 @@ read_seeprom(struct aic7xxx_host *p, int offset,
   };
   struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
 
-#define CLOCK_PULSE(p)                                               \
-  {                                                                  \
-    int limit = 0;                                                   \
-    while (((aic_inb(p, SEECTL) & SEERDY) == 0) && (++limit < 1000)) \
-    {                                                                \
-      mb();                                                          \
-      pause_sequencer(p);  /* This is just to generate some PCI */   \
-                           /* so the PCI read is flushed */          \
-      udelay(10);  /* Do nothing */                                  \
-    }                                                                \
-  }
-
   /*
    * Request access of the memory port.
    */
@@ -7447,7 +7649,6 @@ read_seeprom(struct aic7xxx_host *p, int offset,
   }
 
   return (1);
-#undef CLOCK_PULSE
 }
 
 /*+F*************************************************************************
@@ -7462,12 +7663,18 @@ read_brdctl(struct aic7xxx_host *p)
 {
   unsigned char brdctl, value;
 
+  /*
+   * Make sure the SEEPROM is ready before we access it
+   */
+  CLOCK_PULSE(p);
   if (p->features & AHC_ULTRA2)
   {
     brdctl = BRDRW_ULTRA2;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
-    return(aic_inb(p, BRDCTL));
+    CLOCK_PULSE(p);
+    value = aic_inb(p, BRDCTL);
+    CLOCK_PULSE(p);
+    return(value);
   }
   brdctl = BRDRW;
   if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) ||
@@ -7476,10 +7683,11 @@ read_brdctl(struct aic7xxx_host *p)
     brdctl |= BRDCS;
   }
   aic_outb(p, brdctl, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   value = aic_inb(p, BRDCTL);
+  CLOCK_PULSE(p);
   aic_outb(p, 0, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   return (value);
 }
 
@@ -7495,18 +7703,23 @@ write_brdctl(struct aic7xxx_host *p, unsigned char value)
 {
   unsigned char brdctl;
 
+  /*
+   * Make sure the SEEPROM is ready before we access it
+   */
+  CLOCK_PULSE(p);
   if (p->features & AHC_ULTRA2)
   {
     brdctl = value;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
+    CLOCK_PULSE(p);
     brdctl |= BRDSTB_ULTRA2;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
+    CLOCK_PULSE(p);
     brdctl &= ~BRDSTB_ULTRA2;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
+    CLOCK_PULSE(p);
     read_brdctl(p);
+    CLOCK_PULSE(p);
   }
   else
   {
@@ -7518,16 +7731,16 @@ write_brdctl(struct aic7xxx_host *p, unsigned char value)
     }
     brdctl = BRDSTB | BRDCS;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
     brdctl |= value;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
     brdctl &= ~BRDSTB;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
     brdctl &= ~BRDCS;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
   }
 }
 
@@ -7545,16 +7758,64 @@ aic785x_cable_detect(struct aic7xxx_host *p, int *int_50,
   unsigned char brdctl;
 
   aic_outb(p, BRDRW | BRDCS, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   aic_outb(p, 0, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   brdctl = aic_inb(p, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   *int_50 = !(brdctl & BRDDAT5);
   *ext_present = !(brdctl & BRDDAT6);
   *eeprom = (aic_inb(p, SPIOCAP) & EEPROM);
 }
 
+#undef CLOCK_PULSE
+
+/*+F*************************************************************************
+ * Function:
+ *   aic2940_uwpro_cable_detect
+ *
+ * Description:
+ *   Detect the cables that are present on the 2940-UWPro cards
+ *
+ * NOTE: This functions assumes the SEEPROM will have already been aquired
+ *       prior to invocation of this function.
+ *-F*************************************************************************/
+static void
+aic2940_uwpro_wide_cable_detect(struct aic7xxx_host *p, int *int_68,
+    int *ext_68, int *eeprom)
+{
+  unsigned char brdctl;
+
+  /*
+   * First read the status of our cables.  Set the rom bank to
+   * 0 since the bank setting serves as a multiplexor for the
+   * cable detection logic.  BRDDAT5 controls the bank switch.
+   */
+  write_brdctl(p, 0);
+
+  /*
+   * Now we read the state of the internal 68 connector.  BRDDAT6
+   * is don't care, BRDDAT7 is internal 68.  The cable is
+   * present if the bit is 0
+   */
+  brdctl = read_brdctl(p);
+  *int_68 = !(brdctl & BRDDAT7);
+
+  /*
+   * Set the bank bit in brdctl and then read the external cable state
+   * and the EEPROM status
+   */
+  write_brdctl(p, BRDDAT5);
+  brdctl = read_brdctl(p);
+
+  *ext_68 = !(brdctl & BRDDAT6);
+  *eeprom = !(brdctl & BRDDAT7);
+
+  /*
+   * We're done, the calling function will release the SEEPROM for us
+   */
+}
+
 /*+F*************************************************************************
  * Function:
  *   aic787x_cable_detect
@@ -7659,182 +7920,278 @@ configure_termination(struct aic7xxx_host *p)
       max_target = 8;
     aic_outb(p, SEEMS | SEECS, SEECTL);
     sxfrctl1 &= ~STPWEN;
-    if ( (p->adapter_control & CFAUTOTERM) ||
-         (p->features & AHC_NEW_AUTOTERM) )
+    /*
+     * The termination/cable detection logic is split into three distinct
+     * groups.  Ultra2 and later controllers, 2940UW-Pro controllers, and
+     * older 7850, 7860, 7870, 7880, and 7895 controllers.  Each has its
+     * own unique way of detecting their cables and writing the results
+     * back to the card.
+     */
+    if (p->features & AHC_ULTRA2)
     {
-      if ( (p->adapter_control & CFAUTOTERM) &&
-          !(p->features & AHC_NEW_AUTOTERM) )
-      {
-        printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
-               p->host_no);
-        printk(KERN_INFO "(scsi%d) Please verify driver detected settings are "
-          "correct.\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) If not, then please properly set the device "
-          "termination\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting CTRL-A "
-          "when prompted\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
-      }
-      /* Configure auto termination. */
-
-      if (p->features & AHC_NEW_AUTOTERM)
-      {
-        if (aic7xxx_override_term == -1)
-          aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
-                                     &enableLVD_low, &enableLVD_high,
-                                     &eprom_present);
-        if (!(p->adapter_control & CFSEAUTOTERM))
-        {
-          enableSE_low = (p->adapter_control & CFSTERM);
-          enableSE_high = (p->adapter_control & CFWSTERM);
-        }
-        if (!(p->adapter_control & CFAUTOTERM))
-        {
-          enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
-        }
-        internal50_present = 0;
-        internal68_present = 1;
-        external_present = 1;
-      }
-      else if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
-      {
-        aic787x_cable_detect(p, &internal50_present, &internal68_present,
-          &external_present, &eprom_present);
-      }
-      else
+      /*
+       * As long as user hasn't overridden term settings, always check the
+       * cable detection logic
+       */
+      if (aic7xxx_override_term == -1)
       {
-        aic785x_cable_detect(p, &internal50_present, &external_present,
-          &eprom_present);
+        aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
+                                   &enableLVD_low, &enableLVD_high,
+                                   &eprom_present);
       }
       
-      if (max_target <= 8)
-        internal68_present = 0;
-
-      if ( !(p->features & AHC_NEW_AUTOTERM) )
-      {
-        if (max_target > 8)
-        {
-          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
-                 "Ext-68 %s)\n", p->host_no,
-                 internal50_present ? "YES" : "NO",
-                 internal68_present ? "YES" : "NO",
-                 external_present ? "YES" : "NO");
-        }
-        else
-        {
-          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Ext-50 %s)\n",
-                 p->host_no,
-                 internal50_present ? "YES" : "NO",
-                 external_present ? "YES" : "NO");
-        }
-      }
-      if (aic7xxx_verbose & VERBOSE_PROBE2)
-        printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
-             eprom_present ? "is" : "is not");
-
       /*
-       * Now set the termination based on what we found.  BRDDAT6
-       * controls wide termination enable.
-       * Flash Enable = BRDDAT7
-       * SE High Term Enable = BRDDAT6
-       * SE Low Term Enable = BRDDAT5 (7890)
-       * LVD High Term Enable = BRDDAT4 (7890)
+       * If the user is overriding settings, then they have been preserved
+       * to here as fake adapter_control entries.  Parse them and allow
+       * them to override the detected settings (if we even did detection).
        */
-      if ( !(p->features & AHC_NEW_AUTOTERM) &&
-           (internal50_present && internal68_present && external_present) )
-      {
-        printk(KERN_INFO "(scsi%d) Illegal cable configuration!!  Only two\n",
-               p->host_no);
-        printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
-               "in use at a time!\n", p->host_no);
-        /*
-         * Force termination (low and high byte) on.  This is safer than
-         * leaving it completely off, especially since this message comes
-         * most often from motherboard controllers that don't even have 3
-         * connectors, but instead are failing the cable detection.
-         */
-        internal50_present = external_present = 0;
-        enableSE_high = enableSE_low = 1;
-      }
-
-      if ((max_target > 8) &&
-          ((external_present == 0) || (internal68_present == 0) ||
-           (enableSE_high != 0)))
+      if (!(p->adapter_control & CFSEAUTOTERM))
       {
-        brddat |= BRDDAT6;
-        p->flags |= AHC_TERM_ENB_SE_HIGH;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
-                 p->host_no);
+        enableSE_low = (p->adapter_control & CFSTERM);
+        enableSE_high = (p->adapter_control & CFWSTERM);
       }
-
-      if ( (((internal50_present ? 1 : 0) +
-             (internal68_present ? 1 : 0) +
-             (external_present   ? 1 : 0)) <= 1) ||
-           (enableSE_low != 0) )
+      if (!(p->adapter_control & CFAUTOTERM))
       {
-        if (p->features & AHC_NEW_AUTOTERM)
-          brddat |= BRDDAT5;
-        else
-          sxfrctl1 |= STPWEN;
-        p->flags |= AHC_TERM_ENB_SE_LOW;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
-                 p->host_no);
+        enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
       }
 
+      /*
+       * Now take those settings that we have and translate them into the
+       * values that must be written into the registers.
+       *
+       * Flash Enable = BRDDAT7
+       * Secondary High Term Enable = BRDDAT6
+       * Secondary Low Term Enable = BRDDAT5
+       * LVD/Primary High Term Enable = BRDDAT4
+       * LVD/Primary Low Term Enable = STPWEN bit in SXFRCTL1
+       */
       if (enableLVD_low != 0)
       {
         sxfrctl1 |= STPWEN;
         p->flags |= AHC_TERM_ENB_LVD;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) LVD/Primary Low byte termination "
+                 "Enabled\n", p->host_no);
       }
           
       if (enableLVD_high != 0)
       {
         brddat |= BRDDAT4;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) LVD/Primary High byte termination "
+                 "Enabled\n", p->host_no);
       }
-    }
-    else
-    {
-      if (p->adapter_control & CFSTERM)
+
+      if (enableSE_low != 0)
       {
-        if (p->features & AHC_NEW_AUTOTERM)
-          brddat |= BRDDAT5;
-        else
-          sxfrctl1 |= STPWEN;
+        brddat |= BRDDAT5;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) Secondary Low byte termination "
+                 "Enabled\n", p->host_no);
       }
 
-      if (p->adapter_control & CFWSTERM)
+      if (enableSE_high != 0)
       {
         brddat |= BRDDAT6;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) Secondary High byte termination "
+                 "Enabled\n", p->host_no);
       }
     }
-    aic_outb(p, sxfrctl1, SXFRCTL1);
-    write_brdctl(p, brddat);
-    release_seeprom(p);
-  }
-}
+    else if (p->features & AHC_NEW_AUTOTERM)
+    {
+      /*
+       * The 50 pin connector termination is controlled by STPWEN in the
+       * SXFRCTL1 register.  Since the Adaptec docs typically say the
+       * controller is not allowed to be in the middle of a cable and
+       * this is the only connection on that stub of the bus, there is
+       * no need to even check for narrow termination, it's simply
+       * always on.
+       */
+      sxfrctl1 |= STPWEN;
+      if (aic7xxx_verbose & VERBOSE_PROBE2)
+        printk(KERN_INFO "(scsi%d) Narrow channel termination Enabled\n",
+               p->host_no);
 
-/*+F*************************************************************************
- * Function:
- *   detect_maxscb
- *
- * Description:
- *   Detects the maximum number of SCBs for the controller and returns
- *   the count and a mask in p (p->maxscbs, p->qcntmask).
- *-F*************************************************************************/
+      if (p->adapter_control & CFAUTOTERM)
+      {
+        aic2940_uwpro_wide_cable_detect(p, &internal68_present,
+                                        &external_present,
+                                        &eprom_present);
+        printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
+               "Ext-68 %s)\n", p->host_no,
+               "Don't Care",
+               internal68_present ? "YES" : "NO",
+               external_present ? "YES" : "NO");
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+               eprom_present ? "is" : "is not");
+        if (internal68_present && external_present)
+        {
+          brddat = 0;
+          p->flags &= ~AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Disabled\n",
+                   p->host_no);
+        }
+        else
+        {
+          brddat = BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+                   p->host_no);
+        }
+      }
+      else
+      {
+        /*
+         * The termination of the Wide channel is done more like normal
+         * though, and the setting of this termination is done by writing
+         * either a 0 or 1 to BRDDAT6 of the BRDDAT register
+         */
+        if (p->adapter_control & CFWSTERM)
+        {
+          brddat = BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+                   p->host_no);
+        }
+        else
+        {
+          brddat = 0;
+        }
+      }
+    }
+    else
+    {
+      if (p->adapter_control & CFAUTOTERM)
+      {
+        if (p->flags & AHC_MOTHERBOARD)
+        {
+          printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
+                 p->host_no);
+          printk(KERN_INFO "(scsi%d) Please verify driver detected settings "
+            "are correct.\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) If not, then please properly set the "
+            "device termination\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting "
+            "CTRL-A when prompted\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
+        }
+        /* Configure auto termination. */
+
+        if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
+        {
+          aic787x_cable_detect(p, &internal50_present, &internal68_present,
+            &external_present, &eprom_present);
+        }
+        else
+        {
+          aic785x_cable_detect(p, &internal50_present, &external_present,
+            &eprom_present);
+        }
+
+        if (max_target <= 8)
+          internal68_present = 0;
+
+        if (max_target > 8)
+        {
+          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
+                 "Ext-68 %s)\n", p->host_no,
+                 internal50_present ? "YES" : "NO",
+                 internal68_present ? "YES" : "NO",
+                 external_present ? "YES" : "NO");
+        }
+        else
+        {
+          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Ext-50 %s)\n",
+                 p->host_no,
+                 internal50_present ? "YES" : "NO",
+                 external_present ? "YES" : "NO");
+        }
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+               eprom_present ? "is" : "is not");
+
+        /*
+         * Now set the termination based on what we found.  BRDDAT6
+         * controls wide termination enable.
+         * Flash Enable = BRDDAT7
+         * SE High Term Enable = BRDDAT6
+         */
+        if (internal50_present && internal68_present && external_present)
+        {
+          printk(KERN_INFO "(scsi%d) Illegal cable configuration!!  Only two\n",
+                 p->host_no);
+          printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
+                 "in use at a time!\n", p->host_no);
+          /*
+           * Force termination (low and high byte) on.  This is safer than
+           * leaving it completely off, especially since this message comes
+           * most often from motherboard controllers that don't even have 3
+           * connectors, but instead are failing the cable detection.
+           */
+          internal50_present = external_present = 0;
+          enableSE_high = enableSE_low = 1;
+        }
+
+        if ((max_target > 8) &&
+            ((external_present == 0) || (internal68_present == 0)) )
+        {
+          brddat |= BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+                   p->host_no);
+        }
+
+        if ( ((internal50_present ? 1 : 0) +
+              (internal68_present ? 1 : 0) +
+              (external_present   ? 1 : 0)) <= 1 )
+        {
+          sxfrctl1 |= STPWEN;
+          p->flags |= AHC_TERM_ENB_SE_LOW;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+                   p->host_no);
+        }
+      }
+      else /* p->adapter_control & CFAUTOTERM */
+      {
+        if (p->adapter_control & CFSTERM)
+        {
+          sxfrctl1 |= STPWEN;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+                   p->host_no);
+        }
+
+        if (p->adapter_control & CFWSTERM)
+        {
+          brddat |= BRDDAT6;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+                   p->host_no);
+        }
+      }
+    }
+
+    aic_outb(p, sxfrctl1, SXFRCTL1);
+    write_brdctl(p, brddat);
+    release_seeprom(p);
+  }
+}
+
+/*+F*************************************************************************
+ * Function:
+ *   detect_maxscb
+ *
+ * Description:
+ *   Detects the maximum number of SCBs for the controller and returns
+ *   the count and a mask in p (p->maxscbs, p->qcntmask).
+ *-F*************************************************************************/
 static void
 detect_maxscb(struct aic7xxx_host *p)
 {
@@ -7907,12 +8264,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
   unsigned char term, scsi_conf;
   struct Scsi_Host *host;
 
-  /*
-   * Lock out other contenders for our i/o space.
-   */
-  request_region(p->base, MAXREG - MINREG, "aic7xxx");
-
-
   host = p->host;
 
   p->scb_data->maxscbs = AIC7XXX_MAXSCB;
@@ -7984,7 +8335,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
       printk("VLB slot %d\n", p->pci_device_fn);
       break;
     default:
-      printk("PCI %d/%d\n", PCI_SLOT(p->pci_device_fn),
+      printk("PCI %d/%d/%d\n", p->pci_bus, PCI_SLOT(p->pci_device_fn),
         PCI_FUNC(p->pci_device_fn));
       break;
   }
@@ -8020,6 +8371,20 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
   }
   aic_outb(p, 0, SEQ_FLAGS);
 
+  /*
+   * We are starting to do real work on the card....it's possible we could
+   * generate some spurious interrupts at this point, especially in the
+   * event of a PCI error or some such.  If there are other devices already
+   * registered on the same interrupt as us, this could cause the machine
+   * to lock up.  So, we disable the interrupt this card is on until we
+   * finish our card setup.  We only need to do this for modules, if we are
+   * compiled into the kernel then interrupts are already off during this
+   * part of the code.
+   */
+#ifdef MODULE
+  disable_irq(p->irq);
+#endif
+
   detect_maxscb(p);
 
 
@@ -8055,15 +8420,15 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
 #endif
       if ( (aic7xxx_stpwlev >> p->instance) & 0x01 )
       {
-        devconfig |= 0x02;
+        devconfig |= STPWLEVEL;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("(scsi%d) Force setting STPWLEV bit\n", p->host_no);
+          printk("(scsi%d) Force setting STPWLEVEL bit\n", p->host_no);
       }
       else
       {
-        devconfig &= ~0x02;
+        devconfig &= ~STPWLEVEL;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("(scsi%d) Force clearing STPWLEV bit\n", p->host_no);
+          printk("(scsi%d) Force clearing STPWLEVEL bit\n", p->host_no);
       }
 #if LINUX_KERNEL_VERSION > KERNEL_VERSION(2,1,92)
       pci_write_config_byte(p->pdev, DEVCONFIG, devconfig);
@@ -8124,11 +8489,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
     }
   }
 
-  /*
-   * Clear out any possible pending interrupts.
-   */
-  aic7xxx_clear_intstat(p);
-
   /*
    * Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels
    */
@@ -8172,7 +8532,17 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
   aic_outb(p, (scsi_conf & ENSPCHK) | aic7xxx_seltime | term | 
        ENSTIMER | ACTNEGEN, SXFRCTL1);
   aic_outb(p, 0, SIMODE0);
-  aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
+  /*
+   * If we are a cardbus adapter then don't enable SCSI reset detection.
+   * We shouldn't likely be sharing SCSI busses with someone else, and
+   * if we don't have a cable currently plugged into the controller then
+   * we won't have a power source for the SCSI termination, which means
+   * we'll see infinite incoming bus resets.
+   */
+  if(p->flags & AHC_NO_STPWEN)
+    aic_outb(p, ENSELTIMO | ENSCSIPERR, SIMODE1);
+  else
+    aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
   aic_outb(p, 0, SCSIRATE);
   if ( p->features & AHC_ULTRA2)
     aic_outb(p, 0, SCSIOFFSET);
@@ -8245,6 +8615,10 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
     {
       printk("(scsi%d) Unable to allocate hardware SCB array; "
              "failing detection.\n", p->host_no);
+      aic_outb(p, 0, SIMODE1);
+#ifdef MODULE
+      enable_irq(p->irq);
+#endif
       p->irq = 0;
       return(0);
     }
@@ -8318,11 +8692,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
   p->next = first_aic7xxx;
   first_aic7xxx = p;
 
-  /*
-   * Clear out any possible pending interrupts, again.
-   */
-  aic7xxx_clear_intstat(p);
-
   /*
    * Allocate the first set of scbs for this controller.  This is to stream-
    * line code elsewhere in the driver.  If we have to check for the existence
@@ -8377,20 +8746,21 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
       printk(KERN_INFO "(scsi%d) Resetting channel%s\n", p->host_no, channel);
     }
     
-    /*
-     * Some of the new Ultra2 chipsets need a longer delay after a chip
-     * reset than just the init setup creates, so we have to delay here
-     * before we go into a reset in order to make the chips happy.
-     */
-    if (p->features & AHC_ULTRA2)
-      mdelay(250);
     aic7xxx_reset_current_bus(p);
 
     /*
-     * Delay for the reset delay.
+     * Delay for the reset delay by setting the timer, this will delay
+     * future commands sent to any devices.
      */
-    if (!reset_delay)
-      aic7xxx_delay(AIC7XXX_RESET_DELAY);
+    p->flags |= AHC_RESET_DELAY;
+    for(i=0; i<MAX_TARGETS; i++)
+    {
+      p->dev_expires[i] = jiffies + (4 * HZ);
+      p->dev_timer_active |= (0x01 << i);
+    }
+    p->dev_timer.expires = p->dev_expires[p->scsi_id];
+    add_timer(&p->dev_timer);
+    p->dev_timer_active |= (0x01 << MAX_TARGETS);
   }
   else
   {
@@ -8400,11 +8770,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
              "the no_reset\n", p->host_no);
       printk(KERN_INFO "(scsi%d) option unless you have a verifiable need "
              "for it.\n", p->host_no);
-      printk(KERN_INFO "(scsi%d) The no_reset option is known to break some "
-             "systems,\n", p->host_no);
-      printk(KERN_INFO "(scsi%d) and is not supported by the driver author\n",
-             p->host_no);
-      aic7xxx_delay(AIC7XXX_RESET_DELAY);
     }
   }
   
@@ -8430,10 +8795,23 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
   {
     printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring "
            "controller.\n", p->host_no, p->irq);
+    aic_outb(p, 0, SIMODE1);
+#ifdef MODULE
+    enable_irq(p->irq);
+#endif
     p->irq = 0;
     return (0);
   }
 
+  if(aic_inb(p, INTSTAT) & INT_PEND)
+    printk(INFO_LEAD "spurious interrupt during configuration, cleared.\n",
+      p->host_no, -1, -1 , -1);
+  aic7xxx_clear_intstat(p);
+
+#ifdef MODULE
+  enable_irq(p->irq);
+#endif
+
   unpause_sequencer(p, /* unpause_always */ TRUE);
 
   return (found);
@@ -8463,10 +8841,10 @@ aic7xxx_chip_reset(struct aic7xxx_host *p)
    * In the future, we may call this function as a last resort for
    * error handling.  Let's be nice and not do any unecessary delays.
    */
-  wait = 1000;  /* 1 second (1000 * 1 msec) */
+  wait = 1000;  /* 1 msec (1000 * 1 msec) */
   while (--wait && !(aic_inb(p, HCNTRL) & CHIPRSTACK))
   {
-    mdelay(1);  /* 1 msec */
+    udelay(1);  /* 1 usec */
   }
 
   pause_sequencer(p);
@@ -9102,260 +9480,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
   template->sg_tablesize = AIC7XXX_MAX_SG;
 
 
-#if defined(__i386__) || defined(__alpha__)
-#ifdef CONFIG_PCI
-  /*
-   * PCI-bus chipset probe.
-   */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
-  if (pci_present())
-  {
-    if (pci_find_device(PCI_VENDOR_ID_INTEL,
-                        PCI_DEVICE_ID_INTEL_82450GX,
-                        NULL))
-      aic7xxx_no_probe = 1;
-    if (pci_find_device(PCI_VENDOR_ID_INTEL,
-                        PCI_DEVICE_ID_INTEL_82451NX,
-                        NULL))
-      aic7xxx_no_probe = 1;
-  }
-#else
-#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
-  if (pcibios_present())
-  {
-    unsigned char pci_bus, pci_devfn;
-    if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
-                              PCI_DEVICE_ID_INTEL_82450GX,
-                              0, &pci_bus, &pci_devfn)) )
-      aic7xxx_no_probe = 1;
-    if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
-                              PCI_DEVICE_ID_INTEL_82451NX,
-                              0, &pci_bus, &pci_devfn)) )
-      aic7xxx_no_probe = 1;
-  }
-#endif /* LINUX_VERSION_CODE */
-#endif /* CONFIG_PCI */
-  /*
-   * EISA/VL-bus card signature probe.
-   */
-  slot = MINSLOT;
-  while ( (slot <= MAXSLOT) && 
-         !(aic7xxx_no_probe) )
-  {
-    base = SLOTBASE(slot) + MINREG;
-
-    if (check_region(base, MAXREG - MINREG))
-    {
-      /*
-       * Some other driver has staked a
-       * claim to this i/o region already.
-       */
-      slot++;
-      continue; /* back to the beginning of the for loop */
-    }
-    flags = 0;
-    type = aic7xxx_probe(slot, base + AHC_HID0, &flags);
-    if (type == -1)
-    {
-      slot++;
-      continue;
-    }
-    temp_p = kmalloc(sizeof(struct aic7xxx_host), GFP_ATOMIC);
-    if (temp_p == NULL)
-    {
-      printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
-      slot++;
-      continue; /* back to the beginning of the while loop */
-    }
-    /*
-     * Pause the card preserving the IRQ type.  Allow the operator
-     * to override the IRQ trigger.
-     */
-    if (aic7xxx_irq_trigger == 1)
-      hcntrl = IRQMS;  /* Level */
-    else if (aic7xxx_irq_trigger == 0)
-      hcntrl = 0;  /* Edge */
-    else
-      hcntrl = inb(base + HCNTRL) & IRQMS;  /* Default */
-    memset(temp_p, 0, sizeof(struct aic7xxx_host));
-    temp_p->unpause = hcntrl | INTEN;
-    temp_p->pause = hcntrl | PAUSE | INTEN;
-    temp_p->base = base;
-    temp_p->mbase = 0;
-    temp_p->maddr = 0;
-    temp_p->pci_bus = 0;
-    temp_p->pci_device_fn = slot;
-    aic_outb(temp_p, hcntrl | PAUSE, HCNTRL);
-    while( (aic_inb(temp_p, HCNTRL) & PAUSE) == 0 ) ;
-    if (aic7xxx_chip_reset(temp_p) == -1)
-      temp_p->irq = 0;
-    else
-      temp_p->irq = aic_inb(temp_p, INTDEF) & 0x0F;
-    temp_p->flags |= AHC_PAGESCBS;
-
-    switch (temp_p->irq)
-    {
-      case 9:
-      case 10:
-      case 11:
-      case 12:
-      case 14:
-      case 15:
-        break;
-
-      default:
-        printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ "
-          "level %d, ignoring.\n", temp_p->irq);
-        kfree(temp_p);
-        slot++;
-        continue; /* back to the beginning of the while loop */
-    }
-
-    /*
-     * We are commited now, everything has been checked and this card
-     * has been found, now we just set it up
-     */
-
-    /*
-     * Insert our new struct into the list at the end
-     */
-    if (list_p == NULL)
-    {
-      list_p = current_p = temp_p;
-    }
-    else
-    {
-      current_p = list_p;
-      while (current_p->next != NULL)
-        current_p = current_p->next;
-      current_p->next = temp_p;
-    }
-
-    switch (type)
-    {
-      case 0:
-        temp_p->board_name_index = 2;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("aic7xxx: <%s> at EISA %d\n",
-               board_names[2], slot);
-        /* FALLTHROUGH */
-      case 1:
-      {
-        temp_p->chip = AHC_AIC7770 | AHC_EISA;
-        temp_p->features |= AHC_AIC7770_FE;
-        temp_p->bios_control = aic_inb(temp_p, HA_274_BIOSCTRL);
-
-        /*
-         * Get the primary channel information.  Right now we don't
-         * do anything with this, but someday we will be able to inform
-         * the mid-level SCSI code which channel is primary.
-         */
-        if (temp_p->board_name_index == 0)
-        {
-          temp_p->board_name_index = 3;
-          if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at EISA %d\n",
-                 board_names[3], slot);
-        }
-        if (temp_p->bios_control & CHANNEL_B_PRIMARY)
-        {
-          temp_p->flags |= AHC_CHANNEL_B_PRIMARY;
-        }
-
-        if ((temp_p->bios_control & BIOSMODE) == BIOSDISABLED)
-        {
-          temp_p->flags &= ~AHC_BIOS_ENABLED;
-        }
-        else
-        {
-          temp_p->flags &= ~AHC_USEDEFAULTS;
-          temp_p->flags |= AHC_BIOS_ENABLED;
-          if ( (temp_p->bios_control & 0x20) == 0 )
-          {
-            temp_p->bios_address = 0xcc000;
-            temp_p->bios_address += (0x4000 * (temp_p->bios_control & 0x07));
-          }
-          else
-          {
-            temp_p->bios_address = 0xd0000;
-            temp_p->bios_address += (0x8000 * (temp_p->bios_control & 0x06));
-          }
-        }
-        temp_p->adapter_control = aic_inb(temp_p, SCSICONF) << 8;
-        temp_p->adapter_control |= aic_inb(temp_p, SCSICONF + 1);
-        if (temp_p->features & AHC_WIDE)
-        {
-          temp_p->scsi_id = temp_p->adapter_control & HWSCSIID;
-          temp_p->scsi_id_b = temp_p->scsi_id;
-        }
-        else
-        {
-          temp_p->scsi_id = (temp_p->adapter_control >> 8) & HSCSIID;
-          temp_p->scsi_id_b = temp_p->adapter_control & HSCSIID;
-        }
-        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
-        break;
-      }
-
-      case 2:
-      case 3:
-        temp_p->chip = AHC_AIC7770 | AHC_VL;
-        temp_p->features |= AHC_AIC7770_FE;
-        if (type == 2)
-          temp_p->flags |= AHC_BIOS_ENABLED;
-        else
-          temp_p->flags &= ~AHC_BIOS_ENABLED;
-        if (aic_inb(temp_p, SCSICONF) & TERM_ENB)
-          sxfrctl1 = STPWEN;
-        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
-        temp_p->board_name_index = 4;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("aic7xxx: <%s> at VLB %d\n",
-               board_names[2], slot);
-        switch( aic_inb(temp_p, STATUS_2840) & BIOS_SEL )
-        {
-          case 0x00:
-            temp_p->bios_address = 0xe0000;
-            break;
-          case 0x20:
-            temp_p->bios_address = 0xc8000;
-            break;
-          case 0x40:
-            temp_p->bios_address = 0xd0000;
-            break;
-          case 0x60:
-            temp_p->bios_address = 0xd8000;
-            break;
-          default:
-            break; /* can't get here */
-        }
-        break;
-
-      default:  /* Won't get here. */
-        break;
-    }
-    if (aic7xxx_verbose & VERBOSE_PROBE2)
-    {
-      printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s)\n",
-        (temp_p->flags & AHC_USEDEFAULTS) ? "dis" : "en", temp_p->base,
-        temp_p->irq,
-        (temp_p->pause & IRQMS) ? "level sensitive" : "edge triggered");
-      printk(KERN_INFO "aic7xxx: Extended translation %sabled.\n",
-             (temp_p->flags & AHC_EXTEND_TRANS_A) ? "en" : "dis");
-    }
-
-    /*
-     * Set the FIFO threshold and the bus off time.
-     */
-    hostconf = aic_inb(temp_p, HOSTCONF);
-    aic_outb(temp_p, hostconf & DFTHRSH, BUSSPD);
-    aic_outb(temp_p, (hostconf << 2) & BOFF, BUSTIME);
-    slot++;
-    found++;
-  }
-
-#endif /* defined(__i386__) || defined(__alpha__) */
-
 #ifdef CONFIG_PCI
   /*
    * PCI-bus probe.
@@ -9399,7 +9523,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
        AHC_AIC7860_FE,                                       7,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
-       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
        AHC_AIC7860_FE,                                       7,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7861, AHC_AIC7860,
@@ -9407,7 +9531,8 @@ aic7xxx_detect(Scsi_Host_Template *template)
        AHC_AIC7860_FE,                                       8,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7870, AHC_AIC7870,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,      9,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+       AHC_AIC7870_FE,                                       9,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7871, AHC_AIC7870,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,     10,
@@ -9424,7 +9549,8 @@ aic7xxx_detect(Scsi_Host_Template *template)
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,     13,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7880, AHC_AIC7880,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     14,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+       AHC_AIC7880_FE,                                      14,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7881, AHC_AIC7880,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     15,
@@ -9447,78 +9573,78 @@ aic7xxx_detect(Scsi_Host_Template *template)
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7887, AHC_AIC7880,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 18,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 19,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7888, AHC_AIC7880,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7895, AHC_AIC7895,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7895_FE,                                      19,
+       AHC_AIC7895_FE,                                      20,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      20,
+       AHC_AIC7890_FE,                                      21,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890B, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      20,
+       AHC_AIC7890_FE,                                      21,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2930U2, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      21,
+       AHC_AIC7890_FE,                                      22,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      22,
+       AHC_AIC7890_FE,                                      23,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7896, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      23,
+       AHC_AIC7896_FE,                                      24,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3940U2, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      24,
+       AHC_AIC7896_FE,                                      25,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      25,
+       AHC_AIC7896_FE,                                      26,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
-       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7860_FE,                                      26,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_NO_STPWEN,
+       AHC_AIC7860_FE,                                      27,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892A, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892B, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892D, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892P, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899A, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899B, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899D, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899P, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
     };
 
@@ -9594,10 +9720,11 @@ aic7xxx_detect(Scsi_Host_Template *template)
           if ( temp_p == NULL )
             continue;
           if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at PCI %d/%d\n", 
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
-              PCI_SLOT(temp_p->pdev->devfn),
-              PCI_FUNC(temp_p->pdev->devfn));
+              temp_p->pci_bus,
+              PCI_SLOT(temp_p->pci_device_fn),
+              PCI_FUNC(temp_p->pci_device_fn));
           pci_read_config_word(pdev, PCI_COMMAND, &command);
           if (aic7xxx_verbose & VERBOSE_PROBE2)
           {
@@ -9653,8 +9780,9 @@ aic7xxx_detect(Scsi_Host_Template *template)
           if ( temp_p == NULL )
             continue;
           if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at PCI %d/%d\n", 
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
+              temp_p->pci_bus,
               PCI_SLOT(temp_p->pci_device_fn),
               PCI_FUNC(temp_p->pci_device_fn));
           pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
@@ -9684,14 +9812,28 @@ aic7xxx_detect(Scsi_Host_Template *template)
 #endif /* AIC7XXX_STRICT_PCI_SETUP */
 #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
 
+          if(check_region(temp_p->base, MAXREG - MINREG))
+          {
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
+              board_names[aic_pdevs[i].board_name_index],
+              temp_p->pci_bus,
+              PCI_SLOT(temp_p->pci_device_fn),
+              PCI_FUNC(temp_p->pci_device_fn));
+            printk("aic7xxx: I/O ports already in use, ignoring.\n");
+            kfree(temp_p);
+            temp_p = NULL;
+            continue;
+          }
+
           temp_p->unpause = INTEN;
           temp_p->pause = temp_p->unpause | PAUSE;
           if ( ((temp_p->base == 0) &&
                 (temp_p->mbase == 0)) ||
                (temp_p->irq == 0) )
           {
-            printk("aic7xxx: <%s> at PCI %d/%d\n", 
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
+              temp_p->pci_bus,
               PCI_SLOT(temp_p->pci_device_fn),
               PCI_FUNC(temp_p->pci_device_fn));
             printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
@@ -9726,8 +9868,9 @@ aic7xxx_detect(Scsi_Host_Template *template)
                 /*
                  * OK.....we failed our test....go back to programmed I/O
                  */
-                printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n", 
+                printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n", 
                   board_names[aic_pdevs[i].board_name_index],
+                  temp_p->pci_bus,
                   PCI_SLOT(temp_p->pci_device_fn),
                   PCI_FUNC(temp_p->pci_device_fn));
                 printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to "
@@ -9743,6 +9886,11 @@ aic7xxx_detect(Scsi_Host_Template *template)
           }
 #endif
 
+          /*
+           * Lock out other contenders for our i/o space.
+           */
+          request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
+
           /*
            * We HAVE to make sure the first pause_sequencer() and all other
            * subsequent I/O that isn't PCI config space I/O takes place
@@ -9775,14 +9923,31 @@ aic7xxx_detect(Scsi_Host_Template *template)
           /*
            * Get current termination setting
            */
-          sxfrctl1 = aic_inb(temp_p, SXFRCTL1) & STPWEN;
+          sxfrctl1 = aic_inb(temp_p, SXFRCTL1);
 
           if (aic7xxx_chip_reset(temp_p) == -1)
           {
+            release_region(temp_p->base, MAXREG - MINREG);
             kfree(temp_p);
             temp_p = NULL;
             continue;
           }
+          /*
+           * Very quickly put the term setting back into the register since
+           * the chip reset may cause odd things to happen.  This is to keep
+           * LVD busses with lots of drives from draining the power out of
+           * the diffsense line before we get around to running the
+           * configure_termination() function.  Also restore the STPWLEVEL
+           * bit of DEVCONFIG
+           */
+          aic_outb(temp_p, sxfrctl1, SXFRCTL1);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
+          pcibios_write_config_dword(temp_p->pci_bus, temp_p->pci_device_fn,
+            DEVCONFIG, devconfig);
+#else
+          pci_write_config_dword(temp_p->pdev, DEVCONFIG, devconfig);
+#endif
+          sxfrctl1 &= STPWEN;
 
           /*
            * We need to set the CHNL? assignments before loading the SEEPROM
@@ -10009,8 +10174,9 @@ aic7xxx_detect(Scsi_Host_Template *template)
                 }
                 else if (aic_inb(temp_p, DSCOMMAND0) & RAMPSM_ULTRA2)
                 {
-                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n", 
+                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n", 
                     board_names[aic_pdevs[i].board_name_index],
+                    temp_p->pci_bus,
                     PCI_SLOT(temp_p->pci_device_fn),
                     PCI_FUNC(temp_p->pci_device_fn));
                   printk("aic7xxx: external SCB RAM detected, "
@@ -10027,8 +10193,9 @@ aic7xxx_detect(Scsi_Host_Template *template)
                 }
                 else if (devconfig & RAMPSM)
                 {
-                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n", 
+                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n", 
                     board_names[aic_pdevs[i].board_name_index],
+                    temp_p->pci_bus,
                     PCI_SLOT(temp_p->pci_device_fn),
                     PCI_FUNC(temp_p->pci_device_fn));
                   printk("aic7xxx: external SCB RAM detected, "
@@ -10093,6 +10260,235 @@ aic7xxx_detect(Scsi_Host_Template *template)
     } /* for PCI_DEVICES */
   } /* PCI BIOS present */
 #endif CONFIG_PCI
+
+#if defined(__i386__) || defined(__alpha__)
+  /*
+   * EISA/VL-bus card signature probe.
+   */
+  slot = MINSLOT;
+  while ( (slot <= MAXSLOT) && 
+         !(aic7xxx_no_probe) )
+  {
+    base = SLOTBASE(slot) + MINREG;
+
+    if (check_region(base, MAXREG - MINREG))
+    {
+      /*
+       * Some other driver has staked a
+       * claim to this i/o region already.
+       */
+      slot++;
+      continue; /* back to the beginning of the for loop */
+    }
+    flags = 0;
+    type = aic7xxx_probe(slot, base + AHC_HID0, &flags);
+    if (type == -1)
+    {
+      slot++;
+      continue;
+    }
+    temp_p = kmalloc(sizeof(struct aic7xxx_host), GFP_ATOMIC);
+    if (temp_p == NULL)
+    {
+      printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
+      slot++;
+      continue; /* back to the beginning of the while loop */
+    }
+    /*
+     * Lock out other contenders for our i/o space.
+     */
+    request_region(base, MAXREG - MINREG, "aic7xxx");
+
+    /*
+     * Pause the card preserving the IRQ type.  Allow the operator
+     * to override the IRQ trigger.
+     */
+    if (aic7xxx_irq_trigger == 1)
+      hcntrl = IRQMS;  /* Level */
+    else if (aic7xxx_irq_trigger == 0)
+      hcntrl = 0;  /* Edge */
+    else
+      hcntrl = inb(base + HCNTRL) & IRQMS;  /* Default */
+    memset(temp_p, 0, sizeof(struct aic7xxx_host));
+    temp_p->unpause = hcntrl | INTEN;
+    temp_p->pause = hcntrl | PAUSE | INTEN;
+    temp_p->base = base;
+    temp_p->mbase = 0;
+    temp_p->maddr = 0;
+    temp_p->pci_bus = 0;
+    temp_p->pci_device_fn = slot;
+    aic_outb(temp_p, hcntrl | PAUSE, HCNTRL);
+    while( (aic_inb(temp_p, HCNTRL) & PAUSE) == 0 ) ;
+    if (aic7xxx_chip_reset(temp_p) == -1)
+      temp_p->irq = 0;
+    else
+      temp_p->irq = aic_inb(temp_p, INTDEF) & 0x0F;
+    temp_p->flags |= AHC_PAGESCBS;
+
+    switch (temp_p->irq)
+    {
+      case 9:
+      case 10:
+      case 11:
+      case 12:
+      case 14:
+      case 15:
+        break;
+
+      default:
+        printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ "
+          "level %d, ignoring.\n", temp_p->irq);
+        kfree(temp_p);
+        release_region(base, MAXREG - MINREG);
+        slot++;
+        continue; /* back to the beginning of the while loop */
+    }
+
+    /*
+     * We are commited now, everything has been checked and this card
+     * has been found, now we just set it up
+     */
+
+    /*
+     * Insert our new struct into the list at the end
+     */
+    if (list_p == NULL)
+    {
+      list_p = current_p = temp_p;
+    }
+    else
+    {
+      current_p = list_p;
+      while (current_p->next != NULL)
+        current_p = current_p->next;
+      current_p->next = temp_p;
+    }
+
+    switch (type)
+    {
+      case 0:
+        temp_p->board_name_index = 2;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk("aic7xxx: <%s> at EISA %d\n",
+               board_names[2], slot);
+        /* FALLTHROUGH */
+      case 1:
+      {
+        temp_p->chip = AHC_AIC7770 | AHC_EISA;
+        temp_p->features |= AHC_AIC7770_FE;
+        temp_p->bios_control = aic_inb(temp_p, HA_274_BIOSCTRL);
+
+        /*
+         * Get the primary channel information.  Right now we don't
+         * do anything with this, but someday we will be able to inform
+         * the mid-level SCSI code which channel is primary.
+         */
+        if (temp_p->board_name_index == 0)
+        {
+          temp_p->board_name_index = 3;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk("aic7xxx: <%s> at EISA %d\n",
+                 board_names[3], slot);
+        }
+        if (temp_p->bios_control & CHANNEL_B_PRIMARY)
+        {
+          temp_p->flags |= AHC_CHANNEL_B_PRIMARY;
+        }
+
+        if ((temp_p->bios_control & BIOSMODE) == BIOSDISABLED)
+        {
+          temp_p->flags &= ~AHC_BIOS_ENABLED;
+        }
+        else
+        {
+          temp_p->flags &= ~AHC_USEDEFAULTS;
+          temp_p->flags |= AHC_BIOS_ENABLED;
+          if ( (temp_p->bios_control & 0x20) == 0 )
+          {
+            temp_p->bios_address = 0xcc000;
+            temp_p->bios_address += (0x4000 * (temp_p->bios_control & 0x07));
+          }
+          else
+          {
+            temp_p->bios_address = 0xd0000;
+            temp_p->bios_address += (0x8000 * (temp_p->bios_control & 0x06));
+          }
+        }
+        temp_p->adapter_control = aic_inb(temp_p, SCSICONF) << 8;
+        temp_p->adapter_control |= aic_inb(temp_p, SCSICONF + 1);
+        if (temp_p->features & AHC_WIDE)
+        {
+          temp_p->scsi_id = temp_p->adapter_control & HWSCSIID;
+          temp_p->scsi_id_b = temp_p->scsi_id;
+        }
+        else
+        {
+          temp_p->scsi_id = (temp_p->adapter_control >> 8) & HSCSIID;
+          temp_p->scsi_id_b = temp_p->adapter_control & HSCSIID;
+        }
+        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+        break;
+      }
+
+      case 2:
+      case 3:
+        temp_p->chip = AHC_AIC7770 | AHC_VL;
+        temp_p->features |= AHC_AIC7770_FE;
+        if (type == 2)
+          temp_p->flags |= AHC_BIOS_ENABLED;
+        else
+          temp_p->flags &= ~AHC_BIOS_ENABLED;
+        if (aic_inb(temp_p, SCSICONF) & TERM_ENB)
+          sxfrctl1 = STPWEN;
+        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+        temp_p->board_name_index = 4;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk("aic7xxx: <%s> at VLB %d\n",
+               board_names[2], slot);
+        switch( aic_inb(temp_p, STATUS_2840) & BIOS_SEL )
+        {
+          case 0x00:
+            temp_p->bios_address = 0xe0000;
+            break;
+          case 0x20:
+            temp_p->bios_address = 0xc8000;
+            break;
+          case 0x40:
+            temp_p->bios_address = 0xd0000;
+            break;
+          case 0x60:
+            temp_p->bios_address = 0xd8000;
+            break;
+          default:
+            break; /* can't get here */
+        }
+        break;
+
+      default:  /* Won't get here. */
+        break;
+    }
+    if (aic7xxx_verbose & VERBOSE_PROBE2)
+    {
+      printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s)\n",
+        (temp_p->flags & AHC_USEDEFAULTS) ? "dis" : "en", temp_p->base,
+        temp_p->irq,
+        (temp_p->pause & IRQMS) ? "level sensitive" : "edge triggered");
+      printk(KERN_INFO "aic7xxx: Extended translation %sabled.\n",
+             (temp_p->flags & AHC_EXTEND_TRANS_A) ? "en" : "dis");
+    }
+
+    /*
+     * Set the FIFO threshold and the bus off time.
+     */
+    hostconf = aic_inb(temp_p, HOSTCONF);
+    aic_outb(temp_p, hostconf & DFTHRSH, BUSSPD);
+    aic_outb(temp_p, (hostconf << 2) & BOFF, BUSTIME);
+    slot++;
+    found++;
+  }
+
+#endif /* defined(__i386__) || defined(__alpha__) */
+
   /*
    * Now, we re-order the probed devices by BIOS address and BUS class.
    * In general, we follow this algorithm to make the adapters show up
@@ -11165,8 +11561,10 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
              (scb->flags & SCB_WAITINGQ) ? "WAITINGQ" : "Sent" );
     }
   }
-#endif
   sti();
+#else
+  spin_unlock_irq(&io_request_lock);
+#endif
   for(;;) barrier();
 }
 
@@ -11956,6 +12354,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
           0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
           0xe0, 0xf1, 0xf4, 0xfc} },
   };
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
 #ifdef CONFIG_PCI
   static struct register_ranges cards_ns[] = {
     { 0, {0,} }, /* none */
@@ -11976,6 +12375,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
     { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
           0xff, 0xff} }
   };
+#endif
 #endif
   chip = p->chip & AHC_CHIPID_MASK;
   /*
@@ -11993,11 +12393,12 @@ aic7xxx_print_card(struct aic7xxx_host *p)
       break;
     case AHC_PCI:
     default:
-      printk("PCI %d/%d.\n", PCI_SLOT(p->pci_device_fn),
+      printk("PCI %d/%d/%d.\n", p->pci_bus, PCI_SLOT(p->pci_device_fn),
              PCI_FUNC(p->pci_device_fn));
       break;
   }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
 #ifdef CONFIG_PCI
   {
     unsigned char temp;
@@ -12010,11 +12411,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
           j <= cards_ns[chip].range_val[ i * 2 + 1 ] ;
           j++)
       {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
-        pci_read_config_byte(p->pdev, j, &temp);
-#else
         pcibios_read_config_byte(p->pci_bus, p->pci_device_fn, j, &temp);
-#endif
         printk("%02x:%02x ", j, temp);
         if(++k == 13)
         {
@@ -12027,6 +12424,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
   if(k != 0)
     printk("\n");
 #endif /* CONFIG_PCI */
+#endif
 
   /*
    * Now the registers on the card....
@@ -12049,6 +12447,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
   }
   if(k != 0)
     printk("\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
   if (p->flags & AHC_SEEPROM_FOUND)
   {
     unsigned short *sc1;
@@ -12064,6 +12463,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
         printk("  ");
     }
   }
+#endif
 
   /*
    * If this was an Ultra2 controller, then we just hosed the card in terms
index 6cc347d5b82b2bd9e130b6deca0fb68e5597add7..fb554727b40e8a76ee709685f8e6f7be5cf993f5 100644 (file)
@@ -691,7 +691,8 @@ register INTSTAT {
        mask    NO_IDENT        0x20|SEQINT     /* no IDENTIFY after reconnect*/
        mask    NO_MATCH        0x30|SEQINT     /* no cmd match for reconnect */
        mask    EXTENDED_MSG    0x40|SEQINT     /* Extended message received */
-       mask    ABORT_REQUESTED 0x50|SEQINT     /* Reconect of aborted SCB */
+       mask    WIDE_RESIDUE    0x50|SEQINT     /* need kernel to back up */
+                                               /* the SG array for us */
        mask    REJECT_MSG      0x60|SEQINT     /* Reject message received */
        mask    BAD_STATUS      0x70|SEQINT     /* Bad status from target */
        mask    RESIDUAL        0x80|SEQINT     /* Residual byte count != 0 */
index 07729599f5fc6d67b2cee77b3ad7b05f9ee8bd15..248e8ee383ae99d53f3f0bf52113b5c1b66bd6a7 100644 (file)
@@ -182,6 +182,15 @@ initialize_scsiid:
                and     SCSIID, OID;            /* Clear old target */
                or      SCSIID, A;
        }
+       mov     SCSIDATL, ALLZEROS;             /* clear out the latched */
+                                               /* data register, this */
+                                               /* fixes a bug on some */
+                                               /* controllers where the */
+                                               /* last byte written to */
+                                               /* this register can leak */
+                                               /* onto the data bus at */
+                                               /* bad times, such as during */
+                                               /* selection timeouts */
        mvi     SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
 
 /*
@@ -448,8 +457,9 @@ data_phase_reinit:
                if ((p->features & AHC_ULTRA2) != 0) {
                        bmov    HADDR, SHADDR, 4;
                        bmov    HCNT, SCB_RESID_DCNT, 3;
+               } else {
+                       bmov    STCNT, SCB_RESID_DCNT, 3;
                }
-               bmov    STCNT, SCB_RESID_DCNT, 3;
        } else {
                mvi     DINDEX, STCNT;
                mvi     SCB_RESID_DCNT  call bcopy_3;
@@ -517,10 +527,12 @@ data_phase_loop:
        }
 data_phase_inbounds:
 /* If we are the last SG block, tell the hardware. */
-if ((p->features & AHC_ULTRA2) == 0) {
        cmp     SG_COUNT,0x01 jne data_phase_wideodd;
-       and     DMAPARAMS, ~WIDEODD;
-}
+       if ((p->features & AHC_ULTRA2) == 0) {
+               and     DMAPARAMS, ~WIDEODD;
+       } else {
+               mvi     SG_CACHEPTR, LAST_SEG;
+       }
 data_phase_wideodd:
        if ((p->features & AHC_ULTRA2) != 0) {
                mov     SINDEX, ALLONES;
@@ -530,7 +542,7 @@ data_phase_dma_loop:
                test    SSTAT0, SDONE jnz data_phase_dma_done;
                test    SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */
 data_phase_dma_phasemis:
-               test    SSTAT0,SDONE    jnz . + 2;
+               test    SSTAT0,SDONE    jnz data_phase_dma_done;
                clr     SINDEX;                 /* Remember the phasemiss */
        } else {
                mov     DMAPARAMS  call dma;
@@ -615,9 +627,10 @@ prefetched_segs_avail:
        test    SSTAT1, REQINIT jz .;
        test    SSTAT1,PHASEMIS jz data_phase_loop;
 
+/* This drops the last SG segment down to the shadow layer for us */
        if ((p->features & AHC_ULTRA2) != 0) {
                mov     DFCNTRL, DMAPARAMS;
-               test    SSTAT0, SDONE jnz .;
+               test    SSTAT0, SDONE   jnz .;
        }
 
 data_phase_finish:
@@ -713,7 +726,7 @@ p_command:
                mvi     DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
                test    SSTAT0, SDONE jnz .;
 p_command_dma_loop:
-               test    SSTAT0, DMADONE jnz p_command_ultra2_dma_done;
+               test    SSTAT0, SDONE jnz p_command_ultra2_dma_done;
                test    SSTAT1,PHASEMIS jz p_command_dma_loop;  /* ie. underrun */
 p_command_ultra2_dma_done:
                and     DFCNTRL, ~HDMAEN;
@@ -830,6 +843,7 @@ p_mesgin:
        cmp     A,MSG_EXTENDED          je mesgin_extended;
        cmp     A,MSG_MESSAGE_REJECT    je mesgin_reject;
        cmp     A,MSG_NOOP              je mesgin_done;
+       cmp     A,MSG_IGN_WIDE_RESIDUE  je mesgin_wide_residue;
 
 rej_mesgin:
 /*
@@ -1056,6 +1070,33 @@ mesgin_reject:
        mvi     INTSTAT, REJECT_MSG;
        jmp     mesgin_done;
 
+/*
+ * Wide Residue.  We handle the simple cases, but pass of the one hard case
+ * to the kernel (when the residue byte happened to cause us to advance our
+ * sg element array, so we know have to back that advance out).
+ */
+mesgin_wide_residue:
+       mvi     ARG_1   call inb_next; /* ACK the wide_residue and get */
+                                      /* the size byte */
+/*
+ * See if we'll ignore this wide residue (because it's an overrun byte)
+ */
+       test    SCB_RESID_SGCNT,0xff jnz wide_residue_int;
+       test    SCB_RESID_DCNT[0],0xff jnz wide_residue_int;
+       test    SCB_RESID_DCNT[1],0xff jnz wide_residue_int;
+       test    SCB_RESID_DCNT[2],0xff jnz wide_residue_int;
+       jmp     mesgin_done;
+
+wide_residue_int:
+/*
+ * In order for this to be reliable, we have to do all sorts of horrible
+ * magic in terms of resetting the datafifo and reloading the shadow layer
+ * with the correct new values (so that a subsequent save data pointers
+ * message will do the right thing).  We let the kernel do that work.
+ */
+       mvi     INTSTAT,WIDE_RESIDUE;
+       jmp     mesgin_done;
+       
 /*
  * [ ADD MORE MESSAGE HANDLING HERE ]
  */
@@ -1093,7 +1134,7 @@ inb_next_wait:
         * before continuing.
         */
        test    SSTAT1, REQINIT jz inb_next_wait;
-       test    SSTAT1, SCSIPERR jnz inb_next_wait;
+       test    SSTAT1, SCSIPERR jnz .;
        and     LASTPHASE, PHASE_MASK, SCSISIGI;
        cmp     LASTPHASE, P_MESGIN jne mesgin_phasemis;
 inb_first:
index 1fb00893e3cc8c27b4fd9791946d5eaa1bd0f01c..ec80af90d91cc08391e1ab30be08c0d56f169560 100644 (file)
@@ -178,7 +178,7 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
   size += sprintf(BLS, "           SCSI Adapter: %s\n",
       board_names[p->board_name_index]);
   if (p->flags & AHC_TWIN)
-    size += sprintf(BLS, "                         Twin Channel\n");
+    size += sprintf(BLS, "                         Twin Channel Controller ");
   else
   {
     char *channel = "";
@@ -209,9 +209,22 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
       ultra = "Ultra-2 LVD/SE ";
     else if (p->features & AHC_ULTRA)
       ultra = "Ultra ";
-    size += sprintf(BLS, "                           %s%sController%s\n",
+    size += sprintf(BLS, "                           %s%sController%s ",
       ultra, wide, channel);
   }
+  switch(p->chip & ~AHC_CHIPID_MASK)
+  {
+    case AHC_VL:
+      size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
+      break;
+    case AHC_EISA:
+      size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
+      break;
+    default:
+      size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
+        PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
+      break;
+  }
   if( !(p->maddr) )
   {
     size += sprintf(BLS, "    Programmed I/O Base: %lx\n", p->base);
@@ -224,11 +237,6 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
   {
     size += sprintf(BLS, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
   }
-  if( p->chip & AHC_PCI )
-  {
-    size += sprintf(BLS, "    PCI Bus 0x%02x Device 0x%02x\n", p->pci_bus,
-              p->pci_device_fn);
-  }
   size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
           (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
          ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
index f86e1bec8a264f2503716485a7518fd023e2bce7..4baa009116e43688a05727573d3b3608faced1c4 100644 (file)
 #define                BRDRW                   0x04
 #define                BRDRW_ULTRA2            0x02
 #define                BRDCTL1                 0x02
-#define                BRDSTB_ULTRA2           0x01
 #define                BRDCTL0                 0x01
+#define                BRDSTB_ULTRA2           0x01
 
 #define        SEECTL                          0x1e
 #define                EXTARBACK               0x80
 #define                RESIDUAL                0x81
 #define                BAD_STATUS              0x71
 #define                REJECT_MSG              0x61
-#define                ABORT_REQUESTED         0x51
+#define                WIDE_RESIDUE            0x51
 #define                EXTENDED_MSG            0x41
 #define                NO_MATCH                0x31
 #define                NO_IDENT                0x21
 #define                TARGCRCENDEN            0x08
 #define                TARGCRCCNTEN            0x04
 
+#define        QOUTCNT                         0x9e
+
 #define        SCSIPHASE                       0x9e
 #define                SP_STATUS               0x20
 #define                SP_COMMAND              0x10
 #define                SP_DATA_IN              0x02
 #define                SP_DATA_OUT             0x01
 
-#define        QOUTCNT                         0x9e
-
 #define        SFUNCT                          0x9f
 #define                ALT_MODE                0x80
 
 #define                RD_DFTHRSH_63           0x03
 #define                RD_DFTHRSH_50           0x02
 #define                RD_DFTHRSH_25           0x01
-#define                WR_DFTHRSH_MIN          0x00
 #define                RD_DFTHRSH_MIN          0x00
+#define                WR_DFTHRSH_MIN          0x00
 
 #define        SG_CACHEPTR                     0xfc
 #define                SG_USER_DATA            0xfc
 #define                LAST_SEG_DONE           0x01
 
 
+#define        CMD_GROUP_CODE_SHIFT    0x05
+#define        BUS_8_BIT       0x00
+#define        QOUTFIFO_OFFSET 0x01
+#define        CCSGRAM_MAXSEGS 0x10
 #define        CMD_GROUP2_BYTE_DELTA   0xfa
 #define        MAX_OFFSET_8BIT 0x0f
 #define        BUS_16_BIT      0x01
 #define        QINFIFO_OFFSET  0x02
 #define        CMD_GROUP5_BYTE_DELTA   0x0b
-#define        CMD_GROUP_CODE_SHIFT    0x05
 #define        MAX_OFFSET_ULTRA2       0x7f
 #define        MAX_OFFSET_16BIT        0x08
-#define        BUS_8_BIT       0x00
-#define        QOUTFIFO_OFFSET 0x01
 #define        UNTAGGEDSCB_OFFSET      0x00
-#define        CCSGRAM_MAXSEGS 0x10
 #define        SCB_LIST_NULL   0xff
 #define        SG_SIZEOF       0x08
 #define        CMD_GROUP4_BYTE_DELTA   0x04
index 49502b6cd5bc9e3f0ec0fe3312c3d30588b3e3a6..343f29f7906503f03f91c910ea3b736b023227b6 100644 (file)
@@ -8,14 +8,14 @@ static unsigned char seqprog[] = {
        0x12, 0x6a, 0x00, 0x00,
        0xff, 0x6a, 0xd6, 0x09,
        0xff, 0x6a, 0xdc, 0x09,
-       0x00, 0x65, 0x42, 0x59,
+       0x00, 0x65, 0x44, 0x59,
        0xf7, 0x01, 0x02, 0x08,
        0xff, 0x4e, 0xc8, 0x08,
        0xbf, 0x60, 0xc0, 0x08,
-       0x60, 0x0b, 0x86, 0x68,
+       0x60, 0x0b, 0x88, 0x68,
        0x40, 0x00, 0x0e, 0x68,
        0x08, 0x1f, 0x3e, 0x10,
-       0x60, 0x0b, 0x86, 0x68,
+       0x60, 0x0b, 0x88, 0x68,
        0x40, 0x00, 0x0e, 0x68,
        0x08, 0x1f, 0x3e, 0x10,
        0xff, 0x3e, 0x4a, 0x60,
@@ -26,12 +26,12 @@ static unsigned char seqprog[] = {
        0x00, 0x4d, 0x12, 0x70,
        0x01, 0x4e, 0x9c, 0x18,
        0xbf, 0x60, 0xc0, 0x08,
-       0x00, 0x6a, 0xa8, 0x5c,
+       0x00, 0x6a, 0xbe, 0x5c,
        0xff, 0x4e, 0xc8, 0x18,
-       0x02, 0x6a, 0xbe, 0x5b,
+       0x02, 0x6a, 0xd4, 0x5b,
        0xff, 0x52, 0x20, 0x09,
        0x0d, 0x6a, 0x6a, 0x00,
-       0x00, 0x52, 0x34, 0x5c,
+       0x00, 0x52, 0x4a, 0x5c,
        0x03, 0xb0, 0x52, 0x31,
        0xff, 0xb0, 0x52, 0x09,
        0xff, 0xb1, 0x54, 0x09,
@@ -52,51 +52,52 @@ static unsigned char seqprog[] = {
        0xf0, 0xa1, 0xc8, 0x08,
        0x0f, 0x05, 0x0a, 0x08,
        0x00, 0x05, 0x0a, 0x00,
+       0xff, 0x6a, 0x0c, 0x08,
        0x5a, 0x6a, 0x00, 0x04,
        0x12, 0x65, 0x02, 0x00,
        0x31, 0x6a, 0xca, 0x00,
-       0x80, 0x37, 0x6e, 0x68,
+       0x80, 0x37, 0x70, 0x68,
        0xff, 0x65, 0xca, 0x18,
        0xff, 0x37, 0xdc, 0x08,
        0xff, 0x6e, 0xc8, 0x08,
-       0x00, 0x6c, 0x76, 0x78,
+       0x00, 0x6c, 0x78, 0x78,
        0x20, 0x01, 0x02, 0x00,
        0x4c, 0x37, 0xc8, 0x28,
-       0x08, 0x1f, 0x7e, 0x78,
+       0x08, 0x1f, 0x80, 0x78,
        0x08, 0x37, 0x6e, 0x00,
        0x08, 0x64, 0xc8, 0x00,
        0x70, 0x64, 0xca, 0x18,
        0xff, 0x6c, 0x0a, 0x08,
        0x20, 0x64, 0xca, 0x18,
        0xff, 0x6c, 0x08, 0x0c,
-       0x40, 0x0b, 0x0e, 0x69,
-       0x80, 0x0b, 0x00, 0x79,
+       0x40, 0x0b, 0x10, 0x69,
+       0x80, 0x0b, 0x02, 0x79,
        0xa4, 0x6a, 0x06, 0x00,
        0x40, 0x6a, 0x16, 0x00,
-       0x10, 0x03, 0xfc, 0x78,
+       0x10, 0x03, 0xfe, 0x78,
        0xff, 0x50, 0xc8, 0x08,
        0x88, 0x6a, 0xcc, 0x00,
-       0x49, 0x6a, 0x24, 0x5c,
+       0x49, 0x6a, 0x3a, 0x5c,
        0x01, 0x6a, 0x26, 0x01,
        0xff, 0x6a, 0xca, 0x08,
        0x08, 0x01, 0x02, 0x00,
-       0x02, 0x0b, 0x9c, 0x78,
+       0x02, 0x0b, 0x9e, 0x78,
        0xf7, 0x01, 0x02, 0x08,
        0xff, 0x06, 0xcc, 0x08,
        0xff, 0x66, 0x32, 0x09,
        0x01, 0x65, 0xca, 0x18,
-       0x80, 0x66, 0xaa, 0x78,
+       0x80, 0x66, 0xac, 0x78,
        0xff, 0x66, 0xa2, 0x08,
-       0x10, 0x03, 0x9a, 0x68,
+       0x10, 0x03, 0x9c, 0x68,
        0xfc, 0x65, 0xc8, 0x18,
-       0x00, 0x65, 0xb2, 0x48,
+       0x00, 0x65, 0xb4, 0x48,
        0xff, 0x6a, 0x32, 0x01,
        0x01, 0x64, 0x18, 0x19,
        0xff, 0x6a, 0x1a, 0x09,
        0xff, 0x6a, 0x1c, 0x09,
        0x84, 0x6a, 0x06, 0x00,
        0x08, 0x01, 0x02, 0x00,
-       0x02, 0x0b, 0xbc, 0x78,
+       0x02, 0x0b, 0xbe, 0x78,
        0xff, 0x06, 0xc8, 0x08,
        0xff, 0x64, 0x32, 0x09,
        0xff, 0x6a, 0xca, 0x08,
@@ -110,33 +111,33 @@ static unsigned char seqprog[] = {
        0x0b, 0x65, 0xca, 0x18,
        0xff, 0x65, 0xc8, 0x08,
        0x00, 0x8c, 0x18, 0x19,
-       0x02, 0x0b, 0xd8, 0x78,
-       0x01, 0x65, 0xde, 0x60,
+       0x02, 0x0b, 0xda, 0x78,
+       0x01, 0x65, 0xe0, 0x60,
        0xf7, 0x01, 0x02, 0x08,
        0xff, 0x06, 0x32, 0x09,
        0xff, 0x65, 0xca, 0x18,
-       0xff, 0x65, 0xd8, 0x68,
+       0xff, 0x65, 0xda, 0x68,
        0x0a, 0x93, 0x26, 0x01,
-       0x00, 0x65, 0x9a, 0x5c,
-       0x40, 0x51, 0xf0, 0x78,
+       0x00, 0x65, 0xb0, 0x5c,
+       0x40, 0x51, 0xf2, 0x78,
        0xe4, 0x6a, 0x06, 0x00,
        0x08, 0x01, 0x02, 0x00,
-       0x04, 0x6a, 0x56, 0x5b,
+       0x04, 0x6a, 0x6c, 0x5b,
        0x01, 0x50, 0xa0, 0x18,
-       0x00, 0x50, 0xf6, 0xe0,
+       0x00, 0x50, 0xf8, 0xe0,
        0xff, 0x6a, 0xa0, 0x08,
        0xff, 0x6a, 0x3a, 0x01,
        0x02, 0x6a, 0x22, 0x01,
-       0x40, 0x51, 0xfc, 0x68,
+       0x40, 0x51, 0xfe, 0x68,
        0xff, 0x6a, 0x06, 0x08,
        0x00, 0x65, 0x0e, 0x40,
        0x20, 0x6a, 0x16, 0x00,
        0xf0, 0x19, 0x6e, 0x08,
        0x08, 0x6a, 0x18, 0x00,
        0x08, 0x11, 0x22, 0x00,
-       0x08, 0x6a, 0x66, 0x58,
+       0x08, 0x6a, 0x68, 0x58,
        0x08, 0x6a, 0x68, 0x00,
-       0x00, 0x65, 0x22, 0x41,
+       0x00, 0x65, 0x24, 0x41,
        0x12, 0x6a, 0x00, 0x00,
        0x40, 0x6a, 0x16, 0x00,
        0xff, 0x3e, 0x20, 0x09,
@@ -144,23 +145,23 @@ static unsigned char seqprog[] = {
        0xff, 0xa1, 0x6e, 0x08,
        0x08, 0x6a, 0x18, 0x00,
        0x08, 0x11, 0x22, 0x00,
-       0x08, 0x6a, 0x66, 0x58,
+       0x08, 0x6a, 0x68, 0x58,
        0x80, 0x6a, 0x68, 0x00,
        0x80, 0x36, 0x6c, 0x00,
-       0x00, 0x65, 0x08, 0x5c,
+       0x00, 0x65, 0x1e, 0x5c,
        0xff, 0x3d, 0xc8, 0x08,
-       0xbf, 0x64, 0x5a, 0x79,
-       0x80, 0x64, 0x20, 0x72,
-       0xa0, 0x64, 0x50, 0x72,
-       0xc0, 0x64, 0x48, 0x72,
-       0xe0, 0x64, 0x90, 0x72,
+       0xbf, 0x64, 0x5c, 0x79,
+       0x80, 0x64, 0x24, 0x72,
+       0xa0, 0x64, 0x54, 0x72,
+       0xc0, 0x64, 0x4c, 0x72,
+       0xe0, 0x64, 0x94, 0x72,
        0x01, 0x6a, 0x22, 0x01,
-       0x00, 0x65, 0x22, 0x41,
+       0x00, 0x65, 0x24, 0x41,
        0xf7, 0x11, 0x22, 0x08,
-       0x00, 0x65, 0x42, 0x59,
+       0x00, 0x65, 0x44, 0x59,
        0xff, 0x06, 0xd4, 0x08,
        0xf7, 0x01, 0x02, 0x08,
-       0x09, 0x0c, 0x3c, 0x79,
+       0x09, 0x0c, 0x3e, 0x79,
        0x08, 0x0c, 0x0e, 0x68,
        0x01, 0x6a, 0x22, 0x01,
        0xff, 0x6a, 0x26, 0x09,
@@ -173,25 +174,25 @@ static unsigned char seqprog[] = {
        0x03, 0xa9, 0x18, 0x31,
        0x03, 0xa9, 0x10, 0x30,
        0x08, 0x6a, 0xcc, 0x00,
-       0xa9, 0x6a, 0x1e, 0x5c,
-       0x00, 0x65, 0x7a, 0x41,
+       0xa9, 0x6a, 0x34, 0x5c,
+       0x00, 0x65, 0x7c, 0x41,
        0xa8, 0x6a, 0x6a, 0x00,
        0x79, 0x6a, 0x6a, 0x00,
-       0x40, 0x3d, 0x62, 0x69,
+       0x40, 0x3d, 0x64, 0x69,
        0x04, 0x35, 0x6a, 0x00,
-       0x00, 0x65, 0x78, 0x5b,
+       0x00, 0x65, 0x8e, 0x5b,
        0x80, 0x6a, 0xd4, 0x01,
-       0x10, 0x36, 0x4e, 0x69,
+       0x10, 0x36, 0x50, 0x69,
        0x10, 0x36, 0x6c, 0x00,
        0x07, 0xac, 0x10, 0x31,
        0x03, 0x8c, 0x10, 0x30,
        0x05, 0xa3, 0x70, 0x30,
        0x88, 0x6a, 0xcc, 0x00,
-       0xac, 0x6a, 0x16, 0x5c,
-       0x00, 0x65, 0x10, 0x5c,
+       0xac, 0x6a, 0x2c, 0x5c,
+       0x00, 0x65, 0x26, 0x5c,
        0x38, 0x6a, 0xcc, 0x00,
-       0xa3, 0x6a, 0x1a, 0x5c,
-       0xff, 0x38, 0x8a, 0x69,
+       0xa3, 0x6a, 0x30, 0x5c,
+       0xff, 0x38, 0x8c, 0x69,
        0x80, 0x02, 0x04, 0x00,
        0xe7, 0x35, 0x6a, 0x08,
        0x03, 0x69, 0x18, 0x31,
@@ -199,327 +200,337 @@ static unsigned char seqprog[] = {
        0xff, 0x6a, 0x10, 0x00,
        0xff, 0x6a, 0x12, 0x00,
        0xff, 0x6a, 0x14, 0x00,
-       0x01, 0x38, 0x8e, 0x61,
+       0x01, 0x38, 0x92, 0x61,
        0xbf, 0x35, 0x6a, 0x08,
+       0x02, 0x6a, 0xf8, 0x01,
        0xff, 0x69, 0xca, 0x08,
        0xff, 0x35, 0x26, 0x09,
-       0x04, 0x0b, 0x92, 0x69,
-       0x04, 0x0b, 0x9e, 0x69,
-       0x10, 0x0c, 0x94, 0x79,
-       0x04, 0x0b, 0x9c, 0x69,
+       0x04, 0x0b, 0x96, 0x69,
+       0x04, 0x0b, 0xa2, 0x69,
+       0x10, 0x0c, 0x98, 0x79,
+       0x04, 0x0b, 0xa2, 0x69,
        0xff, 0x6a, 0xca, 0x08,
-       0x00, 0x35, 0x60, 0x5b,
-       0x80, 0x02, 0xf2, 0x69,
-       0xff, 0x65, 0xe2, 0x79,
+       0x00, 0x35, 0x76, 0x5b,
+       0x80, 0x02, 0xf6, 0x69,
+       0xff, 0x65, 0xe6, 0x79,
        0xff, 0x38, 0x70, 0x18,
-       0xff, 0x38, 0xe2, 0x79,
-       0x80, 0xea, 0xbe, 0x61,
+       0xff, 0x38, 0xe6, 0x79,
+       0x80, 0xea, 0xc2, 0x61,
        0xef, 0x38, 0xc8, 0x18,
        0x80, 0x6a, 0xc8, 0x00,
-       0x00, 0x65, 0xb0, 0x49,
+       0x00, 0x65, 0xb4, 0x49,
        0x33, 0x38, 0xc8, 0x28,
        0xff, 0x64, 0xd0, 0x09,
        0x04, 0x39, 0xc0, 0x31,
        0x09, 0x6a, 0xd6, 0x01,
-       0x80, 0xeb, 0xb6, 0x79,
+       0x80, 0xeb, 0xba, 0x79,
        0xf7, 0xeb, 0xd6, 0x09,
-       0x08, 0xeb, 0xba, 0x69,
+       0x08, 0xeb, 0xbe, 0x69,
        0x01, 0x6a, 0xd6, 0x01,
        0x08, 0xe9, 0x10, 0x31,
        0x03, 0x8c, 0x10, 0x30,
        0x88, 0x6a, 0xcc, 0x00,
-       0x39, 0x6a, 0x1c, 0x5c,
+       0x39, 0x6a, 0x32, 0x5c,
        0x08, 0x6a, 0x18, 0x01,
        0xff, 0x6a, 0x1a, 0x09,
        0xff, 0x6a, 0x1c, 0x09,
        0x0d, 0x93, 0x26, 0x01,
-       0x00, 0x65, 0x9a, 0x5c,
-       0x88, 0x6a, 0x8a, 0x5c,
-       0x00, 0x65, 0x10, 0x5c,
+       0x00, 0x65, 0xb0, 0x5c,
+       0x88, 0x6a, 0xa0, 0x5c,
+       0x00, 0x65, 0x26, 0x5c,
        0xff, 0x6a, 0xc8, 0x08,
        0x08, 0x39, 0x72, 0x18,
        0x00, 0x3a, 0x74, 0x20,
-       0x01, 0x0c, 0xda, 0x79,
-       0x10, 0x0c, 0x7a, 0x79,
+       0x01, 0x0c, 0xde, 0x79,
+       0x10, 0x0c, 0x7c, 0x79,
        0xff, 0x35, 0x26, 0x09,
-       0x04, 0x0b, 0xe0, 0x69,
-       0x00, 0x65, 0xfa, 0x59,
+       0x04, 0x0b, 0xe4, 0x69,
+       0x00, 0x65, 0xfe, 0x59,
        0x03, 0x08, 0x52, 0x31,
        0xff, 0x38, 0x50, 0x09,
        0xff, 0x08, 0x52, 0x09,
        0xff, 0x09, 0x54, 0x09,
        0xff, 0x0a, 0x56, 0x09,
        0xff, 0x38, 0x50, 0x09,
-       0x00, 0x65, 0x22, 0x41,
-       0x00, 0x65, 0xfa, 0x59,
+       0x00, 0x65, 0x24, 0x41,
+       0x00, 0x65, 0xfe, 0x59,
        0x7f, 0x02, 0x04, 0x08,
        0xe1, 0x6a, 0x22, 0x01,
-       0x00, 0x65, 0x22, 0x41,
-       0x04, 0x93, 0x10, 0x6a,
+       0x00, 0x65, 0x24, 0x41,
+       0x04, 0x93, 0x14, 0x6a,
        0xdf, 0x93, 0x26, 0x09,
-       0x20, 0x93, 0xfe, 0x69,
+       0x20, 0x93, 0x02, 0x6a,
        0x02, 0x93, 0x26, 0x01,
-       0x01, 0x94, 0x00, 0x7a,
-       0x01, 0x94, 0x00, 0x7a,
-       0x01, 0x94, 0x00, 0x7a,
-       0x01, 0x94, 0x00, 0x7a,
-       0x01, 0x94, 0x00, 0x7a,
-       0x01, 0x94, 0x00, 0x7a,
-       0x10, 0x94, 0x0e, 0x6a,
+       0x01, 0x94, 0x04, 0x7a,
+       0x01, 0x94, 0x04, 0x7a,
+       0x01, 0x94, 0x04, 0x7a,
+       0x01, 0x94, 0x04, 0x7a,
+       0x01, 0x94, 0x04, 0x7a,
+       0x01, 0x94, 0x04, 0x7a,
+       0x10, 0x94, 0x12, 0x6a,
        0xf7, 0x93, 0x26, 0x09,
-       0x08, 0x93, 0x12, 0x6a,
+       0x08, 0x93, 0x16, 0x6a,
        0xdf, 0x93, 0x26, 0x09,
-       0x20, 0x93, 0x16, 0x6a,
+       0x20, 0x93, 0x1a, 0x6a,
        0x03, 0x08, 0x52, 0x31,
        0xff, 0x38, 0x50, 0x09,
        0x12, 0x01, 0x02, 0x00,
        0xff, 0x6a, 0xd4, 0x0c,
-       0x00, 0x65, 0x78, 0x5b,
+       0x00, 0x65, 0x8e, 0x5b,
        0x05, 0xb4, 0x10, 0x31,
        0x02, 0x6a, 0x1a, 0x31,
        0x03, 0x8c, 0x10, 0x30,
        0x88, 0x6a, 0xcc, 0x00,
-       0xb4, 0x6a, 0x1a, 0x5c,
+       0xb4, 0x6a, 0x30, 0x5c,
        0xff, 0x6a, 0x1a, 0x09,
        0xff, 0x6a, 0x1c, 0x09,
-       0x00, 0x65, 0x10, 0x5c,
-       0x3d, 0x6a, 0x60, 0x5b,
+       0x00, 0x65, 0x26, 0x5c,
+       0x3d, 0x6a, 0x76, 0x5b,
        0xac, 0x6a, 0x26, 0x01,
-       0x04, 0x0b, 0x36, 0x6a,
-       0x01, 0x0b, 0x3c, 0x6a,
-       0x10, 0x0c, 0x38, 0x7a,
+       0x04, 0x0b, 0x3a, 0x6a,
+       0x04, 0x0b, 0x40, 0x6a,
+       0x10, 0x0c, 0x3c, 0x7a,
        0xf7, 0x93, 0x26, 0x09,
-       0x08, 0x93, 0x3e, 0x6a,
+       0x08, 0x93, 0x42, 0x6a,
        0xdf, 0x93, 0x26, 0x09,
-       0x20, 0x93, 0x42, 0x6a,
+       0x20, 0x93, 0x46, 0x6a,
        0x12, 0x01, 0x02, 0x00,
-       0x00, 0x65, 0x22, 0x41,
-       0x00, 0x65, 0x78, 0x5b,
+       0x00, 0x65, 0x24, 0x41,
+       0x00, 0x65, 0x8e, 0x5b,
        0xff, 0x06, 0x44, 0x09,
-       0x00, 0x65, 0x22, 0x41,
+       0x00, 0x65, 0x24, 0x41,
        0x10, 0x3d, 0x06, 0x00,
        0xff, 0x34, 0xca, 0x08,
-       0x80, 0x65, 0x74, 0x62,
+       0x80, 0x65, 0x78, 0x62,
        0x0f, 0xa1, 0xca, 0x08,
        0x07, 0xa1, 0xca, 0x08,
        0x40, 0xa0, 0xc8, 0x08,
        0x00, 0x65, 0xca, 0x00,
        0x80, 0x65, 0xca, 0x00,
-       0x80, 0xa0, 0x64, 0x7a,
+       0x80, 0xa0, 0x68, 0x7a,
        0xff, 0x65, 0x0c, 0x08,
-       0x00, 0x65, 0x76, 0x42,
-       0x20, 0xa0, 0x7c, 0x7a,
+       0x00, 0x65, 0x7a, 0x42,
+       0x20, 0xa0, 0x80, 0x7a,
        0xff, 0x65, 0x0c, 0x08,
-       0x00, 0x65, 0x08, 0x5c,
-       0xa0, 0x3d, 0x84, 0x62,
+       0x00, 0x65, 0x1e, 0x5c,
+       0xa0, 0x3d, 0x88, 0x62,
        0x23, 0xa0, 0x0c, 0x08,
-       0x00, 0x65, 0x08, 0x5c,
-       0xa0, 0x3d, 0x84, 0x62,
-       0x00, 0xb9, 0x7c, 0x42,
-       0xff, 0x65, 0x7c, 0x62,
+       0x00, 0x65, 0x1e, 0x5c,
+       0xa0, 0x3d, 0x88, 0x62,
+       0x00, 0xb9, 0x80, 0x42,
+       0xff, 0x65, 0x80, 0x62,
        0xa1, 0x6a, 0x22, 0x01,
        0xff, 0x6a, 0xd4, 0x08,
-       0x10, 0x51, 0x84, 0x72,
+       0x10, 0x51, 0x88, 0x72,
        0x40, 0x6a, 0x18, 0x00,
        0xff, 0x65, 0x0c, 0x08,
-       0x00, 0x65, 0x08, 0x5c,
-       0xa0, 0x3d, 0x4e, 0x72,
+       0x00, 0x65, 0x1e, 0x5c,
+       0xa0, 0x3d, 0x52, 0x72,
        0x40, 0x6a, 0x18, 0x00,
        0xff, 0x34, 0xa6, 0x08,
-       0x80, 0x34, 0x8c, 0x62,
+       0x80, 0x34, 0x90, 0x62,
        0x7f, 0xa0, 0x40, 0x09,
        0x08, 0x6a, 0x68, 0x00,
-       0x00, 0x65, 0x22, 0x41,
-       0x64, 0x6a, 0x50, 0x5b,
-       0x80, 0x64, 0x00, 0x6b,
-       0x04, 0x64, 0xe2, 0x72,
-       0x02, 0x64, 0xe8, 0x72,
-       0x00, 0x6a, 0xaa, 0x72,
-       0x03, 0x64, 0xfc, 0x72,
-       0x01, 0x64, 0xde, 0x72,
-       0x07, 0x64, 0x3e, 0x73,
-       0x08, 0x64, 0xa6, 0x72,
+       0x00, 0x65, 0x24, 0x41,
+       0x64, 0x6a, 0x66, 0x5b,
+       0x80, 0x64, 0x06, 0x6b,
+       0x04, 0x64, 0xe8, 0x72,
+       0x02, 0x64, 0xee, 0x72,
+       0x00, 0x6a, 0xb0, 0x72,
+       0x03, 0x64, 0x02, 0x73,
+       0x01, 0x64, 0xe4, 0x72,
+       0x07, 0x64, 0x44, 0x73,
+       0x08, 0x64, 0xac, 0x72,
+       0x23, 0x64, 0x48, 0x73,
        0x11, 0x6a, 0x22, 0x01,
-       0x07, 0x6a, 0x42, 0x5b,
+       0x07, 0x6a, 0x58, 0x5b,
        0xff, 0x06, 0xd4, 0x08,
-       0x00, 0x65, 0x22, 0x41,
-       0xff, 0xa8, 0xae, 0x6a,
-       0xff, 0xa2, 0xc6, 0x7a,
+       0x00, 0x65, 0x24, 0x41,
+       0xff, 0xa8, 0xb4, 0x6a,
+       0xff, 0xa2, 0xcc, 0x7a,
        0x01, 0x6a, 0x6a, 0x00,
-       0x00, 0xb9, 0x34, 0x5c,
-       0xff, 0xa2, 0xc6, 0x7a,
+       0x00, 0xb9, 0x4a, 0x5c,
+       0xff, 0xa2, 0xcc, 0x7a,
        0x71, 0x6a, 0x22, 0x01,
        0xff, 0x6a, 0xd4, 0x08,
-       0x40, 0x51, 0xc6, 0x62,
+       0x40, 0x51, 0xcc, 0x62,
        0x0d, 0x6a, 0x6a, 0x00,
-       0x00, 0xb9, 0x34, 0x5c,
+       0x00, 0xb9, 0x4a, 0x5c,
        0xff, 0x3e, 0x74, 0x09,
        0xff, 0x90, 0x7c, 0x08,
        0x00, 0x65, 0x50, 0x58,
-       0x00, 0x65, 0x34, 0x41,
-       0x20, 0xa0, 0xce, 0x6a,
+       0x00, 0x65, 0x36, 0x41,
+       0x20, 0xa0, 0xd4, 0x6a,
        0xff, 0x37, 0xc8, 0x08,
-       0x00, 0x6a, 0xde, 0x5b,
-       0xff, 0x6a, 0xf4, 0x5b,
+       0x00, 0x6a, 0xf4, 0x5b,
+       0xff, 0x6a, 0x0a, 0x5c,
        0xff, 0xf8, 0xc8, 0x08,
        0xff, 0x4f, 0xc8, 0x08,
-       0x01, 0x6a, 0xde, 0x5b,
-       0x00, 0xb9, 0xf4, 0x5b,
+       0x01, 0x6a, 0xf4, 0x5b,
+       0x00, 0xb9, 0x0a, 0x5c,
        0x01, 0x4f, 0x9e, 0x18,
        0x02, 0x6a, 0x22, 0x01,
-       0x00, 0x65, 0xa2, 0x5c,
-       0x00, 0x65, 0x34, 0x41,
+       0x00, 0x65, 0xb8, 0x5c,
+       0x00, 0x65, 0x36, 0x41,
        0x41, 0x6a, 0x22, 0x01,
-       0x00, 0x65, 0x22, 0x41,
+       0x00, 0x65, 0x24, 0x41,
        0x04, 0xa0, 0x40, 0x01,
-       0x00, 0x65, 0xba, 0x5c,
-       0x00, 0x65, 0x34, 0x41,
-       0x10, 0x36, 0xa6, 0x7a,
+       0x00, 0x65, 0xd0, 0x5c,
+       0x00, 0x65, 0x36, 0x41,
+       0x10, 0x36, 0xac, 0x7a,
        0x05, 0x38, 0x46, 0x31,
        0x04, 0x14, 0x58, 0x31,
        0x03, 0xa9, 0x60, 0x31,
        0xa3, 0x6a, 0xcc, 0x00,
-       0x38, 0x6a, 0x1a, 0x5c,
+       0x38, 0x6a, 0x30, 0x5c,
        0xac, 0x6a, 0xcc, 0x00,
-       0x14, 0x6a, 0x1c, 0x5c,
-       0xa9, 0x6a, 0x1e, 0x5c,
-       0x00, 0x65, 0xa6, 0x42,
+       0x14, 0x6a, 0x32, 0x5c,
+       0xa9, 0x6a, 0x34, 0x5c,
+       0x00, 0x65, 0xac, 0x42,
        0xef, 0x36, 0x6c, 0x08,
-       0x00, 0x65, 0xa6, 0x42,
+       0x00, 0x65, 0xac, 0x42,
        0x0f, 0x64, 0xc8, 0x08,
        0x07, 0x64, 0xc8, 0x08,
        0x00, 0x37, 0x6e, 0x00,
        0xff, 0x6a, 0xa4, 0x00,
-       0x00, 0x65, 0xae, 0x5b,
-       0xff, 0x51, 0x12, 0x73,
-       0x20, 0x36, 0x1c, 0x7b,
-       0x00, 0x90, 0x9c, 0x5b,
-       0x00, 0x65, 0x1e, 0x43,
+       0x00, 0x65, 0xc4, 0x5b,
+       0xff, 0x51, 0x18, 0x73,
+       0x20, 0x36, 0x22, 0x7b,
+       0x00, 0x90, 0xb2, 0x5b,
+       0x00, 0x65, 0x24, 0x43,
        0xff, 0x06, 0xd4, 0x08,
-       0x00, 0x65, 0x08, 0x5c,
-       0xe0, 0x3d, 0x38, 0x63,
-       0x20, 0x12, 0x38, 0x63,
-       0x51, 0x6a, 0x46, 0x5b,
-       0x00, 0x65, 0x96, 0x5b,
+       0x00, 0x65, 0x1e, 0x5c,
+       0xe0, 0x3d, 0x3e, 0x63,
+       0x20, 0x12, 0x3e, 0x63,
+       0x51, 0x6a, 0x5c, 0x5b,
+       0x00, 0x65, 0xac, 0x5b,
        0xff, 0x37, 0xc8, 0x08,
-       0x00, 0xa1, 0x30, 0x63,
-       0x04, 0xa0, 0x30, 0x7b,
+       0x00, 0xa1, 0x36, 0x63,
+       0x04, 0xa0, 0x36, 0x7b,
        0xfb, 0xa0, 0x40, 0x09,
        0x80, 0x36, 0x6c, 0x00,
-       0x80, 0xa0, 0xa6, 0x7a,
+       0x80, 0xa0, 0xac, 0x7a,
        0x7f, 0xa0, 0x40, 0x09,
-       0xff, 0x6a, 0x42, 0x5b,
-       0x00, 0x65, 0xa6, 0x42,
-       0x04, 0xa0, 0x36, 0x7b,
-       0x00, 0x65, 0xba, 0x5c,
-       0x00, 0x65, 0x38, 0x43,
-       0x00, 0x65, 0xa2, 0x5c,
+       0xff, 0x6a, 0x58, 0x5b,
+       0x00, 0x65, 0xac, 0x42,
+       0x04, 0xa0, 0x3c, 0x7b,
+       0x00, 0x65, 0xd0, 0x5c,
+       0x00, 0x65, 0x3e, 0x43,
+       0x00, 0x65, 0xb8, 0x5c,
        0x31, 0x6a, 0x22, 0x01,
-       0x0c, 0x6a, 0x42, 0x5b,
-       0x00, 0x65, 0xa6, 0x42,
+       0x0c, 0x6a, 0x58, 0x5b,
+       0x00, 0x65, 0xac, 0x42,
        0x61, 0x6a, 0x22, 0x01,
-       0x00, 0x65, 0xa6, 0x42,
+       0x00, 0x65, 0xac, 0x42,
+       0x51, 0x6a, 0x5c, 0x5b,
+       0xff, 0xa8, 0x54, 0x6b,
+       0xff, 0xa9, 0x54, 0x6b,
+       0xff, 0xaa, 0x54, 0x6b,
+       0xff, 0xab, 0x54, 0x6b,
+       0x00, 0x65, 0xac, 0x42,
+       0x51, 0x6a, 0x22, 0x01,
+       0x00, 0x65, 0xac, 0x42,
        0x10, 0x3d, 0x06, 0x00,
        0xff, 0x65, 0x68, 0x0c,
        0xff, 0x06, 0xd4, 0x08,
-       0x01, 0x0c, 0x48, 0x7b,
-       0x04, 0x0c, 0x48, 0x6b,
+       0x01, 0x0c, 0x5e, 0x7b,
+       0x04, 0x0c, 0x60, 0x6b,
        0xe0, 0x03, 0x7a, 0x08,
-       0xe0, 0x3d, 0x5c, 0x63,
+       0xe0, 0x3d, 0x72, 0x63,
        0xff, 0x65, 0xcc, 0x08,
        0xff, 0x12, 0xda, 0x0c,
        0xff, 0x06, 0xd4, 0x0c,
        0xff, 0x65, 0x0c, 0x08,
-       0x02, 0x0b, 0x58, 0x7b,
+       0x02, 0x0b, 0x6e, 0x7b,
        0xff, 0x6a, 0xd4, 0x0c,
        0xd1, 0x6a, 0x22, 0x01,
-       0x00, 0x65, 0x22, 0x41,
+       0x00, 0x65, 0x24, 0x41,
        0xff, 0x65, 0x26, 0x09,
-       0x01, 0x0b, 0x70, 0x6b,
-       0x10, 0x0c, 0x62, 0x7b,
-       0x04, 0x0b, 0x6a, 0x6b,
+       0x01, 0x0b, 0x86, 0x6b,
+       0x10, 0x0c, 0x78, 0x7b,
+       0x04, 0x0b, 0x80, 0x6b,
        0xff, 0x6a, 0xca, 0x08,
-       0x04, 0x93, 0x6e, 0x6b,
-       0x01, 0x94, 0x6c, 0x7b,
-       0x10, 0x94, 0x6e, 0x6b,
+       0x04, 0x93, 0x84, 0x6b,
+       0x01, 0x94, 0x82, 0x7b,
+       0x10, 0x94, 0x84, 0x6b,
        0xc7, 0x93, 0x26, 0x09,
        0xff, 0x99, 0xd4, 0x08,
-       0x38, 0x93, 0x72, 0x6b,
+       0x38, 0x93, 0x88, 0x6b,
        0xff, 0x6a, 0xd4, 0x0c,
-       0x80, 0x36, 0x76, 0x6b,
+       0x80, 0x36, 0x8c, 0x6b,
        0x21, 0x6a, 0x22, 0x05,
        0xff, 0x65, 0x20, 0x09,
-       0xff, 0x51, 0x84, 0x63,
+       0xff, 0x51, 0x9a, 0x63,
        0xff, 0x37, 0xc8, 0x08,
-       0xa1, 0x6a, 0x90, 0x43,
+       0xa1, 0x6a, 0xa6, 0x43,
        0xff, 0x51, 0xc8, 0x08,
-       0xb9, 0x6a, 0x90, 0x43,
+       0xb9, 0x6a, 0xa6, 0x43,
        0xff, 0x90, 0xa4, 0x08,
-       0xff, 0xba, 0x94, 0x73,
+       0xff, 0xba, 0xaa, 0x73,
        0xff, 0xba, 0x20, 0x09,
        0xff, 0x65, 0xca, 0x18,
-       0x00, 0x6c, 0x88, 0x63,
+       0x00, 0x6c, 0x9e, 0x63,
        0xff, 0x90, 0xca, 0x0c,
        0xff, 0x6a, 0xca, 0x04,
-       0x20, 0x36, 0xa8, 0x7b,
-       0x00, 0x90, 0x7c, 0x5b,
-       0xff, 0x65, 0xa8, 0x73,
-       0xff, 0x52, 0xa6, 0x73,
+       0x20, 0x36, 0xbe, 0x7b,
+       0x00, 0x90, 0x92, 0x5b,
+       0xff, 0x65, 0xbe, 0x73,
+       0xff, 0x52, 0xbc, 0x73,
        0xff, 0xba, 0xcc, 0x08,
        0xff, 0x52, 0x20, 0x09,
        0xff, 0x66, 0x74, 0x09,
        0xff, 0x65, 0x20, 0x0d,
        0xff, 0xba, 0x7e, 0x0c,
-       0x00, 0x6a, 0xa8, 0x5c,
+       0x00, 0x6a, 0xbe, 0x5c,
        0x0d, 0x6a, 0x6a, 0x00,
-       0x00, 0x51, 0x34, 0x44,
-       0xff, 0x3f, 0x02, 0x74,
+       0x00, 0x51, 0x4a, 0x44,
+       0xff, 0x3f, 0x18, 0x74,
        0xff, 0x6a, 0xa2, 0x00,
-       0x00, 0x3f, 0x7c, 0x5b,
-       0xff, 0x65, 0x02, 0x74,
+       0x00, 0x3f, 0x92, 0x5b,
+       0xff, 0x65, 0x18, 0x74,
        0x20, 0x36, 0x6c, 0x00,
-       0x20, 0xa0, 0xbc, 0x6b,
+       0x20, 0xa0, 0xd2, 0x6b,
        0xff, 0xb9, 0xa2, 0x0c,
        0xff, 0x6a, 0xa2, 0x04,
        0xff, 0x65, 0xa4, 0x08,
        0xe0, 0x6a, 0xcc, 0x00,
-       0x45, 0x6a, 0x28, 0x5c,
+       0x45, 0x6a, 0x3e, 0x5c,
        0x01, 0x6a, 0xd0, 0x01,
        0x09, 0x6a, 0xd6, 0x01,
-       0x80, 0xeb, 0xc8, 0x7b,
+       0x80, 0xeb, 0xde, 0x7b,
        0x01, 0x6a, 0xd6, 0x01,
        0x01, 0xe9, 0xa4, 0x34,
        0x88, 0x6a, 0xcc, 0x00,
-       0x45, 0x6a, 0x28, 0x5c,
+       0x45, 0x6a, 0x3e, 0x5c,
        0x01, 0x6a, 0x18, 0x01,
        0xff, 0x6a, 0x1a, 0x09,
        0xff, 0x6a, 0x1c, 0x09,
        0x0d, 0x6a, 0x26, 0x01,
-       0x00, 0x65, 0x9a, 0x5c,
+       0x00, 0x65, 0xb0, 0x5c,
        0xff, 0x99, 0xa4, 0x0c,
        0xff, 0x65, 0xa4, 0x08,
        0xe0, 0x6a, 0xcc, 0x00,
-       0x45, 0x6a, 0x28, 0x5c,
+       0x45, 0x6a, 0x3e, 0x5c,
        0x01, 0x6a, 0xd0, 0x01,
        0x01, 0x6a, 0xdc, 0x05,
        0x88, 0x6a, 0xcc, 0x00,
-       0x45, 0x6a, 0x28, 0x5c,
+       0x45, 0x6a, 0x3e, 0x5c,
        0x01, 0x6a, 0x18, 0x01,
        0xff, 0x6a, 0x1a, 0x09,
        0xff, 0x6a, 0x1c, 0x09,
        0x01, 0x6a, 0x26, 0x05,
        0x01, 0x65, 0xd8, 0x31,
        0x09, 0xee, 0xdc, 0x01,
-       0x80, 0xee, 0xf8, 0x7b,
+       0x80, 0xee, 0x0e, 0x7c,
        0xff, 0x6a, 0xdc, 0x0d,
        0xff, 0x65, 0x32, 0x09,
        0x0a, 0x93, 0x26, 0x01,
-       0x00, 0x65, 0x9a, 0x44,
+       0x00, 0x65, 0xb0, 0x44,
        0xff, 0x37, 0xc8, 0x08,
-       0x00, 0x6a, 0xbe, 0x5b,
+       0x00, 0x6a, 0xd4, 0x5b,
        0xff, 0x52, 0xa2, 0x0c,
-       0x01, 0x0c, 0x08, 0x7c,
-       0x04, 0x0c, 0x08, 0x6c,
+       0x01, 0x0c, 0x1e, 0x7c,
+       0x04, 0x0c, 0x1e, 0x6c,
        0xe0, 0x03, 0x06, 0x08,
        0xe0, 0x03, 0x7a, 0x0c,
        0xff, 0x8c, 0x10, 0x08,
@@ -542,29 +553,29 @@ static unsigned char seqprog[] = {
        0x00, 0x6c, 0xda, 0x24,
        0xff, 0x65, 0xc8, 0x08,
        0xe0, 0x6a, 0xcc, 0x00,
-       0x41, 0x6a, 0x24, 0x5c,
+       0x41, 0x6a, 0x3a, 0x5c,
        0xff, 0x90, 0xe2, 0x09,
        0x20, 0x6a, 0xd0, 0x01,
-       0x04, 0x35, 0x46, 0x7c,
+       0x04, 0x35, 0x5c, 0x7c,
        0x1d, 0x6a, 0xdc, 0x01,
-       0xdc, 0xee, 0x42, 0x64,
-       0x00, 0x65, 0x52, 0x44,
+       0xdc, 0xee, 0x58, 0x64,
+       0x00, 0x65, 0x68, 0x44,
        0x01, 0x6a, 0xdc, 0x01,
        0x20, 0xa0, 0xd8, 0x31,
        0x09, 0xee, 0xdc, 0x01,
-       0x80, 0xee, 0x4c, 0x7c,
+       0x80, 0xee, 0x62, 0x7c,
        0x19, 0x6a, 0xdc, 0x01,
-       0xd8, 0xee, 0x50, 0x64,
+       0xd8, 0xee, 0x66, 0x64,
        0xff, 0x6a, 0xdc, 0x09,
-       0x18, 0xee, 0x54, 0x6c,
+       0x18, 0xee, 0x6a, 0x6c,
        0xff, 0x6a, 0xd4, 0x0c,
        0x88, 0x6a, 0xcc, 0x00,
-       0x41, 0x6a, 0x24, 0x5c,
+       0x41, 0x6a, 0x3a, 0x5c,
        0x20, 0x6a, 0x18, 0x01,
        0xff, 0x6a, 0x1a, 0x09,
        0xff, 0x6a, 0x1c, 0x09,
        0xff, 0x35, 0x26, 0x09,
-       0x04, 0x35, 0x7e, 0x6c,
+       0x04, 0x35, 0x94, 0x6c,
        0xa0, 0x6a, 0xca, 0x00,
        0x20, 0x65, 0xc8, 0x18,
        0xff, 0x6c, 0x32, 0x09,
@@ -575,14 +586,14 @@ static unsigned char seqprog[] = {
        0xff, 0x6c, 0x32, 0x09,
        0xff, 0x6c, 0x32, 0x09,
        0xff, 0x6c, 0x32, 0x09,
-       0x00, 0x65, 0x6a, 0x64,
+       0x00, 0x65, 0x80, 0x64,
        0x0a, 0x93, 0x26, 0x01,
-       0x00, 0x65, 0x9a, 0x5c,
-       0x04, 0x35, 0x76, 0x7b,
-       0xa0, 0x6a, 0x8a, 0x5c,
-       0x00, 0x65, 0x8c, 0x5c,
-       0x00, 0x65, 0x8c, 0x5c,
-       0x00, 0x65, 0x8c, 0x44,
+       0x00, 0x65, 0xb0, 0x5c,
+       0x04, 0x35, 0x8c, 0x7b,
+       0xa0, 0x6a, 0xa0, 0x5c,
+       0x00, 0x65, 0xa2, 0x5c,
+       0x00, 0x65, 0xa2, 0x5c,
+       0x00, 0x65, 0xa2, 0x44,
        0xff, 0x65, 0xcc, 0x08,
        0xff, 0x99, 0xda, 0x08,
        0xff, 0x99, 0xda, 0x08,
@@ -591,19 +602,19 @@ static unsigned char seqprog[] = {
        0xff, 0x99, 0xda, 0x08,
        0xff, 0x99, 0xda, 0x08,
        0xff, 0x99, 0xda, 0x0c,
-       0x08, 0x94, 0x9a, 0x7c,
+       0x08, 0x94, 0xb0, 0x7c,
        0xf7, 0x93, 0x26, 0x09,
-       0x08, 0x93, 0x9e, 0x6c,
+       0x08, 0x93, 0xb4, 0x6c,
        0xff, 0x6a, 0xd4, 0x0c,
        0xff, 0x40, 0x74, 0x09,
        0xff, 0x90, 0x80, 0x08,
        0xff, 0x6a, 0x72, 0x05,
-       0xff, 0x40, 0xb6, 0x64,
-       0xff, 0x3f, 0xae, 0x64,
+       0xff, 0x40, 0xcc, 0x64,
+       0xff, 0x3f, 0xc4, 0x64,
        0xff, 0x6a, 0xca, 0x04,
        0xff, 0x3f, 0x20, 0x09,
        0x01, 0x6a, 0x6a, 0x00,
-       0x00, 0xb9, 0x34, 0x5c,
+       0x00, 0xb9, 0x4a, 0x5c,
        0xff, 0xba, 0x7e, 0x0c,
        0xff, 0x40, 0x20, 0x09,
        0xff, 0xba, 0x80, 0x0c,
@@ -744,66 +755,68 @@ struct sequencer_patch {
        { aic7xxx_patch4_func, 40, 4, 1 },
        { aic7xxx_patch8_func, 44, 3, 2 },
        { aic7xxx_patch0_func, 47, 3, 1 },
-       { aic7xxx_patch9_func, 52, 7, 1 },
-       { aic7xxx_patch4_func, 60, 3, 1 },
-       { aic7xxx_patch8_func, 63, 2, 1 },
-       { aic7xxx_patch1_func, 68, 60, 1 },
-       { aic7xxx_patch8_func, 162, 1, 2 },
-       { aic7xxx_patch0_func, 163, 2, 1 },
-       { aic7xxx_patch2_func, 167, 3, 3 },
-       { aic7xxx_patch8_func, 167, 2, 1 },
-       { aic7xxx_patch0_func, 170, 2, 1 },
-       { aic7xxx_patch8_func, 173, 1, 2 },
-       { aic7xxx_patch0_func, 174, 1, 1 },
-       { aic7xxx_patch2_func, 178, 1, 1 },
-       { aic7xxx_patch2_func, 181, 3, 2 },
-       { aic7xxx_patch0_func, 184, 5, 1 },
-       { aic7xxx_patch2_func, 192, 2, 3 },
-       { aic7xxx_patch8_func, 192, 1, 1 },
-       { aic7xxx_patch0_func, 194, 3, 1 },
-       { aic7xxx_patch10_func, 197, 2, 1 },
-       { aic7xxx_patch8_func, 199, 7, 2 },
-       { aic7xxx_patch0_func, 206, 1, 1 },
-       { aic7xxx_patch2_func, 211, 14, 3 },
-       { aic7xxx_patch10_func, 224, 1, 1 },
-       { aic7xxx_patch0_func, 225, 9, 1 },
-       { aic7xxx_patch8_func, 239, 2, 1 },
-       { aic7xxx_patch8_func, 241, 1, 1 },
-       { aic7xxx_patch10_func, 242, 6, 3 },
-       { aic7xxx_patch2_func, 242, 2, 2 },
-       { aic7xxx_patch0_func, 244, 4, 1 },
-       { aic7xxx_patch8_func, 249, 1, 1 },
-       { aic7xxx_patch8_func, 253, 19, 1 },
-       { aic7xxx_patch2_func, 273, 3, 3 },
-       { aic7xxx_patch10_func, 275, 1, 1 },
-       { aic7xxx_patch0_func, 276, 5, 1 },
-       { aic7xxx_patch10_func, 281, 1, 2 },
-       { aic7xxx_patch0_func, 282, 9, 1 },
-       { aic7xxx_patch11_func, 298, 1, 2 },
-       { aic7xxx_patch0_func, 299, 1, 1 },
-       { aic7xxx_patch5_func, 359, 1, 2 },
-       { aic7xxx_patch0_func, 360, 1, 1 },
-       { aic7xxx_patch3_func, 363, 1, 1 },
-       { aic7xxx_patch2_func, 373, 3, 2 },
-       { aic7xxx_patch0_func, 376, 5, 1 },
-       { aic7xxx_patch11_func, 384, 1, 2 },
-       { aic7xxx_patch0_func, 385, 1, 1 },
-       { aic7xxx_patch6_func, 390, 1, 1 },
-       { aic7xxx_patch1_func, 427, 3, 1 },
-       { aic7xxx_patch10_func, 432, 11, 1 },
-       { aic7xxx_patch2_func, 480, 7, 2 },
-       { aic7xxx_patch0_func, 487, 8, 1 },
-       { aic7xxx_patch2_func, 496, 4, 2 },
-       { aic7xxx_patch0_func, 500, 6, 1 },
-       { aic7xxx_patch2_func, 506, 4, 2 },
-       { aic7xxx_patch0_func, 510, 3, 1 },
-       { aic7xxx_patch12_func, 520, 10, 1 },
-       { aic7xxx_patch2_func, 539, 17, 4 },
-       { aic7xxx_patch13_func, 547, 4, 2 },
-       { aic7xxx_patch0_func, 551, 2, 1 },
-       { aic7xxx_patch0_func, 556, 33, 1 },
-       { aic7xxx_patch12_func, 589, 4, 1 },
-       { aic7xxx_patch6_func, 593, 2, 1 },
-       { aic7xxx_patch6_func, 596, 9, 1 },
+       { aic7xxx_patch9_func, 53, 7, 1 },
+       { aic7xxx_patch4_func, 61, 3, 1 },
+       { aic7xxx_patch8_func, 64, 2, 1 },
+       { aic7xxx_patch1_func, 69, 60, 1 },
+       { aic7xxx_patch8_func, 163, 1, 2 },
+       { aic7xxx_patch0_func, 164, 2, 1 },
+       { aic7xxx_patch2_func, 168, 3, 4 },
+       { aic7xxx_patch8_func, 168, 2, 2 },
+       { aic7xxx_patch0_func, 170, 1, 1 },
+       { aic7xxx_patch0_func, 171, 2, 1 },
+       { aic7xxx_patch8_func, 174, 1, 2 },
+       { aic7xxx_patch0_func, 175, 1, 1 },
+       { aic7xxx_patch2_func, 179, 1, 1 },
+       { aic7xxx_patch2_func, 182, 3, 2 },
+       { aic7xxx_patch0_func, 185, 5, 1 },
+       { aic7xxx_patch2_func, 193, 2, 3 },
+       { aic7xxx_patch8_func, 193, 1, 1 },
+       { aic7xxx_patch0_func, 195, 3, 1 },
+       { aic7xxx_patch10_func, 199, 1, 2 },
+       { aic7xxx_patch0_func, 200, 1, 1 },
+       { aic7xxx_patch8_func, 201, 7, 2 },
+       { aic7xxx_patch0_func, 208, 1, 1 },
+       { aic7xxx_patch2_func, 213, 14, 3 },
+       { aic7xxx_patch10_func, 226, 1, 1 },
+       { aic7xxx_patch0_func, 227, 9, 1 },
+       { aic7xxx_patch8_func, 241, 2, 1 },
+       { aic7xxx_patch8_func, 243, 1, 1 },
+       { aic7xxx_patch10_func, 244, 6, 3 },
+       { aic7xxx_patch2_func, 244, 2, 2 },
+       { aic7xxx_patch0_func, 246, 4, 1 },
+       { aic7xxx_patch8_func, 251, 1, 1 },
+       { aic7xxx_patch8_func, 255, 19, 1 },
+       { aic7xxx_patch2_func, 275, 3, 3 },
+       { aic7xxx_patch10_func, 277, 1, 1 },
+       { aic7xxx_patch0_func, 278, 5, 1 },
+       { aic7xxx_patch10_func, 283, 1, 2 },
+       { aic7xxx_patch0_func, 284, 9, 1 },
+       { aic7xxx_patch11_func, 300, 1, 2 },
+       { aic7xxx_patch0_func, 301, 1, 1 },
+       { aic7xxx_patch5_func, 362, 1, 2 },
+       { aic7xxx_patch0_func, 363, 1, 1 },
+       { aic7xxx_patch3_func, 366, 1, 1 },
+       { aic7xxx_patch2_func, 376, 3, 2 },
+       { aic7xxx_patch0_func, 379, 5, 1 },
+       { aic7xxx_patch11_func, 387, 1, 2 },
+       { aic7xxx_patch0_func, 388, 1, 1 },
+       { aic7xxx_patch6_func, 393, 1, 1 },
+       { aic7xxx_patch1_func, 438, 3, 1 },
+       { aic7xxx_patch10_func, 443, 11, 1 },
+       { aic7xxx_patch2_func, 491, 7, 2 },
+       { aic7xxx_patch0_func, 498, 8, 1 },
+       { aic7xxx_patch2_func, 507, 4, 2 },
+       { aic7xxx_patch0_func, 511, 6, 1 },
+       { aic7xxx_patch2_func, 517, 4, 2 },
+       { aic7xxx_patch0_func, 521, 3, 1 },
+       { aic7xxx_patch12_func, 531, 10, 1 },
+       { aic7xxx_patch2_func, 550, 17, 4 },
+       { aic7xxx_patch13_func, 558, 4, 2 },
+       { aic7xxx_patch0_func, 562, 2, 1 },
+       { aic7xxx_patch0_func, 567, 33, 1 },
+       { aic7xxx_patch12_func, 600, 4, 1 },
+       { aic7xxx_patch6_func, 604, 2, 1 },
+       { aic7xxx_patch6_func, 607, 9, 1 },
 
 };
index bc1a4e4a32c5de665ff4b99f161355f94a569a26..c39a0f25f32559dd7fc5e4fd66346c03fb7ce077 100644 (file)
@@ -111,6 +111,11 @@ irq_numok:
        {
                tmport += 0x1f;
                j = inb(tmport);
+               if((j&0x80)==0)
+               {
+                       dev->in_int=0;
+                       return;
+               }
 
                tmpcip = dev->pciport;
                if ((inb(tmpcip) & 0x08) != 0) 
index 393d03f4e38399b2afe9d6724a1123ca973f5d15..b64f34eb7e91cf2596da8e5599885edc1cacac4a 100644 (file)
@@ -484,10 +484,10 @@ extern void scsi_unregister_module(int, void *);
 #ifdef CONFIG_SCSI_PLUTO_MODULE
 #define SD_EXTRA_DEVS 40
 #else
-#define SD_EXTRA_DEVS 4
+#define SD_EXTRA_DEVS 16
 #endif
 #define ST_EXTRA_DEVS 2
-#define SR_EXTRA_DEVS 2
+#define SR_EXTRA_DEVS 4
 #define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS)
 
 #endif
index f68f656e41388ae2775ec4361f6af303f2760ae1..5ccf0c8be8b6dfdb0d7fb6d76bd345bb6d86bb76 100644 (file)
@@ -2,14 +2,14 @@
  *
  *                    Linux MegaRAID device driver
  *
- * Copyright 1999 American Megatrends Inc.
+ * Copyright 1998 American Megatrends Inc.
  *
  *              This program is free software; you can redistribute it and/or
  *              modify it under the terms of the GNU General Public License
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Version : 1.07
+ * Version : 1.04
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
  *    The addtional 32 bit field for 64bit address in the newly defined
  *      mailbox64 structure is set to 0 at this point.
  *
- * Version 1.05
- *    Changed the queing implementation for handling SCBs and completed
- *      commands.
- *    Added spinlocks in the interrupt service routine to enable the dirver
- *      function in the SMP environment.
- *    Fixed the problem of unnecessary aborts in the abort entry point, which
- *      also enables the driver to handle large amount of I/O requests for
- *      long duration of time.
- *
- * Version 1.07
- *    Removed the usage of uaccess.h file for kernel versions less than
- *    2.0.36, as this file is not present in those versions.
- *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
  *     fails to detect the controller as a pci device on the system.
 #define CRLFSTR "\n"
 #define IOCTL_CMD_NEW  0x81
 
-#define MEGARAID_VERSION "v107 (December 22, 1999)"
-
+#define MEGARAID_VERSION "v1.04 (August 16, 1999)"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -159,6 +145,8 @@ MODULE_DESCRIPTION ("AMI MegaRAID driver");
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
@@ -181,9 +169,7 @@ MODULE_DESCRIPTION ("AMI MegaRAID driver");
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#if LINUX_VERSION_CODE > 0x020024
 #include <asm/uaccess.h>
-#endif
 
 #include "sd.h"
 #include "scsi.h"
@@ -223,6 +209,31 @@ typedef struct {
 #define MAX_SERBUF 160
 #define COM_BASE 0x2f8
 
+#define ENQUEUE(obj,type,list,next) \
+{ type **node; long cpuflag; \
+  spin_lock_irqsave(&mega_lock,cpuflag);\
+  for(node=&(list); *node; node=(type **)&(*node)->##next); \
+  (*node) = obj; \
+  (*node)->##next = NULL; \
+  spin_unlock_irqrestore(&mega_lock,cpuflag);\
+}
+
+/* a non-locking version (if we already have the lock) */
+#define ENQUEUE_NL(obj,type,list,next) \
+{ type **node; \
+  for(node=&(list); *node; node=(type **)&(*node)->##next); \
+  (*node) = obj; \
+  (*node)->##next = NULL; \
+}
+
+#define DEQUEUE(obj,type,list,next) \
+{ long cpuflag; \
+  spin_lock_irqsave(&mega_lock,cpuflag);\
+  if ((obj=list) != NULL) {\
+    list = (type *)(list)->##next; \
+  } \
+  spin_unlock_irqrestore(&mega_lock,cpuflag);\
+};
 
 u32 RDINDOOR (mega_host_config * megaCfg)
 {
@@ -254,67 +265,19 @@ static int megaIssueCmd (mega_host_config * megaCfg,
                         u_char * mboxData,
                         mega_scb * scb,
                         int intr);
-static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
                         u32 * buffer, u32 * length);
 
 static int mega_busyWaitMbox(mega_host_config *);
 static void mega_runpendq (mega_host_config *);
-static void mega_rundoneq (mega_host_config *);
+static void mega_rundoneq (void);
 static void mega_cmd_done (mega_host_config *, mega_scb *, int);
 static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
-static inline void mega_freeSgList(mega_host_config *megaCfg);
+static inline void freeSgList(mega_host_config *megaCfg);
 static void mega_Convert8ldTo40ld(  mega_RAIDINQ  *inquiry,
                                     mega_Enquiry3 *enquiry3,
                                     megaRaidProductInfo *productInfo );
 
-
-
-
-#if LINUX_VERSION_CODE > 0x020100
-#  include <asm/spinlock.h>
-#  include <linux/smp.h>
-#  define cpuid smp_processor_id()
-#  if LINUX_VERSION_CODE < 0x020195
-#    define DRIVER_LOCK_T unsigned long cpu_flags = 0;
-#    define DRIVER_LOCK_INIT(p) \
-       spin_lock_init(&p->mega_lock);
-#    define DRIVER_LOCK(p) \
-       if(!p->cpu_lock_count[cpuid]) { \
-         spin_lock_irqsave(&p->mega_lock, cpu_flags); \
-         p->cpu_lock_count[cpuid]++; \
-       } else { \
-         p->cpu_lock_count[cpuid]++; \
-       }
-#    define DRIVER_UNLOCK(p) \
-       if(--p->cpu_lock_count[cpuid] == 0) \
-         spin_unlock_irqrestore(&p->mega_lock, cpu_flags);
-#    define IO_LOCK(p)   spin_lock_irqsave(&io_request_lock,cpu_flags);
-#    define IO_UNLOCK(p) spin_unlock_irqrestore(&io_request_lock,cpu_flags);
-#  else
-#    define DRIVER_LOCK_T
-#    define DRIVER_LOCK_INIT(p)
-#    define DRIVER_LOCK(p)
-#    define DRIVER_UNLOCK(p)
-#    define IO_LOCK_T unsigned long io_flags = 0;
-#    define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
-#    define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
-#  endif
-#else
-#  define cpuid 0
-#  define DRIVER_LOCK_T long cpu_flags;
-#  define DRIVER_LOCK_INIT(p)
-#  define DRIVER_LOCK(p) \
-       save_flags(cpu_flags); \
-       cli();
-#  define DRIVER_UNLOCK(p) \
-       restore_flags(cpu_flags);
-#  define IO_LOCK_T unsigned long io_flags = 0;
-#  define IO_LOCK(p)   DRIVER_LOCK(p)
-#  define IO_UNLOCK(p) DRIVER_UNLOCK(p)
-#  define le32_to_cpu(x) (x)
-#  define cpu_to_le32(x) (x)
-#endif
-
 /* set SERDEBUG to 1 to enable serial debugging */
 #define SERDEBUG 0
 #if SERDEBUG
@@ -334,7 +297,6 @@ static int ser_printk (const char *fmt,...);
 /*  Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
     XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE
     processor id cannot be scanned */
-
 static char *megaraid;
 #if LINUX_VERSION_CODE > 0x20100
 #ifdef MODULE
@@ -352,10 +314,13 @@ static u32 maxCmdTime = 0;
 
 static mega_scb *pLastScb = NULL;
 
+/* Queue of pending/completed SCBs */
+static Scsi_Cmnd *qCompleted = NULL;
 
 #if SERDEBUG
 volatile static spinlock_t serial_lock;
 #endif
+volatile static spinlock_t mega_lock;
 
 struct proc_dir_entry proc_scsi_megaraid =
 {
@@ -421,7 +386,7 @@ static int ser_printk (const char *fmt,...)
 #define TRACE(A)
 #endif
 
-static void callDone (Scsi_Cmnd * SCpnt)
+void callDone (Scsi_Cmnd * SCpnt)
 {
   if (SCpnt->result) {
     TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
@@ -441,66 +406,37 @@ static void callDone (Scsi_Cmnd * SCpnt)
  * Free a SCB structure
  *=======================
  */
-static void mega_freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
+static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
 {
-
-  mega_scb *pScbtmp;
-
-  if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
-    return ;
-  }
+  mega_scb **ppScb;
 
   /* Unlink from pending queue */
-
-  if(pScb == megaCfg->qPendingH) {
-    if(megaCfg->qPendingH == megaCfg->qPendingT ) 
-      megaCfg->qPendingH = megaCfg->qPendingT = NULL;
-    else {
-      megaCfg->qPendingH = megaCfg->qPendingH->next;
-    }
-    megaCfg->qPcnt--;
-  }
-  else {
-    for(pScbtmp=megaCfg->qPendingH; pScbtmp; pScbtmp=pScbtmp->next) {
-      if (pScbtmp->next == pScb) {
-        pScbtmp->next = pScb->next;
-        if(pScb == megaCfg->qPendingT) {
-          megaCfg->qPendingT = pScbtmp;
-        }
-        megaCfg->qPcnt--;
+  for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
+    if (*ppScb == pScb) {
+       *ppScb = pScb->next;
        break;
     }
   }
-  }
 
-  /* Link back into free list */
+  /* Link back into list */
   pScb->state = SCB_FREE;
   pScb->SCpnt = NULL;
 
-  if(megaCfg->qFreeH == (mega_scb *) NULL ) {
-    megaCfg->qFreeH = megaCfg->qFreeT = pScb;
-  }
-  else {
-    megaCfg->qFreeT->next  = pScb;
-    megaCfg->qFreeT = pScb;
-  }
-  megaCfg->qFreeT->next = NULL;
-  megaCfg->qFcnt++;
-
+  pScb->next     = megaCfg->qFree;
+  megaCfg->qFree = pScb;
 }
 
 /*===========================
  * Allocate a SCB structure
  *===========================
  */
-static mega_scb * mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
 {
   mega_scb *pScb;
 
   /* Unlink command from Free List */
-  if ((pScb = megaCfg->qFreeH) != NULL) {
-    megaCfg->qFreeH = pScb->next;
-    megaCfg->qFcnt--;
+  if ((pScb = megaCfg->qFree) != NULL) {
+    megaCfg->qFree = pScb->next;
     
     pScb->isrcount = jiffies;
     pScb->next  = NULL;
@@ -519,72 +455,62 @@ static mega_scb * mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpn
  * Initialize SCB structures
  *================================================
  */
-static int mega_initSCB (mega_host_config * megaCfg)
+static int initSCB (mega_host_config * megaCfg)
 {
   int idx;
 
-  megaCfg->qFreeH = NULL;
-  megaCfg->qFcnt = 0;
-#if DEBUG
-if(megaCfg->max_cmds >= MAX_COMMANDS) {
-printk("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", megaCfg->max_cmds, MAX_COMMANDS);
-}
-#endif
-
+  megaCfg->qFree = NULL;
   for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
     megaCfg->scbList[idx].idx    = idx;
     megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
                                           GFP_ATOMIC | GFP_DMA);
     if (megaCfg->scbList[idx].sgList == NULL) {
       printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
-      mega_freeSgList(megaCfg);
+      freeSgList(megaCfg);
       return -1;
     }
     
     if (idx < MAX_COMMANDS) {
       /* Link to free list */
-      mega_freeSCB(megaCfg, &megaCfg->scbList[idx]);
+      freeSCB(megaCfg, &megaCfg->scbList[idx]);
     }
   }
   return 0;
 }
 
 /* Run through the list of completed requests */
-static void mega_rundoneq (mega_host_config *megaCfg)
+static void mega_rundoneq ()
 {
   Scsi_Cmnd *SCpnt;
 
-  while ((SCpnt = megaCfg->qCompletedH) != NULL) {
-    megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
-    megaCfg->qCcnt--;
+  while (1) {
+    DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    if (SCpnt == NULL)
+      return;
 
-    SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
     /* Callback */
     callDone (SCpnt);
   }
-  megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
 }
 
 /*
* Runs through the list of pending requests
* Assumes that mega_lock spin_lock has been acquired.
- */
+  Runs through the list of pending requests
+  Assumes that mega_lock spin_lock has been acquired.
+*/
 static void mega_runpendq(mega_host_config *megaCfg)
 {
   mega_scb *pScb;
 
   /* Issue any pending commands to the card */
-  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
+  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
     if (pScb->state == SCB_ACTIVE) {
-      if(megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1))
-       return;
+      megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
     }
   }
 }
 
 /* Add command to the list of completed requests */
-static void
-mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
+static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
                           int status)
 {
   int islogical;
@@ -598,6 +524,7 @@ mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
   }
 
   SCpnt = pScb->SCpnt;
+  /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
   pthru = &pScb->pthru;
   mbox = (mega_mailbox *) &pScb->mboxData;
 
@@ -606,7 +533,7 @@ mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
        TRACE(("pScb->idx = ",pScb->idx));
        TRACE(("pScb->state = ",pScb->state));
        TRACE(("pScb->state = ",pScb->state));
-       printk("megaraid:Problem...!\n");
+       printk("Problem...!\n");
        while(1);
   }
 
@@ -661,18 +588,10 @@ else{
   /* not IOCTL_CMD_NEW SCB, freeSCB()*/
   /* For IOCTL_CMD_NEW SCB, delay freeSCB() in megaraid_queue()
    * after copy data back to user space*/
-     mega_freeSCB(megaCfg, pScb);
+     freeSCB(megaCfg, pScb);
 
   /* Add Scsi_Command to end of completed queue */
-    if( megaCfg->qCompletedH == NULL ) {
-      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-    }
-    else {
-      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-      megaCfg->qCompletedT = SCpnt;
-   }
-   megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-   megaCfg->qCcnt++;
+  ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
 }
 
 /*-------------------------------------------------------------------
@@ -712,11 +631,13 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
 
   if ( islogical ) {
        lun = (SCpnt->target * 8) + lun;
+#if 1
         if ( lun > FC_MAX_LOGICAL_DRIVES ){
             SCpnt->result = (DID_BAD_TARGET << 16);
             callDone (SCpnt);
             return NULL;
         }
+#endif
   }
   /*-----------------------------------------------------
    *
@@ -740,7 +661,7 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
     case READ_CAPACITY:
     case INQUIRY:
       /* Allocate a SCB and initialize passthru */
-      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
        SCpnt->result = (DID_ERROR << 16);
        callDone (SCpnt);
        return NULL;
@@ -771,7 +692,7 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
     case READ_10:
     case WRITE_10:
       /* Allocate a SCB and initialize mailbox */
-      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
        SCpnt->result = (DID_ERROR << 16);
        callDone (SCpnt);
        return NULL;
@@ -807,7 +728,7 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
       }
 
       /* Calculate Scatter-Gather info */
-      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
+      mbox->numsgelements = build_sglist (megaCfg, pScb,
                                          (u32 *) & mbox->xferaddr,
                                          (u32 *) & seg);
 
@@ -826,7 +747,7 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
    *-----------------------------------------------------*/
   else {
     /* Allocate a SCB and initialize passthru */
-    if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+    if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
       SCpnt->result = (DID_ERROR << 16);
       callDone (SCpnt);
       return NULL;
@@ -847,7 +768,7 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
     pthru->cdblen = SCpnt->cmd_len;
     memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
-    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
+    pthru->numsgelements = build_sglist (megaCfg, pScb,
                                         (u32 *) & pthru->dataxferaddr,
                                         (u32 *) & pthru->dataxferlen);
 
@@ -874,12 +795,20 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
   unsigned char *data = (unsigned char *)SCpnt->request_buffer;
   int i;
 
-  if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+  if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
     SCpnt->result = (DID_ERROR << 16);
     callDone (SCpnt);
     return NULL;
   }
 
+#if 0
+  printk("\nBUF: ");
+  for (i=0;i<18;i++) {
+     printk(" %x",data[i]);
+  }
+  printk("......\n");
+#endif
+
   mboxdata = (u8 *) & pScb->mboxData;
   mbox = (mega_ioctl_mbox *) & pScb->mboxData;
   mailbox = (mega_mailbox *) & pScb->mboxData;
@@ -902,7 +831,7 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
     mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
     mailbox->xferaddr = virt_to_bus (pthru);
 
-    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
+    pthru->numsgelements = build_sglist (megaCfg, pScb,
                                         (u32 *) & pthru->dataxferaddr,
                                         (u32 *) & pthru->dataxferlen);
 
@@ -914,14 +843,6 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
   }
   /* else normal (nonpassthru) command */
 
-#if LINUX_VERSION_CODE > 0x020024
-/*
- * usage of the function copy from user is used in case of data more than
- * 4KB.  This is used only with adapters which supports more than 8 logical
- * drives.  This feature is disabled on kernels earlier or same as 2.0.36
- * as the uaccess.h file is not available with those kernels.
- */
-
   if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) { 
             /* use external data area for large xfers  */
      /* If cmnd[0] is set to IOCTL_CMD_NEW then *
@@ -947,7 +868,6 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
       copy_from_user(kern_area,user_area,xfer_size);
       pScb->kern_area = kern_area;
   }
-#endif
 
   mbox->cmd = data[0];
   mbox->channel = data[1];
@@ -970,7 +890,7 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
   } 
   else {
 
-      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
+      mbox->numsgelements = build_sglist (megaCfg, pScb,
                                      (u32 *) & mbox->xferaddr,
                                      (u32 *) & seg);
 
@@ -998,36 +918,32 @@ static void showMbox(mega_scb *pScb)
 }
 #endif
 
-#if DEBUG
-static unsigned int cum_time = 0;
-static unsigned int cum_time_cnt = 0;
-#endif
-
 /*--------------------------------------------------------------------
  * Interrupt service routine
  *--------------------------------------------------------------------*/
 static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
-#if LINUX_VERSION_CODE >= 0x20100
-  IO_LOCK_T
-#endif
   mega_host_config    *megaCfg;
   u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
-  u32 dword=0;
+  u32 dword;
   mega_mailbox *mbox;
   mega_scb *pScb;
-  u_char qCnt, qStatus;
-  u_char            completed[MAX_FIRMWARE_STATUS];
-  Scsi_Cmnd *SCpnt;
+  long flags;
+  int qCnt, qStatus;
 
   megaCfg = (mega_host_config *) devp;
   mbox = (mega_mailbox *)tmpBox;
 
-  if (megaCfg->host->irq == irq) {
+#if LINUX_VERSION_CODE >= 0x20100
+  spin_lock_irqsave (&io_request_lock, flags);
+#endif
+
+  while (megaCfg->host->irq == irq) {
+
+    spin_lock_irqsave (&mega_lock, flags);
 
     if (megaCfg->flag & IN_ISR) {
       TRACE (("ISR called reentrantly!!\n"));
-      printk ("ISR called reentrantly!!\n");
     }
 
     megaCfg->flag |= IN_ISR;
@@ -1036,67 +952,48 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
        printk(KERN_WARNING "Error: mailbox busy in isr!\n");
     }
 
+
     /* Check if a valid interrupt is pending */
     if (megaCfg->flag & BOARD_QUARTZ) {
       dword = RDOUTDOOR (megaCfg);
       if (dword != 0x10001234) {
        /* Spurious interrupt */
        megaCfg->flag &= ~IN_ISR;
-       return;
+       spin_unlock_irqrestore (&mega_lock, flags);
+       break;
       }
+      WROUTDOOR (megaCfg, dword);
+
+      /* Copy to temp location */
+      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+
+      /* Acknowledge interrupt */
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+      while (RDINDOOR (megaCfg) & 0x02);
     }
     else {
       byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
       if ((byte & VALID_INTR_BYTE) == 0) {
        /* Spurious interrupt */
        megaCfg->flag &= ~IN_ISR;
-       return;
+       spin_unlock_irqrestore (&mega_lock, flags);
+       break;
       }
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
-    }
 
-    for(idx=0;idx<MAX_FIRMWARE_STATUS;idx++ ) completed[idx] = 0;
+      /* Copy to temp location */
+      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
 
-#if LINUX_VERSION_CODE >= 0x20100
-    IO_LOCK;
-#endif
-
-    qCnt = 0xff;
-    while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) 
-      ;
-
-    qStatus = 0xff;
-    while ((qStatus = megaCfg->mbox->status) == 0xFF)
-      ;
-
-    /* Get list of completed requests */
-    for (idx = 0; idx<qCnt; idx++) {
-      while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {
-       printk("p");
-      }
-      completed[idx] = sIdx;
-      sIdx = 0xFF;
-    }
-
-    if (megaCfg->flag & BOARD_QUARTZ) {
-      WROUTDOOR (megaCfg, dword);
       /* Acknowledge interrupt */
-      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
-      while (RDINDOOR (megaCfg) & 0x02);
-    }
-    else {
       CLEAR_INTR (megaCfg->host->io_port);
     }
 
-#if DEBUG
-    if(qCnt >= MAX_FIRMWARE_STATUS) {
-      printk("megaraid_isr: cmplt=%d ", qCnt);
-    }
-#endif
+    qCnt = mbox->numstatus;
+    qStatus = mbox->status;
 
     for (idx = 0; idx < qCnt; idx++) {
-      sIdx = completed[idx];
-      if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
+      sIdx = mbox->completed[idx];
+      if (sIdx > 0) {
        pScb = &megaCfg->scbList[sIdx - 1];
 
        /* ASSERT(pScb->state == SCB_ISSUED); */
@@ -1104,30 +1001,12 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 #if DEBUG
        if (((jiffies) - pScb->isrcount) > maxCmdTime) {
          maxCmdTime = (jiffies) - pScb->isrcount;
-         printk("megaraid_isr : cmd time = %u\n", maxCmdTime);
+         printk("cmd time = %u\n", maxCmdTime);
        }
 #endif
-/*
- * Assuming that the scsi command, for which an abort request was received
- * earlier has completed.
- */
+
        if (pScb->state == SCB_ABORTED) {
-          SCpnt = pScb->SCpnt;
-       }
-       if (pScb->state == SCB_RESET) {
-          SCpnt = pScb->SCpnt;
-         mega_freeSCB (megaCfg, pScb);
-         SCpnt->result = (DID_RESET << 16) ;
-          if( megaCfg->qCompletedH == NULL ) {
-            megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-          }
-          else {
-            megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-            megaCfg->qCompletedT = SCpnt;
-          }
-          megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-          megaCfg->qCcnt++;
-          continue;
+         printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
        }
 
         if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW) 
@@ -1138,23 +1017,24 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
        mega_cmd_done(megaCfg, pScb, qStatus);
 
       }
-      else {
-        printk("megaraid: wrong cmd id completed from firmware:id=%x\n",sIdx);
-       for(;;);
-      }
-    }
 
-    mega_rundoneq(megaCfg);
+    }
+    spin_unlock_irqrestore (&mega_lock, flags);
 
     megaCfg->flag &= ~IN_ISR;
+
+    mega_rundoneq();
+
     /* Loop through any pending requests */
+    spin_lock_irqsave(&mega_lock, flags);
     mega_runpendq(megaCfg);
-#if LINUX_VERSION_CODE >= 0x20100
-    IO_UNLOCK;
-#endif
+    spin_unlock_irqrestore(&mega_lock,flags);
 
   }
 
+#if LINUX_VERSION_CODE >= 0x20100
+  spin_unlock_irqrestore (&io_request_lock, flags);
+#endif
 }
 
 /*==================================================*/
@@ -1198,6 +1078,7 @@ static int megaIssueCmd (mega_host_config * megaCfg,
   mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
   u_char byte;
   u32 cmdDone;
+  Scsi_Cmnd *SCpnt;
   u32 phys_mbox;
   u8 retval=-1;
 
@@ -1206,12 +1087,18 @@ static int megaIssueCmd (mega_host_config * megaCfg,
 
   phys_mbox = virt_to_bus (megaCfg->mbox);
 
+#if 0
+  if (intr && mbox->busy) {
+    return 0;
+  }
+#endif
+
 #if DEBUG
   showMbox(pScb);
 #endif
 
   /* Wait until mailbox is free */
-  if (mega_busyWaitMbox (megaCfg)) {
+  while (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox......!!\n");
     udelay(1000);
 
@@ -1221,10 +1108,14 @@ static int megaIssueCmd (mega_host_config * megaCfg,
     
     /* Abort command */
     if (pScb == NULL) {
-       TRACE(("NULL pScb in megaIssue\n"));
        printk("NULL pScb in megaIssue\n");
+       TRACE(("NULL pScb in megaIssue\n"));
     }
-    mega_cmd_done (megaCfg, pScb, 0x08);
+    SCpnt = pScb->SCpnt;
+    freeSCB(megaCfg, pScb);
+
+    SCpnt->result = (DID_ABORT << 16);
+    callDone(SCpnt);
     return -1;
   }
 
@@ -1263,6 +1154,7 @@ static int megaIssueCmd (mega_host_config * megaCfg,
 
       if (pScb) {
        mega_cmd_done (megaCfg, pScb, mbox->status);
+       mega_rundoneq ();
       }
 
       WRINDOOR (megaCfg, phys_mbox | 0x2);
@@ -1276,25 +1168,26 @@ static int megaIssueCmd (mega_host_config * megaCfg,
       while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
 
+
       ENABLE_INTR (megaCfg->host->io_port);
       CLEAR_INTR (megaCfg->host->io_port);
 
       if (pScb) {
        mega_cmd_done (megaCfg, pScb, mbox->status);
+       mega_rundoneq ();
       }
       else {
        TRACE (("Error: NULL pScb!\n"));
       }
+
     }
     enable_irq(megaCfg->host->irq);
     retval=mbox->status;
   }
-#if DEBUG
   while (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox on exit......!\n");
     udelay(1000);
   }
-#endif
 
   return retval;
 }
@@ -1302,7 +1195,7 @@ static int megaIssueCmd (mega_host_config * megaCfg,
 /*-------------------------------------------------------------------
  * Copies data to SGLIST
  *-------------------------------------------------------------------*/
-static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
              u32 * buffer, u32 * length)
 {
   struct scatterlist *sgList;
@@ -1361,7 +1254,9 @@ static int mega_register_mailbox (mega_host_config * megaCfg, u32 paddr)
   paddr = (paddr + 4 + 16) & 0xfffffff0;
 
   /* Register mailbox area with the firmware */
-  if (!(megaCfg->flag & BOARD_QUARTZ)) {
+  if (megaCfg->flag & BOARD_QUARTZ) {
+  }
+  else {
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
@@ -1419,6 +1314,8 @@ static int mega_i_query_adapter (mega_host_config * megaCfg)
   u32 paddr;
   u8 retval;
 
+  spin_lock_init (&mega_lock);
+
   /* Initialize adapter inquiry mailbox*/
   paddr = virt_to_bus (megaCfg->mega_buffer);
   mbox = (mega_mailbox *) mboxData;
@@ -1478,17 +1375,28 @@ static int mega_i_query_adapter (mega_host_config * megaCfg)
     /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/ 
   megaCfg->host->max_lun =              /* max lun */
     (megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; 
-  megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
 
   megaCfg->numldrv = enquiry3Pnt->numLDrv;
   megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
-  if(megaCfg->max_cmds > MAX_COMMANDS) megaCfg->max_cmds = MAX_COMMANDS - 1;
 
-  megaCfg->host->can_queue   = megaCfg->max_cmds;
+#if 0 
+  int i;
+  printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
+  for (i = 0; i < megaCfg->numldrv; i++) {
+    printk ("%d: size: %d prop: %x state: %x\n", i,
+           enquiry3Pnt->lDrvSize[i],
+           enquiry3Pnt->lDrvProp[i],
+           enquiry3Pnt->lDrvState[i]);
+  }
 
-  if (megaCfg->host->can_queue >= MAX_COMMANDS) {
-    megaCfg->host->can_queue = MAX_COMMANDS-1;
+  printk (KERN_DEBUG "---- Physical drive info ----\n");
+  for (i = 0; i < FC_MAX_PHYSICAL_DEVICES; i++) {
+    if (i && !(i % 8))
+      printk ("\n");
+    printk ("%d: %x   ", i, enquiry3Pnt->pDrvState[i]);
   }
+  printk ("\n");
+#endif
 
 #ifdef HP                      /* use HP firmware and bios version encoding */
   sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
@@ -1535,7 +1443,7 @@ int megaraid_proc_info (char *buffer, char **start, off_t offset,
   return 0;
 }
 
-int mega_findCard (Scsi_Host_Template * pHostTmpl,
+int findCard (Scsi_Host_Template * pHostTmpl,
          u16 pciVendor, u16 pciDev,
          long flag)
 {
@@ -1548,6 +1456,10 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl,
 
 #if LINUX_VERSION_CODE < 0x20100
   while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
+
+#if 0
+  } /* keep auto-indenters happy */
+#endif
 #else
   
   struct pci_dev *pdev = pci_devices;
@@ -1561,7 +1473,7 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl,
       pcibios_read_config_word (pciBus, pciDevFun,
                                PCI_CONF_AMISIG,
                                &magic);
-      if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471) ){
+      if (magic != AMI_SIGNATURE) {
         pciIdx++;
        continue;               /* not an AMI board */
       }
@@ -1606,15 +1518,8 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl,
            host->host_no, (u_int) megaBase, megaIrq);
 
     /* Copy resource info into structure */
-    megaCfg->qCompletedH = NULL;
-    megaCfg->qCompletedT = NULL;
-    megaCfg->qPendingH = NULL;
-    megaCfg->qPendingT = NULL;
-    megaCfg->qFreeH    = NULL;
-    megaCfg->qFreeT    = NULL;
-    megaCfg->qFcnt = 0;
-    megaCfg->qPcnt = 0;
-    megaCfg->qCcnt = 0;
+    megaCfg->qPending = NULL;
+    megaCfg->qFree    = NULL;
     megaCfg->flag = flag;
     megaCfg->host = host;
     megaCfg->base = megaBase;
@@ -1646,7 +1551,7 @@ int mega_findCard (Scsi_Host_Template * pHostTmpl,
     mega_i_query_adapter (megaCfg);
     
     /* Initialize SCBs */
-    if (mega_initSCB (megaCfg)) {
+    if (initSCB (megaCfg)) {
       scsi_unregister (host);
       continue;
     }
@@ -1684,9 +1589,9 @@ int megaraid_detect (Scsi_Host_Template * pHostTmpl)
 
   printk ("megaraid: " MEGARAID_VERSION CRLFSTR);
 
-  count += mega_findCard (pHostTmpl, 0x101E, 0x9010, 0);
-  count += mega_findCard (pHostTmpl, 0x101E, 0x9060, 0);
-  count += mega_findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+  count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
+  count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
+  count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
 
   return count;
 }
@@ -1721,13 +1626,13 @@ int megaraid_release (struct Scsi_Host *pSHost)
     release_region (megaCfg->host->io_port, 16);
   }
 
-  mega_freeSgList(megaCfg);
+  freeSgList(megaCfg);
   scsi_unregister (pSHost);
 
   return 0;
 }
 
-static inline void mega_freeSgList(mega_host_config *megaCfg)
+static inline void freeSgList(mega_host_config *megaCfg)
 {
   int i;
 
@@ -1773,12 +1678,13 @@ const char * megaraid_info (struct Scsi_Host *pSHost)
  *-----------------------------------------------------------------*/
 int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
 {
-  DRIVER_LOCK_T
   mega_host_config *megaCfg;
   mega_scb *pScb;
+  long flags;
+
+  spin_lock_irqsave(&mega_lock,flags);
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
-  DRIVER_LOCK(megaCfg);
 
   if (!(megaCfg->flag & (1L << SCpnt->channel))) {
     if (SCpnt->channel < SCpnt->host->max_channel)
@@ -1796,56 +1702,33 @@ int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
   /* If driver in abort or reset.. cancel this command */
   if (megaCfg->flag & IN_ABORT) {
     SCpnt->result = (DID_ABORT << 16);
-    /* Add Scsi_Command to end of completed queue */
-    if( megaCfg->qCompletedH == NULL ) {
-      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-    }
-    else {
-      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-      megaCfg->qCompletedT = SCpnt;
-    }
-    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-    megaCfg->qCcnt++;
+    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
 
-    DRIVER_UNLOCK(megaCfg);
+    spin_unlock_irqrestore(&mega_lock,flags);
     return 0;
   }
   else if (megaCfg->flag & IN_RESET) {
     SCpnt->result = (DID_RESET << 16);
-    /* Add Scsi_Command to end of completed queue */
-    if( megaCfg->qCompletedH == NULL ) {
-      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-    }
-    else {
-      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-      megaCfg->qCompletedT = SCpnt;
-    }
-    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-    megaCfg->qCcnt++;
+    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
 
-    DRIVER_UNLOCK(megaCfg);
+    spin_unlock_irqrestore(&mega_lock,flags);
     return 0;
   }
 
-  megaCfg->flag |= IN_QUEUE;
   /* Allocate and build a SCB request */
   if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
               /*build SCpnt for IOCTL_CMD_NEW cmd in mega_ioctl()*/
     /* Add SCB to the head of the pending queue */
-    /* Add SCB to the head of the pending queue */
-    if( megaCfg->qPendingH == NULL ) {
-      megaCfg->qPendingH = megaCfg->qPendingT = pScb;
+    ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
+
+    /* Issue any pending command to the card if not in ISR */
+    if (!(megaCfg->flag & IN_ISR)) {
+      mega_runpendq(megaCfg);
     }
     else {
-      megaCfg->qPendingT->next = pScb;
-      megaCfg->qPendingT = pScb;
+      printk("IRQ pend...\n");
     }
-    megaCfg->qPendingT->next = NULL;
-    megaCfg->qPcnt++;
 
-      mega_runpendq(megaCfg);
-
-#if LINUX_VERSION_CODE > 0x020024
     if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
     {  /* user data from external user buffer */
           char *user_area;
@@ -1861,13 +1744,12 @@ int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
 
           kfree(pScb->kern_area);
 
-          mega_freeSCB(megaCfg, pScb);
+          freeSCB(megaCfg, pScb);
     }
-#endif
+
   }
 
-  megaCfg->flag &= ~IN_QUEUE;
-  DRIVER_UNLOCK(megaCfg);
+  spin_unlock_irqrestore(&mega_lock,flags);
 
   return 0;
 }
@@ -1905,92 +1787,78 @@ int megaraid_command (Scsi_Cmnd * SCpnt)
 /*---------------------------------------------------------------------
  * Abort a previous SCSI request
  *---------------------------------------------------------------------*/
-int
-megaraid_abort (Scsi_Cmnd * SCpnt)
+int megaraid_abort (Scsi_Cmnd * SCpnt)
 {
   mega_host_config *megaCfg;
-  int   rc; //, idx;
+  int   rc, idx;
+  long  flags;
   mega_scb *pScb;
 
-  rc = SCSI_ABORT_NOT_RUNNING;
+  rc = SCSI_ABORT_SUCCESS;
+
+  spin_lock_irqsave (&mega_lock, flags);
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_ABORT;
 
-  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
+  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
     if (pScb->SCpnt == SCpnt) {
       /* Found an aborting command */
 #if DEBUG
       showMbox(pScb);
 #endif
 
-/*
- * If the command is queued to be issued to the firmware, abort the scsi cmd,
- * If the command is already aborted in a previous call to the _abort entry
- *  point, return SCSI_ABORT_SNOOZE, suggesting a reset.
- * If the command is issued to the firmware, which might complete after
- *  some time, we will mark the scb as aborted, and return to the mid layer, 
- *  that abort could not be done.
- *  In the ISR, when this command actually completes, we will perform a normal
- *  completion.
- *
- * Oct 27, 1999
- */
+      printk("Abort: %d %u\n", 
+            SCpnt->timeout_per_command,
+            (uint)((jiffies) - pScb->isrcount));
 
       switch(pScb->state) {
       case SCB_ABORTED: /* Already aborted */
        rc = SCSI_ABORT_SNOOZE;
        break;
       case SCB_ISSUED: /* Waiting on ISR result */
-       rc = SCSI_ABORT_NOT_RUNNING;
+       rc = SCSI_ABORT_PENDING;
        pScb->state = SCB_ABORTED;
        break;
-      case SCB_ACTIVE: /* still on the pending queue */
-       mega_freeSCB (megaCfg, pScb);
-       SCpnt->result = (DID_ABORT << 16) ;
-        if( megaCfg->qCompletedH == NULL ) {
-          megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-        }
-        else {
-          megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-          megaCfg->qCompletedT = SCpnt;
-        }
-        megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-        megaCfg->qCcnt++;
-       rc = SCSI_ABORT_SUCCESS;
-        break;
-      default:
-        printk("megaraid_abort: unknown command state!!\n");
-        rc = SCSI_ABORT_NOT_RUNNING;
-       break;
       }
-      break;
     }
   }
 
-  megaCfg->flag &= ~IN_ABORT;
-
+#if 0
+  TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
+         SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+         SCpnt->lun));
+  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+    if (pScb->SCpnt == SCpnt) { 
+      ser_printk("** %d<%x>  %c\n", pScb->SCpnt->pid, pScb->idx+1,
+                pScb->state == SCB_ACTIVE ? 'A' : 'I');
 #if DEBUG
-if(megaCfg->flag & IN_QUEUE)  printk("ma:flag is in queue\n");
-if(megaCfg->qCompletedH == NULL) printk("ma:qchead == null\n");
+      showMbox(pScb);
 #endif
+    }
+  }
+#endif
+
+  /*
+   * Walk list of SCBs for any that are still outstanding
+   */
+  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
+    if (megaCfg->scbList[idx].state != SCB_FREE) {
+      if (megaCfg->scbList[idx].SCpnt == SCpnt) {
+       freeSCB (megaCfg, &megaCfg->scbList[idx]);
+
+       SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
+       ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+      }
+    }
+  }
   
-/*
- * This is required here to complete any completed requests to be communicated
- * over to the mid layer.
- * Calling just mega_rundoneq() did not work.
- */
-if(megaCfg->qCompletedH) {
-  SCpnt = megaCfg->qCompletedH;
-  megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
-  megaCfg->qCcnt--;
-
-  SCpnt->host_scribble = (unsigned char *) NULL ;
-  /* Callback */
-  callDone (SCpnt);
-}
-  mega_rundoneq(megaCfg);
+  megaCfg->flag &= ~IN_ABORT;
+
+  spin_unlock_irqrestore (&mega_lock, flags);
+
+  mega_rundoneq();
 
   return rc;
 }
@@ -2002,18 +1870,14 @@ int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags)
 {
   mega_host_config *megaCfg;
   int idx;
-  int rc;
-  mega_scb *pScb;
+  long flags;
+
+  spin_lock_irqsave (&mega_lock, flags);
 
-  rc = SCSI_RESET_NOT_RUNNING;
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_RESET;
 
-  printk ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
-       SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
-         SCpnt->lun, rstflags);
-
   TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
        SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
          SCpnt->lun));
@@ -2024,18 +1888,20 @@ int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags)
   for (idx = 0; idx < megaCfg->max_cmds; idx++) {
     if (megaCfg->scbList[idx].state != SCB_FREE) {
       SCpnt = megaCfg->scbList[idx].SCpnt;
-      pScb = &megaCfg->scbList[idx];
       if (SCpnt != NULL) {
-        pScb->state = SCB_RESET;
-        break;
+       freeSCB (megaCfg, &megaCfg->scbList[idx]);
+       SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+       ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
       }
     }
   }
 
   megaCfg->flag &= ~IN_RESET;
 
-  mega_rundoneq(megaCfg);
-  return rc;
+  spin_unlock_irqrestore (&mega_lock, flags);
+
+  mega_rundoneq();
+  return SCSI_RESET_PUNT;
 }
 
 /*-------------------------------------------------------------
@@ -2081,3 +1947,4 @@ Scsi_Host_Template driver_template = MEGARAID;
 
 #include "scsi_module.c"
 #endif
+
index 5fd1744d8c9fe67be0a40761e748b8b9d4750909..83fe02785b4719e92cd2f4d7f051ac69c4bb27ef 100644 (file)
@@ -8,7 +8,6 @@
 #define IN_ISR                  0x80000000L
 #define IN_ABORT                0x40000000L
 #define IN_RESET                0x20000000L
-#define IN_QUEUE                0x10000000L
 #define BOARD_QUARTZ            0x08000000L
 #define BOARD_40LD              0x04000000L
 
 
 #define MEGA_CMD_TIMEOUT        10
 
-/* Feel free to fiddle with these.. max values are:
-   SGLIST     0..26
-   COMMANDS   0..253
-   CMDPERLUN  0..63
-*/
-#define MAX_SGLIST              0x1A
-#define MAX_COMMANDS            127
+#define MAX_SGLIST              17
+#define MAX_COMMANDS            250
 #define MAX_CMD_PER_LUN         63
-#define MAX_FIRMWARE_STATUS     46
 
 #define MAX_LOGICAL_DRIVES      8
 #define MAX_CHANNEL             5
 #define PCI_CONF_IRQ_OFFSET        0x3c
 #define PCI_CONF_AMISIG            0xa0
 #define AMI_SIGNATURE              0x3344
-#define AMI_SIGNATURE_471          0xCCCC
 
 #if LINUX_VERSION_CODE < 0x20100
 #define MEGARAID \
@@ -513,7 +505,7 @@ typedef struct mega_passthru {
     u32 dataxferlen;
 } mega_passthru;
 
-struct _mega_mailbox {
+typedef struct _mega_mailbox {
     /* 0x0 */ u8 cmd;
     /* 0x1 */ u8 cmdid;
     /* 0x2 */ u16 numsectors;
@@ -528,9 +520,8 @@ struct _mega_mailbox {
     /* 0x12 */ u8 completed[46];
     u8 mraid_poll;
     u8 mraid_ack;
-    u8 pad[16]; /* for alignment purposes */
-}__attribute__((packed));
-typedef struct _mega_mailbox mega_mailbox;
+    u8 pad[16];
+} mega_mailbox;
 
 typedef struct {
     u32 xferSegment;      /* for 64-bit controllers */
@@ -584,16 +575,8 @@ typedef struct _mega_host_config {
     u32 flag;
     u32 base;
  
-    mega_scb *qFreeH;
-    mega_scb *qFreeT;
-    mega_scb *qPendingH;
-    mega_scb *qPendingT;
-    
-    Scsi_Cmnd *qCompletedH;
-    Scsi_Cmnd *qCompletedT;
-    u32 qFcnt;
-    u32 qPcnt;
-    u32 qCcnt;
+    mega_scb *qFree;
+    mega_scb *qPending;
 
     u32 nReads[FC_MAX_LOGICAL_DRIVES];
     u32 nWrites[FC_MAX_LOGICAL_DRIVES];
index 731b1853386b3ebe34264b1531031fabfbb3db84..1e0ae9c0dd1ec99d3489b71f79fecbc2d36aad49 100644 (file)
@@ -3800,6 +3800,32 @@ int ixj_ioctl(struct inode *inode, struct file *file_p,
        case PHONE_CPT_STOP:
                ixj_cpt_stop(board);
                break;
+       case PHONE_QUERY_CODEC:
+       {
+               struct phone_codec_data pd;
+               int val;
+               int proto_size[] = {
+                       -1, 
+                       12, 10, 16, 9, 8, 48, 5,
+                       40, 40, 80, 40, 40
+               };
+               if(copy_from_user(&pd, (void *)arg, sizeof(pd)))
+                       return -EFAULT;
+               if(pd.type<1 || pd.type>12)
+                       return -EPROTONOSUPPORT;
+               if(pd.type<G729)
+                       val=proto_size[pd.type];
+               else switch(j->baseframe.low)
+               {
+                       case 0xA0:val=2*proto_size[pd.type];break;
+                       case 0x50:val=proto_size[pd.type];break;
+                       default:val=proto_size[pd.type]*3;break;
+               }
+               pd.buf_min=pd.buf_max=pd.buf_opt=val;
+               if(copy_to_user((void *)arg, &pd, sizeof(pd)))
+                       return -EFAULT;
+               return 0;
+       }
        case IXJCTL_DSP_IDLE:
                idle(board);
                break;
@@ -3840,6 +3866,7 @@ int ixj_ioctl(struct inode *inode, struct file *file_p,
                ixj_daa_cr4(board, arg | 0x02);
                break;
        case IXJCTL_PSTN_LINETEST:
+       case PHONE_PSTN_LINETEST:
                retval = ixj_linetest(board);
                break;
        case IXJCTL_CID:
index 23397a180456698544e60897f04ab9dfea010db5..fed7c11b7fbfd5cace696e5111ef316803abc8fb 100644 (file)
@@ -1087,12 +1087,8 @@ void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h
 
 static inline void fbcon_softback_note(struct vc_data *conp, int t, int count)
 {
-    unsigned short *p;
-    
-    if (conp->vc_num != fg_console)
-       return;
-    p = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
-
+    unsigned short *p = (unsigned short *)
+       (conp->vc_origin + t * conp->vc_size_row);
     while (count) {
        scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row);
        count--;
index a6753d27682f04890d295c05839199e691a2069c..110326df21143696eb0d06f39082dcaec5cdfdd1 100644 (file)
@@ -196,15 +196,18 @@ revalidate:
                                 * version stamp to detect whether or
                                 * not the directory has been modified
                                 * during the copy operation.
+                                * AV: It can't be modified, but it fscking
+                                * can be seeked by another process that shares
+                                * the descriptor.
                                 */
-                               unsigned long version = inode->i_version;
+                               unsigned long version = filp->f_version;
 
                                error = filldir(dirent, de->name,
                                                de->name_len,
                                                filp->f_pos, le32_to_cpu(de->inode));
                                if (error)
                                        break;
-                               if (version != inode->i_version)
+                               if (version != filp->f_version)
                                        goto revalidate;
                                stored ++;
                        }
index 7f5c464a4d620f513d6e947c032aa49fd9abe20e..6b562006e4db6e5bfa31c54e53413222170f8792 100644 (file)
@@ -20,8 +20,8 @@
 #define  IOBASE_LEN     0x00300000  /* Length of the IO area */
 #define  IOBASE_END     0xfe300000
 #define  DVMA_VADDR     0xfff00000  /* Base area of the DVMA on suns */
-#define  DVMA_LEN       0x00040000  /* Size of the DVMA address space */
-#define  DVMA_END       0xfff40000
+#define  DVMA_LEN       0x000c0000  /* Size of the DVMA address space */
+#define  DVMA_END       0xfffc0000
 
 /* IOMMU Mapping area, must be on a 16MB boundary!  Note this
  * doesn't count the DVMA areas, the prom lives between the
index 82cf1eb41dc87242b9be6920acc87081ce7091af..b08d979e69938277e4009cd449b25b30d4b719cd 100644 (file)
@@ -106,7 +106,16 @@ extern void __global_restore_flags(unsigned long flags);
 #define read_pcr(__p)  __asm__ __volatile__("rd        %%pcr, %0" : "=r" (__p))
 #define write_pcr(__p) __asm__ __volatile__("wr        %0, 0x0, %%pcr" : : "r" (__p));
 #define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
-#define reset_pic()    __asm__ __volatile__("wr        %g0, 0x0, %pic");
+
+/* Blackbird errata workaround.  See commentary in
+ * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
+ * for more information.
+ */
+#define reset_pic()                                                    \
+       __asm__ __volatile__("ba,pt     %xcc, 99f\n\t"          \
+                            ".align    64\n"                   \
+                         "99:wr        %g0, 0x0, %pic\n\t"     \
+                            "rd        %pic, %g0")
 
 #ifndef __ASSEMBLY__
 
index 082b885f192bcd6894ead66a7c74ebf0ca4be006..c3e4c55737ae46dd8f37e60ab028ccd00bb18b11 100644 (file)
@@ -158,6 +158,16 @@ typedef enum {
        WSS = 12
 } phone_codec;
 
+struct phone_codec_data
+{
+       phone_codec type;
+       unsigned short buf_min, buf_opt, buf_max;
+};
+
+#define PHONE_QUERY_CODEC              _IOWR ('q', 0xA7, struct phone_codec_data *)
+#define PHONE_PSTN_LINETEST            _IO ('q', 0xA8)
+
+
 /******************************************************************************
 *
 * The exception structure allows us to multiplex multiple events onto the
index b342740906b4341f0786ada116fb3c4726f0446a..f42ad08396ab23d66bcc28285970c7a9ca07d7a8 100644 (file)
@@ -238,7 +238,7 @@ struct video_unit
 #define VIDIOCGPICT            _IOR('v',6,struct video_picture)        /* Get picture properties */
 #define VIDIOCSPICT            _IOW('v',7,struct video_picture)        /* Set picture properties */
 #define VIDIOCCAPTURE          _IOW('v',8,int)                         /* Start, end capture */
-#define VIDIOCGWIN             _IOR('v',9, struct video_window)        /* Set the video overlay window */
+#define VIDIOCGWIN             _IOR('v',9, struct video_window)        /* Get the video overlay window */
 #define VIDIOCSWIN             _IOW('v',10, struct video_window)       /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
 #define VIDIOCGFBUF            _IOR('v',11, struct video_buffer)       /* Get frame buffer */
 #define VIDIOCSFBUF            _IOW('v',12, struct video_buffer)       /* Set frame buffer - root only */
index c617c0d8431e4c11cefeb5a5877d5f17d919c9dd..242126f4fcc7b620cbba16cfbe7bd54c13904e0f 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -282,7 +282,7 @@ static void update_queue (struct semid_ds * sma)
         for (q = sma->sem_pending; q; q = q->next) {
                         
                 if (q->status == 1)
-                        return; /* wait for other process */
+                       continue; /* this one was woken up before */
 
                 error = try_atomic_semop(sma, q->sops, q->nsops,
                                          q->undo, q->pid, q->alter);
index 909e858fc28182465206f61228be6c5dccc6d76b..94560de6f445d5761661cc67eb3fa225d7ea9bcd 100644 (file)
@@ -857,6 +857,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
                sin->sin_family = AF_INET;
                sin->sin_port = skb->h.uh->source;
                sin->sin_addr.s_addr = skb->nh.iph->saddr;
+               memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
                if (flags&MSG_PROXY)
                {