]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.45pre1 2.3.45pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:31:22 +0000 (15:31 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:31:22 +0000 (15:31 -0500)
176 files changed:
Makefile
arch/alpha/kernel/pci_iommu.c
arch/arm/kernel/armksyms.c
arch/arm/kernel/entry-common.S
arch/arm/kernel/irq.c
arch/arm/kernel/semaphore.c
arch/arm/mm/Makefile
arch/arm/mm/consistent.c [new file with mode: 0644]
arch/arm/mm/proc-arm6,7.S
arch/arm/nwfpe/fpmodule.c
arch/arm/nwfpe/fpsr.h
arch/i386/boot/bootsect.S
arch/i386/kernel/pci-pc.c
arch/ia64/config.in
arch/ia64/ia32/ia32_entry.S
arch/ia64/ia32/ia32_signal.c
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/gate.S
arch/ia64/kernel/head.S
arch/ia64/kernel/irq.c
arch/ia64/kernel/irq_lock.c
arch/ia64/kernel/pci-dma.c
arch/ia64/kernel/pci.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/sys_ia64.c
arch/ia64/lib/Makefile
arch/ia64/tools/print_offsets.c
arch/ppc/coffboot/misc.S
arch/ppc/configs/common_defconfig
arch/ppc/configs/gemini_defconfig
arch/ppc/defconfig
arch/ppc/kernel/entry.S
arch/ppc/kernel/head.S
arch/ppc/kernel/irq.c
arch/ppc/kernel/misc.S
arch/ppc/kernel/mk_defs.c
arch/ppc/kernel/open_pic.c
arch/ppc/kernel/pmac_pic.c
arch/ppc/kernel/pmac_setup.c
arch/ppc/kernel/pmac_time.c
arch/ppc/kernel/ppc_asm.h
arch/ppc/kernel/ppc_asm.tmpl
arch/ppc/kernel/ppc_ksyms.c
arch/ppc/kernel/process.c
arch/ppc/kernel/prom.c
arch/ppc/kernel/setup.c
arch/ppc/kernel/smp.c
arch/ppc/kernel/syscalls.c
arch/ppc/kernel/traps.c
arch/ppc/lib/string.S
arch/ppc/mm/init.c
arch/ppc/xmon/start.c
arch/sparc/kernel/ioport.c
arch/sparc/kernel/pcic.c
arch/sparc/mm/sun4c.c
arch/sparc/mm/swift.S
drivers/acorn/char/keyb_ps2.c
drivers/block/loop.c
drivers/char/nvram.c
drivers/macintosh/mac_keyb.c
drivers/macintosh/macserial.c
drivers/net/3c59x.c
drivers/net/8139too.c [new file with mode: 0644]
drivers/net/Config.in
drivers/net/Makefile
drivers/net/a2065.c
drivers/net/arcnet/arc-rimi.c
drivers/net/arcnet/arcnet.c
drivers/net/arcnet/com20020-isa.c
drivers/net/arcnet/com20020-pci.c
drivers/net/arcnet/com90io.c
drivers/net/arcnet/com90xx.c
drivers/net/arcnet/rfc1201.c
drivers/net/bmac.c
drivers/net/de4x5.c
drivers/net/eepro100.c
drivers/net/epic100.c
drivers/net/gmac.c
drivers/net/mace.c
drivers/net/ncr885e.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c575_cb.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/aironet4500_cs.c
drivers/net/pcmcia/netwave_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/tulip_cb.c
drivers/net/pcmcia/wavelan_cs.c
drivers/net/pcmcia/wavelan_cs.h
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/rcpci45.c
drivers/net/rtl8129.c [new file with mode: 0644]
drivers/net/rtl8139.c [deleted file]
drivers/net/seeq8005.c
drivers/net/smc-mca.c
drivers/net/smc9194.c
drivers/net/strip.c
drivers/net/wan/cycx_x25.c
drivers/net/wan/lapbether.c
drivers/net/wan/sbni.c
drivers/net/wan/sbni.h
drivers/net/wan/x25_asy.c
drivers/net/wan/z85230.c
drivers/net/wan/z85230.h
drivers/net/wavelan.c
drivers/net/znet.c
drivers/scsi/qla1280.c
drivers/scsi/qlogicisp.c
drivers/sound/dmasound.c
drivers/usb/keybdev.c
drivers/video/aty128fb.c
drivers/video/atyfb.c
drivers/video/igafb.c
fs/Config.in
fs/adfs/file.c
fs/adfs/inode.c
fs/adfs/map.c
fs/attr.c
fs/hpfs/namei.c
fs/nfsd/nfsfh.c
fs/nfsd/vfs.c
fs/open.c
include/asm-alpha/pgtable.h
include/asm-arm/hardirq.h
include/asm-arm/io.h
include/asm-arm/md.h [deleted file]
include/asm-arm/pci.h
include/asm-arm/pgtable.h
include/asm-arm/proc-armo/semaphore.h
include/asm-arm/proc-armv/locks.h [new file with mode: 0644]
include/asm-arm/proc-armv/semaphore.h [deleted file]
include/asm-arm/semaphore.h
include/asm-arm/softirq.h
include/asm-i386/pgtable.h
include/asm-ia64/dma.h
include/asm-ia64/fpswa.h
include/asm-ia64/hardirq.h
include/asm-ia64/mmu_context.h
include/asm-ia64/offsets.h
include/asm-ia64/pgtable.h
include/asm-ia64/ptrace.h
include/asm-ia64/semaphore.h
include/asm-ia64/smp.h
include/asm-ia64/softirq.h
include/asm-ia64/types.h
include/asm-m68k/pgtable.h
include/asm-mips/pgtable.h
include/asm-ppc/elf.h
include/asm-ppc/hardirq.h
include/asm-ppc/page.h
include/asm-ppc/pgtable.h
include/asm-ppc/posix_types.h
include/asm-ppc/processor.h
include/asm-ppc/smp.h
include/asm-ppc/softirq.h
include/asm-ppc/spinlock.h
include/asm-ppc/types.h
include/asm-sh/pgtable.h
include/asm-sparc64/floppy.h
include/asm-sparc64/pgtable.h
include/linux/adfs_fs_i.h
include/linux/i2c-id.h
include/linux/kmod.h
include/linux/netdevice.h
kernel/ksyms.c
kernel/ptrace.c
mm/memory.c
mm/mmap.c
net/core/dev.c
net/ipv6/af_inet6.c
net/khttpd/sockets.c
net/netsyms.c
scripts/tkcond.c

index 4be320a0f0f8e014947a543c7b16ef0b3b82765b..980b840f140cc19f1b2f08abc96c6d4548ebda6b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 44
+SUBLEVEL = 45
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
index 8faa669010a2b0fa525428365ab65cdda33cce95..14a127c14f717ebf2ff7f5583e4824b835857520 100644 (file)
@@ -16,7 +16,6 @@
 
 
 #define DEBUG_ALLOC 0
-
 #if DEBUG_ALLOC > 0
 # define DBGA(args...)         printk(KERN_DEBUG ##args)
 #else
@@ -40,6 +39,20 @@ calc_npages(long bytes)
 {
        return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
 }
+
+static inline long
+calc_order(long size)
+{
+       int order;
+
+       size = (size-1) >> (PAGE_SHIFT-1);
+       order = -1;
+       do {
+               size >>= 1;
+               order++;
+       } while (size);
+       return order;
+}
 \f
 struct pci_iommu_arena *
 iommu_arena_new(dma_addr_t base, unsigned long window_size,
@@ -173,10 +186,6 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size)
        ret = arena->dma_base + dma_ofs * PAGE_SIZE;
        ret += (unsigned long)cpu_addr & ~PAGE_MASK;
 
-       /* ??? This shouldn't have been needed, since the entries
-          we've just modified were not in the iommu tlb.  */
-       alpha_mv.mv_pci_tbi(hose, ret, ret + size - 1);
-
        DBGA("pci_map_single: [%p,%lx] np %ld -> sg %x from %p\n",
             cpu_addr, size, npages, ret, __builtin_return_address(0));
 
@@ -239,11 +248,12 @@ void *
 pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
 {
        void *cpu_addr;
+       long order = calc_order(size);
 
-       cpu_addr = kmalloc(size, GFP_ATOMIC);
+       cpu_addr = (void *)__get_free_pages(GFP_ATOMIC, order);
        if (! cpu_addr) {
-               printk(KERN_INFO "dma_alloc_consistent: "
-                      "kmalloc failed from %p\n",
+               printk(KERN_INFO "pci_alloc_consistent: "
+                      "get_free_pages failed from %p\n",
                        __builtin_return_address(0));
                /* ??? Really atomic allocation?  Otherwise we could play
                   with vmalloc and sg if we can't find contiguous memory.  */
@@ -253,11 +263,11 @@ pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
 
        *dma_addrp = pci_map_single(pdev, cpu_addr, size);
        if (*dma_addrp == 0) {
-               kfree_s(cpu_addr, size);
+               free_pages((unsigned long)cpu_addr, order);
                return NULL;
        }
                
-       DBGA2("dma_alloc_consistent: %lx -> [%p,%x] from %p\n",
+       DBGA2("pci_alloc_consistent: %lx -> [%p,%x] from %p\n",
              size, cpu_addr, *dma_addrp, __builtin_return_address(0));
 
        return cpu_addr;
@@ -275,32 +285,33 @@ pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr,
                    dma_addr_t dma_addr)
 {
        pci_unmap_single(pdev, dma_addr, size);
-       kfree_s(cpu_addr, size);
+       free_pages((unsigned long)cpu_addr, calc_order(size));
 
-       DBGA2("dma_free_consistent: [%x,%lx] from %p\n",
+       DBGA2("pci_free_consistent: [%x,%lx] from %p\n",
              dma_addr, size, __builtin_return_address(0));
 }
 
 
 /* Classify the elements of the scatterlist.  Write dma_address
    of each element with:
-       0   : Not mergable.
-       1   : Followers all physically adjacent.
-       [23]: Followers all virtually adjacent.
-       -1  : Not leader.
+       0   : Followers all physically adjacent.
+       1   : Followers all virtually adjacent.
+       -1  : Not leader, physically adjacent to previous.
+       -2  : Not leader, virtually adjacent to previous.
    Write dma_length of each leader with the combined lengths of
    the mergable followers.  */
 
 static inline void
-sg_classify(struct scatterlist *sg, struct scatterlist *end)
+sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
 {
        unsigned long next_vaddr;
        struct scatterlist *leader;
+       long leader_flag, leader_length;
 
        leader = sg;
-       leader->dma_address = 0;
-       leader->dma_length = leader->length;
-       next_vaddr = (unsigned long)leader->address + leader->length;
+       leader_flag = 0;
+       leader_length = leader->length;
+       next_vaddr = (unsigned long)leader->address + leader_length;
 
        for (++sg; sg < end; ++sg) {
                unsigned long addr, len;
@@ -309,20 +320,24 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end)
 
                if (next_vaddr == addr) {
                        sg->dma_address = -1;
-                       leader->dma_address |= 1;
-                       leader->dma_length += len;
-               } else if (((next_vaddr | addr) & ~PAGE_MASK) == 0) {
-                       sg->dma_address = -1;
-                       leader->dma_address |= 2;
-                       leader->dma_length += len;
+                       leader_length += len;
+               } else if (((next_vaddr | addr) & ~PAGE_MASK) == 0 && virt_ok) {
+                       sg->dma_address = -2;
+                       leader_flag = 1;
+                       leader_length += len;
                } else {
+                       leader->dma_address = leader_flag;
+                       leader->dma_length = leader_length;
                        leader = sg;
-                       leader->dma_address = 0;
-                       leader->dma_length = len;
+                       leader_flag = 0;
+                       leader_length = len;
                }
 
                next_vaddr = addr + len;
        }
+
+       leader->dma_address = leader_flag;
+       leader->dma_length = leader_length;
 }
 
 /* Given a scatterlist leader, choose an allocation method and fill
@@ -334,21 +349,21 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
        dma_addr_t max_dma)
 {
        unsigned long paddr = virt_to_phys(leader->address);
-       unsigned long size = leader->dma_length;
+       long size = leader->dma_length;
        struct scatterlist *sg;
        unsigned long *ptes;
        long npages, dma_ofs, i;
 
        /* If everything is physically contiguous, and the addresses
           fall into the direct-map window, use it.  */
-       if (leader->dma_address < 2
+       if (leader->dma_address == 0
            && paddr + size + __direct_map_base - 1 <= max_dma
            && paddr + size <= __direct_map_size) {
                out->dma_address = paddr + __direct_map_base;
                out->dma_length = size;
 
-               DBGA2("sg_fill: [%p,%lx] -> direct %x\n",
-                     leader->address, size, out->dma_address);
+               DBGA("    sg_fill: [%p,%lx] -> direct %x\n",
+                    leader->address, size, out->dma_address);
 
                return 0;
        }
@@ -365,48 +380,70 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
        out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
        out->dma_length = size;
 
-       DBGA("sg_fill: [%p,%lx] -> sg %x\n",
-            leader->address, size, out->dma_address);
+       DBGA("    sg_fill: [%p,%lx] -> sg %x np %ld\n",
+            leader->address, size, out->dma_address, npages);
 
        ptes = &arena->ptes[dma_ofs];
        sg = leader;
-       do {
-               paddr = virt_to_phys(sg->address);
-               npages = calc_npages((paddr & ~PAGE_MASK) + sg->length);
+       if (0 && leader->dma_address == 0) {
+               /* All physically contiguous.  We already have the
+                  length, all we need is to fill in the ptes.  */
 
-               DBGA("        (%ld) [%p,%x]\n",
-                     sg - leader, sg->address, sg->length);
-
-               paddr &= PAGE_MASK;
+               paddr = virt_to_phys(sg->address) & PAGE_MASK;
                for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
                        *ptes++ = mk_iommu_pte(paddr);
 
-               ++sg;
-       } while (sg < end && sg->dma_address == -1);
+#if DEBUG_ALLOC > 0
+               DBGA("    (0) [%p,%x] np %ld\n",
+                    sg->address, sg->length, npages);
+               for (++sg; sg < end && (int) sg->dma_address < 0; ++sg)
+                       DBGA("        (%ld) [%p,%x] cont\n",
+                            sg - leader, sg->address, sg->length);
+#endif
+       } else {
+               /* All virtually contiguous.  We need to find the
+                  length of each physically contiguous subsegment
+                  to fill in the ptes.  */
+               do {
+                       struct scatterlist *last_sg = sg;
+
+                       size = sg->length;
+                       paddr = virt_to_phys(sg->address);
+
+                       while (sg+1 < end && (int) sg[1].dma_address == -1) {
+                               size += sg[1].length;
+                               sg++;
+                       }
+
+                       npages = calc_npages((paddr & ~PAGE_MASK) + size);
+
+                       paddr &= PAGE_MASK;
+                       for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
+                               *ptes++ = mk_iommu_pte(paddr);
+
+#if DEBUG_ALLOC > 0
+                       DBGA("    (%ld) [%p,%x] np %ld\n",
+                            last_sg - leader, last_sg->address,
+                            last_sg->length, npages);
+                       while (++last_sg <= sg) {
+                               DBGA("        (%ld) [%p,%x] cont\n",
+                                    last_sg - leader, last_sg->address,
+                                    last_sg->length);
+                       }
+#endif
+               } while (++sg < end && (int) sg->dma_address < 0);
+       }
 
        return 1;
 }
 
-/* TODO: Only use the iommu when it helps.  Non-mergable scatterlist
-   entries might as well use direct mappings.  */
-
 int
 pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
 {
        struct scatterlist *start, *end, *out;
        struct pci_controler *hose;
        struct pci_iommu_arena *arena;
-       dma_addr_t max_dma, fstart, fend;
-
-       /* If pci_tbi is not available, we must not be able to control
-          an iommu.  Direct map everything, no merging.  */
-       if (! alpha_mv.mv_pci_tbi) {
-               for (end = sg + nents; sg < end; ++sg) {
-                       sg->dma_address = virt_to_bus(sg->address);
-                       sg->dma_length = sg->length;
-               }
-               return nents;
-       }
+       dma_addr_t max_dma;
 
        /* Fast path single entry scatterlists.  */
        if (nents == 1) {
@@ -416,50 +453,42 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
                return sg->dma_address != 0;
        }
 
-       hose = pdev ? pdev->sysdata : pci_isa_hose;
-       max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
-       arena = hose->sg_pci;
-       if (!arena || arena->dma_base + arena->size > max_dma)
-               arena = hose->sg_isa;
        start = sg;
        end = sg + nents;
-       fstart = -1;
-       fend = 0;
-       
+
        /* First, prepare information about the entries.  */
-       sg_classify(sg, end);
+       sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0);
+
+       /* Second, figure out where we're going to map things.  */
+       if (alpha_mv.mv_pci_tbi) {
+               hose = pdev ? pdev->sysdata : pci_isa_hose;
+               max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+               arena = hose->sg_pci;
+               if (!arena || arena->dma_base + arena->size > max_dma)
+                       arena = hose->sg_isa;
+       } else {
+               max_dma = -1;
+               arena = NULL;
+               hose = NULL;
+       }
 
-       /* Second, iterate over the scatterlist leaders and allocate
+       /* Third, iterate over the scatterlist leaders and allocate
           dma space as needed.  */
        for (out = sg; sg < end; ++sg) {
                int ret;
 
-               if (sg->dma_address == -1)
+               if ((int) sg->dma_address < 0)
                        continue;
 
                ret = sg_fill(sg, end, out, arena, max_dma);
                if (ret < 0)
                        goto error;
-               else if (ret > 0) {
-                       dma_addr_t ts, te;
-
-                       ts = out->dma_address;
-                       te = ts + out->dma_length - 1;
-                       if (fstart > ts)
-                               fstart = ts;
-                       if (fend < te)
-                               fend = te;
-               }
                out++;
        }
 
-       /* ??? This shouldn't have been needed, since the entries
-          we've just modified were not in the iommu tlb.  */
-       if (fend)
-               alpha_mv.mv_pci_tbi(hose, fstart, fend);
-
        if (out - start == 0)
                printk(KERN_INFO "pci_map_sg failed: no entries?\n");
+       DBGA("pci_map_sg: %ld entries\n", out - start);
 
        return out - start;
 
@@ -496,9 +525,11 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
        arena = hose->sg_pci;
        if (!arena || arena->dma_base + arena->size > max_dma)
                arena = hose->sg_isa;
+
+       DBGA("pci_unmap_sg: %d entries\n", nents);
+
        fstart = -1;
        fend = 0;
-
        for (end = sg + nents; sg < end; ++sg) {
                unsigned long addr, size;
 
@@ -508,7 +539,8 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
                if (addr >= __direct_map_base
                    && addr < __direct_map_base + __direct_map_size) {
                        /* Nothing to do.  */
-                       DBGA2("pci_unmap_sg: direct [%lx,%lx]\n", addr, size);
+                       DBGA("    (%ld) direct [%lx,%lx]\n",
+                             sg - end + nents, addr, size);
                } else {
                        long npages, ofs;
                        dma_addr_t tend;
@@ -523,7 +555,8 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
                        if (fend < tend)
                                fend = tend;
 
-                       DBGA2("pci_unmap_sg: sg [%lx,%lx]\n", addr, size);
+                       DBGA("    (%ld) sg [%lx,%lx]\n",
+                             sg - end + nents, addr, size);
                }
        }
        if (fend)
index 0caf4bf26057f6c6de5bd925f7a7d812280bdcae..63d4631a4b2b8ac30148eb177a5a7af5ec991b3f 100644 (file)
@@ -188,6 +188,10 @@ EXPORT_SYMBOL(uaccess_kernel);
 EXPORT_SYMBOL(uaccess_user);
 #endif
 
+EXPORT_SYMBOL(consistent_alloc);
+EXPORT_SYMBOL(consistent_free);
+EXPORT_SYMBOL(consistent_sync);
+
        /* gcc lib functions */
 EXPORT_SYMBOL_NOVERS(__gcc_bcmp);
 EXPORT_SYMBOL_NOVERS(__ashldi3);
@@ -234,5 +238,8 @@ EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
 EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL_NOVERS(__down_read_failed);
+EXPORT_SYMBOL_NOVERS(__down_write_failed);
+EXPORT_SYMBOL_NOVERS(__rwsem_wake);
 
 EXPORT_SYMBOL(get_wchan);
index 2be1a601216025107795e2ca6656bd186c9168b7..5dc61c6d7de738e0a7faba939737299b6856061d 100644 (file)
 #define HARVARD_CACHE
 #endif
 
+               .macro  get_softirq, rd
+#ifdef __SMP__
+#error SMP not supported
+#else
+               ldr     \rd, __softirq_state
+#endif
+               .endm
+
                .globl  ret_from_sys_call
 
                .align  5
 fast_syscall_return:
-               str     r0, [sp, #S_R0 + S_OFF]         @ returned r0
+               str     r0, [sp, #S_R0 + S_OFF] @ returned r0
 slow_syscall_return:
                add     sp, sp, #S_OFF
-ret_from_sys_call:
-#ifdef HARVARD_CACHE
-               ldr     r0, bh_data
-               ldr     r4, bh_data+4
-#else
-               adr     r0, bh_data
-               ldmia   r0, {r0, r4}
-#endif
-               ldr     r0, [r0]
-               ldr     r1, [r4]
+ret_from_sys_call:                             @ external entry
+               get_softirq r0
+               ldmia   r0, {r0, r1}
+               mov     r4, #1                  @ flag this as being syscall return
                tst     r0, r1
-               blne    SYMBOL_NAME(do_bottom_half)
-ret_with_reschedule:
+               blne    SYMBOL_NAME(do_softirq)
+ret_with_reschedule:                           @ external entry (__irq_usr)
                get_current_task r5
                ldr     r0, [r5, #TSK_NEED_RESCHED]
                ldr     r1, [r5, #TSK_SIGPENDING]
@@ -43,30 +45,23 @@ ret_with_reschedule:
                teq     r1, #0                  @ check for signals
                bne     ret_signal
 
-ret_from_all:  restore_user_regs
+ret_from_all:  restore_user_regs               @ internal
 
-ret_signal:    mov     r1, sp
+ret_signal:    mov     r1, sp                  @ internal
                adrsvc  al, lr, ret_from_all
                mov     r2, r4
                b       SYMBOL_NAME(do_signal)
 
-ret_reschedule:        adrsvc  al, lr, ret_with_reschedule
+ret_reschedule:        adrsvc  al, lr, ret_with_reschedule     @ internal
                b       SYMBOL_NAME(schedule)
 
                .globl  ret_from_exception
-ret_from_exception:
-#ifdef HARVARD_CACHE
-               ldr     r0, bh_data
-               ldr     r1, bh_data + 4
-#else
-               adr     r0, bh_data
+ret_from_exception:                            @ external entry
+               get_softirq r0
                ldmia   r0, {r0, r1}
-#endif
-               ldr     r0, [r0]
-               ldr     r1, [r1]
                mov     r4, #0
                tst     r0, r1
-               blne    SYMBOL_NAME(do_bottom_half)
+               blne    SYMBOL_NAME(do_softirq)
                ldr     r0, [sp, #S_PSR]
                tst     r0, #3                  @ returning to user mode?
                beq     ret_with_reschedule
@@ -147,8 +142,8 @@ vector_swi: save_user_regs
 
                .align  5
 
-bh_data:       .word   SYMBOL_NAME(bh_mask)
-               .word   SYMBOL_NAME(bh_active)
+__softirq_state:
+               .word   SYMBOL_NAME(softirq_state)
 
 ENTRY(sys_call_table)
 #include "calls.S"
index f6c310905dd93052ffa9cd1d63d9aaaf77052a4f..6e3c863d5f78cdded831fc81f9d34fe365e8ca64 100644 (file)
@@ -237,16 +237,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 
        irq_exit(cpu, irq);
 
-       /*
-        * This should be conditional: we should really get
-        * a return code from the irq handler to tell us
-        * whether the handler wants us to do software bottom
-        * half handling or not..
-        */
-       if (1) {
-               if (bh_active & bh_mask)
-                       do_bottom_half();
-       }
+       if (softirq_state[cpu].active & softirq_state[cpu].mask)
+               do_softirq();
 }
 
 #if defined(CONFIG_ARCH_ACORN)
index 71bf85e093e368a21909813984c60c88f942591e..a2ec71526b0e696a7e655b733ec0d873602360e6 100644 (file)
@@ -164,6 +164,126 @@ int __down_trylock(struct semaphore * sem)
        return 1;
 }
 
+struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
+{
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+
+       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
+
+       for (;;) {
+               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
+                       break;
+               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+               if (!sem->read_bias_granted)
+                       schedule();
+       }
+
+       remove_wait_queue(&sem->wait, &wait);
+       tsk->state = TASK_RUNNING;
+
+       return sem;
+}
+
+struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
+{
+        struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+
+       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
+
+       for (;;) {
+               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
+                       break;
+               set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+               if (!sem->write_bias_granted)
+                       schedule();
+       }
+
+       remove_wait_queue(&sem->write_bias_wait, &wait);
+       tsk->state = TASK_RUNNING;
+
+       /* if the lock is currently unbiased, awaken the sleepers
+        * FIXME: this wakes up the readers early in a bit of a
+        * stampede -> bad!
+        */
+       if (atomic_read(&sem->count) >= 0)
+               wake_up(&sem->wait);
+
+       return sem;
+}
+
+/* Wait for the lock to become unbiased.  Readers
+ * are non-exclusive. =)
+ */
+struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
+{
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+
+       /* this takes care of granting the lock */
+       __up_op_read(sem, __rwsem_wake);
+
+       add_wait_queue(&sem->wait, &wait);
+
+       while (atomic_read(&sem->count) < 0) {
+               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+               if (atomic_read(&sem->count) >= 0)
+                       break;
+               schedule();
+       }
+
+       remove_wait_queue(&sem->wait, &wait);
+       tsk->state = TASK_RUNNING;
+
+       return sem;
+}
+
+/* Wait for the lock to become unbiased. Since we're
+ * a writer, we'll make ourselves exclusive.
+ */
+struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
+{
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+
+       /* this takes care of granting the lock */
+       __up_op_write(sem, __rwsem_wake);
+
+       add_wait_queue_exclusive(&sem->wait, &wait);
+
+       while (atomic_read(&sem->count) < 0) {
+               set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+               if (atomic_read(&sem->count) >= 0)
+                       break;  /* we must attempt to aquire or bias the lock */                schedule();
+       }
+
+       remove_wait_queue(&sem->wait, &wait);
+       tsk->state = TASK_RUNNING;
+
+       return sem;
+}
+
+/* Called when someone has done an up that transitioned from
+ * negative to non-negative, meaning that the lock has been
+ * granted to whomever owned the bias.
+ */
+struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
+{
+       if (xchg(&sem->read_bias_granted, 1))
+               BUG();
+       wake_up(&sem->wait);
+       return sem;
+}
+
+struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
+{
+       if (xchg(&sem->write_bias_granted, 1))
+               BUG();
+       wake_up(&sem->write_bias_wait);
+       return sem;
+}
+
 /*
  * The semaphore operations have a special calling sequence that
  * allow us to do a simpler in-line version of them. These routines
@@ -174,30 +294,65 @@ int __down_trylock(struct semaphore * sem)
  * registers (r0 to r3, ip and lr) except r0 in the cases where it
  * is used as a return value..
  */
-asm(".align    5
+asm("  .section        .text.lock, \"ax\"
+       .align  5
        .globl  __down_failed
 __down_failed:
        stmfd   sp!, {r0 - r3, ip, lr}
        bl      __down
-       ldmfd   sp!, {r0 - r3, ip, pc}");
+       ldmfd   sp!, {r0 - r3, ip, pc}
 
-asm(".align    5
+       .align  5
        .globl  __down_interruptible_failed
 __down_interruptible_failed:
        stmfd   sp!, {r1 - r3, ip, lr}
        bl      __down_interruptible
-       ldmfd   sp!, {r1 - r3, ip, pc}");
+       ldmfd   sp!, {r1 - r3, ip, pc}
 
-asm(".align    5
+       .align  5
        .globl  __down_trylock_failed
 __down_trylock_failed:
        stmfd   sp!, {r1 - r3, ip, lr}
        bl      __down_trylock
-       ldmfd   sp!, {r1 - r3, ip, pc}");
+       ldmfd   sp!, {r1 - r3, ip, pc}
 
-asm(".align    5
+       .align  5
        .globl  __up_wakeup
 __up_wakeup:
        stmfd   sp!, {r0 - r3, ip, lr}
        bl      __up
-       ldmfd   sp!, {r0 - r3, ip, pc}");
+       ldmfd   sp!, {r0 - r3, ip, pc}
+
+       .align  5
+       .globl  __down_read_failed
+__down_read_failed:
+       stmfd   sp!, {r0 - r3, ip, lr}
+       bcc     1f
+       bl      down_read_failed_biased
+       ldmfd   sp!, {r0 - r3, ip, pc}
+1:     bl      down_read_failed
+       /***/
+
+       .align  5
+       .globl  __down_write_failed
+__down_write_failed:
+       stmfd   sp!, {r0 - r3, ip, lr}
+       bcc     1f
+       bl      down_write_failed_biased
+       ldmfd   sp!, {r0 - r3, ip, pc}
+1:     bl      down_write_failed
+       /***/
+
+       .align  5
+       .globl  __rwsem_wake
+__rwsem_wake:
+       stmfd   sp!, {r0 - r3, ip, lr}
+       beq     1f
+       bl      rwsem_wake_readers
+       ldmfd   sp!, {r0 - r3, ip, pc}
+1:     bl      rwsem_wake_writer
+       ldmfd   sp!, {r0 - r3, ip, pc}
+
+       .previous
+       ");
+
index b9bffb7c95b628a8aa45cc8bd259858436010a8a..1c02473bbd36b1c45d3d528ea34cbbe118b4af5b 100644 (file)
@@ -8,8 +8,8 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET       := mm.o
-O_OBJS         := init.o extable.o fault-$(PROCESSOR).o mm-$(PROCESSOR).o \
-                  small_page.o
+O_OBJS         := consistent.o extable.o fault-$(PROCESSOR).o init.o \
+                  mm-$(PROCESSOR).o small_page.o
 
 ifeq ($(CONFIG_CPU_26),y)
   O_OBJS       += proc-arm2,3.o
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
new file mode 100644 (file)
index 0000000..4fece51
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Dynamic DMA mapping support.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+/* Pure 2^n version of get_order */
+extern __inline__ int __get_order(unsigned long size)
+{
+       int order;
+
+       size = (size-1) >> (PAGE_SHIFT-1);
+       order = -1;
+       do {
+               size >>= 1;
+               order++;
+       } while (size);
+       return order;
+}
+
+/*
+ * This allocates one page of cache-coherent memory space and returns
+ * both the virtual and a "dma" address to that space.  It is not clear
+ * whether this could be called from an interrupt context or not.  For
+ * now, we expressly forbid it, especially as some of the stuff we do
+ * here is not interrupt context safe.
+ */
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+{
+       int order;
+       unsigned long page;
+       struct vm_struct *area;
+       void *ret;
+
+       if (in_interrupt())
+               BUG();
+
+       order = __get_order(size);
+
+       page = __get_free_pages(gfp, order);
+       if (!page)
+               goto no_page;
+
+       memset((void *)page, 0, PAGE_SIZE << order);
+       clean_cache_area(page, PAGE_SIZE << order);
+
+       *dma_handle = virt_to_bus((void *)page);
+
+       area = get_vm_area(size, VM_IOREMAP); /* maybe new type? */
+       if (!area)
+               goto no_area;
+
+       ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0);
+       if (ret)
+               return ret;
+
+no_area:
+       free_pages(page, order);
+no_page:
+       BUG();
+       return NULL;
+}
+
+/*
+ * free a page as defined by the above mapping.  We expressly forbid
+ * calling this from interrupt context.
+ */
+void consistent_free(void *vaddr)
+{
+       if (in_interrupt())
+               BUG();
+
+       __iounmap(vaddr);
+}
+
+/*
+ * make an area consistent.
+ */
+void consistent_sync(void *vaddr, size_t size, int rw)
+{
+       switch (rw) {
+       case 0:
+               BUG();
+       case 1: /* invalidate only */
+               dma_cache_inv(vaddr, size);
+               break;
+       case 2: /* writeback only */
+               dma_cache_wback(vaddr, size);
+               break;
+       case 3: /* writeback and invalidate */
+               dma_cache_wback_inv(vaddr, size);
+               break;
+       }
+}
index 23508c197ed174df069510a98f95e832ab49f302..b83f05a05469e209a67758db29a4186abd97d6d5 100644 (file)
@@ -103,9 +103,9 @@ msg:                .ascii  "DA*%p=%p\n\0"
                .align
 
 ENTRY(cpu_arm6_data_abort)
-Ldata_simple:
                ldr     r4, [r0]                        @ read instruction causing problem
                mov     r2, r4, lsr #19                 @ r2 b1 = L
+Ldata_simple:
                and     r2, r2, #2                      @ check read/write bit
                mrc     p15, 0, r0, c6, c0, 0           @ get FAR
                mrc     p15, 0, r1, c5, c0, 0           @ get FSR
index b9ca935ebf7988dfd2485547a52df3f2327c0e39..9d4f1570d5002f70ccd67bd1e6c1497ff81b50ba 100644 (file)
@@ -128,23 +128,41 @@ cumulative exceptions flag byte are set and we return.
 
 void float_raise(signed char flags)
 {
+  register unsigned int fpsr, cumulativeTraps;
+  
 #ifdef CONFIG_DEBUG_USER
   printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n",
         current->comm, current->pid, flags,
         __builtin_return_address(0), userRegisters[15]);
 #endif
 
+  /* Keep SoftFloat exception flags up to date.  */
   float_exception_flags |= flags;
-  if (readFPSR() & (flags << 16))
-  {
-    /* raise exception */
+
+  /* Read fpsr and initialize the cumulativeTraps.  */
+  fpsr = readFPSR();
+  cumulativeTraps = 0;
+  
+  /* For each type of exception, the cumulative trap exception bit is only
+     set if the corresponding trap enable bit is not set.  */
+  if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC))
+     cumulativeTraps |= BIT_IXC;  
+  if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC))
+     cumulativeTraps |= BIT_UFC;  
+  if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC))
+     cumulativeTraps |= BIT_OFC;  
+  if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC))
+     cumulativeTraps |= BIT_DZC;  
+  if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC))
+     cumulativeTraps |= BIT_IOC;  
+
+  /* Set the cumulative exceptions flags.  */
+  if (cumulativeTraps)
+    writeFPSR(fpsr | cumulativeTraps);
+
+  /* Raise an exception if necessary.  */
+  if (fpsr & (flags << 16))
     fp_send_sig(SIGFPE, current, 1);
-  }
-  else
-  {
-    /* set the cumulative exceptions flags */
-    writeFPSR(flags);
-  }
 }
 
 module_init(fpe_init);
index f40f3872c199319d5f6895cbbfc59ca729349429..6dafb0f5243cae5bef2b7d8077fbc3d1d24df125 100644 (file)
@@ -63,12 +63,12 @@ typedef unsigned int FPCR;  /* type for floating point control register */
 #define MASK_SYSTEM_CONTROL    0x0000ff00
 #define MASK_TRAP_STRICT       0x00001f00
 
-#define BIT_AC 0x00100000      /* use alternative C-flag definition
+#define BIT_AC 0x00001000      /* use alternative C-flag definition
                                   for compares */
-#define BIT_EP 0x00080000      /* use expanded packed decimal format */
-#define BIT_SO 0x00040000      /* select synchronous operation of FPA */
-#define BIT_NE 0x00020000      /* NaN exception bit */
-#define BIT_ND 0x00010000      /* no denormalized numbers bit */
+#define BIT_EP 0x00000800      /* use expanded packed decimal format */
+#define BIT_SO 0x00000400      /* select synchronous operation of FPA */
+#define BIT_NE 0x00000200      /* NaN exception bit */
+#define BIT_ND 0x00000100      /* no denormalized numbers bit */
 
 /* CUMULATIVE EXCEPTION FLAGS BYTE
 ---------------------------------- */
index 4a9d59908cd0d063d5dbf0ddcb3a5afa4f5fd111..f345ea1004cf6056e02c4f566c3d6726f1918609 100644 (file)
@@ -106,9 +106,8 @@ go: movw    $0x4000-12, %di         # 0x4000 is an arbitrary value >=
        pushw   %ds
        ldsw    %fs:(%bx), %si          # ds:si is source
        movb    $6, %cl                 # copy 12 bytes
-       cld
        pushw   %di                     # di = 0x4000-12.
-       rep
+       rep                             # don't need cld -> done on line 66
        movsw
        popw    %di
        popw    %ds
@@ -140,20 +139,7 @@ load_setup:
        jmp     load_setup
 
 ok_load_setup:
-# Get disk drive parameters, specifically nr of sectors/track.
-
-#if 0
-
-# bde - the Phoenix BIOS manual says function 0x08 only works for fixed
-# disks.  It doesn't work for one of my BIOS's (1987 Award).  It was
-# fatal not to check the error code.
-
-       xorb    %dl, %dl
-       movb    $0x08, %ah              # AH=8 is get drive parameters
-       int     $0x13
-       xorb    %ch, %ch
-
-#else
+# Get disk drive parameters, specifically number of sectors/track.
 
 # It seems that there is no BIOS call to get the number of sectors.
 # Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
@@ -176,7 +162,6 @@ probe_loop:
        movw    $0x0201, %ax            # service 2, 1 sector
        int     $0x13
        jc      probe_loop              # try next value
-#endif
 
 got_sectors:
        movw    $INITSEG, %ax
@@ -200,11 +185,11 @@ got_sectors:
 # Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
 # depending on the number of sectors we pretend to know we have.
 
-       movw    %cs:root_dev, %ax
+       movw    root_dev, %ax
        orw     %ax, %ax
        jne     root_defined
        
-       movw    %cs:sectors, %bx
+       movw    sectors, %bx
        movw    $0x0208, %ax            # /dev/ps0 - 1.2Mb
        cmpw    $15, %bx
        je      root_defined
@@ -219,7 +204,7 @@ got_sectors:
        
        movb    $0, %al                 # /dev/fd0 - autodetect
 root_defined:
-       movw    %ax, %cs:root_dev
+       movw    %ax, root_dev
 
 # After that (everything loaded), we jump to the setup-routine
 # loaded directly after the bootblock:
index 5308572d9057a50e2a1ed3a34653743eb1d460e8..d5b2b0062f70105eb01fbe32b148fcbf8613195b 100644 (file)
@@ -1057,8 +1057,8 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
 static unsigned int pcibios_irq_mask = 0xfff8;
 
 static unsigned pcibios_irq_penalty[16] = {
-       1000, 1000, 1000, 10, 10, 0, 0, 10,
-       0, 0, 0, 0, 10, 100, 100, 100
+       10000, 10000, 10000, 100, 100, 0, 0, 100,
+       0, 0, 0, 0, 100, 1000, 1000, 1000
 };
 
 static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *rt, int pin, int assign)
index d006c1d05a7e397ad6e3492b23eeb312aeb0cd7b..2d2388590c68f0dad93cd9d3528715987733e1f0 100644 (file)
@@ -3,6 +3,8 @@ mainmenu_name "Kernel configuration of Linux for IA-64 machines"
 mainmenu_option next_comment
 comment 'General setup'
 
+define_bool CONFIG_IA64 y
+
 choice 'IA-64 system type'                                     \
        "Generic                CONFIG_IA64_GENERIC             \
         HP-simulator           CONFIG_IA64_HP_SIM              \
index 1342e64f0125822b9e3876ce980c87b061e173b4..82ba58129beb205640cd6f46a07400a740f84835 100644 (file)
@@ -144,7 +144,7 @@ ia32_syscall_table:
        data8 sys32_settimeofday
        data8 sys_getgroups       /* 80 */
        data8 sys_setgroups
-       data8 sys_ni_syscall
+       data8 old_select
        data8 sys_symlink
        data8 sys_ni_syscall
        data8 sys_readlink        /* 85 */
index ed443ee66ddef43a1bbdda077a56ad2a63c6e0b0..2c2c53741e202d9c5c6f4d025f2d9ce743929abb 100644 (file)
@@ -342,7 +342,16 @@ ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
 }
 
 asmlinkage int
-sys32_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack)
+sys32_sigreturn(
+int arg0,
+int arg1,
+int arg2,
+int arg3,
+int arg4,
+int arg5,
+int arg6,
+int arg7,
+unsigned long stack)
 {
        struct pt_regs *regs = (struct pt_regs *) &stack;
        struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(regs->r12- 8);
@@ -375,7 +384,16 @@ badframe:
 }      
 
 asmlinkage int
-sys32_rt_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack)
+sys32_rt_sigreturn(
+int arg0,
+int arg1,
+int arg2,
+int arg3,
+int arg4,
+int arg5,
+int arg6,
+int arg7,
+unsigned long stack)
 {
        struct pt_regs *regs = (struct pt_regs *) &stack;
        struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(regs->r12 - 4);
index 7b4c4995eb92e5465a3d6a64a847b44fcebcb38a..d61f1cfe5e142802a3b0a236a9108045ee90e88f 100644 (file)
@@ -240,18 +240,29 @@ do_mmap_fake(struct file *file, unsigned long addr, unsigned long len,
                return -EINVAL;
        if (prot & PROT_WRITE)
                prot |= PROT_EXEC;
+#ifdef DDD
+#else  // DDD
+       prot |= PROT_WRITE;
+#endif // DDD
        front = NULL;
        back = NULL;
        if ((baddr = (addr & PAGE_MASK)) != addr && get_user(c, (char *)baddr) == 0) {
                front = kmalloc(addr - baddr, GFP_KERNEL);
                memcpy(front, (void *)baddr, addr - baddr);
        }
-       if ((addr + len) & ~PAGE_MASK && get_user(c, (char *)(addr + len)) == 0) {
+#ifndef        DDD
+       if (addr)
+#endif
+       if (((addr + len) & ~PAGE_MASK) && get_user(c, (char *)(addr + len)) == 0) {
                back = kmalloc(PAGE_SIZE - ((addr + len) & ~PAGE_MASK), GFP_KERNEL);
                memcpy(back, addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
        }
        if ((r = do_mmap(0, baddr, len + (addr - baddr), prot, flags | MAP_ANONYMOUS, 0)) < 0)
                return(r);
+#ifndef        DDD
+       if (addr == 0)
+               addr = r;
+#endif // DDD
        if (back) {
                memcpy(addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
                kfree(back);
@@ -315,7 +326,11 @@ sys32_mmap(struct mmap_arg_struct *arg)
        }
        a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
+#ifdef DDD
        if ((a.flags & MAP_FIXED) && ((a.addr & ~PAGE_MASK) || (a.offset & ~PAGE_MASK))) {
+#else  // DDD
+       if (1) {
+#endif // DDD
                unlock_kernel();
                up(&current->mm->mmap_sem);
                error = do_mmap_fake(file, a.addr, a.len, a.prot, a.flags, a.offset);
@@ -665,7 +680,7 @@ struct dirent32 {
 };
 
 static void
-xlate_dirent(void *dirent, long n)
+xlate_dirent(void *dirent64, void *dirent32, long n)
 {
        long off;
        struct dirent *dirp;
@@ -673,9 +688,9 @@ xlate_dirent(void *dirent, long n)
 
        off = 0;
        while (off < n) {
-               dirp = (struct dirent *)(dirent + off);
+               dirp = (struct dirent *)(dirent64 + off);
+               dirp32 = (struct dirent32 *)(dirent32 + off);
                off += dirp->d_reclen;
-               dirp32 = (struct dirent32 *)dirp;
                dirp32->d_ino = dirp->d_ino;
                dirp32->d_off = (unsigned int)dirp->d_off;
                dirp32->d_reclen = dirp->d_reclen;
@@ -685,26 +700,27 @@ xlate_dirent(void *dirent, long n)
 }
 
 asmlinkage long
-sys32_getdents(unsigned int fd, void * dirent, unsigned int count)
+sys32_getdents(unsigned int fd, void * dirent32, unsigned int count)
 {
        long n;
+       void *dirent64;
 
-       if ((n = sys_getdents(fd, dirent, count)) < 0)
+       dirent64 = (unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
+       if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0)
                return(n);
-       xlate_dirent(dirent, n);
+       xlate_dirent(dirent64, dirent32, n);
        return(n);
 }
 
 asmlinkage int
-sys32_readdir(unsigned int fd, void * dirent, unsigned int count)
+sys32_readdir(unsigned int fd, void * dirent32, unsigned int count)
 {
        int n;
-       struct dirent *dirp;
+       struct dirent dirent64;
 
-       if ((n = old_readdir(fd, dirent, count)) < 0)
+       if ((n = old_readdir(fd, &dirent64, count)) < 0)
                return(n);
-       dirp = (struct dirent *)dirent;
-       xlate_dirent(dirent, dirp->d_reclen);
+       xlate_dirent(&dirent64, dirent32, dirent64.d_reclen);
        return(n);
 }
 
@@ -809,6 +825,23 @@ out_nofds:
        return ret;
 }
 
+struct sel_arg_struct {
+       unsigned int n;
+       unsigned int inp;
+       unsigned int outp;
+       unsigned int exp;
+       unsigned int tvp;
+};
+
+asmlinkage int old_select(struct sel_arg_struct *arg)
+{
+       struct sel_arg_struct a;
+
+       if (copy_from_user(&a, arg, sizeof(a)))
+               return -EFAULT;
+       return sys32_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+}
+
 struct rusage32 {
         struct timeval32 ru_utime;
         struct timeval32 ru_stime;
index dd7de2ab079e4c5e76e1f29e301b3d6773ea43ff..6e0d09ea7f919815ed9ce20a6866da1bf4ac96e4 100644 (file)
@@ -15,7 +15,6 @@
  *
  * Implemented EFI runtime services and virtual mode calls.  --davidm
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -166,14 +165,12 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
                      case EFI_BOOT_SERVICES_CODE:
                      case EFI_BOOT_SERVICES_DATA:
                      case EFI_CONVENTIONAL_MEMORY:
-#ifndef CONFIG_IA64_VIRTUAL_MEM_MAP
                        if (md->phys_addr > 1024*1024*1024UL) {
                                printk("Warning: ignoring %luMB of memory above 1GB!\n",
                                       md->num_pages >> 8);
                                md->type = EFI_UNUSABLE_MEMORY;
                                continue;
                        }
-#endif
 
                        curr.start = PAGE_OFFSET + md->phys_addr;
                        curr.end   = curr.start + (md->num_pages << 12);
index 87e77c67733e2f7aaf3125e51d38bdf92b1469c5..47b972cb492f7c522ed7c42392f1a178fe25be15 100644 (file)
@@ -496,18 +496,27 @@ ia64_ret_from_syscall:
 (p7)   br.cond.spnt.few handle_syscall_error   // handle potential syscall failure
 
 ia64_leave_kernel:
-       // check & deliver software interrupts (bottom half handlers):
+       // check & deliver software interrupts:
 
-       movl r2=bh_active               // sheesh, why aren't these two in
-       movl r3=bh_mask                 // a struct??
+#ifdef CONFIG_SMP
+       adds    r2=IA64_TASK_PROCESSOR_OFFSET,r13
+       movl    r3=softirq_state
        ;;
-       ld8 r2=[r2]
-       ld8 r3=[r3]
+       ld4     r2=[r2]
+       ;;
+       shladd  r3=r2,3,r3
+#else
+       movl r3=softirq_state
+#endif
+       ;;
+       ld8 r2=[r3]             // r3 is guaranteed to be 8-byte aligned!
+       ;;
+       shr r3=r2,32
        ;;
        and r2=r2,r3
        ;;
-       cmp.ne p6,p7=r2,r0              // any soft interrupts ready for delivery?
-(p6)   br.call.dpnt.few rp=invoke_do_bottom_half
+       cmp4.ne p6,p7=r2,r0
+(p6)   br.call.spnt.many rp=invoke_do_softirq
 1:
 (pKern)        br.cond.dpnt.many restore_all   // yup -> skip check for rescheduling & signal delivery
 
@@ -751,20 +760,20 @@ invoke_schedule_tail:
 #endif /* CONFIG_SMP */
 
        /*
-        * Invoke do_bottom_half() while preserving in0-in7, which may be needed
+        * Invoke do_softirq() while preserving in0-in7, which may be needed
         * in case a system call gets restarted.
         */
-       .proc invoke_do_bottom_half
-invoke_do_bottom_half:
+       .proc invoke_do_softirq
+invoke_do_softirq:
        alloc loc0=ar.pfs,8,2,0,0
        mov loc1=rp
        ;;
-       br.call.sptk.few rp=do_bottom_half
+       br.call.sptk.few rp=do_softirq
 .ret9:
        mov ar.pfs=loc0
        mov rp=loc1
        br.ret.sptk.many rp
-       .endp invoke_do_bottom_half
+       .endp invoke_do_softirq
 
        /*
         * Invoke schedule() while preserving in0-in7, which may be needed
index 24dc10ee4e0053b8770dc2cf2cda274724399ca6..65de8e589712e7ccd472e4232ea5237d1c0c9a8d 100644 (file)
@@ -132,6 +132,7 @@ back_from_setup_rbs:
        ld8 r8=[base0]                          // restore (perhaps modified) CFM0, EC0, and CPL0
        cmp.ne p8,p0=r14,r15                    // do we need to restore the rbs?
 (p8)   br.cond.spnt.few restore_rbs            // yup -> (clobbers r14 and r16)
+       ;;
 back_from_restore_rbs:
        {
          and r9=0x7f,r8                        // r9  <- CFM0.sof
index 50d965e029f070f31649dacda151d7af7d3f2471..35a52628ae093a6e002d02601279c68d45c85681 100644 (file)
@@ -133,6 +133,7 @@ alive_msg:
 #endif /* CONFIG_IA64_EARLY_PRINTK */
 
        alloc r2=ar.pfs,8,0,2,0
+       ;;
 #ifdef CONFIG_SMP
 (isAP) br.call.sptk.few rp=smp_callin
 .ret1:
@@ -174,7 +175,7 @@ ia64_save_debug_regs:
        st8.nta [in0]=r16,8
        st8.nta [r19]=r17,8
        br.cloop.sptk.few 1b
-
+       ;;
        mov ar.lc=r20                   // restore ar.lc
        br.ret.sptk.few b0
        .endp ia64_save_debug_regs
@@ -197,7 +198,7 @@ ia64_load_debug_regs:
        mov dbr[r18]=r16
        mov ibr[r18]=r17
        br.cloop.sptk.few 1b
-
+       ;;
        mov ar.lc=r20                   // restore ar.lc
        br.ret.sptk.few b0
        .endp ia64_load_debug_regs
index 01c20113757f13af0a1b2d51983d7b90bbada880..5efe501645fc470f532f801c1789daddde1c2178 100644 (file)
@@ -128,6 +128,18 @@ get_irq_list (char *buf)
        return p - buf;
 }
 
+int usbfix;
+
+static int __init
+usbfix_option (char *str)
+{
+       printk("irq: enabling USB workaround\n");
+       usbfix = 1;
+       return 1;
+}
+
+__setup("usbfix", usbfix_option);
+
 /*
  * That's where the IVT branches when we get an external
  * interrupt. This branches to the correct hardware IRQ handler via
@@ -146,7 +158,8 @@ ia64_handle_irq (unsigned long irq, struct pt_regs *regs)
        unsigned long eoi_ptr;
  
 # ifdef CONFIG_USB
-       disable_usb();
+       if (usbfix)
+               disable_usb();
 # endif
        /*
         * Stop IPIs by getting the ivr_read_lock
@@ -170,7 +183,8 @@ ia64_handle_irq (unsigned long irq, struct pt_regs *regs)
        spin_unlock(&ivr_read_lock);
 
 # ifdef CONFIG_USB
-       reenable_usb();
+       if (usbfix)
+               reenable_usb();
 # endif
 
 # ifndef CONFIG_SMP
index 9c512dd4ef74b4b9111cb7cc54c13f76eabaf133..4a2ead673840240309ba16ed283951d7fd64ae10 100644 (file)
@@ -26,7 +26,7 @@ int global_irq_holder = NO_PROC_ID;
 spinlock_t global_irq_lock;
 atomic_t global_irq_count;
 atomic_t global_bh_count;
-atomic_t global_bh_lock;
+spinlock_t global_bh_lock;
 
 #define INIT_STUCK (1<<26)
 
index f86f45537587cf18f5882a684702ece410ccf0d0..9989356d3eba0cfc990bb0b22c363b820b6f2531 100644 (file)
@@ -21,7 +21,7 @@
 extern __inline__ unsigned long
 get_order (unsigned long size)
 {
-       unsigned long order = ia64_fls(size);
+       unsigned long order = ia64_fls(size - 1) + 1;
 
        printk ("get_order: size=%lu, order=%lu\n", size, order);
 
index 3bceeed8e1ad52389cce538f147bd7bd31a8b659..4acc7f04182d88d3ebf8d11e56c42d320bd00ca8 100644 (file)
@@ -226,14 +226,3 @@ void
 pcibios_align_resource (void *data, struct resource *res, unsigned long size)
 {
 }
-
-#if 0 /*def CONFIG_PROC_FS*/
-/*
- * This is an ugly hack to get a (weak) unresolved reference to something that is
- * in drivers/pci/proc.c.  Without this, the file does not get linked in at all
- * (I suspect the reason this isn't needed on Linux/x86 is that most people compile
- * with module support, in which case the EXPORT_SYMBOL() stuff will ensure the
- * code gets linked in.  Sigh...  --davidm 99/12/20.
- */
-asm ("data8 proc_bus_pci_add");
-#endif
index 48a3d68b4b8581d49d2177d59db9a14605029837..ed5d594a63b07c46875681a8903ae8c2d0cbac92 100644 (file)
@@ -57,7 +57,7 @@ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
 unsigned long cpu_online_map = 1;
 #endif
 
-volatile int cpu_number_map[NR_CPUS] = { -1, };      /* SAPIC ID -> Logical ID */
+volatile int __cpu_number_map[NR_CPUS] = { -1, };    /* SAPIC ID -> Logical ID */
 volatile int __cpu_logical_map[NR_CPUS] = { -1, };   /* logical ID -> SAPIC ID */
 int smp_num_cpus = 1;          
 int bootstrap_processor = -1;                        /* SAPIC ID of BSP */
@@ -586,7 +586,7 @@ smp_boot_one_cpu(int cpuid, int cpunum)
 
 alive:
        /* Remember the AP data */
-       cpu_number_map[cpuid] = cpunum;
+       __cpu_number_map[cpuid] = cpunum;
 #ifdef CONFIG_KDB
         cpu_online_map |= (1<<cpunum);
         printk ("DEBUGGER: cpu_online_map = 0x%08x\n", cpu_online_map);
@@ -612,12 +612,12 @@ smp_boot_cpus(void)
        extern int acpi_apic_map[32];
 
        /* Take care of some initial bookkeeping.  */
-       memset(&cpu_number_map, -1, sizeof(cpu_number_map));
+       memset(&__cpu_number_map, -1, sizeof(__cpu_number_map));
        memset(&__cpu_logical_map, -1, sizeof(__cpu_logical_map));
        memset(&ipi_op, 0, sizeof(ipi_op));
 
        /* Setup BSP mappings */
-       cpu_number_map[bootstrap_processor] = 0;
+       __cpu_number_map[bootstrap_processor] = 0;
        __cpu_logical_map[0] = bootstrap_processor;
        current->processor = bootstrap_processor;
 
index 18a498a09ed5b5d41d82ac5d4c73336d70b98c1d..f06d3bea8e3a2c11c3dc5ba840a45128117f2e23 100644 (file)
@@ -2,8 +2,8 @@
  * This file contains various system calls that have different calling
  * conventions on different platforms.
  *
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #include <linux/config.h>
 #include <linux/errno.h>
index 8a958174799d71db633663b6f13522926a95584c..88a4aadd479745f8481390cfcd5d41aef7efdf87 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 .S.o:
-       $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $@
+       $(CC) -D__ASSEMBLY__ $(AFLAGS) -c $< -o $@
 
 OBJS  = __divdi3.o __divsi3.o __udivdi3.o __udivsi3.o          \
        __moddi3.o __modsi3.o __umoddi3.o __umodsi3.o           \
index 85b15aae1ffe8a8ec88597bbd21819cd4a185758..f1b298e211228e268b81ab74df90351eadbf83b7 100644 (file)
@@ -47,6 +47,7 @@ tab[] =
     { "IA64_TASK_FLAGS_OFFSET",                offsetof (struct task_struct, flags) },
     { "IA64_TASK_SIGPENDING_OFFSET",   offsetof (struct task_struct, sigpending) },
     { "IA64_TASK_NEED_RESCHED_OFFSET", offsetof (struct task_struct, need_resched) },
+    { "IA64_TASK_PROCESSOR_OFFSET",    offsetof (struct task_struct, processor) },
     { "IA64_TASK_THREAD_OFFSET",       offsetof (struct task_struct, thread) },
     { "IA64_TASK_THREAD_KSP_OFFSET",   offsetof (struct task_struct, thread.ksp) },
     { "IA64_TASK_PID_OFFSET",          offsetof (struct task_struct, pid) },
index 7defc69e870d7c4ffee1c5484b22dbbf2d6de3f4..05639bdd1c242e20deeee5497f862975bdf237fa 100644 (file)
@@ -9,7 +9,7 @@
        .text
 
 /*
- * Use the BAT0 registers to map the 1st 8MB of RAM to
+ * Use the BAT3 registers to map the 1st 8MB of RAM to
  * the address given as the 1st argument.
  */
        .globl  setup_bats
index ac258f16e74b1cef765daa65af8f4991b1a93b52..17217702f86864066f42417473874cfe056f282a 100644 (file)
@@ -24,7 +24,7 @@ CONFIG_ALL_PPC=y
 # CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
 # CONFIG_SMP is not set
-# CONFIG_ALTIVEC is not set
+CONFIG_ALTIVEC=y
 
 #
 # Loadable module support
@@ -76,7 +76,7 @@ CONFIG_BOOTX_TEXT=y
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -178,9 +178,12 @@ CONFIG_SCSI=y
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
 
 #
@@ -239,6 +242,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
@@ -275,6 +279,7 @@ CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
 CONFIG_BMAC=y
+CONFIG_GMAC=y
 # CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -472,6 +477,7 @@ CONFIG_USB=y
 # USB Controllers
 #
 # CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
 CONFIG_USB_OHCI=y
 
 #
@@ -491,8 +497,7 @@ CONFIG_USB_OHCI=y
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_OV511 is not set
 # CONFIG_USB_DC2XX is not set
-CONFIG_USB_SCSI=m
-CONFIG_USB_SCSI_DEBUG=y
+# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_DABUSB is not set
 
 #
@@ -513,11 +518,15 @@ CONFIG_USB_MOUSE=y
 #
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
+CONFIG_HFS_FS=y
 # CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=y
@@ -549,10 +558,51 @@ CONFIG_LOCKD=y
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
 
 #
 # Sound
index 6fe267c9a184f4902e9299a39369674aa83915fa..90cc5b71f3dc673b9b5588cdd1b0b71dd394a95b 100644 (file)
@@ -24,7 +24,7 @@ CONFIG_6xx=y
 CONFIG_GEMINI=y
 # CONFIG_APUS is not set
 # CONFIG_SMP is not set
-# CONFIG_ALTIVEC is not set
+CONFIG_ALTIVEC=y
 CONFIG_MACH_SPECIFIC=y
 
 #
@@ -87,7 +87,6 @@ CONFIG_KERNEL_ELF=y
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_IDE_MODES is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -151,9 +150,12 @@ CONFIG_SCSI=y
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_CHR_DEV_ST is not set
+CONFIG_ST_EXTRA_DEVS=2
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
 # CONFIG_CHR_DEV_SG is not set
 
 #
@@ -208,6 +210,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
@@ -216,6 +219,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_MESH is not set
 # CONFIG_SCSI_MAC53C94 is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -242,6 +246,7 @@ CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
 CONFIG_NCR885E=y
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -369,6 +374,7 @@ CONFIG_UNIX98_PTY_COUNT=256
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -405,10 +411,7 @@ CONFIG_LOCKD=y
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
index ac258f16e74b1cef765daa65af8f4991b1a93b52..17217702f86864066f42417473874cfe056f282a 100644 (file)
@@ -24,7 +24,7 @@ CONFIG_ALL_PPC=y
 # CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
 # CONFIG_SMP is not set
-# CONFIG_ALTIVEC is not set
+CONFIG_ALTIVEC=y
 
 #
 # Loadable module support
@@ -76,7 +76,7 @@ CONFIG_BOOTX_TEXT=y
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -178,9 +178,12 @@ CONFIG_SCSI=y
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
 
 #
@@ -239,6 +242,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
@@ -275,6 +279,7 @@ CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
 CONFIG_BMAC=y
+CONFIG_GMAC=y
 # CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -472,6 +477,7 @@ CONFIG_USB=y
 # USB Controllers
 #
 # CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
 CONFIG_USB_OHCI=y
 
 #
@@ -491,8 +497,7 @@ CONFIG_USB_OHCI=y
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_OV511 is not set
 # CONFIG_USB_DC2XX is not set
-CONFIG_USB_SCSI=m
-CONFIG_USB_SCSI_DEBUG=y
+# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_DABUSB is not set
 
 #
@@ -513,11 +518,15 @@ CONFIG_USB_MOUSE=y
 #
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
+CONFIG_HFS_FS=y
 # CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=y
@@ -549,10 +558,51 @@ CONFIG_LOCKD=y
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
 
 #
 # Sound
index 2d1238a6baf35ec153b7666385277dfdacd60bc9..013812afc4da010469cc8ab26ef44212586dbfe5 100644 (file)
@@ -176,7 +176,7 @@ ret_from_syscall_2:
 7:     .string "syscall %d(%x, %x, %x, %x, %x, "
 77:    .string "%x, %x), current=%p\n"
 79:    .string " -> %x\n"
-       .align  2
+       .align  2,0
 #endif
 
 /*
@@ -209,6 +209,9 @@ _GLOBAL(_switch)
        mflr    r20             /* Return to switch caller */
        mfmsr   r22
        li      r0,MSR_FP       /* Disable floating-point */
+#ifdef CONFIG_ALTIVEC
+       oris    r0,r0,MSR_VEC@h
+#endif /* CONFIG_ALTIVEC */
        andc    r22,r22,r0
        stw     r20,_NIP(r1)
        stw     r22,_MSR(r1)
@@ -274,7 +277,7 @@ _GLOBAL(_switch)
        SYNC
        rfi
 
-#ifdef __SMP__ 
+#ifdef CONFIG_SMP      
        .globl  ret_from_smpfork
 ret_from_smpfork:
        bl      schedule_tail
@@ -310,22 +313,32 @@ ret_from_except:
        lwz     r5,_MSR(r1)
        andi.   r5,r5,MSR_EE
        beq     2f
+       .globl  lost_irq_ret
+lost_irq_ret:
 3:     lis     r4,ppc_n_lost_interrupts@ha
        lwz     r4,ppc_n_lost_interrupts@l(r4)
        cmpi    0,r4,0
        beq+    1f
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      do_IRQ
-       .globl  lost_irq_ret
-lost_irq_ret:
        b       3b
-1:     lis     r4,bh_mask@ha
-       lwz     r4,bh_mask@l(r4)
-       lis     r5,bh_active@ha
-       lwz     r5,bh_active@l(r5)
-       and.    r4,r4,r5
+1:     lis     r4,softirq_state@ha
+       addi    r4,r4,softirq_state@l
+#ifdef CONFIG_SMP
+       /* get processor # */
+       lwz     r3,PROCESSOR(r2)
+#ifndef CONFIG_PPC64
+       slwi    r3,r3,5
+#else
+#error not 64-bit ready        
+#endif
+       add     r4,r4,r3
+#endif /* CONFIG_SMP */
+       lwz     r5,0(r4)
+       lwz     r4,4(r4)
+       and.    r5,r5,r4
        beq+    2f
-       bl      do_bottom_half
+       bl      do_softirq
        .globl  do_bottom_half_ret
 do_bottom_half_ret:
 2:     /* disable interrupts */        
index 8b56c635cba32187adc18382949fcc70805eb349..dd16b8c27174150be72387f4d22880a6544de3a4 100644 (file)
@@ -460,8 +460,24 @@ SystemCall:
        STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
 
        STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
-#ifdef CONFIG_ALTIVEC  
-       STD_EXCEPTION(0xf20, AltiVec, AltiVecUnavailable)
+#ifndef CONFIG_ALTIVEC
+       STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+#else  
+/*
+ * The Altivec unavailable trap is at 0x0f20.  Foo.
+ * We effectively remap it to 0x3000.
+ */
+       . = 0xf00
+       b       Trap_0f
+trap_0f_cont:
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       bl      transfer_to_handler
+       .long   UnknownException
+       .long   ret_from_except
+
+       . = 0xf20
+       b       AltiVecUnavailable
 #endif /* CONFIG_ALTIVEC */
 
 /*
@@ -674,6 +690,21 @@ DataStoreTLBMiss:
 
        . = 0x3000
 
+#ifdef CONFIG_ALTIVEC
+AltiVecUnavailable:
+       EXCEPTION_PROLOG
+       bne     load_up_altivec         /* if from user, just load it up */
+       li      r20,MSR_KERNEL
+       bl      transfer_to_handler     /* if from kernel, take a trap */
+       .long   KernelAltiVec
+       .long   ret_from_except
+
+/* here are the bits of trap 0xf00 which got displaced */
+Trap_0f:
+       EXCEPTION_PROLOG
+       b       trap_0f_cont
+#endif /* CONFIG_ALTIVEC */
+       
 /*
  * This code finishes saving the registers to the exception frame
  * and jumps to the appropriate handler for the exception, turning
@@ -813,72 +844,134 @@ KernelFP:
 86:    .string "floating point used in kernel (task=%p, pc=%x)\n"
        .align  4
 
+#ifdef CONFIG_ALTIVEC
+/* Note that the AltiVec support is closely modeled after the FP
+ * support.  Changes to one are likely to be applicable to the
+ * other!  */
+load_up_altivec:
 /*
- * Take away the altivec regs.
- *
- * For now, ignore the vrsave regs and save them all
- *   -- Cort
+ * Disable AltiVec for the task which had AltiVec previously,
+ * and save its AltiVec registers in its thread_struct.
+ * Enables AltiVec for use in the kernel on return.
+ * On SMP we know the AltiVec units are free, since we give it up every
+ * switch.  -- Kumar
  */
-       .globl giveup_altivec
-giveup_altivec:
-#ifdef CONFIG_ALTIVEC  
-       /* check for altivec */
-       mfspr   r4,PVR
-       srwi    r4,r4,16
-       cmpi    0,r4,12
-       bnelr
-       
-       /* enable altivec so we can save */
-       mfmsr   r4
-       oris    r4,r4,MSR_VEC@h
-       mtmsr   r4
+       mfmsr   r5
+       oris    r5,r5,MSR_VEC@h
+       SYNC
+       mtmsr   r5                      /* enable use of AltiVec now */
+       SYNC
+/*
+ * For SMP, we don't do lazy AltiVec switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another.  Instead we call giveup_altivec in switch_to.
+ */
+#ifndef __SMP__
+#ifndef CONFIG_APUS
+       lis     r6,-KERNELBASE@h
+#else
+       lis     r6,CYBERBASEp@h
+       lwz     r6,0(r6)
+#endif
+       addis   r3,r6,last_task_used_altivec@ha
+       lwz     r4,last_task_used_altivec@l(r3)
+       cmpi    0,r4,0
+       beq     1f
+       add     r4,r4,r6
+       addi    r4,r4,THREAD    /* want THREAD of last_task_used_altivec */
+       SAVE_32VR(0,r20,r4)
+       MFVSCR(vr0)
+       li      r20,THREAD_VSCR
+       STVX(vr0,r20,r4)
+       lwz     r5,PT_REGS(r4)
+       add     r5,r5,r6
+       lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+       lis     r20,MSR_VEC@h
+       andc    r4,r4,r20       /* disable altivec for previous task */
+       stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* __SMP__ */
+       /* enable use of AltiVec after return */
+       oris    r23,r23,MSR_VEC@h
+       mfspr   r5,SPRG3                /* current task's THREAD (phys) */
+       li      r20,THREAD_VSCR
+       LVX(vr0,r20,r5)
+       MTVSCR(vr0)
+       REST_32VR(0,r20,r5)
+#ifndef __SMP__
+       subi    r4,r5,THREAD
+       sub     r4,r4,r6
+       stw     r4,last_task_used_altivec@l(r3)
+#endif /* __SMP__ */
+       /* restore registers and return */
+       lwz     r3,_CCR(r21)
+       lwz     r4,_LINK(r21)
+       mtcrf   0xff,r3
+       mtlr    r4
+       REST_GPR(1, r21)
+       REST_4GPRS(3, r21)
+       /* we haven't used ctr or xer */
+       mtspr   SRR1,r23
+       mtspr   SRR0,r22
+       REST_GPR(20, r21)
+       REST_2GPRS(22, r21)
+       lwz     r21,GPR21(r21)
+       SYNC
+       rfi
 
-       /* make sure our tsk pointer is valid */
-       cmpi    0,r3,0
-       beqlr
+/*
+ * AltiVec unavailable trap from kernel - print a message, but let
+ * the task use AltiVec in the kernel until it returns to user mode.
+ */
+KernelAltiVec:
+       lwz     r3,_MSR(r1)
+       oris    r3,r3,MSR_VEC@h
+       stw     r3,_MSR(r1)     /* enable use of AltiVec after return */
+       lis     r3,87f@h
+       ori     r3,r3,87f@l
+       mr      r4,r2           /* current */
+       lwz     r5,_NIP(r1)
+       bl      printk
+       b       ret_from_except
+87:    .string "AltiVec used in kernel  (task=%p, pc=%x)  \n"
+       .align  4
 
-       /* save altivec regs */
-       addi    r4,r3,THREAD+THREAD_VRSAVE
-       mfspr   r5,256          /* vrsave */
-       stw     r5,0(r4)
-       
-       /* get regs for the task */
-       addi    r4,r3,THREAD+PT_REGS
-       /* turn off the altivec bit in the tasks regs */
-       lwz     r5,_MSR(r4)
-       lis     r6,MSR_VEC@h
-       andi.   r5,r5,r6
-       stw     r5,_MSR(r4)
-
-       /* we've given up the altivec - clear the pointer */
-       li      r3,0
-       lis     r4,last_task_used_altivec@h
-       stw     r3,last_task_used_altivec@l(r4)
-#endif /* CONFIG_ALTIVEC */
-       blr
-       
-       .globl load_up_altivec
-load_up_altivec:
-#ifdef CONFIG_ALTIVEC  
-       /* check for altivec */
-       mfspr   r4,PVR
-       srwi    r4,r4,16
-       cmpi    0,r4,12
-       bnelr
-       
-       /* restore altivec regs */
-       addi    r4,r3,THREAD+THREAD_VRSAVE
-       lwz     r5,0(r4)
-       mtspr   256,r5          /* vrsave */
-       
-       /* get regs for the task */
-       addi    r4,r3,THREAD+PT_REGS
-       /* turn on the altivec bit in the tasks regs */
-       lwz     r5,_MSR(r4)
+/*
+ * giveup_altivec(tsk)
+ * Disable AltiVec for the task given as the argument,
+ * and save the AltiVec registers in its thread_struct.
+ * Enables AltiVec for use in the kernel on return.
+ */
+
+       .globl  giveup_altivec
+giveup_altivec:
+       mfmsr   r5
        oris    r5,r5,MSR_VEC@h
-       stw     r5,_MSR(r4)
-#endif /* CONFIG_ALTIVEC */
+       SYNC
+       mtmsr   r5                      /* enable use of AltiVec now */
+       SYNC
+       cmpi    0,r3,0
+       beqlr-                          /* if no previous owner, done */
+       addi    r3,r3,THREAD            /* want THREAD of task */
+       lwz     r5,PT_REGS(r3)
+       cmpi    0,r5,0
+       SAVE_32VR(0, r4, r3)
+       MFVSCR(vr0)
+       li      r4,THREAD_VSCR
+       STVX(vr0, r4, r3)
+       beq     1f
+       lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+       lis     r3,MSR_VEC@h
+       andc    r4,r4,r3                /* disable AltiVec for previous task */
+       stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef __SMP__
+       li      r5,0
+       lis     r4,last_task_used_altivec@ha
+       stw     r5,last_task_used_altivec@l(r4)
+#endif /* __SMP__ */
        blr
+#endif /* CONFIG_ALTIVEC */
        
 /*
  * giveup_fpu(tsk)
@@ -1437,17 +1530,16 @@ mmu_off:
 
 #if 0 /* That's useful debug stuff */
 setup_screen_bat:
+       li      r3,0
+       mtspr   DBAT1U,r3
+       mtspr   IBAT1U,r3
        lis     r3, 0x9100
-#ifdef __SMP__
-       ori     r3,r3,0x12
-#else
-       ori     r3,r3,0x2
-#endif
-       mtspr   DBAT1L, r3
-       mtspr   IBAT1L, r3
+       ori     r4,r3,0x2a
+       mtspr   DBAT1L,r4
+       mtspr   IBAT1L,r4
        ori     r3,r3,(BL_8M<<2)|0x2    /* set up BAT registers for 604 */
-       mtspr   DBAT1U, r3
-       mtspr   IBAT1U, r3
+       mtspr   DBAT1U,r3
+       mtspr   IBAT1U,r3
        blr
 #endif
        
index 8b5f590fb780c5c24215eabad3e75c22865d5880..fd77fbc367a419da5b6809c699755e2b3c5ce76a 100644 (file)
@@ -74,8 +74,8 @@ volatile unsigned char *chrp_int_ack_special;
 
 irq_desc_t irq_desc[NR_IRQS];
 int ppc_spurious_interrupts = 0;
-unsigned int ppc_local_bh_count[NR_CPUS];
-unsigned int ppc_local_irq_count[NR_CPUS];
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
 struct irqaction *ppc_irq_action[NR_IRQS];
 unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
 unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
@@ -350,7 +350,6 @@ unsigned volatile int global_irq_lock;
 atomic_t global_irq_count;
 
 atomic_t global_bh_count;
-atomic_t global_bh_lock;
 
 static void show(char * str)
 {
@@ -361,12 +360,12 @@ static void show(char * str)
        printk("\n%s, CPU %d:\n", str, cpu);
        printk("irq:  %d [%d %d]\n",
               atomic_read(&global_irq_count),
-              ppc_local_irq_count[0],
-              ppc_local_irq_count[1]);
+              local_irq_count[0],
+              local_irq_count[1]);
        printk("bh:   %d [%d %d]\n",
               atomic_read(&global_bh_count),
-              ppc_local_bh_count[0],
-              ppc_local_bh_count[1]);
+              local_bh_count[0],
+              local_bh_count[1]);
        stack = (unsigned long *) &str;
        for (i = 40; i ; i--) {
                unsigned long x = *++stack;
@@ -401,7 +400,7 @@ static inline void wait_on_irq(int cpu)
                 * already executing in one..
                 */
                if (!atomic_read(&global_irq_count)) {
-                       if (ppc_local_bh_count[cpu]
+                       if (local_bh_count[cpu]
                            || !atomic_read(&global_bh_count))
                                break;
                }
@@ -423,7 +422,7 @@ static inline void wait_on_irq(int cpu)
                                continue;
                        if (global_irq_lock)
                                continue;
-                       if (!ppc_local_bh_count[cpu]
+                       if (!local_bh_count[cpu]
                            && atomic_read(&global_bh_count))
                                continue;
                        if (!test_and_set_bit(0,&global_irq_lock))
@@ -514,7 +513,7 @@ void __global_cli(void)
        if (flags & (1 << 15)) {
                int cpu = smp_processor_id();
                __cli();
-               if (!ppc_local_irq_count[cpu])
+               if (!local_irq_count[cpu])
                        get_irqlock(cpu);
        }
 }
@@ -523,7 +522,7 @@ void __global_sti(void)
 {
        int cpu = smp_processor_id();
 
-       if (!ppc_local_irq_count[cpu])
+       if (!local_irq_count[cpu])
                release_irqlock(cpu);
        __sti();
 }
@@ -547,7 +546,7 @@ unsigned long __global_save_flags(void)
        retval = 2 + local_enabled;
 
        /* check for global flags if we're not in an interrupt */
-       if (!ppc_local_irq_count[smp_processor_id()]) {
+       if (!local_irq_count[smp_processor_id()]) {
                if (local_enabled)
                        retval = 1;
                if (global_irq_holder == (unsigned char) smp_processor_id())
index fde7112c7722a36e2e239ea4bc9ef75c60e32546..a543169e7afd0e3ee675c19b2499b76ec470d666 100644 (file)
@@ -271,6 +271,38 @@ _GLOBAL(clear_page)
        bdnz    1b
        blr
 
+/*
+ * Copy a whole page.  We use the dcbz instruction on the destination
+ * to reduce memory traffic (it eliminates the unnecessary reads of
+ * the destination into cache).  This requires that the destination
+ * is cacheable.
+ */
+_GLOBAL(copy_page)
+       li      r0,4096/CACHE_LINE_SIZE
+       mtctr   r0
+       addi    r3,r3,-4
+       addi    r4,r4,-4
+       li      r5,4
+1:     dcbz    r5,r3
+       lwz     r6,4(r4)
+       lwz     r7,8(r4)
+       lwz     r8,12(r4)
+       lwzu    r9,16(r4)
+       stw     r6,4(r3)
+       stw     r7,8(r3)
+       stw     r8,12(r3)
+       stwu    r9,16(r3)
+       lwz     r6,4(r4)
+       lwz     r7,8(r4)
+       lwz     r8,12(r4)
+       lwzu    r9,16(r4)
+       stw     r6,4(r3)
+       stw     r7,8(r3)
+       stw     r8,12(r3)
+       stwu    r9,16(r3)
+       bdnz    1b
+       blr
+
 /*
  * Atomic [test&set] exchange
  *
index 34682bd2a89d7104855c70ca60dafe28164dc601..3efc7bbf9fcc568e366bac9d8d289e4c3a059077 100644 (file)
@@ -48,9 +48,11 @@ main(void)
        DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
        DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
        DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
-       DEFINE(THREAD_VRF, offsetof(struct thread_struct, vrf));
-       DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
+#ifdef CONFIG_ALTIVEC
+       DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
        DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
+       DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
+#endif /* CONFIG_ALTIVEC */
        /* Interrupt register frame */
        DEFINE(TASK_UNION_SIZE, sizeof(union task_union));
        DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
index d4dbe05e5cdf2b4ea145e49192dd59b9a7503841..301a82ba8f4cfc6d37162d89e77ae0226107280e 100644 (file)
@@ -279,7 +279,7 @@ void __init openpic_init(int main_pic)
                /* Initialize the spurious interrupt */
                if ( ppc_md.progress ) ppc_md.progress("openpic spurious",0x3bd);
                openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-               if ( !(_machine && (_MACH_gemini|_MACH_Pmac)) )
+               if ( !(_machine & (_MACH_gemini|_MACH_Pmac)) )
                {
                        if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
                                        "82c59 cascade", NULL))
@@ -490,7 +490,7 @@ void openpic_enable_irq(u_int irq)
        /* make sure mask gets to controller before we return to user */
        do {
                mb(); /* sync is probably useless here */
-       } while(openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
+       } while(openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority,
                        OPENPIC_MASK));
 }
 
@@ -501,7 +501,7 @@ void openpic_disable_irq(u_int irq)
        /* make sure mask gets to controller before we return to user */
        do {
                mb();  /* sync is probably useless here */
-       } while(!openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
+       } while(!openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority,
                        OPENPIC_MASK));
 }
 
index d2d5e6b25d59819fabb596dd619abdfbbc4957e1..d13875c9fde3937c6e1b57d1222dd3a50190b1b5 100644 (file)
@@ -31,8 +31,6 @@ static int max_irqs;
 static int max_real_irqs;
 static int has_openpic = 0;
 
-#define MAXCOUNT 10000000
-
 #define GATWICK_IRQ_POOL_SIZE        10
 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
 
@@ -187,25 +185,6 @@ pmac_get_irq(struct pt_regs *regs)
                smp_message_recv();
                return -2;      /* ignore, already handled */
         }
-
-        {
-                unsigned int loops = MAXCOUNT;
-                while (test_bit(0, &global_irq_lock)) {
-                        if (smp_processor_id() == global_irq_holder) {
-                                printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
-                                xmon(0);
-#endif
-                                break;
-                        }
-                        if (loops-- == 0) {
-                                printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
-                                xmon(0);
-#endif
-                        }
-                }
-        }
 #endif /* __SMP__ */
 
        /* Yeah, I know, this could be a separate do_IRQ function */
index e1c1815acf2f5515993a71a1d5ebfb985c5e2264..5fef07e89e8f0d50e0dc32a25ecb8a8d6352c714 100644 (file)
@@ -60,6 +60,7 @@
 #include <asm/machdep.h>
 #include <asm/keyboard.h>
 #include <asm/dma.h>
+#include <asm/bootx.h>
 
 #include "time.h"
 #include "local_irq.h"
@@ -440,6 +441,7 @@ kdev_t __init find_ide_boot(void)
 {
        char *p;
        int n;
+       kdev_t __init pmac_find_ide_boot(char *bootdevice, int n);
 
        if (bootdevice == NULL)
                return 0;
@@ -695,9 +697,12 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
 #ifdef CONFIG_BOOTX_TEXT
 extern void drawchar(char c);
 extern void drawstring(const char *c);
+extern boot_infos_t *disp_bi;
 void
 pmac_progress(char *s, unsigned short hex)
 {
+       if (disp_bi == 0)
+               return;
        drawstring(s);
        drawchar('\n');
 }
index 1c935a62565579c02ef044966e42c13642a9958e..3b7dd283f9d5a20afc34b0dc80693d0e01f75150 100644 (file)
@@ -71,8 +71,8 @@ unsigned long pmac_get_rtc_time(void)
                if (req.reply_len != 7)
                        printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
                               req.reply_len);
-               return (unsigned long)(req.reply[1] << 24) + (req.reply[2] << 16)
-                       + (req.reply[3] << 8) + (unsigned long)req.reply[4] - RTC_OFFSET;
+               return (req.reply[3] << 24) + (req.reply[4] << 16)
+                       + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
 #endif /* CONFIG_ADB_CUDA */
 #ifdef CONFIG_ADB_PMU
        case SYS_CTRLER_PMU:
index 2b999ab36878e3f3f31e32051ffca22613567d7d..d9093c9e19905a7a150a0f100ab03a43ad9a88a2 100644 (file)
 #define REST_16FPRS(n, base)   REST_8FPRS(n, base); REST_8FPRS(n+8, base)
 #define REST_32FPRS(n, base)   REST_16FPRS(n, base); REST_16FPRS(n+16, base)
 
+/*
+ * Once a version of gas that understands the AltiVec instructions
+ * is freely available, we can do this the normal way...  - paulus
+ */
+#define LVX(r,a,b)     .long   (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(103<<1)
+#define STVX(r,a,b)    .long   (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(231<<1)
+#define MFVSCR(r)      .long   (4<<26)+((r)<<21)+(1540<<1)
+#define MTVSCR(r)      .long   (4<<26)+((r)<<11)+(802<<1)
+
+#define SAVE_VR(n,b,base)      li b,THREAD_VR0+(16*(n)); STVX(n,b,base)
+#define SAVE_2VR(n,b,base)     SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) 
+#define SAVE_4VR(n,b,base)     SAVE_2VR(n,b,base); SAVE_2VR(n+2,b,base) 
+#define SAVE_8VR(n,b,base)     SAVE_4VR(n,b,base); SAVE_4VR(n+4,b,base) 
+#define SAVE_16VR(n,b,base)    SAVE_8VR(n,b,base); SAVE_8VR(n+8,b,base)
+#define SAVE_32VR(n,b,base)    SAVE_16VR(n,b,base); SAVE_16VR(n+16,b,base)
+#define REST_VR(n,b,base)      li b,THREAD_VR0+(16*(n)); LVX(n,b,base)
+#define REST_2VR(n,b,base)     REST_VR(n,b,base); REST_VR(n+1,b,base) 
+#define REST_4VR(n,b,base)     REST_2VR(n,b,base); REST_2VR(n+2,b,base) 
+#define REST_8VR(n,b,base)     REST_4VR(n,b,base); REST_4VR(n+4,b,base) 
+#define REST_16VR(n,b,base)    REST_8VR(n,b,base); REST_8VR(n+8,b,base) 
+#define REST_32VR(n,b,base)    REST_16VR(n,b,base); REST_16VR(n+16,b,base)
+
 #define SYNC \
        sync; \
        isync
index 94a5bd74c4893dffaaec52b9897bf14cfa717e14..c35192bb4fe631ff56ebcdb8ed3a7ddccfa176b7 100644 (file)
 #define        fr29    29
 #define        fr30    30
 #define        fr31    31
+
+#define        vr0     0
+#define        vr1     1
+#define        vr2     2
+#define        vr3     3
+#define        vr4     4
+#define        vr5     5
+#define        vr6     6
+#define        vr7     7
+#define        vr8     8
+#define        vr9     9
+#define        vr10    10
+#define        vr11    11
+#define        vr12    12
+#define        vr13    13
+#define        vr14    14
+#define        vr15    15
+#define        vr16    16
+#define        vr17    17
+#define        vr18    18
+#define        vr19    19
+#define        vr20    20
+#define        vr21    21
+#define        vr22    22
+#define        vr23    23
+#define        vr24    24
+#define        vr25    25
+#define        vr26    26
+#define        vr27    27
+#define        vr28    28
+#define        vr29    29
+#define        vr30    30
+#define        vr31    31
index 9a5444a51fac5318919e324ae9b86398d79ee903..d81f0056a8e865c4c997a6637a4731f42d88478d 100644 (file)
@@ -72,8 +72,8 @@ EXPORT_SYMBOL(do_lost_interrupts);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(disable_irq_nosync);
-EXPORT_SYMBOL(ppc_local_irq_count);
-EXPORT_SYMBOL(ppc_local_bh_count);
+EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(local_bh_count);
 #ifdef __SMP__
 EXPORT_SYMBOL(kernel_flag);
 #endif /* __SMP__ */
@@ -272,4 +272,3 @@ EXPORT_SYMBOL(ppc_irq_dispatch_handler);
 EXPORT_SYMBOL(decrementer_count);
 EXPORT_SYMBOL(get_wchan);
 EXPORT_SYMBOL(console_drivers);
-EXPORT_SYMBOL(do_bottom_half);
index ed98ba6f0486169d02cda7c360c8366ed6eff487..3b30f50efa2246ac3702200313cbaeae65a2782b 100644 (file)
@@ -140,15 +140,31 @@ int check_stack(struct task_struct *tsk)
 }
 #endif /* defined(CHECK_STACK) */
 
+#ifdef CONFIG_ALTIVEC
 int
-dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
 {
-       if (regs->msr & MSR_FP)
-               giveup_fpu(current);
-       memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
+       if (regs->msr & MSR_VEC)
+               giveup_altivec(current);
+       memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
        return 1;
 }
 
+void 
+enable_kernel_altivec(void)
+{
+#ifdef __SMP__
+       if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
+               giveup_altivec(current);
+       else
+               giveup_altivec(NULL):   /* just enable AltiVec for kernel - force */
+#else
+       giveup_altivec(last_task_used_altivec);
+#endif /* __SMP __ */
+       printk("MSR_VEC in enable_altivec_kernel\n");
+}
+#endif /* CONFIG_ALTIVEC */
+
 void
 enable_kernel_fp(void)
 {
@@ -162,6 +178,15 @@ enable_kernel_fp(void)
 #endif /* __SMP__ */
 }
 
+int
+dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+{
+       if (regs->msr & MSR_FP)
+               giveup_fpu(current);
+       memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
+       return 1;
+}
+
 void
 _switch_to(struct task_struct *prev, struct task_struct *new,
          struct task_struct **last)
@@ -194,6 +219,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new,
         */
        if ( prev->thread.regs && (prev->thread.regs->msr & MSR_FP) )
                giveup_fpu(prev);
+#ifdef CONFIG_ALTIVEC  
        /*
         * If the previous thread 1) has some altivec regs it wants saved
         * (has bits in vrsave set) and 2) used altivec in the last quantum
@@ -206,6 +232,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new,
        if ( (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) &&
             prev->thread.vrsave )
                giveup_altivec(prev);
+#endif /* CONFIG_ALTIVEC */    
        prev->last_processor = prev->processor;
        current_set[smp_processor_id()] = new;
 #endif /* __SMP__ */
@@ -337,13 +364,18 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        p->thread.fpscr = current->thread.fpscr;
        childregs->msr &= ~MSR_FP;
 
+#ifdef CONFIG_ALTIVEC
+       /*
+        * copy altiVec info - assume lazy altiVec switch
+        * - kumar
+        */
        if (regs->msr & MSR_VEC)
                giveup_altivec(current);
-       if ( p->thread.vrsave )
-               memcpy(&p->thread.vrf, &current->thread.vrf, sizeof(p->thread.vrf));
+
+       memcpy(&p->thread.vr, &current->thread.vr, sizeof(p->thread.vr));
        p->thread.vscr = current->thread.vscr;
-       p->thread.vrsave = current->thread.vrsave;
        childregs->msr &= ~MSR_VEC;
+#endif /* CONFIG_ALTIVEC */
 
 #ifdef __SMP__
        p->last_processor = NO_PROC_ID;
@@ -463,6 +495,10 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
                goto out;
        if (regs->msr & MSR_FP)
                giveup_fpu(current);
+#ifdef CONFIG_ALTIVEC
+       if (regs->msr & MSR_VEC)
+               giveup_altivec(current);
+#endif /* CONFIG_ALTIVEC */ 
        error = do_execve(filename, (char **) a1, (char **) a2, regs);
        putname(filename);
 out:
index a52bdd804a9810c95698c6cfd2bd7f8e3089ddb3..b86e2a153e666dbc4b6ab8756f4d10ecb382f904 100644 (file)
@@ -802,42 +802,19 @@ setup_disp_fake_bi(ihandle dp)
 {
        unsigned int len;
        int width = 640, height = 480, depth = 8, pitch;
-       unsigned  address;
+       unsigned address;
        boot_infos_t* bi;
        unsigned long offset = reloc_offset();
        
-       prom_print(RELOC("Initing fake screen\n"));
+       prom_print(RELOC("Initializing fake screen\n"));
 
-       len = 0;
+       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &width, sizeof(width));
+       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &height, sizeof(height));
        call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"), &len, sizeof(len));
-       if (len == 0)
-               prom_print(RELOC("Warning: assuming display depth = 8\n"));
-       else
-               depth = len;
-       width = len = 0;
-       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &len, sizeof(len));
-       width = len;
-       if (width == 0) {
-               prom_print(RELOC("Failed to get width\n"));
-               return;
-       }
-       height = len = 0;
-       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &len, sizeof(len));
-       height = len;
-       if (height == 0) {
-               prom_print(RELOC("Failed to get height\n"));
-               return;
-       }
-       pitch = len = 0;
+       pitch = width * ((depth + 7) / 8);
        call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"), &len, sizeof(len));
-       pitch = len;
-       if (pitch == 0) {
-               prom_print(RELOC("Failed to get pitch\n"));
-               return;
-       }
-       address = len = 0;
+       address = 0;
        call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), &len, sizeof(len));
-       address = len;
        if (address == 0) {
                prom_print(RELOC("Failed to get address\n"));
                return;
@@ -846,22 +823,22 @@ setup_disp_fake_bi(ihandle dp)
        /* kludge for valkyrie */
        if (strcmp(dp->name, "valkyrie") == 0) 
            address += 0x1000;
-    }
 #endif
  
-    RELOC(disp_bi) = &fake_bi;
-    bi = PTRRELOC((&fake_bi));
-    RELOC(g_loc_X) = 0;
-    RELOC(g_loc_Y) = 0;
-    RELOC(g_max_loc_X) = width / 8;
-    RELOC(g_max_loc_Y) = height / 16;
-    bi->logicalDisplayBase = (unsigned char *)address;
-    bi->dispDeviceBase = (unsigned char *)address;
-    bi->dispDeviceRowBytes = pitch;
-    bi->dispDeviceDepth = depth;
-    bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
-    bi->dispDeviceRect[2] = width;
-    bi->dispDeviceRect[3] = height;
+       RELOC(disp_bi) = &fake_bi;
+       bi = PTRRELOC((&fake_bi));
+       RELOC(g_loc_X) = 0;
+       RELOC(g_loc_Y) = 0;
+       RELOC(g_max_loc_X) = width / 8;
+       RELOC(g_max_loc_Y) = height / 16;
+       bi->logicalDisplayBase = (unsigned char *)address;
+       bi->dispDeviceBase = (unsigned char *)address;
+       bi->dispDeviceRowBytes = pitch;
+       bi->dispDeviceDepth = depth;
+       bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
+       bi->dispDeviceRect[2] = width;
+       bi->dispDeviceRect[3] = height;
+       RELOC(disp_bi) = 0;
 }
 #endif
 
index 19ce0a25e185c2b3ff5a3460c2798847bd38072f..7502ad08e82a3421ce59dfe64d2f4573b1aef573 100644 (file)
@@ -221,7 +221,7 @@ int get_cpuinfo(char *buffer)
                if ( i )
                        len += sprintf(len+buffer,"\n");
                len += sprintf(len+buffer,"processor\t: %lu\n",i);
-               len += sprintf(len+buffer,"cpu\t\t:  ");
+               len += sprintf(len+buffer,"cpu\t\t: ");
 
                pvr = GET_PVR;
        
@@ -656,7 +656,6 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_BOOTX_TEXT
        map_bootx_text();
-       prom_print("identify machine\n");
 #endif
 
 #ifdef CONFIG_XMON
index 386764ddd058e354edda244137282c8f79c2be3e..83dff9246181583cbc1902bb60974205ebb9bb03 100644 (file)
@@ -53,7 +53,6 @@ unsigned int prof_counter[NR_CPUS];
 cycles_t cacheflush_time;
 
 /* all cpu mappings are 1-1 -- Cort */
-int cpu_number_map[NR_CPUS] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
 volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
 
 int start_secondary(void *);
index e1a3fdcbbe14086736aa79db7e43c24a75669c3a..e31b34cc9a4faf9fc4049257fa32820749df0d50 100644 (file)
@@ -252,14 +252,13 @@ asmlinkage int sys_pause(void)
 
 asmlinkage int sys_uname(struct old_utsname * name)
 {
-       int err;
-       
-       if (!name)
-               return -EFAULT;
+       int err = -EFAULT;
+
        down_read(&uts_sem);
-       err = copy_to_user(name, &system_utsname, sizeof (*name));
-       up(&uts_sem);
-       return err ? -EFAULT : 0;
+       if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+               err = 0;
+       up_read(&uts_sem);
+       return err;
 }
 
 asmlinkage int sys_olduname(struct oldold_utsname * name)
@@ -282,8 +281,8 @@ asmlinkage int sys_olduname(struct oldold_utsname * name)
        error -= __put_user(0,name->version+__OLD_UTS_LEN);
        error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
        error = __put_user(0,name->machine+__OLD_UTS_LEN);
-       error = error ? -EFAULT : 0;
-       up(&uts_sem);
+       up_read(&uts_sem);
 
+       error = error ? -EFAULT : 0;
        return error;
 }
index 5cc34c5a5a514d787d2db9ee9159aac9e4750577..ac7f47602d77081ff3071ed4e9e93f3dc03ed48f 100644 (file)
@@ -118,11 +118,11 @@ MachineCheckException(struct pt_regs *regs)
                default:
                        printk("Unknown values in msr\n");
                }
+               show_regs(regs);
+               print_backtrace((unsigned long *)regs->gpr[1]);
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
                debugger(regs);
 #endif
-               show_regs(regs);
-               print_backtrace((unsigned long *)regs->gpr[1]);
                panic("machine check");
        }
        _exception(SIGSEGV, regs);      
@@ -142,44 +142,6 @@ SMIException(struct pt_regs *regs)
        panic("System Management Interrupt");
 }
 
-#if defined(CONFIG_ALTIVEC)
-void
-AltiVecUnavailable(struct pt_regs *regs)
-{
-       /*
-        * This should be changed so we don't take a trap if coming
-        * back when last_task_used_altivec == current.  We should also
-        * allow the kernel to use the altivec regs on UP to store tasks
-        * regs during switch
-        *  -- Cort
-        */
-       if ( regs->msr & MSR_VEC )
-       {
-               show_regs(regs);
-               panic("AltiVec trap with Altivec enabled!\n");
-       }
-               
-       if ( !user_mode(regs) )
-       {
-               show_regs(regs);
-               panic("Kernel Used Altivec with MSR_VEC off!\n");
-       }
-
-       if ( last_task_used_altivec != current )
-       {
-               if ( last_task_used_altivec )
-                       giveup_altivec(current);
-               load_up_altivec(current);
-               /* on SMP we always save/restore on switch */
-#ifndef __SMP__                
-               last_task_used_altivec = current;
-#endif         
-       }
-       /* enable altivec for the task on return */
-       regs->msr |= MSR_VEC;
-}
-#endif /* CONFIG_ALTIVEC */
-
 void
 UnknownException(struct pt_regs *regs)
 {
index 4ab90f8b748c11a8a32779ca1effa66a0c4f2c6e..1c4f1f78edf7b732ed1eb8a2ec523ea2103c8e37 100644 (file)
 #include <asm/processor.h>
 #include <asm/errno.h>
 
+CACHELINE_BYTES = 32
+LG_CACHELINE_BYTES = 5
+CACHELINE_MASK = 0x1f
+CACHELINE_WORDS = 8
+
        .globl  strcpy
 strcpy:
        addi    r5,r3,-1
@@ -70,6 +75,55 @@ strlen:
        subf    r3,r3,r4
        blr
 
+/*
+ * Use dcbz on the complete cache lines in the destination
+ * to set them to zero.  This requires that the destination
+ * area is cacheable.  -- paulus
+ */
+       .globl  cacheable_memzero
+cacheable_memzero:
+       mr      r5,r4
+       li      r4,0
+       addi    r6,r3,-4
+       cmplwi  0,r5,4
+       blt     7f
+       stwu    r4,4(r6)
+       beqlr
+       andi.   r0,r6,3
+       add     r5,r0,r5
+       subf    r6,r0,r6
+       clrlwi  r7,r6,32-LG_CACHELINE_BYTES
+       add     r8,r7,r5
+       srwi    r9,r8,LG_CACHELINE_BYTES
+       addic.  r9,r9,-1        /* total number of complete cachelines */
+       ble     2f
+       xori    r0,r7,CACHELINE_MASK & ~3
+       srwi.   r0,r0,2
+       beq     3f
+       mtctr   r0
+4:     stwu    r4,4(r6)
+       bdnz    4b
+3:     mtctr   r9
+       li      r7,4
+10:    dcbz    r7,r6
+       addi    r6,r6,CACHELINE_BYTES
+       bdnz    10b
+       clrlwi  r5,r8,32-LG_CACHELINE_BYTES
+       addi    r5,r5,4
+2:     srwi    r0,r5,2
+       mtctr   r0
+       bdz     6f
+1:     stwu    r4,4(r6)
+       bdnz    1b
+6:     andi.   r5,r5,3
+7:     cmpwi   0,r5,0
+       beqlr
+       mtctr   r5
+       addi    r6,r6,3
+8:     stbu    r4,1(r6)
+       bdnz    8b
+       blr
+
        .globl  memset
 memset:
        rlwimi  r4,r4,8,16,23
@@ -82,7 +136,7 @@ memset:
        andi.   r0,r6,3
        add     r5,r0,r5
        subf    r6,r0,r6
-       rlwinm  r0,r5,32-2,2,31
+       srwi    r0,r5,2
        mtctr   r0
        bdz     6f
 1:     stwu    r4,4(r6)
@@ -103,6 +157,87 @@ bcopy:
        mr      r4,r6
        b       memcpy
 
+/*
+ * This version uses dcbz on the complete cache lines in the
+ * destination area to reduce memory traffic.  This requires that
+ * the destination area is cacheable.
+ * We only use this version if the source and dest don't overlap.
+ * -- paulus.
+ */
+       .global cacheable_memcpy
+cacheable_memcpy:
+       add     r7,r3,r5                /* test if the src & dst overlap */
+       add     r8,r4,r5
+       cmplw   0,r4,r7
+       cmplw   1,r3,r8
+       crand   0,0,4                   /* cr0.lt &= cr1.lt */
+       blt     memcpy                  /* if regions overlap */
+
+       addi    r4,r4,-4
+       addi    r6,r3,-4
+       neg     r0,r3
+       andi.   r0,r0,CACHELINE_MASK    /* # bytes to start of cache line */
+       beq     58f
+
+       cmplw   0,r5,r0                 /* is this more than total to do? */
+       blt     63f                     /* if not much to do */
+       andi.   r8,r0,3                 /* get it word-aligned first */
+       subf    r5,r0,r5
+       mtctr   r8
+       beq+    61f
+70:    lbz     r9,4(r4)                /* do some bytes */
+       stb     r9,4(r6)
+       addi    r4,r4,1
+       addi    r6,r6,1
+       bdnz    70b
+61:    srwi.   r0,r0,2
+       mtctr   r0
+       beq     58f
+72:    lwzu    r9,4(r4)                /* do some words */
+       stwu    r9,4(r6)
+       bdnz    72b
+
+58:    srwi.   r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
+       clrlwi  r5,r5,32-LG_CACHELINE_BYTES
+       li      r11,4
+       mtctr   r0
+       beq     63f
+53:    dcbz    r11,r6
+       lwz     r7,4(r4)
+       lwz     r8,8(r4)
+       lwz     r9,12(r4)
+       lwzu    r10,16(r4)
+       stw     r7,4(r6)
+       stw     r8,8(r6)
+       stw     r9,12(r6)
+       stwu    r10,16(r6)
+       lwz     r7,4(r4)
+       lwz     r8,8(r4)
+       lwz     r9,12(r4)
+       lwzu    r10,16(r4)
+       stw     r7,4(r6)
+       stw     r8,8(r6)
+       stw     r9,12(r6)
+       stwu    r10,16(r6)
+       bdnz    53b
+
+63:    srwi.   r0,r5,2
+       mtctr   r0
+       beq     64f
+30:    lwzu    r0,4(r4)
+       stwu    r0,4(r6)
+       bdnz    30b
+
+64:    andi.   r0,r5,3
+       mtctr   r0
+       beq+    65f
+40:    lbz     r0,4(r4)
+       stb     r0,4(r6)
+       addi    r4,r4,1
+       addi    r6,r6,1
+       bdnz    40b
+65:    blr
+
        .globl  memmove
 memmove:
        cmplw   0,r3,r4
@@ -111,7 +246,7 @@ memmove:
 
        .globl  memcpy
 memcpy:
-       rlwinm. r7,r5,32-3,3,31         /* r0 = r5 >> 3 */
+       srwi.   r7,r5,3
        addi    r6,r3,-4
        addi    r4,r4,-4
        beq     2f                      /* if less than 8 bytes to do */
@@ -218,106 +353,167 @@ memchr:
 
        .globl  __copy_tofrom_user
 __copy_tofrom_user:
-       srwi.   r7,r5,3
-       addi    r6,r3,-4
        addi    r4,r4,-4
-       li      r3,0            /* success return value */
-       beq     2f              /* if less than 8 bytes to do */
-       andi.   r0,r6,3         /* get dest word aligned */
-       mtctr   r7
-       bne     5f
-1:     lwz     r7,4(r4)
-11:    lwzu    r8,8(r4)
-12:    stw     r7,4(r6)
-13:    stwu    r8,8(r6)
-       bdnz    1b
-       andi.   r5,r5,7
-2:     cmplwi  0,r5,4
-       blt     3f
-14:    lwzu    r0,4(r4)
-       addi    r5,r5,-4
-15:    stwu    r0,4(r6)
-3:     cmpwi   0,r5,0          /* do 1 byte at a time for the remainder */
-       beqlr
-       mtctr   r5
-       addi    r4,r4,3
-       addi    r6,r6,3
-4:     lbzu    r0,1(r4)
-16:    stbu    r0,1(r6)
-       bdnz    4b
-       blr
-5:     subfic  r0,r0,4         /* copy bytes until we have the */
-       mtctr   r0              /* destination 4-byte aligned */
-       subf    r5,r0,r5
-6:     lbz     r7,4(r4)
+       addi    r6,r3,-4
+       neg     r0,r3
+       andi.   r0,r0,CACHELINE_MASK    /* # bytes to start of cache line */
+       beq     58f
+
+       cmplw   0,r5,r0                 /* is this more than total to do? */
+       blt     63f                     /* if not much to do */
+       andi.   r8,r0,3                 /* get it word-aligned first */
+       mtctr   r8
+       beq+    61f
+70:    lbz     r9,4(r4)                /* do some bytes */
+71:    stb     r9,4(r6)
        addi    r4,r4,1
-17:    stb     r7,4(r6)
        addi    r6,r6,1
-       bdnz    6b
-       srwi.   r7,r5,3
-       beq     2b
-       mtctr   r7
-       b       1b
-/* we come here on a fault in the 8-byte-at-a-time loop */
-88:    subi    r4,r4,8         /* compensate for the lwzu */
-98:    mfctr   r0
-       rlwimi  r5,r0,3,0,28    /* use the byte-at-a-time loop to */
-       b       3b              /* copy up to the byte at fault */
-/* here on a write fault in the single-word copy */
-96:    subi    r4,r4,4
-       b       3b
-/* here on a read fault in the initial single-byte copy */
-90:    mfctr   r3
-       add     r3,r3,r5
-       b       70f
-/* here on a read fault in the final single-byte copy */
-99:    mfctr   r3
-       subi    r6,r6,3
-/* clear out the rest of the destination: r3 bytes starting at 4(r6) */
-70:    li      r0,0
-       mr.     r5,r3
-       beq     76f
-71:    andi.   r4,r6,3
-       beq     72f
-77:    stb     r0,4(r6)
+       bdnz    70b
+61:    subf    r5,r0,r5
+       srwi.   r0,r0,2
+       mtctr   r0
+       beq     58f
+72:    lwzu    r9,4(r4)                /* do some words */
+73:    stwu    r9,4(r6)
+       bdnz    72b
+
+58:    srwi.   r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
+       clrlwi  r5,r5,32-LG_CACHELINE_BYTES
+       li      r11,4
+       mtctr   r0
+       beq     63f
+53:    dcbz    r11,r6
+10:    lwz     r7,4(r4)
+11:    lwz     r8,8(r4)
+12:    lwz     r9,12(r4)
+13:    lwzu    r10,16(r4)
+14:    stw     r7,4(r6)
+15:    stw     r8,8(r6)
+16:    stw     r9,12(r6)
+17:    stwu    r10,16(r6)
+20:    lwz     r7,4(r4)
+21:    lwz     r8,8(r4)
+22:    lwz     r9,12(r4)
+23:    lwzu    r10,16(r4)
+24:    stw     r7,4(r6)
+25:    stw     r8,8(r6)
+26:    stw     r9,12(r6)
+27:    stwu    r10,16(r6)
+       bdnz    53b
+
+63:    srwi.   r0,r5,2
+       mtctr   r0
+       beq     64f
+30:    lwzu    r0,4(r4)
+31:    stwu    r0,4(r6)
+       bdnz    30b
+
+64:    andi.   r0,r5,3
+       mtctr   r0
+       beq+    65f
+40:    lbz     r0,4(r4)
+41:    stb     r0,4(r6)
+       addi    r4,r4,1
        addi    r6,r6,1
-       addic.  r5,r5,-1
-       bne     71b
-72:    srwi.   r7,r5,2
-       beq     73f
-       mtctr   r7
-74:    stwu    r0,4(r6)
-       bdnz    74b
-73:    andi.   r5,r5,3
-       beq     76f
-       mtctr   r5
-       addi    r6,r6,3
-75:    stbu    r0,1(r6)
-       bdnz    75b
-76:    blr
-/* here on a write fault in the initial single-byte copy */
-80:    mfctr   r3
-       add     r3,r3,r5
-       blr
-/* here on a write fault in the final single-byte copy */
-81:    mfctr   r3
+       bdnz    40b
+65:    li      r3,0
        blr
 
+/* read fault, initial single-byte copy */
+100:   li      r4,0
+       b       90f
+/* write fault, initial single-byte copy */
+101:   li      r4,1
+90:    subf    r5,r8,r5
+       li      r3,0
+       b       99f
+/* read fault, initial word copy */
+102:   li      r4,0
+       b       91f
+/* write fault, initial word copy */
+103:   li      r4,1
+91:    li      r3,2
+       b       99f
+/* read fault in 2nd half of cacheline loop */
+106:   addi    r5,r5,-16
+/* read fault in 1st half of cacheline loop */
+104:   li      r4,0
+       b       92f
+/* write fault in 2nd half of cacheline loop */
+107:   addi    r5,r5,-16
+/* fault on dcbz (effectively a write fault) */
+/* or write fault in 1st half of cacheline loop */
+105:   li      r4,1
+92:    li      r3,LG_CACHELINE_BYTES
+       b       99f
+/* read fault in final word loop */
+108:   li      r4,0
+       b       93f
+/* write fault in final word loop */
+109:   li      r4,1
+93:    andi.   r5,r5,3
+       li      r3,2
+       b       99f
+/* read fault in final byte loop */
+110:   li      r4,0
+       b       94f
+/* write fault in final byte loop */
+111:   li      r4,1
+94:    li      r5,0
+       li      r3,0
+/*
+ * At this stage the number of bytes not copied is
+ * r5 + (ctr << r3), and r4 is 0 for read or 1 for write.
+ */
+99:    mfctr   r0
+       slw     r3,r0,r3
+       add     r3,r3,r5
+       cmpwi   0,r4,0
+       bne     120f
+/* for read fault, clear out the destination: r3 bytes starting at 4(r6) */
+       srwi.   r0,r3,2
+       li      r9,0
+       mtctr   r0
+       beq     113f
+112:   stwu    r9,4(r6)
+       bdnz    112b
+113:   andi.   r0,r3,3
+       mtctr   r0
+       beq     120f
+114:   stb     r9,4(r6)
+       addi    r6,r6,1
+       bdnz    114b
+120:   blr
+
 .section __ex_table,"a"
        .align  2
-       .long   1b,98b
-       .long   11b,98b
-       .long   12b,88b
-       .long   13b,88b
-       .long   14b,3b
-       .long   15b,96b
-       .long   4b,99b
-       .long   16b,81b
-       .long   6b,90b
-       .long   17b,80b
-       .long   77b,76b
-       .long   74b,76b
-       .long   75b,76b
+       .long   70b,100b
+       .long   71b,101b
+       .long   72b,102b
+       .long   73b,103b
+       .long   53b,105b
+       .long   10b,104b
+       .long   11b,104b
+       .long   12b,104b
+       .long   13b,104b
+       .long   14b,105b
+       .long   15b,105b
+       .long   16b,105b
+       .long   17b,105b
+       .long   20b,106b
+       .long   21b,106b
+       .long   22b,106b
+       .long   23b,106b
+       .long   24b,107b
+       .long   25b,107b
+       .long   26b,107b
+       .long   27b,107b
+       .long   30b,108b
+       .long   31b,109b
+       .long   40b,110b
+       .long   41b,111b
+       .long   112b,120b
+       .long   114b,120b
 .text
 
        .globl  __clear_user
@@ -334,7 +530,6 @@ __clear_user:
        andi.   r0,r6,3
        add     r4,r0,r4
        subf    r6,r0,r6
-       /*rlwinm        r0,r4,32-2,2,31*/
        srwi    r0,r4,2
        mtctr   r0
        bdz     6f
index 216527e34344e8b1caa4b690cdcbe9f95dda8f83..25d728fdda3d505bc1bfe3489be2d8498282c327 100644 (file)
@@ -1107,7 +1107,7 @@ unsigned long __init find_available_memory(void)
  */
 void __init paging_init(void)
 {
-       unsigned int zones_size[MAX_NR_ZONES], i;
+       unsigned long zones_size[MAX_NR_ZONES], i;
 
        /*
         * Grab some memory for bad_page and bad_pagetable to use.
@@ -1197,7 +1197,7 @@ unsigned long __init *pmac_find_end_of_memory(void)
        unsigned long a, total;
        
        /* max amount of RAM we allow -- Cort */
-#define RAM_LIMIT (64<<20)
+#define RAM_LIMIT (768<<20)
 
        memory_node = find_devices("memory");
        if (memory_node == NULL) {
index f25060c942dbefa83d7848d2789ba2baa47e7fdb..8e924699fa830a53d46fc5f81a5bd4c746da953e 100644 (file)
@@ -115,42 +115,41 @@ extern void pmu_poll(void);
 int
 xmon_write(void *handle, void *ptr, int nb)
 {
-    char *p = ptr;
-    int i, c, ct;
+       char *p = ptr;
+       int i, c, ct;
 
 #ifdef CONFIG_BOOTX_TEXT
-    if (use_screen) {
-       /* write it on the screen */
-       for (i = 0; i < nb; ++i)
-           drawchar(*p++);
-       return nb;
-    }
+       if (use_screen) {
+               /* write it on the screen */
+               for (i = 0; i < nb; ++i)
+                       drawchar(*p++);
+               return nb;
+       }
 #endif
-    if (!scc_initialized)
-       xmon_init_scc();
-    for (i = 0; i < nb; ++i) {
-    ct = 0;
-       while ((*sccc & TXRDY) == 0)
+       if (!scc_initialized)
+               xmon_init_scc();
+       ct = 0;
+       for (i = 0; i < nb; ++i) {
+               while ((*sccc & TXRDY) == 0) {
 #ifdef CONFIG_ADB          
-           if (sys_ctrler == SYS_CTRLER_PMU)
-               pmu_poll();
-#else
-               ;
+                       if (sys_ctrler == SYS_CTRLER_PMU)
+                               pmu_poll();
 #endif /* CONFIG_ADB */
-       c = p[i];
-       if (c == '\n' && !ct) {
-           c = '\r';
-               ct = 1;
-           --i;
-       } else {
-           if (console)
-               printk("%c", c);
-           ct = 0;
+               }
+               c = p[i];
+               if (c == '\n' && !ct) {
+                       c = '\r';
+                       ct = 1;
+                       --i;
+               } else {
+                       if (console)
+                               printk("%c", c);
+                       ct = 0;
+               }
+               buf_access();
+               *sccd = c;
        }
-       buf_access();
-       *sccd = c;
-    }
-    return i;
+       return i;
 }
 
 int xmon_wants_key;
@@ -285,7 +284,7 @@ xmon_init_scc()
        {
                int i, x;
 
-               if (macio_node != 0) {
+               if (via_modem && macio_node != 0) {
                        unsigned int t0;
 
                        feature_set(macio_node, FEATURE_Modem_power);
index 336ae208ff7111f9a9fd52b8952f3711024f268b..f746f824b5a5cff2a98b059692c80bf47afa57e5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.31 2000/02/06 22:55:32 zaitcev Exp $
+/* $Id: ioport.c,v 1.32 2000/02/12 03:04:48 zaitcev Exp $
  * ioport.c:  Simple io mapping allocator.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -562,7 +562,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
        {
                int x;
                for (x = 0; x < n; x += PAGE_SIZE) {
-                       (*_sparc_unmapioaddr)(p + n);
+                       (*_sparc_unmapioaddr)((unsigned long)p + n);
                }
        }
 
index b504e2412306d5cd56069412ff50bf40987ac9ad..335eba2083c5a0005247cc47457f2819429b4b7b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.12 2000/01/22 07:35:25 zaitcev Exp $
+/* $Id: pcic.c,v 1.13 2000/02/12 03:05:37 zaitcev Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -784,6 +784,7 @@ void __init pci_time_init(void)
 
 static __inline__ unsigned long do_gettimeoffset(void)
 {
+       struct tasklet_struct *t;
        unsigned long offset = 0;
 
        /* 
@@ -794,7 +795,8 @@ static __inline__ unsigned long do_gettimeoffset(void)
            readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
        count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
 
-       if(test_bit(TIMER_BH, &bh_active))
+       t = &bh_task_vec[TIMER_BH];
+       if (test_bit(TASKLET_STATE_SCHED, &t->state))
                offset = 1000000;
        return offset + count;
 }
index 715bdb864f53516898224e1c18753409ef843590..ae5d5e3714cc619c737c06ed881026ec314ec24d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.187 2000/02/08 07:46:01 davem Exp $
+/* $Id: sun4c.c,v 1.188 2000/02/12 03:07:35 zaitcev Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -591,7 +591,7 @@ static unsigned long sun4c_translate_dvma(unsigned long busa)
        return (pte << PAGE_SHIFT) + PAGE_OFFSET;
 }
 
-static unsigned long sun4c_unmap_dma_area(unsigned long busa, int len)
+static void sun4c_unmap_dma_area(unsigned long busa, int len)
 {
        /* Fortunately for us, bus_addr == uncached_virt in sun4c. */
        /* XXX Implement this */
index e9fe43293568f3d3917abe81231aa23a3e663063..914f3071de219a5e7205ca9161bb92cc087c47e1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: swift.S,v 1.3 1999/11/14 06:13:56 zaitcev Exp $
+/* $Id: swift.S,v 1.4 2000/02/12 03:08:47 zaitcev Exp $
  * swift.S: MicroSparc-II mmu/cache operations.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -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 d915a42918d0494d1f8e120ae7f8e6fa79bae3fe..306feb2e90fb9eae90c727410ff217c89ad94713 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/iomd.h>
 #include <asm/system.h>
 
+extern struct tasklet_struct keyboard_tasklet;
 extern void kbd_reset_kdown(void);
 int kbd_read_mask;
 
@@ -318,7 +319,7 @@ static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs)
 
        while (inb(IOMD_KCTRL) & (1 << 5))
                handle_rawcode(inb(IOMD_KARTRX));
-       mark_bh(KEYBOARD_BH);
+       tasklet_schedule(&keyboard_tasklet);
 }
 
 static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs)
index dd742cbc4a1dd16bc554d150c1bb7839b4a2bf7f..9eab534aac0ff65ec9bfe9c64cf1cb2456a0af14 100644 (file)
  *   it passes the underlying device's block number instead of the
  *   offset. This makes it change for a given block when the file is 
  *   moved/restored/copied and also doesn't work over NFS. 
- * AV, Feb 11, 2000: for files we pass the page index now. It should fix the
- *   problem above. Since the granularity is PAGE_CACHE_SIZE now it seems to
- *   be correct way. OTOH, taking the thing from x86 to Alpha may become
- *   interesting, so we might want to rethink it.
+ * AV, Feb 12, 2000: we pass the logical block number now. It fixes the
+ *   problem above. Encryption modules that used to rely on the old scheme
+ *   should just call ->i_mapping->bmap() to calculate the physical block
+ *   number.
  */ 
 
 #include <linux/module.h>
@@ -164,7 +164,8 @@ static void figure_loop_size(struct loop_device *lo)
        loop_sizes[lo->lo_number] = size;
 }
 
-static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos)
+static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos,
+       int blksize)
 {
        struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
        struct address_space *mapping = lo->lo_dentry->d_inode->i_mapping;
@@ -177,6 +178,7 @@ static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos)
        index = pos >> PAGE_CACHE_SHIFT;
        offset = pos & (PAGE_CACHE_SIZE - 1);
        while (len > 0) {
+               int IV = index * (PAGE_CACHE_SIZE/blksize) + offset/blksize;
                size = PAGE_CACHE_SIZE - offset;
                if (size > len)
                        size = len;
@@ -187,7 +189,7 @@ static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos)
                if (aops->prepare_write(page, offset, offset+size))
                        goto unlock;
                kaddr = (char*)page_address(page);
-               if ((lo->transfer)(lo, WRITE, kaddr+offset, data, size, index))
+               if ((lo->transfer)(lo, WRITE, kaddr+offset, data, size, IV))
                        goto write_fail;
                if (aops->commit_write(file, page, offset, offset+size))
                        goto unlock;
@@ -217,6 +219,7 @@ fail:
 struct lo_read_data {
        struct loop_device *lo;
        char *data;
+       int blksize;
 };
 
 static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
@@ -225,12 +228,13 @@ static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned l
        unsigned long count = desc->count;
        struct lo_read_data *p = (struct lo_read_data*)desc->buf;
        struct loop_device *lo = p->lo;
+       int IV = page->index * (PAGE_CACHE_SIZE/p->blksize) + offset/p->blksize;
 
        if (size > count)
                size = count;
 
        kaddr = (char*)kmap(page);
-       if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,page->index)) {
+       if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,IV)) {
                size = 0;
                printk(KERN_ERR "loop: transfer error block %ld\n",page->index);
                desc->error = -EINVAL;
@@ -243,7 +247,8 @@ static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned l
        return size;
 }
 
-static int lo_receive(struct loop_device *lo, char *data, int len, loff_t pos)
+static int lo_receive(struct loop_device *lo, char *data, int len, loff_t pos,
+       int blksize)
 {
        struct file *file = lo->lo_backing_file;
        struct lo_read_data cookie;
@@ -251,6 +256,7 @@ static int lo_receive(struct loop_device *lo, char *data, int len, loff_t pos)
 
        cookie.lo = lo;
        cookie.data = data;
+       cookie.blksize = blksize;
        desc.written = 0;
        desc.count = len;
        desc.buf = (char*)&cookie;
@@ -287,8 +293,6 @@ repeat:
 
        dest_addr = current_request->buffer;
        len = current_request->current_nr_sectors << 9;
-       if (lo->lo_flags & LO_FLAGS_DO_BMAP)
-               goto file_backed;
 
        blksize = BLOCK_SIZE;
        if (blksize_size[MAJOR(lo->lo_device)]) {
@@ -296,6 +300,10 @@ repeat:
            if (!blksize)
              blksize = BLOCK_SIZE;
        }
+
+       if (lo->lo_flags & LO_FLAGS_DO_BMAP)
+               goto file_backed;
+
        if (blksize < 512) {
                block = current_request->sector * (512/blksize);
                offset = 0;
@@ -357,10 +365,10 @@ file_backed:
        pos = ((loff_t)current_request->sector << 9) + lo->lo_offset;
        spin_unlock_irq(&io_request_lock);
        if (current_request->cmd == WRITE) {
-               if (lo_send(lo, dest_addr, len, pos))
+               if (lo_send(lo, dest_addr, len, pos, blksize))
                        goto error_out_lock;
        } else {
-               if (lo_receive(lo, dest_addr, len, pos))
+               if (lo_receive(lo, dest_addr, len, pos, blksize))
                        goto error_out_lock;
        }
 done:
@@ -416,6 +424,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
                   a file structure */
                lo->lo_backing_file = NULL;
        } else if (S_ISREG(inode->i_mode)) {
+               struct address_space_operations *aops;
                /* Backed by a regular file - we need to hold onto a file
                   structure for this file.  Friggin' NFS can't live without
                   it on write and for reading we use do_generic_file_read(),
@@ -444,16 +453,23 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
                                lo->lo_backing_file = NULL;
                        }
                }
+               aops = lo->lo_dentry->d_inode->i_mapping->a_ops;
+               /*
+                * If we can't read - sorry. If we only can't write - well,
+                * it's going to be read-only.
+                */
+               if (!aops->readpage)
+                       error = -EINVAL;
+               else if (!aops->prepare_write || !aops->commit_write)
+                       lo->lo_flags |= LO_FLAGS_READ_ONLY;
        }
        if (error)
                goto out_putf;
 
-       if (IS_RDONLY (inode) || is_read_only(lo->lo_device)) {
+       if (IS_RDONLY (inode) || is_read_only(lo->lo_device))
                lo->lo_flags |= LO_FLAGS_READ_ONLY;
-               set_device_ro(dev, 1);
-       } else {
-               set_device_ro(dev, 0);
-       }
+
+       set_device_ro(dev, (lo->lo_flags & LO_FLAGS_READ_ONLY)!=0);
 
        lo->lo_dentry = dget(file->f_dentry);
        lo->transfer = NULL;
index e49144c1a2190af4d2c03aa4d978fd425b98c2f5..c61a6e6a94773efe26ad3f9d2c620d27676b7f5b 100644 (file)
@@ -38,7 +38,7 @@
 /* select machine configuration */
 #if defined(CONFIG_ATARI)
 #define MACH ATARI
-#elif defined(__i386__) /* and others?? */
+#elif defined(__i386__) || defined(__arm__) /* and others?? */
 #define MACH PC
 #else
 #error Cannot build nvram driver for this machine configuration.
index 2ba5baac21cff72ecace24365424a23a14a3ff03..04999bb4cefdcee3f82d7a1d1dce526c83e48449 100644 (file)
@@ -391,16 +391,17 @@ input_keycode(int keycode, int repeat)
                 case 0x39:
                        handle_scancode(0x39, 1);
                        handle_scancode(0x39, 0);
-                       mark_bh(KEYBOARD_BH);
+                       tasklet_schedule(&keyboard_tasklet);
                        return;
                 case 0x47:
                 /*case 0xc7:*/
-                       mark_bh(KEYBOARD_BH);
+                       tasklet_schedule(&keyboard_tasklet);
                        break;
                 }
        }
 
        handle_scancode(keycode, !up_flag);
+       tasklet_schedule(&keyboard_tasklet);
 }
 
 static void
index 2555d5383680117349be7a1876799349bda31b25..94ec60e1c4bf340c74491cb3781ffb24b0c38db1 100644 (file)
@@ -2796,7 +2796,6 @@ static struct console sercons = {
 void __init serial_console_init(void)
 {
        register_console(&sercons);
-       return kmem_start;
 }
 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
 
index 781084dbf6d881c98965cbc3d2e1d6e0b2c3120c..b5be783380ae10e9a61aca59c38890b77ca4d8e1 100644 (file)
@@ -403,8 +403,6 @@ struct vortex_private {
        struct sk_buff* rx_skbuff[RX_RING_SIZE];
        struct sk_buff* tx_skbuff[TX_RING_SIZE];
        struct net_device *next_module;
-       void *priv_addr;
-       dma_addr_t ring_dma;
        unsigned int cur_rx, cur_tx;            /* The next free ring entry */
        unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
        struct net_device_stats stats;
@@ -769,13 +767,11 @@ static struct net_device *vortex_probe1(struct pci_dev *pdev,
        vp->pci_devfn = pdev == NULL ? 0 : pdev->devfn;
        vp->pdev = pdev;
 
-       vp->priv_addr = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
-                                            + sizeof(struct boom_tx_desc) * TX_RING_SIZE
-                                            + 15, &vp->ring_dma);
-       /* Make sure rings are 16 byte aligned. */
-       vp->rx_ring = (void *)(((long)vp->priv_addr + 15) & ~15);
+       /* Makes sure rings are at least 16 byte aligned. */
+       vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+                                          + sizeof(struct boom_tx_desc) * TX_RING_SIZE,
+                                          &vp->rx_ring_dma);
        vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
-       vp->rx_ring_dma = (vp->ring_dma + 15) & ~15;
        vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE;
 
        /* The lower four bits are the media type. */
@@ -2062,7 +2058,7 @@ static void __exit vortex_cleanup_module (void)
                kfree(root_vortex_dev);
                pci_free_consistent(vp->pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
                                            + sizeof(struct boom_tx_desc) * TX_RING_SIZE
-                                           + 15, vp->priv_addr, vp->ring_dma);
+                                           + 15, vp->rx_ring, vp->rx_ring_dma);
                kfree(vp);
                root_vortex_dev = next_dev;
        }
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
new file mode 100644 (file)
index 0000000..d6a7f66
--- /dev/null
@@ -0,0 +1,1812 @@
+/*
+
+       8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux.
+
+       Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+       Originally: Written 1997-1999 by Donald Becker.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       Contributors:
+
+               Donald Becker - he wrote the original driver, kudos to him!
+               (but please don't e-mail him for support, this isn't his driver)
+
+               Tigran Aivazian - bug fixes, skbuff free cleanup
+
+               Martin Mares - suggestions for PCI cleanup
+               
+               David S. Miller - PCI DMA and softnet updates
+
+-----------------------------------------------------------------------------
+
+                               Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the RealTek RTL8139 series, the RealTek
+Fast Ethernet controllers for PCI and CardBus.  This chip is used on many
+low-end boards, sometimes with its markings changed.
+
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+
+III. Driver operation
+
+IIIa. Rx Ring buffers
+
+The receive unit uses a single linear ring buffer rather than the more
+common (and more efficient) descriptor-based architecture.  Incoming frames
+are sequentially stored into the Rx region, and the host copies them into
+skbuffs.
+
+Comment: While it is theoretically possible to process many frames in place,
+any delay in Rx processing would cause us to drop frames.  More importantly,
+the Linux protocol stack is not designed to operate in this manner.
+
+IIIb. Tx operation
+
+The RTL8139 uses a fixed set of four Tx descriptors in register space.
+In a stunningly bad design choice, Tx frames must be 32 bit aligned.  Linux
+aligns the IP header on word boundaries, and 14 byte ethernet header means
+that almost all frames will need to be copied to an alignment buffer.
+
+IVb. References
+
+http://www.realtek.com.tw/cn/cn.html
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+
+IVc. Errata
+
+1) The RTL-8139 has a serious problem with motherboards which do
+posted MMIO writes to PCI space.  This driver works around the
+problem by having an MMIO  register write be immediately followed by
+an MMIO register read.
+
+2) The RTL-8129 is only supported in Donald Becker's rtl8139 driver.
+
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <asm/io.h>
+
+
+#define RTL8139_VERSION "0.9.0"
+#define RTL8139_MODULE_NAME "8139too"
+#define RTL8139_DRIVER_NAME   RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION
+#define PFX RTL8139_MODULE_NAME ": "
+
+#undef RTL8139_DEBUG /* define to 1 to enable copious debugging info */
+
+#ifdef RTL8139_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define RTL8139_NDEBUG 0       /* define to 1 to disable lightweight runtime checks */
+#if RTL8139_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+        if(!(expr)) {                                  \
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",        \
+        #expr,__FILE__,__FUNCTION__,__LINE__);         \
+        }
+#endif
+
+#define arraysize(x)            (sizeof(x)/sizeof(*(x)))
+
+
+#ifndef PCI_GET_DRIVER_DATA
+  #define PCI_GET_DRIVER_DATA(pdev)            ((pdev)->driver_data)
+  #define PCI_SET_DRIVER_DATA(pdev,data)       (((pdev)->driver_data) = (data))
+#endif /* PCI_GET_DRIVER_DATA */
+
+
+/* A few user-configurable values. */
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
+static int multicast_filter_limit = 32;
+
+/* Size of the in-memory receive ring. */
+#define RX_BUF_LEN_IDX 2       /* 0==8K, 1==16K, 2==32K, 3==64K */
+#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
+/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
+#define TX_BUF_SIZE    1536
+
+/* PCI Tuning Parameters
+   Threshold is bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 256     /* In bytes, rounded down to 32 byte units. */
+
+/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024. */
+#define RX_FIFO_THRESH 4       /* Rx buffer level before first PCI xfer.  */
+#define RX_DMA_BURST   4       /* Maximum PCI burst, '4' is 256 bytes */
+#define TX_DMA_BURST   4       /* Calculate as 16<<val. */
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (6*HZ)
+
+
+enum {
+       HAS_CHIP_XCVR = 0x020000,
+       HAS_LNK_CHNG = 0x040000,
+};
+
+#define RTL_IO_SIZE 256
+
+#define RTL8139_CAPS  HAS_CHIP_XCVR|HAS_LNK_CHNG
+
+typedef enum {
+       UNKNOWN = 0,
+       RTL8139,
+       RTL8139_CB,
+       SMC1211TX,
+       MPX5030,
+       SIS900,
+       SIS7016,
+} chip_t;
+
+static struct {
+       chip_t chip;
+       const char *name;
+} chip_info[] __devinitdata = {
+       { RTL8139, "RealTek RTL8139 Fast Ethernet"},
+       { RTL8139_CB, "RealTek RTL8139B PCI/CardBus"},
+       { SMC1211TX, "SMC1211TX EZCard 10/100 (RealTek RTL8139)"},
+       { MPX5030, "Accton MPX5030 (RealTek RTL8139)"},
+       { SIS900, "SiS 900 (RealTek RTL8139) Fast Ethernet"},
+       { SIS7016, "SiS 7016 (RealTek RTL8139) Fast Ethernet"},
+       {0,},
+};
+
+static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = {
+       {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+       {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139_CB },
+       {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX },
+       {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },
+       {0x1039, 0x0900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS900 },
+       {0x1039, 0x7016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS7016 },
+       {0,},
+};
+MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);
+
+
+/* The rest of these values should never change. */
+#define NUM_TX_DESC    4       /* Number of Tx descriptor registers. */
+
+/* Symbolic offsets to registers. */
+enum RTL8139_registers {
+       MAC0 = 0,               /* Ethernet hardware address. */
+       MAR0 = 8,               /* Multicast filter. */
+       TxStatus0 = 0x10,       /* Transmit status (Four 32bit registers). */
+       TxAddr0 = 0x20,         /* Tx descriptors (also four 32bit). */
+       RxBuf = 0x30,
+       RxEarlyCnt = 0x34,
+       RxEarlyStatus = 0x36,
+       ChipCmd = 0x37,
+       RxBufPtr = 0x38,
+       RxBufAddr = 0x3A,
+       IntrMask = 0x3C,
+       IntrStatus = 0x3E,
+       TxConfig = 0x40,
+       RxConfig = 0x44,
+       Timer = 0x48,           /* A general-purpose counter. */
+       RxMissed = 0x4C,        /* 24 bits valid, write clears. */
+       Cfg9346 = 0x50,
+       Config0 = 0x51,
+       Config1 = 0x52,
+       FlashReg = 0x54,
+       GPPinData = 0x58,
+       GPPinDir = 0x59,
+       Config4 = 0x5A,         /* absent on RTL-8139A */
+       HltClk = 0x5B,
+       MultiIntr = 0x5C,
+       TxSummary = 0x60,
+       BasicModeCtrl = 0x62,
+       BasicModeStatus = 0x64,
+       NWayAdvert = 0x66,
+       NWayLPAR = 0x68,
+       NWayExpansion = 0x6A,
+       /* Undocumented registers, but required for proper operation. */
+       FIFOTMS = 0x70,         /* FIFO Control and test. */
+       CSCR = 0x74,            /* Chip Status and Configuration Register. */
+       PARA78 = 0x78,
+       PARA7c = 0x7c,          /* Magic transceiver parameter register. */
+};
+
+enum ChipCmdBits {
+       CmdReset = 0x10,
+       CmdRxEnb = 0x08,
+       CmdTxEnb = 0x04,
+       RxBufEmpty = 0x01,
+};
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatusBits {
+       PCIErr = 0x8000,
+       PCSTimeout = 0x4000,
+       RxFIFOOver = 0x40,
+       RxUnderrun = 0x20,
+       RxOverflow = 0x10,
+       TxErr = 0x08,
+       TxOK = 0x04,
+       RxErr = 0x02,
+       RxOK = 0x01,
+};
+enum TxStatusBits {
+       TxHostOwns = 0x2000,
+       TxUnderrun = 0x4000,
+       TxStatOK = 0x8000,
+       TxOutOfWindow = 0x20000000,
+       TxAborted = 0x40000000,
+       TxCarrierLost = 0x80000000,
+};
+enum RxStatusBits {
+       RxMulticast = 0x8000,
+       RxPhysical = 0x4000,
+       RxBroadcast = 0x2000,
+       RxBadSymbol = 0x0020,
+       RxRunt = 0x0010,
+       RxTooLong = 0x0008,
+       RxCRCErr = 0x0004,
+       RxBadAlign = 0x0002,
+       RxStatusOK = 0x0001,
+};
+
+/* Bits in RxConfig. */
+enum rx_mode_bits {
+       AcceptErr = 0x20,
+       AcceptRunt = 0x10,
+       AcceptBroadcast = 0x08,
+       AcceptMulticast = 0x04,
+       AcceptMyPhys = 0x02,
+       AcceptAllPhys = 0x01,
+};
+
+/* Bits in Config1 */
+enum Config1Bits {
+       Cfg1_PM_Enable = 0x01,
+       Cfg1_VPD_Enable = 0x02,
+       Cfg1_PIO = 0x04,
+       Cfg1_MMIO = 0x08,
+       Cfg1_LWAKE = 0x10,
+       Cfg1_Driver_Load = 0x20,
+       Cfg1_LED0 = 0x40,
+       Cfg1_LED1 = 0x80,
+};
+
+/* Twister tuning parameters from RealTek.
+   Completely undocumented, but required to tune bad links. */
+enum CSCRBits {
+       CSCR_LinkOKBit = 0x0400,
+       CSCR_LinkChangeBit = 0x0800,
+       CSCR_LinkStatusBits = 0x0f000,
+       CSCR_LinkDownOffCmd = 0x003c0,
+       CSCR_LinkDownCmd = 0x0f3c0,
+};
+#define PARA78_default 0x78fa8388
+#define PARA7c_default 0xcb38de43      /* param[0][3] */
+#define PARA7c_xxx             0xcb38de43
+unsigned long param[4][4] = {
+       {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
+       {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+       {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+       {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
+};
+
+struct ring_info {
+       struct sk_buff *skb;
+       dma_addr_t mapping;
+};
+
+
+#define PRIV_ALIGN     15      /* Required alignment mask */
+struct rtl8139_private {
+       chip_t chip;
+       void *mmio_addr;
+       spinlock_t lock;
+       int drv_flags;
+       struct pci_dev *pci_dev;
+       struct net_device_stats stats;
+       struct timer_list timer;        /* Media selection timer. */
+       unsigned char *rx_ring;
+       unsigned int cur_rx;    /* Index into the Rx buffer of next Rx pkt. */
+       unsigned int rx_config;
+       unsigned int cur_tx, dirty_tx, tx_flag;
+       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+       struct ring_info tx_info[NUM_TX_DESC];
+       unsigned char *tx_buf[NUM_TX_DESC];     /* Tx bounce buffers */
+       unsigned char *tx_bufs; /* Tx bounce buffer region. */
+       dma_addr_t rx_ring_dma;
+       dma_addr_t tx_bufs_dma;
+       char phys[4];           /* MII device addresses. */
+       char twistie, twist_row, twist_col;     /* Twister tune state. */
+       unsigned int full_duplex:1;     /* Full-duplex operation requested. */
+       unsigned int duplex_lock:1;
+       unsigned int default_port:4;    /* Last dev->if_port value. */
+       unsigned int media2:4;  /* Secondary monitored media port. */
+       unsigned int medialock:1;       /* Don't sense media type. */
+       unsigned int mediasense:1;      /* Media sensing in progress. */
+};
+
+MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
+MODULE_PARM (multicast_filter_limit, "i");
+MODULE_PARM (max_interrupt_work, "i");
+MODULE_PARM (debug, "i");
+
+static int read_eeprom (void *ioaddr, int location, int addr_len);
+static int rtl8139_open (struct net_device *dev);
+static int mdio_read (struct net_device *dev, int phy_id, int location);
+static void mdio_write (struct net_device *dev, int phy_id, int location,
+                       int val);
+static void rtl8139_timer (unsigned long data);
+static void rtl8139_tx_timeout (struct net_device *dev);
+static void rtl8139_init_ring (struct net_device *dev);
+static int rtl8139_start_xmit (struct sk_buff *skb,
+                              struct net_device *dev);
+static void rtl8139_interrupt (int irq, void *dev_instance,
+                              struct pt_regs *regs);
+static int rtl8139_close (struct net_device *dev);
+static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
+static inline u32 ether_crc (int length, unsigned char *data);
+static void rtl8139_set_rx_mode (struct net_device *dev);
+
+/* read after write, to avoid rtl8139 bug w/ posted MMIO writes */
+#define RTL_W8(reg, val8)      do { writeb (val8, ioaddr + reg); readb (ioaddr + reg); } while (0)
+#define RTL_W16(reg, val16)    do { writew (val16, ioaddr + reg); readw (ioaddr + reg); } while (0)
+#define RTL_W32(reg, val32)    do { writel (val32, ioaddr + reg); readl (ioaddr + reg); } while (0)
+#define RTL_R8(reg)            readb (ioaddr + reg)
+#define RTL_R16(reg)           readw (ioaddr + reg)
+#define RTL_R32(reg)           readl (ioaddr + reg)
+
+
+static const char * __devinit rtl8139_name_from_chip (chip_t chip)
+{
+       int i;
+       
+       for (i = 0; i < arraysize (chip_info); i++)
+               if (chip == chip_info[i].chip)
+                       return chip_info[i].name;
+       
+       return "unknown";
+}
+
+
+static int __devinit rtl8139_init_pci (struct pci_dev *pdev, void **ioaddr_out)
+{
+       void *ioaddr = NULL;
+       u8 tmp8;
+       int rc;
+       u32 pio_start, pio_end, pio_flags;
+       u32 mmio_start, mmio_end, mmio_flags;
+
+       DPRINTK ("ENTER\n");
+
+       assert (pdev != NULL);
+       assert (ioaddr_out != NULL);
+
+       *ioaddr_out = NULL;
+
+       pio_start = pci_resource_start (pdev, 0);
+       pio_end = pci_resource_end (pdev, 0);
+       pio_flags = pci_resource_flags (pdev, 0);
+
+       mmio_start = pci_resource_start (pdev, 1);
+       mmio_end = pci_resource_end (pdev, 1);
+       mmio_flags = pci_resource_flags (pdev, 1);
+
+       /* make sure PCI base addr 0 is PIO */
+       if (pio_start == 0 || pio_end <= pio_start ||
+           (!(pio_flags & IORESOURCE_IO))) {
+               printk (KERN_ERR PFX "no PIO resource, aborting\n");
+               return -ENODEV;
+       }
+       
+       /* make sure PCI base addr 1 is MMIO */
+       if (mmio_start == 0 || mmio_end <= mmio_start ||
+           (!(mmio_flags & IORESOURCE_MEM))) {
+               printk (KERN_ERR PFX "no MMIO resource, aborting\n");
+               return -ENODEV;
+       }
+
+       /* make sure our PIO region in PCI space is available */
+       if (!request_region (pio_start, RTL_IO_SIZE, RTL8139_MODULE_NAME)) {
+               printk (KERN_ERR PFX "no I/O resource available, aborting\n");
+               return -EBUSY;
+       }
+       
+       /* make sure our MMIO region in PCI space is available */
+       if (!request_mem_region (mmio_start, RTL_IO_SIZE, RTL8139_MODULE_NAME)) {
+               release_region (pio_start, RTL_IO_SIZE);
+               printk (KERN_ERR PFX "no mem resource available, aborting\n");
+               return -EBUSY;
+       }
+       
+       /* enable device (incl. PCI PM wakeup), and bus-mastering */
+       pci_enable_device (pdev);
+       pci_set_master (pdev);
+
+       /* ioremap MMIO region */
+       ioaddr = ioremap (mmio_start, RTL_IO_SIZE);
+       if (ioaddr == NULL) {
+               printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");
+               rc = -EIO;
+               goto err_out;
+       }
+
+       /* Bring the chip out of low-power mode. */
+       RTL_W8 (Config1, 0x00);
+
+       /* make sure chip thinks PIO and MMIO are enabled */
+       tmp8 = RTL_R8 (Config1);
+       if ((tmp8 & Cfg1_PIO) == 0) {
+               printk (KERN_ERR PFX "PIO not enabled, Cfg1=%02X, aborting\n", tmp8);
+               rc = -EIO;
+               goto err_out;
+       }
+       if ((tmp8 & Cfg1_MMIO) == 0) {
+               printk (KERN_ERR PFX "MMIO not enabled, Cfg1=%02X, aborting\n", tmp8);
+               rc = -EIO;
+               goto err_out;
+       }
+       
+       /* sanity checks -- ensure PIO and MMIO registers agree */
+       assert (inb (pio_start+Config0) == RTL_R8 (Config0));
+       assert (inb (pio_start+Config1) == RTL_R8 (Config1));
+       assert (inb (pio_start+TxConfig) == RTL_R8 (TxConfig));
+       assert (inb (pio_start+RxConfig) == RTL_R8 (RxConfig));
+
+       DPRINTK ("EXIT, returning 0\n");
+       *ioaddr_out = ioaddr;
+       return 0;       
+
+err_out:
+       if (ioaddr)
+               iounmap (ioaddr);
+       release_region (pio_start, RTL_IO_SIZE);
+       release_mem_region (mmio_start, RTL_IO_SIZE);
+       DPRINTK ("EXIT, returning %d\n", rc);
+       return rc;
+}
+
+
+static int __devinit rtl8139_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct net_device *dev;
+       struct rtl8139_private *tp;
+       int i, addr_len, option = -1;
+       void *ioaddr = NULL;
+
+       DPRINTK ("ENTER\n");
+       
+       assert (pdev != NULL);
+       assert (ent != NULL);
+       
+       i = rtl8139_init_pci (pdev, &ioaddr);
+       if (i < 0) {
+               DPRINTK ("EXIT, returning %d\n", i);
+               return i;
+       }
+       
+       assert (ioaddr != NULL);
+
+       /* dev zeroed in init_etherdev */
+       dev = init_etherdev (NULL, sizeof (*tp) + PRIV_ALIGN);
+       if (dev == NULL) {
+               iounmap (ioaddr);
+               printk (KERN_ERR PFX "unable to alloc new ethernet\n");
+               DPRINTK ("EXIT, returning -ENOMEM\n");
+               return -ENOMEM;
+       }
+
+       addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
+       for (i = 0; i < 3; i++)
+               ((u16 *) (dev->dev_addr))[i] =
+                   le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
+
+       /* The Rtl8139-specific entries in the device structure. */
+       dev->open = rtl8139_open;
+       dev->hard_start_xmit = rtl8139_start_xmit;
+       dev->stop = rtl8139_close;
+       dev->get_stats = rtl8139_get_stats;
+       dev->set_multicast_list = rtl8139_set_rx_mode;
+       dev->do_ioctl = mii_ioctl;
+       dev->tx_timeout = rtl8139_tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
+
+       dev->irq = pdev->irq;
+       dev->base_addr = pci_resource_start (pdev, 1);
+
+       dev->priv = tp = (void *)
+               (((long)dev->priv + PRIV_ALIGN) & ~PRIV_ALIGN);
+
+       printk (KERN_INFO "%s: %s at 0x%lx, IRQ %d, "
+               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+               dev->name, rtl8139_name_from_chip(ent->driver_data),
+               dev->base_addr, dev->irq,
+               dev->dev_addr[0], dev->dev_addr[1],
+               dev->dev_addr[2], dev->dev_addr[3],
+               dev->dev_addr[4], dev->dev_addr[5]);
+
+       /* tp zeroed in init_etherdev */
+       tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                       PCI_COMMAND_MASTER | RTL8139_CAPS;
+       tp->pci_dev = pdev;
+       tp->chip = ent->driver_data;
+       tp->mmio_addr = ioaddr;
+       tp->lock = SPIN_LOCK_UNLOCKED;
+
+       PCI_SET_DRIVER_DATA (pdev, dev);
+
+       tp->phys[0] = 32;
+
+       /* Put the chip into low-power mode. */
+       RTL_W8 (Cfg9346, 0xC0);
+       RTL_W8 (Config1, 0x03); /* Enable PM & PCI VPD */
+       RTL_W8 (HltClk, 'H');   /* 'R' would leave the clock running. */
+
+       /* The lower four bits are the media type. */
+       if (option > 0) {
+               tp->full_duplex = (option & 0x200) ? 1 : 0;
+               tp->default_port = option & 15;
+               if (tp->default_port)
+                       tp->medialock = 1;
+       }
+
+       if (tp->full_duplex) {
+               printk (KERN_INFO
+                       "%s: Media type forced to Full Duplex.\n",
+                       dev->name);
+               mdio_write (dev, tp->phys[0], 4, 0x141);
+               tp->duplex_lock = 1;
+       }
+
+       DPRINTK ("EXIT - returning 0\n");
+       return 0;
+}
+
+
+static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
+{
+       struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+       struct rtl8139_private *np;
+
+       DPRINTK ("ENTER\n");
+
+       assert (dev != NULL);
+
+       np = (struct rtl8139_private *) (dev->priv);
+       assert (np != NULL);
+
+       unregister_netdev (dev);
+
+       iounmap (np->mmio_addr);
+       release_region (pci_resource_start (pdev, 0), RTL_IO_SIZE);
+       release_mem_region (pci_resource_start (pdev, 1), RTL_IO_SIZE);
+
+#ifndef RTL8139_NDEBUG
+       /* poison memory before freeing */
+       memset (dev, 0xC0,
+               sizeof (struct net_device) +
+               sizeof (struct rtl8139_private) +
+               PRIV_ALIGN);
+#endif
+
+       kfree (dev);
+       
+       DPRINTK ("EXIT\n");
+}
+
+
+/* Serial EEPROM section. */
+
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK   0x04    /* EEPROM shift clock. */
+#define EE_CS                  0x08    /* EEPROM chip select. */
+#define EE_DATA_WRITE  0x02    /* EEPROM chip data in. */
+#define EE_WRITE_0             0x00
+#define EE_WRITE_1             0x02
+#define EE_DATA_READ   0x01    /* EEPROM chip data out. */
+#define EE_ENB                 (0x80 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
+ */
+
+#define eeprom_delay() readl(ee_addr)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD   (5)
+#define EE_READ_CMD            (6)
+#define EE_ERASE_CMD   (7)
+
+static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
+{
+       int i;
+       unsigned retval = 0;
+       void *ee_addr = ioaddr + Cfg9346;
+       int read_cmd = location | (EE_READ_CMD << addr_len);
+
+       DPRINTK ("ENTER\n");
+
+       writeb (EE_ENB & ~EE_CS, ee_addr);
+       writeb (EE_ENB, ee_addr);
+       eeprom_delay ();
+
+       /* Shift the read command bits out. */
+       for (i = 4 + addr_len; i >= 0; i--) {
+               int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+               writeb (EE_ENB | dataval, ee_addr);
+               eeprom_delay ();
+               writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+               eeprom_delay ();
+       }
+       writeb (EE_ENB, ee_addr);
+       eeprom_delay ();
+
+       for (i = 16; i > 0; i--) {
+               writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
+               eeprom_delay ();
+               retval =
+                   (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
+                                    0);
+               writeb (EE_ENB, ee_addr);
+               eeprom_delay ();
+       }
+
+       /* Terminate the EEPROM access. */
+       writeb (~EE_CS, ee_addr);
+       eeprom_delay ();
+
+       DPRINTK ("EXIT - returning %d\n", retval);
+       return retval;
+}
+
+/* MII serial management: mostly bogus for now. */
+/* Read and write the MII management registers using software-generated
+   serial MDIO protocol.
+   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+   "overclocking" issues. */
+#define MDIO_DIR               0x80
+#define MDIO_DATA_OUT  0x04
+#define MDIO_DATA_IN   0x02
+#define MDIO_CLK               0x01
+#define MDIO_WRITE0 (MDIO_DIR)
+#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
+
+#define mdio_delay()   readb(mdio_addr)
+
+
+static char mii_2_8139_map[8] = {
+       BasicModeCtrl,
+       BasicModeStatus,
+       0,
+       0,
+       NWayAdvert,
+       NWayLPAR,
+       NWayExpansion,
+       0
+};
+
+
+/* Syncronize the MII management interface by shifting 32 one bits out. */
+static void mdio_sync (void *mdio_addr)
+{
+       int i;
+
+       DPRINTK ("ENTER\n");
+
+       for (i = 32; i >= 0; i--) {
+               writeb (MDIO_WRITE1, mdio_addr);
+               mdio_delay ();
+               writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
+               mdio_delay ();
+       }
+
+       DPRINTK ("EXIT\n");
+}
+
+
+static int mdio_read (struct net_device *dev, int phy_id, int location)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *mdio_addr = tp->mmio_addr + Config4;
+       int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+       int retval = 0;
+       int i;
+
+       DPRINTK ("ENTER\n");
+
+       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
+               DPRINTK ("EXIT after directly using 8139 internal regs\n");
+               return location < 8 && mii_2_8139_map[location] ?
+                   readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
+       }
+       mdio_sync (mdio_addr);
+       /* Shift the read command bits out. */
+       for (i = 15; i >= 0; i--) {
+               int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
+
+               writeb (MDIO_DIR | dataval, mdio_addr);
+               mdio_delay ();
+               writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
+               mdio_delay ();
+       }
+
+       /* Read the two transition, 16 data, and wire-idle bits. */
+       for (i = 19; i > 0; i--) {
+               writeb (0, mdio_addr);
+               mdio_delay ();
+               retval =
+                   (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1
+                                    : 0);
+               writeb (MDIO_CLK, mdio_addr);
+               mdio_delay ();
+       }
+
+       DPRINTK ("EXIT, returning %d\n", (retval >> 1) & 0xffff);
+       return (retval >> 1) & 0xffff;
+}
+
+
+static void mdio_write (struct net_device *dev, int phy_id, int location,
+                       int value)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *mdio_addr = tp->mmio_addr + Config4;
+       int mii_cmd =
+           (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+       int i;
+
+       DPRINTK ("ENTER\n");
+
+       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
+               if (location < 8 && mii_2_8139_map[location]) {
+                       writew (value,
+                               tp->mmio_addr + mii_2_8139_map[location]);
+                       readw (tp->mmio_addr + mii_2_8139_map[location]);
+               }
+               DPRINTK ("EXIT after directly using 8139 internal regs\n");
+               return;
+       }
+       mdio_sync (mdio_addr);
+
+       /* Shift the command bits out. */
+       for (i = 31; i >= 0; i--) {
+               int dataval =
+                   (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+               writeb (dataval, mdio_addr);
+               mdio_delay ();
+               writeb (dataval | MDIO_CLK, mdio_addr);
+               mdio_delay ();
+       }
+
+       /* Clear out extra bits. */
+       for (i = 2; i > 0; i--) {
+               writeb (0, mdio_addr);
+               mdio_delay ();
+               writeb (MDIO_CLK, mdio_addr);
+               mdio_delay ();
+       }
+
+       DPRINTK ("EXIT\n");
+}
+
+
+static int rtl8139_open (struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+       int i;
+
+       DPRINTK ("ENTER\n");
+
+       MOD_INC_USE_COUNT;
+
+       /* Soft reset the chip. */
+       RTL_W8 (ChipCmd, CmdReset);
+
+       if (request_irq (dev->irq, &rtl8139_interrupt, SA_SHIRQ, dev->name, dev)) {
+               DPRINTK ("EXIT, returning -EBUSY\n");
+               MOD_DEC_USE_COUNT;
+               return -EBUSY;
+       }
+
+       tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC,
+                                          &tp->tx_bufs_dma);
+       tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_LEN + 16,
+                                          &tp->rx_ring_dma);
+       if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
+               free_irq(dev->irq, dev);
+
+               if (tp->tx_bufs)
+                       pci_free_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC,
+                                           tp->tx_bufs, tp->tx_bufs_dma);
+               if (tp->rx_ring)
+                       pci_free_consistent(tp->pci_dev, RX_BUF_LEN + 16,
+                                           tp->rx_ring, tp->rx_ring_dma);
+
+               DPRINTK ("EXIT, returning -ENOMEM\n");
+               MOD_DEC_USE_COUNT;
+               return -ENOMEM;
+               
+       }
+       
+       rtl8139_init_ring (dev);
+       tp->full_duplex = tp->duplex_lock;
+       tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
+       tp->rx_config =
+           (RX_FIFO_THRESH << 13) |
+           (RX_BUF_LEN_IDX << 11) |
+           (RX_DMA_BURST << 8);
+
+       /* Check that the chip has finished the reset. */
+       for (i = 1000; i > 0; i--)
+               if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
+                       break;
+
+       RTL_W32 (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
+       RTL_W32 (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
+
+       /* Must enable Tx/Rx before setting transfer thresholds! */
+       RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+       RTL_W32 (RxConfig, tp->rx_config);
+       RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x00000000);
+
+       /* Reset N-Way to chipset defaults */
+       RTL_W16 (BasicModeCtrl, (1<<15)|(1<<12)|(1<<9));
+       for (i = 1000; i > 0; i--)
+               if ((RTL_R8 (BasicModeCtrl) & (1<<15)) == 0)
+                       break;
+       
+       /* Set N-Way to sane defaults */
+       RTL_W16 (FIFOTMS, 0x0000);
+       RTL_W16 (NWayAdvert, (1<<13)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|0x1);
+       RTL_W16 (BasicModeCtrl, (1<<13)|(1<<12)|(1<<9)|(1<<8));
+       
+       RTL_W8 (Cfg9346, 0xC0);
+       RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+       RTL_W8 (Cfg9346, 0x00);
+
+       RTL_W32 (RxBuf, tp->rx_ring_dma);
+
+       /* Start the chip's Tx and Rx process. */
+       RTL_W32 (RxMissed, 0);
+       rtl8139_set_rx_mode (dev);
+
+       RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+
+       /* Enable all known interrupts by setting the interrupt mask. */
+       RTL_W16 (IntrMask,
+                PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
+                | TxErr | TxOK | RxErr | RxOK);
+
+       DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d"
+                       " GP Pins %2.2x %s-duplex.\n",
+                       dev->name, pci_resource_start (tp->pci_dev, 1),
+                       dev->irq, RTL_R8 (GPPinData),
+                       tp->full_duplex ? "full" : "half");
+
+       /* Set the timer to switch to check for link beat and perhaps switch
+          to an alternate media type. */
+       init_timer (&tp->timer);
+       tp->timer.expires = jiffies + 3 * HZ;
+       tp->timer.data = (unsigned long) dev;
+       tp->timer.function = &rtl8139_timer;
+       add_timer (&tp->timer);
+
+       netif_start_queue (dev);
+
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+}
+
+/* Start the hardware at open or resume. */
+static void rtl8139_hw_start (struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+       int i;
+
+       DPRINTK ("ENTER\n");
+
+       /* Soft reset the chip. */
+       RTL_W8 (ChipCmd, CmdReset);
+       /* Check that the chip has finished the reset. */
+       for (i = 1000; i > 0; i--)
+               if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
+                       break;
+
+       /* Restore our idea of the MAC address. */
+       RTL_W32 (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
+       RTL_W32 (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
+
+       /* Hmmm, do these belong here? */
+       RTL_W8 (Cfg9346, 0x00);
+       tp->cur_rx = 0;
+
+       /* Must enable Tx/Rx before setting transfer thresholds! */
+       RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+       RTL_W32 (RxConfig, tp->rx_config);
+       /* Check this value: the documentation contradicts ifself.  Is the
+          IFG correct with bit 28:27 zero, or with |0x03000000 ? */
+       RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x00000000);
+
+       /* Reset N-Way to chipset defaults */
+       RTL_W16 (BasicModeCtrl, (1<<15)|(1<<12)|(1<<9));
+       for (i = 1000; i > 0; i--)
+               if ((RTL_R8 (BasicModeCtrl) & (1<<15)) == 0)
+                       break;
+       
+       /* Set N-Way to sane defaults */
+       RTL_W16 (FIFOTMS, 0x0000);
+       RTL_W16 (NWayAdvert, (1<<13)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|0x1);
+       RTL_W16 (BasicModeCtrl, (1<<13)|(1<<12)|(1<<9)|(1<<8));
+       
+       /* check_duplex() here. */
+       RTL_W8 (Cfg9346, 0xC0);
+       RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+       RTL_W8 (Cfg9346, 0x00);
+
+       RTL_W32 (RxBuf, tp->rx_ring_dma);
+       /* Start the chip's Tx and Rx process. */
+       RTL_W32 (RxMissed, 0);
+       rtl8139_set_rx_mode (dev);
+       RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+       /* Enable all known interrupts by setting the interrupt mask. */
+       RTL_W16 (IntrMask,
+                PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
+                | TxErr | TxOK | RxErr | RxOK);
+
+       netif_start_queue (dev);
+
+       DPRINTK ("EXIT\n");
+}
+
+
+#ifndef RTL_TUNE_TWISTER
+static inline void rtl8139_tune_twister (struct net_device *dev,
+                                 struct rtl8139_private *tp) {}
+#else
+static void rtl8139_tune_twister (struct net_device *dev,
+                                 struct rtl8139_private *tp)
+{
+       int linkcase;
+
+       DPRINTK ("ENTER\n");
+
+       /* This is a complicated state machine to configure the "twister" for
+          impedance/echos based on the cable length.
+          All of this is magic and undocumented.
+        */
+       switch (tp->twistie) {
+       case 1:
+               if (RTL_R16 (CSCR) & CSCR_LinkOKBit) {
+                       /* We have link beat, let us tune the twister. */
+                       RTL_W16 (CSCR, CSCR_LinkDownOffCmd);
+                       tp->twistie = 2;        /* Change to state 2. */
+                       next_tick = HZ / 10;
+               } else {
+                       /* Just put in some reasonable defaults for when beat returns. */
+                       RTL_W16 (CSCR, CSCR_LinkDownCmd);
+                       RTL_W32 (FIFOTMS, 0x20);        /* Turn on cable test mode. */
+                       RTL_W32 (PARA78, PARA78_default);
+                       RTL_W32 (PARA7c, PARA7c_default);
+                       tp->twistie = 0;        /* Bail from future actions. */
+               }
+               break;
+       case 2:
+               /* Read how long it took to hear the echo. */
+               linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits;
+               if (linkcase == 0x7000)
+                       tp->twist_row = 3;
+               else if (linkcase == 0x3000)
+                       tp->twist_row = 2;
+               else if (linkcase == 0x1000)
+                       tp->twist_row = 1;
+               else
+                       tp->twist_row = 0;
+               tp->twist_col = 0;
+               tp->twistie = 3;        /* Change to state 2. */
+               next_tick = HZ / 10;
+               break;
+       case 3:
+               /* Put out four tuning parameters, one per 100msec. */
+               if (tp->twist_col == 0)
+                       RTL_W16 (FIFOTMS, 0);
+               RTL_W32 (PARA7c, param[(int) tp->twist_row]
+                        [(int) tp->twist_col]);
+               next_tick = HZ / 10;
+               if (++tp->twist_col >= 4) {
+                       /* For short cables we are done.
+                          For long cables (row == 3) check for mistune. */
+                       tp->twistie =
+                           (tp->twist_row == 3) ? 4 : 0;
+               }
+               break;
+       case 4:
+               /* Special case for long cables: check for mistune. */
+               if ((RTL_R16 (CSCR) &
+                    CSCR_LinkStatusBits) == 0x7000) {
+                       tp->twistie = 0;
+                       break;
+               } else {
+                       RTL_W32 (PARA7c, 0xfb38de03);
+                       tp->twistie = 5;
+                       next_tick = HZ / 10;
+               }
+               break;
+       case 5:
+               /* Retune for shorter cable (column 2). */
+               RTL_W32 (FIFOTMS, 0x20);
+               RTL_W32 (PARA78, PARA78_default);
+               RTL_W32 (PARA7c, PARA7c_default);
+               RTL_W32 (FIFOTMS, 0x00);
+               tp->twist_row = 2;
+               tp->twist_col = 0;
+               tp->twistie = 3;
+               next_tick = HZ / 10;
+               break;
+
+       default:
+               /* do nothing */
+               break;
+       }
+
+       DPRINTK ("EXIT\n");
+}
+#endif /* RTL_TUNE_TWISTER */
+
+
+static void rtl8139_timer (unsigned long data)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+       int next_tick = 60 * HZ;
+       int mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+
+       DPRINTK ("ENTER\n");
+
+       if (!tp->duplex_lock && mii_reg5 != 0xffff) {
+               int duplex = (mii_reg5 & 0x0100)
+                   || (mii_reg5 & 0x01C0) == 0x0040;
+               if (tp->full_duplex != duplex) {
+                       tp->full_duplex = duplex;
+                       printk (KERN_INFO
+                               "%s: Setting %s-duplex based on MII #%d link"
+                               " partner ability of %4.4x.\n", dev->name,
+                               tp->full_duplex ? "full" : "half",
+                               tp->phys[0], mii_reg5);
+                       RTL_W8 (Cfg9346, 0xC0);
+                       RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+                       RTL_W8 (Cfg9346, 0x00);
+               }
+       }
+
+       rtl8139_tune_twister (dev, tp);
+
+       DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",
+                dev->name, RTL_R16 (NWayLPAR));
+       DPRINTK ("%s:  Other registers are IntMask %4.4x IntStatus %4.4x"
+                " RxStatus %4.4x.\n", dev->name,
+                RTL_R16 (IntrMask),
+                RTL_R16 (IntrStatus),
+                RTL_R32 (RxEarlyStatus));
+       DPRINTK ("%s:  Chip config %2.2x %2.2x.\n",
+                dev->name, RTL_R8 (Config0),
+                RTL_R8 (Config1));
+
+       tp->timer.expires = jiffies + next_tick;
+       add_timer (&tp->timer);
+
+       DPRINTK ("EXIT\n");
+}
+
+
+static void rtl8139_tx_timeout (struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+       int mii_reg, i;
+
+       DPRINTK ("ENTER\n");
+
+       netif_stop_queue (dev);
+
+       DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
+                "media %2.2x.\n", dev->name,
+                readb (ioaddr + ChipCmd),
+                readw (ioaddr + IntrStatus),
+                readb (ioaddr + GPPinData));
+
+       /* Disable interrupts by clearing the interrupt mask. */
+       RTL_W16 (IntrMask, 0x0000);
+       /* Emit info to figure out what went wrong. */
+       printk (KERN_DEBUG
+               "%s: Tx queue start entry %d  dirty entry %d.\n",
+               dev->name, tp->cur_tx, tp->dirty_tx);
+       for (i = 0; i < NUM_TX_DESC; i++)
+               printk (KERN_DEBUG "%s:  Tx descriptor %d is %8.8x.%s\n",
+                       dev->name, i, readl (ioaddr + TxStatus0 + i * 4),
+                       i ==
+                     tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : "");
+       printk (KERN_DEBUG "%s: MII #%d registers are:", dev->name,
+               tp->phys[0]);
+       for (mii_reg = 0; mii_reg < 8; mii_reg++)
+               printk (" %4.4x", mdio_read (dev, tp->phys[0], mii_reg));
+       printk (".\n");
+
+       /* Stop a shared interrupt from scavenging while we are. */
+       tp->dirty_tx = tp->cur_tx = 0;
+
+       /* Dump the unsent Tx packets. */
+       for (i = 0; i < NUM_TX_DESC; i++) {
+               struct ring_info *rp = &tp->tx_info[i];
+               if (rp->skb) {
+                       dev_kfree_skb (rp->skb);
+                       rp->skb = NULL;
+                       tp->stats.tx_dropped++;
+               }
+               if (rp->mapping != 0) {
+                       pci_unmap_single (tp->pci_dev, rp->mapping, rp->skb->len);
+                       rp->mapping = 0;
+               }
+       }
+
+       rtl8139_hw_start (dev);
+
+       DPRINTK ("EXIT\n");
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void rtl8139_init_ring (struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       int i;
+
+       DPRINTK ("ENTER\n");
+
+       tp->cur_rx = 0;
+       tp->dirty_tx = tp->cur_tx = 0;
+
+       for (i = 0; i < NUM_TX_DESC; i++) {
+               tp->tx_info[i].skb = NULL;
+               tp->tx_info[i].mapping = 0;
+               tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
+       }
+
+       DPRINTK ("EXIT\n");
+}
+
+static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+       int entry;
+       unsigned long flags;
+
+       DPRINTK ("ENTER\n");
+       
+       netif_stop_queue (dev);
+
+       /* Calculate the next Tx descriptor entry. */
+       entry = tp->cur_tx % NUM_TX_DESC;
+
+       spin_lock_irqsave (&tp->lock, flags);
+       
+       tp->tx_info[entry].skb = skb;
+       if ((long) skb->data & 3) {     /* Must use alignment buffer. */
+               tp->tx_info[entry].mapping = 0;
+               memcpy (tp->tx_buf[entry], skb->data, skb->len);
+
+               assert (tp->tx_bufs_dma > 0);
+               RTL_W32 (TxAddr0 + entry * 4, tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs));
+       } else {
+               tp->tx_info[entry].mapping =
+                       pci_map_single(tp->pci_dev, skb->data, skb->len);
+
+               assert (tp->tx_info[entry].mapping > 0);
+               RTL_W32 (TxAddr0 + entry * 4, tp->tx_info[entry].mapping);
+       }
+       
+       /* Note: the chip doesn't have auto-pad! */
+       RTL_W32 (TxStatus0 + entry * 4,
+                tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+
+       dev->trans_start = jiffies;
+       if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC)  /* Typical path */
+               netif_start_queue (dev);
+
+       spin_unlock_irqrestore (&tp->lock, flags);
+       
+       DPRINTK ("%s: Queued Tx packet at %p size %lu to slot %d.\n",
+                dev->name, skb->data, skb->len, entry);
+
+       DPRINTK ("EXIT\n");
+       return 0;
+}
+
+
+static inline void rtl8139_tx_interrupt (struct net_device *dev,
+                                        struct rtl8139_private *tp)
+{
+       void *ioaddr;
+       unsigned int dirty_tx;
+
+       assert (dev != NULL);
+       assert (tp != NULL);
+
+       dirty_tx = tp->dirty_tx;
+       ioaddr = tp->mmio_addr;
+
+       while (tp->cur_tx - dirty_tx > 0) {
+               int entry = dirty_tx % NUM_TX_DESC;
+               int txstatus = readl (ioaddr + TxStatus0 + entry * 4);
+
+               if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
+                       break;  /* It still hasn't been Txed */
+
+               /* Note: TxCarrierLost is always asserted at 100mbps. */
+               if (txstatus & (TxOutOfWindow | TxAborted)) {
+                       /* There was an major error, log it. */
+                       DPRINTK ("%s: Transmit error, Tx status %8.8x.\n",
+                                dev->name, txstatus);
+                       tp->stats.tx_errors++;
+                       if (txstatus & TxAborted) {
+                               tp->stats.tx_aborted_errors++;
+                               RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x03000001);
+                       }
+                       if (txstatus & TxCarrierLost)
+                               tp->stats.tx_carrier_errors++;
+                       if (txstatus & TxOutOfWindow)
+                               tp->stats.tx_window_errors++;
+#ifdef ETHER_STATS
+                       if ((txstatus & 0x0f000000) == 0x0f000000)
+                               tp->stats.collisions16++;
+#endif
+               } else {
+                       if (txstatus & TxUnderrun) {
+                               /* Add 64 to the Tx FIFO threshold. */
+                               if (tp->tx_flag < 0x00300000)
+                                       tp->tx_flag += 0x00020000;
+                               tp->stats.tx_fifo_errors++;
+                       }
+                       tp->stats.collisions += (txstatus >> 24) & 15;
+                       tp->stats.tx_bytes += txstatus & 0x7ff;
+                       tp->stats.tx_packets++;
+               }
+
+               if (tp->tx_info[entry].mapping != 0) {
+                       pci_unmap_single (tp->pci_dev,
+                                         tp->tx_info[entry].mapping,
+                                         tp->tx_info[entry].skb->len);
+                       tp->tx_info[entry].mapping = 0;
+               }
+               /* Free the original skb. */
+               dev_kfree_skb_irq (tp->tx_info[entry].skb);
+               tp->tx_info[entry].skb = NULL;
+               dirty_tx++;
+               if (tp->cur_tx - dirty_tx < NUM_TX_DESC)
+                       netif_wake_queue (dev);
+               else
+                       netif_stop_queue (dev);
+       }
+
+#ifndef RTL8139_NDEBUG
+       if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
+               printk (KERN_ERR
+                 "%s: Out-of-sync dirty pointer, %d vs. %d.\n",
+                    dev->name, dirty_tx, tp->cur_tx);
+               dirty_tx += NUM_TX_DESC;
+       }
+#endif
+
+       tp->dirty_tx = dirty_tx;
+}
+
+
+/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
+   field alignments and semantics. */
+static inline void rtl8139_rx_interrupt (struct net_device *dev,
+                                        struct rtl8139_private *tp)
+{
+       void *ioaddr = tp->mmio_addr;
+       unsigned char *rx_ring = tp->rx_ring;
+       u16 cur_rx = tp->cur_rx;
+
+       DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
+                       " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+                       readw (ioaddr + RxBufAddr),
+                       readw (ioaddr + RxBufPtr),
+                       readb (ioaddr + ChipCmd));
+
+       while ((readb (ioaddr + ChipCmd) & RxBufEmpty) == 0) {
+               int ring_offset = cur_rx % RX_BUF_LEN;
+               u32 rx_status =
+                   le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
+               int rx_size = rx_status >> 16;
+
+#ifdef RTL8139_DEBUG
+               int i;
+               DPRINTK ("%s:  rtl8139_rx() status %4.4x, size %4.4x,"
+                       " cur %4.4x.\n", dev->name, rx_status,
+                       rx_size, cur_rx);
+               DPRINTK ("%s: Frame contents ", dev->name);
+               for (i = 0; i < 70; i++)
+                       printk (" %2.2x", rx_ring[ring_offset + i]);
+               printk (".\n");
+#endif
+
+               if (rx_status &
+                   (RxBadSymbol | RxRunt | RxTooLong | RxCRCErr |
+                    RxBadAlign)) {
+                       DPRINTK ("%s: Ethernet frame had errors,"
+                                       " status %8.8x.\n", dev->name,
+                                       rx_status);
+                       if (rx_status & RxTooLong) {
+                               DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
+                                               dev->name, rx_status);
+                               /* A.C.: The chip hangs here. */
+                       }
+                       tp->stats.rx_errors++;
+                       if (rx_status & (RxBadSymbol | RxBadAlign))
+                               tp->stats.rx_frame_errors++;
+                       if (rx_status & (RxRunt | RxTooLong))
+                               tp->stats.rx_length_errors++;
+                       if (rx_status & RxCRCErr)
+                               tp->stats.rx_crc_errors++;
+                       /* Reset the receiver, based on RealTek recommendation. (Bug?) */
+                       tp->cur_rx = 0;
+                       RTL_W8 (ChipCmd, CmdTxEnb);
+                       /* A.C.: Reset the multicast list. */
+                       rtl8139_set_rx_mode (dev);
+                       RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+               } else {
+                       /* Malloc up new buffer, compatible with net-2e. */
+                       /* Omit the four octet CRC from the length. */
+                       struct sk_buff *skb;
+
+                       skb = dev_alloc_skb (rx_size + 2);
+                       if (skb == NULL) {
+                               printk (KERN_WARNING
+                                       "%s: Memory squeeze, deferring packet.\n",
+                                       dev->name);
+                               /* We should check that some rx space is free.
+                                  If not, free one and mark stats->rx_dropped++. */
+                               tp->stats.rx_dropped++;
+                               break;
+                       }
+                       skb->dev = dev;
+                       skb_reserve (skb, 2);   /* 16 byte align the IP fields. */
+                       if (ring_offset + rx_size + 4 > RX_BUF_LEN) {
+                               int semi_count =
+                                   RX_BUF_LEN - ring_offset - 4;
+                               /* This could presumably use two calls to copy_and_sum()? */
+                               memcpy (skb_put (skb, semi_count),
+                                       &rx_ring[ring_offset + 4],
+                                       semi_count);
+                               memcpy (skb_put
+                                       (skb, rx_size - semi_count),
+                                       rx_ring, rx_size - semi_count);
+#ifdef RTL8139_DEBUG
+                               {
+                               int i;
+                               printk (KERN_DEBUG
+                                       "%s:  Frame wrap @%d",
+                                       dev->name, semi_count);
+                               for (i = 0; i < 16; i++)
+                                       printk (" %2.2x",
+                                               rx_ring[i]);
+                               printk (".\n");
+                               memset (rx_ring, 0xcc, 16);
+                               }
+#endif /* RTL8139_DEBUG */
+
+                       } else {
+                               eth_copy_and_sum (skb,
+                                                 &rx_ring[ring_offset +
+                                                          4], rx_size, 0);
+                               skb_put (skb, rx_size);
+                       }
+                       skb->protocol = eth_type_trans (skb, dev);
+                       netif_rx (skb);
+                       tp->stats.rx_bytes += rx_size;
+                       tp->stats.rx_packets++;
+               }
+
+               cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
+               RTL_W16 (RxBufPtr, cur_rx - 16);
+       }
+       DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
+               " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+               readw (ioaddr + RxBufAddr),
+               readw (ioaddr + RxBufPtr),
+               readb (ioaddr + ChipCmd));
+       tp->cur_rx = cur_rx;
+}
+
+
+static inline int rtl8139_weird_interrupt (struct net_device *dev,
+                                          struct rtl8139_private *tp,
+                                          int status, int link_changed)
+{
+       void *ioaddr;
+
+       DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",
+                dev->name, status);
+                
+       assert (dev != NULL);
+       assert (tp != NULL);
+
+       ioaddr = tp->mmio_addr;
+
+       if (status == 0xffffffff) {
+               printk (KERN_WARNING PFX "abnormal interrupt, card ejected? (ok to ignore)\n");
+               return -1;
+       }
+
+       /* Update the error count. */
+       tp->stats.rx_missed_errors +=
+           readl (ioaddr + RxMissed);
+       RTL_W32 (RxMissed, 0);
+
+       if ((status & RxUnderrun) && link_changed &&
+           (tp->drv_flags & HAS_LNK_CHNG)) {
+               /* Really link-change on new chips. */
+               int lpar = readw (ioaddr + NWayLPAR);
+               int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040
+                               || tp->duplex_lock;
+               if (tp->full_duplex != duplex) {
+                       tp->full_duplex = duplex;
+                       RTL_W8 (Cfg9346, 0xC0);
+                       RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+                       RTL_W8 (Cfg9346, 0x00);
+               }
+               status &= ~RxUnderrun;
+       }
+       if (status &
+           (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
+               tp->stats.rx_errors++;
+
+       if (status & (PCSTimeout))
+               tp->stats.rx_length_errors++;
+       if (status & (RxUnderrun | RxFIFOOver))
+               tp->stats.rx_fifo_errors++;
+       if (status & RxOverflow) {
+               tp->stats.rx_over_errors++;
+               tp->cur_rx = readw (ioaddr + RxBufAddr) % RX_BUF_LEN;
+               RTL_W16 (RxBufPtr, tp->cur_rx - 16);
+       }
+       if (status & PCIErr) {
+               u16 pci_cmd_status;
+               pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status);
+
+               printk (KERN_ERR "%s: PCI Bus error %4.4x.\n",
+                       dev->name, pci_cmd_status);
+       }
+       
+       return 0;
+}
+
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void rtl8139_interrupt (int irq, void *dev_instance,
+                              struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) dev_instance;
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       int boguscnt = max_interrupt_work;
+       void *ioaddr = tp->mmio_addr;
+       int link_changed = 0;   /* Grrr, avoid bogus "uninitialized" warning */
+
+       spin_lock_irq (&tp->lock);
+
+       do {
+               int status = readw (ioaddr + IntrStatus);
+               /* Acknowledge all of the current interrupt sources ASAP, but
+                  an first get an additional status bit from CSCR. */
+               if (status & RxUnderrun)
+                       link_changed = readw (ioaddr + CSCR) & CSCR_LinkChangeBit;
+               RTL_W16 (IntrStatus, status);
+
+               DPRINTK ("%s: interrupt  status=%#4.4x new intstat=%#4.4x.\n",
+                               dev->name, status,
+                               readw (ioaddr + IntrStatus));
+
+               if ((status &
+                    (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
+                     RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
+                       break;
+
+               /* Check uncommon events with one test. */
+               if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
+                             RxFIFOOver | TxErr | RxErr))
+                       if (rtl8139_weird_interrupt (dev, tp, status,
+                                                    link_changed) == -1)
+                               break;
+
+               if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver))     /* Rx interrupt */
+                       rtl8139_rx_interrupt (dev, tp);
+
+               if (status & (TxOK | TxErr))
+                       rtl8139_tx_interrupt (dev, tp);
+
+               if (--boguscnt < 0) {
+                       printk (KERN_WARNING
+                               "%s: Too much work at interrupt, "
+                               "IntrStatus=0x%4.4x.\n", dev->name,
+                               status);
+                       /* Clear all interrupt sources. */
+                       RTL_W16 (IntrStatus, 0xffff);
+                       break;
+               }
+       } while (1);
+
+       DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
+                       dev->name, readw (ioaddr + IntrStatus));
+
+       spin_unlock_irq (&tp->lock);
+       return;
+}
+
+static int rtl8139_close (struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+       int i;
+
+       DPRINTK ("ENTER\n");
+
+       netif_stop_queue (dev);
+
+       DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n",
+                       dev->name, readw (ioaddr + IntrStatus));
+
+       /* Disable interrupts by clearing the interrupt mask. */
+       RTL_W16 (IntrMask, 0x0000);
+
+       /* Stop the chip's Tx and Rx DMA processes. */
+       RTL_W8 (ChipCmd, 0x00);
+
+       /* Update the error counts. */
+       tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+       RTL_W32 (RxMissed, 0);
+
+       del_timer (&tp->timer);
+
+       free_irq (dev->irq, dev);
+
+       for (i = 0; i < NUM_TX_DESC; i++) {
+               struct sk_buff *skb = tp->tx_info[i].skb;
+               dma_addr_t mapping = tp->tx_info[i].mapping;
+
+               if (skb) {
+                       if (mapping)
+                               pci_unmap_single (tp->pci_dev, mapping, skb->len);
+                       dev_kfree_skb (skb);
+               }
+               tp->tx_info[i].skb = NULL;
+               tp->tx_info[i].mapping = 0;
+       }
+
+       pci_free_consistent(tp->pci_dev, RX_BUF_LEN + 16,
+                           tp->rx_ring, tp->rx_ring_dma);
+       pci_free_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC,
+                           tp->tx_bufs, tp->tx_bufs_dma);
+       tp->rx_ring = NULL;
+       tp->tx_bufs = NULL;
+
+       /* Green! Put the chip in low-power mode. */
+       RTL_W8 (Cfg9346, 0xC0);
+       RTL_W8 (Config1, 0x03);
+       RTL_W8 (HltClk, 'H');   /* 'R' would leave the clock running. */
+
+       MOD_DEC_USE_COUNT;
+
+       DPRINTK ("EXIT\n");
+       return 0;
+}
+
+static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       u16 *data = (u16 *) & rq->ifr_data;
+
+       DPRINTK ("ENTER\n");
+
+       switch (cmd) {
+       case SIOCDEVPRIVATE:    /* Get the address of the PHY in use. */
+               data[0] = tp->phys[0] & 0x3f;
+               /* Fall Through */
+       case SIOCDEVPRIVATE + 1:        /* Read the specified MII register. */
+               data[3] = mdio_read (dev, data[0], data[1] & 0x1f);
+               DPRINTK ("EXIT\n");
+               return 0;
+       case SIOCDEVPRIVATE + 2:        /* Write the specified MII register */
+               if (!capable (CAP_NET_ADMIN))
+                       return -EPERM;
+               mdio_write (dev, data[0], data[1] & 0x1f, data[2]);
+               DPRINTK ("EXIT\n");
+               return 0;
+       default:
+               DPRINTK ("EXIT\n");
+               return -EOPNOTSUPP;
+       }
+
+       DPRINTK ("EXIT\n");
+}
+
+static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+
+       DPRINTK ("ENTER\n");
+
+       assert (tp != NULL);
+
+       if (test_bit(LINK_STATE_START, &dev->state)) {
+               tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+               RTL_W32 (RxMissed, 0);
+       }
+
+       DPRINTK ("EXIT\n");
+       return &tp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+   This routine is not state sensitive and need not be SMP locked. */
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc (int length, unsigned char *data)
+{
+       int crc = -1;
+
+       DPRINTK ("ENTER\n");
+
+       while (--length >= 0) {
+               unsigned char current_octet = *data++;
+               int bit;
+               for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+                       crc = (crc << 1) ^
+                           ((crc < 0) ^ (current_octet & 1) ?
+                            ethernet_polynomial : 0);
+       }
+
+       DPRINTK ("EXIT\n");
+       return crc;
+}
+
+static void rtl8139_set_rx_mode (struct net_device *dev)
+{
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+       u32 mc_filter[2];       /* Multicast hash filter */
+       int i, rx_mode;
+
+       DPRINTK ("ENTER\n");
+
+       DPRINTK ("%s:   rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
+                       dev->name, dev->flags, readl (ioaddr + RxConfig));
+
+       /* Note: do not reorder, GCC is clever about common statements. */
+       if (dev->flags & IFF_PROMISC) {
+               /* Unconditionally log net taps. */
+               printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
+                       dev->name);
+               rx_mode =
+                   AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
+                   AcceptAllPhys;
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+       } else if ((dev->mc_count > multicast_filter_limit)
+                  || (dev->flags & IFF_ALLMULTI)) {
+               /* Too many to filter perfectly -- accept all multicasts. */
+               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+       } else {
+               struct dev_mc_list *mclist;
+               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+               mc_filter[1] = mc_filter[0] = 0;
+               for (i = 0, mclist = dev->mc_list;
+                    mclist && i < dev->mc_count;
+                    i++, mclist =
+                    mclist->next) set_bit (ether_crc (ETH_ALEN,
+                                                      mclist->
+                                                      dmi_addr) >> 26,
+                                           mc_filter);
+       }
+       /* We can safely update without stopping the chip. */
+       RTL_W32 (RxConfig, tp->rx_config | rx_mode);
+       RTL_W32 (MAR0 + 0, mc_filter[0]);
+       RTL_W32 (MAR0 + 4, mc_filter[1]);
+
+       DPRINTK ("EXIT\n");
+}
+
+
+static void rtl8139_suspend (struct pci_dev *pdev)
+{
+       struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
+
+       netif_stop_queue (dev);
+       
+       /* Disable interrupts, stop Tx and Rx. */
+       RTL_W16 (IntrMask, 0x0000);
+       RTL_W8 (ChipCmd, 0x00);
+
+       /* Update the error counts. */
+       tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+       RTL_W32 (RxMissed, 0);
+}
+
+
+static void rtl8139_resume (struct pci_dev *pdev)
+{
+       struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+
+       rtl8139_hw_start(dev);
+}
+
+
+static struct pci_driver rtl8139_pci_driver = {
+       name:           RTL8139_MODULE_NAME,
+       id_table:       rtl8139_pci_tbl,
+       probe:          rtl8139_init_one,
+       remove:         rtl8139_remove_one,
+       suspend:        rtl8139_suspend,
+       resume:         rtl8139_resume,
+};
+
+
+static int __init rtl8139_init_module (void)
+{
+       int rc;
+       
+       DPRINTK ("ENTER\n");
+
+       rc = pci_register_driver (&rtl8139_pci_driver);
+       
+       if (rc > 0) {
+               printk (KERN_INFO RTL8139_DRIVER_NAME
+                       " loaded (%d device%s registered)\n",
+                       rc, rc > 1 ? "s" : "");
+       }
+
+       DPRINTK ("EXIT\n");
+       return rc > 0 ? 0 : -ENODEV;
+}
+
+
+static void __exit rtl8139_cleanup_module (void)
+{
+       pci_unregister_driver (&rtl8139_pci_driver);
+}
+
+
+module_init(rtl8139_init_module);
+module_exit(rtl8139_cleanup_module);
index f3eba639f26191eaf6dd030ef2cd72e2d069e99e..54ecdad60d19b9b74b6a1f7e127cacc2b86028e2 100644 (file)
@@ -83,10 +83,6 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
     tristate '    NI5210 support' CONFIG_NI52
     tristate '    NI6510 support' CONFIG_NI65
   fi
-  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate '  RealTek 8129/8139 (not 8019/8029!) support (EXPERIMENTAL)' CONFIG_RTL8139
-      tristate '  DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
-   fi
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       tristate '  AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
    fi
@@ -114,8 +110,8 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       tristate '  SKnet MCA support' CONFIG_SKMC
       tristate '  NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA
    fi
-   bool '  EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA
-   if [ "$CONFIG_NET_EISA" = "y" ]; then
+   bool '  EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI
+   if [ "$CONFIG_NET_PCI" = "y" ]; then
       tristate '    AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
         tristate '    Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE
@@ -129,6 +125,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       tristate '    Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
       tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP
       tristate '    Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+         tristate '    DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+      fi
       tristate '    EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
         tristate '    Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390
@@ -136,6 +135,10 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       fi
       tristate '    PCI NE2000 support' CONFIG_NE2K_PCI
       # tristate '    Sundance Alta support' CONFIG_ALTA
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+         tristate '    RealTek 8129 (not 8019/8029!) support (EXPERIMENTAL)' CONFIG_RTL8129
+      fi
+      tristate '    RealTek RTL-8139 PCI Fast Ethernet Adapter support' CONFIG_8139TOO
       tristate '    SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900
       tristate '    TI ThunderLAN support' CONFIG_TLAN
       tristate '    VIA Rhine support' CONFIG_VIA_RHINE
index 01adff34208703d1c6ec25ad9f16b6c9fef18bad..55e6d0e46a41cc9ea819de54122cbd79036249ef 100644 (file)
@@ -228,7 +228,8 @@ obj-$(CONFIG_EL3) += 3c509.o
 obj-$(CONFIG_3C515) += 3c515.o
 obj-$(CONFIG_EEXPRESS) += eexpress.o
 obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_RTL8139) += rtl8139.o
+obj-$(CONFIG_RTL8129) += rtl8129.o
+obj-$(CONFIG_8139TOO) += 8139too.o
 obj-$(CONFIG_WAVELAN) += wavelan.o
 obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
 obj-$(CONFIG_ZNET) += znet.o
index f15e31ae44264711308b7b7aa8e4cb14a59f0208..f62bfebe239dcbd83e672a58bde258a4ee55bd2e 100644 (file)
@@ -164,7 +164,6 @@ static void load_csrs (struct lance_private *lp)
 #define ZERO 0
 
 /* Setup the Lance Rx and Tx rings */
-/* Sets dev->tbusy */
 static void lance_init_ring (struct net_device *dev)
 {
        struct lance_private *lp = (struct lance_private *) dev->priv;
@@ -176,7 +175,7 @@ static void lance_init_ring (struct net_device *dev)
        aib = lp->lance_init_block;
 
        /* Lock out other processes while setting up hardware */
-       dev->tbusy = 1;
+       netif_stop_queue(dev);
        lp->rx_new = lp->tx_new = 0;
        lp->rx_old = lp->tx_old = 0;
 
@@ -442,11 +441,6 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
        if (!(csr0 & LE_C0_INTR))       /* Check if any interrupt has */
                return;                 /* been generated by the Lance. */
 
-       if (dev->interrupt)
-               printk ("%s: again", dev->name);
-
-       dev->interrupt = 1;
-
        /* Acknowledge all the interrupt sources ASAP */
        ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|
                           LE_C0_INIT);
@@ -473,15 +467,14 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
                ll->rdp = LE_C0_STRT;
        }
 
-       if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) {
-               dev->tbusy = 0;
-               mark_bh (NET_BH);
-       }
+       if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+           TX_BUFFS_AVAIL > 0)
+               netif_wake_queue(dev);
+
        ll->rap = LE_CSR0;
        ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|
                                        LE_C0_IDON|LE_C0_INEA;
 
-       dev->interrupt = 0;
 }
 
 struct net_device *last_dev = 0;
@@ -506,9 +499,7 @@ static int lance_open (struct net_device *dev)
        load_csrs (lp);
        lance_init_ring (dev);
 
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
+       netif_start_queue(dev);
 
        status = init_restart_lance (lp);
 
@@ -522,9 +513,8 @@ static int lance_close (struct net_device *dev)
        struct lance_private *lp = (struct lance_private *) dev->priv;
        volatile struct lance_regs *ll = lp->ll;
 
-       dev->start = 0;
-       dev->tbusy = 1;
-       del_timer(&lp->multicast_timer);
+       netif_stop_queue(dev);
+       del_timer_sync(&lp->multicast_timer);
 
        /* Stop the card */
        ll->rap = LE_CSR0;
@@ -548,11 +538,11 @@ static inline int lance_reset (struct net_device *dev)
        ll->rdp = LE_C0_STOP;
 
        load_csrs (lp);
+
        lance_init_ring (dev);
        dev->trans_start = jiffies;
-       dev->interrupt = 0;
-       dev->start = 1;
-       dev->tbusy = 0;
+       netif_start_queue(dev);
+
        status = init_restart_lance (lp);
 #ifdef DEBUG_DRIVER
        printk ("Lance restart=%d\n", status);
@@ -560,6 +550,17 @@ static inline int lance_reset (struct net_device *dev)
        return status;
 }
 
+static void lance_tx_timeout(struct net_device *dev)
+{
+       struct lance_private *lp = (struct lance_private *) dev->priv;
+       volatile struct lance_regs *ll = lp->ll;
+
+       printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
+              dev->name, ll->rdp);
+       lance_reset(dev);
+       netif_wake_queue(dev);
+}
+
 static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
        struct lance_private *lp = (struct lance_private *)dev->priv;
@@ -570,26 +571,6 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
        static int outs;
        unsigned long flags;
 
-       /* Transmitter timeout, serious problems */
-       if (dev->tbusy) {
-               int tickssofar = jiffies - dev->trans_start;
-           
-               if (tickssofar < 100) {
-                       status = -1;
-               } else {
-                       printk ("%s: transmit timed out, status %04x, resetting\n",
-                               dev->name, ll->rdp);
-                       lance_reset (dev);
-               }
-               return status;
-       }
-
-       /* Block a timer-based transmit from overlapping. */
-       if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) {
-               printk ("Transmitter access conflict.\n");
-               return -1;
-       }
-
        skblen = skb->len;
 
        save_flags(flags);
@@ -628,13 +609,15 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
        lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
 
        outs++;
+
+       if (TX_BUFFS_AVAIL <= 0)
+               netif_stop_queue(dev);
+
        /* Kick the lance: transmit now */
        ll->rdp = LE_C0_INEA | LE_C0_TDMD;
        dev->trans_start = jiffies;
        dev_kfree_skb (skb);
     
-       if (TX_BUFFS_AVAIL)
-               dev->tbusy = 0;
        restore_flags(flags);
 
        return status;
@@ -704,21 +687,17 @@ static void lance_set_multicast (struct net_device *dev)
        volatile struct lance_init_block *ib = lp->init_block;
        volatile struct lance_regs *ll = lp->ll;
 
-       if (!dev->start)
+       if (!test_bit(LINK_STATE_START, &dev->state))
                return;
 
-       if (dev->tbusy) {
-               mod_timer(&lp->multicast_timer, jiffies + 2);
-               return;
-       }
-       set_bit (0, (void *) &dev->tbusy);
-
        if (lp->tx_old != lp->tx_new) {
                mod_timer(&lp->multicast_timer, jiffies + 4);
-               dev->tbusy = 0;
+               netif_wake_queue(dev);
                return;
        }
 
+       netif_stop_queue(dev);
+
        ll->rap = LE_CSR0;
        ll->rdp = LE_C0_STOP;
        lance_init_ring (dev);
@@ -731,14 +710,19 @@ static void lance_set_multicast (struct net_device *dev)
        }
        load_csrs (lp);
        init_restart_lance (lp);
-       dev->tbusy = 0;
-       mark_bh(NET_BH);
+       netif_wake_queue(dev);
 }
 
-int __init a2065_probe(struct net_device *dev)
+static int __init a2065_probe(void)
 {
+       struct net_device *dev = NULL;
+       static int called = 0;
        struct zorro_dev *z = NULL;
 
+       if (called)
+               return -ENODEV;
+       called++;
+
        while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
                unsigned long board, base_addr, ram_start;
                int is_cbm;
@@ -765,6 +749,18 @@ int __init a2065_probe(struct net_device *dev)
                        continue;
                }
                strcpy(z->name, "A2065 Ethernet Card");
+
+               dev = init_etherdev(NULL, sizeof(struct lance_private));
+
+               if (dev == NULL) {
+                       release_mem_region(base_addr,
+                                          sizeof(struct lance_regs));
+                       release_mem_region(ram_start, A2065_RAM_SIZE);
+                       return -ENOMEM;
+               }
+               priv = (struct lance_private *)dev->priv;
+               memset(priv, 0, sizeof(struct lance_private));
+
                if (is_cbm) {                           /* Commodore */
                        dev->dev_addr[0] = 0x00;
                        dev->dev_addr[1] = 0x80;
@@ -782,18 +778,6 @@ int __init a2065_probe(struct net_device *dev)
                       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
                       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
-               init_etherdev(dev, 0);
-
-               dev->priv = kmalloc(sizeof(struct lance_private), GFP_KERNEL);
-               if (dev->priv == NULL) {
-                       release_mem_region(base_addr,
-                                          sizeof(struct lance_regs));
-                       release_mem_region(ram_start, A2065_RAM_SIZE);
-                       return -ENOMEM;
-               }
-               priv = (struct lance_private *)dev->priv;
-               memset(priv, 0, sizeof(struct lance_private));
-
                dev->base_addr = ZTWO_VADDR(base_addr);
                dev->mem_start = ZTWO_VADDR(ram_start);
                dev->mem_end = dev->mem_start+A2065_RAM_SIZE;
@@ -812,6 +796,8 @@ int __init a2065_probe(struct net_device *dev)
                dev->open = &lance_open;
                dev->stop = &lance_close;
                dev->hard_start_xmit = &lance_start_xmit;
+               dev->tx_timeout = &lance_tx_timeout;
+               dev->watchdog_timeo = 5*HZ;
                dev->get_stats = &lance_get_stats;
                dev->set_multicast_list = &lance_set_multicast;
                dev->dma = 0;
@@ -828,31 +814,9 @@ int __init a2065_probe(struct net_device *dev)
 }
 
 
-#ifdef MODULE
-static char devicename[9] = { 0, };
-
-static struct net_device a2065_dev =
-{
-       devicename,                     /* filled in by register_netdev() */
-       0, 0, 0, 0,                     /* memory */
-       0, 0,                           /* base, irq */
-       0, 0, 0, NULL, a2065_probe,
-};
-
-int init_module(void)
-{
-       int err;
-
-       if ((err = register_netdev(&a2065_dev))) {
-               if (err == -EIO)
-                       printk("No A2065 board found. Module not loaded.\n");
-               return(err);
-       }
-       return(0);
-}
-
-void cleanup_module(void)
+static void __exit a2065_cleanup(void)
 {
+#ifdef MODULE
        struct lance_private *priv = (struct lance_private *)a2065_dev.priv;
 
        unregister_netdev(&a2065_dev);
@@ -860,6 +824,8 @@ void cleanup_module(void)
                           sizeof(struct lance_regs));
        release_mem_region(ZTWO_PADDR(a2065_dev.mem_start), A2065_RAM_SIZE);
        kfree(priv);
+#endif
 }
 
-#endif /* MODULE */
+module_init(a2065_probe);
+module_exit(a2065_cleanup);
index 1fc708ee1dd3f618ff92641afc610370cca968ea..0829bd82ef56da1039e7e2f677703dff9d25bd28 100644 (file)
@@ -2,7 +2,7 @@
  * Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards
  * 
  * Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
  * Derived from skeleton.c by Donald Becker.
  *
  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -325,20 +325,11 @@ void cleanup_module(void)
 {
        struct net_device *dev = my_dev;
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-       void *ioaddr = lp->mem_start + 0x800;
-
-       if (dev->start)
-               dev->stop(dev);
-
-       /* Flush TX and disable RX */
-       AINTMASK(0);            /* disable IRQ's */
-       ACOMMAND(NOTXcmd);      /* stop transmit */
-       ACOMMAND(NORXcmd);      /* disable receive */
 
+       unregister_netdev(dev);
        free_irq(dev->irq, dev);
        iounmap(lp->mem_start);
        release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
-       unregister_netdev(dev);
        kfree(dev->priv);
        kfree(dev);
 }
index 98b2ac4dac647eb4f0f473735b88b65cb25a027c..9b54d0b0273e1e1b3f99d77e63ed2487cd2a802d 100644 (file)
@@ -3,7 +3,7 @@
  * 
  * Written 1997 by David Woodhouse.
  * Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
  * Derived from skeleton.c by Donald Becker.
  *
  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -41,7 +41,7 @@
  *     <jojo@repas.de>
  */
 
-#define VERSION "arcnet: v3.91 BETA 99/12/18 - by Avery Pennarun et al.\n"
+#define VERSION "arcnet: v3.92 BETA 2000/02/13 - by Avery Pennarun et al.\n"
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -97,6 +97,7 @@ EXPORT_SYMBOL(arcnet_interrupt);
 static int arcnet_open(struct net_device *dev);
 static int arcnet_close(struct net_device *dev);
 static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void arcnet_timeout(struct net_device *dev);
 static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
                         unsigned short type, void *daddr, void *saddr,
                         unsigned len);
@@ -347,6 +348,7 @@ void arcdev_setup(struct net_device *dev)
        dev->addr_len = 1;
        dev->tx_queue_len = 30;
        dev->broadcast[0] = 0x00;       /* for us, broadcasts are address 0 */
+       dev->watchdog_timeo = TX_TIMEOUT;
 
        /* New-style flags. */
        dev->flags = IFF_BROADCAST;
@@ -358,6 +360,7 @@ void arcdev_setup(struct net_device *dev)
        dev->open = arcnet_open;
        dev->stop = arcnet_close;
        dev->hard_start_xmit = arcnet_send_packet;
+       dev->tx_timeout = arcnet_timeout;
        dev->get_stats = arcnet_get_stats;
        dev->hard_header = arcnet_header;
        dev->rebuild_header = arcnet_rebuild_header;
@@ -397,10 +400,6 @@ static int arcnet_open(struct net_device *dev)
        if (ARCRESET(0) && ARCRESET(1))
                return -ENODEV;
 
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 0;
-
        newmtu = choose_mtu();
        if (newmtu < dev->mtu)
                dev->mtu = newmtu;
@@ -441,9 +440,6 @@ static int arcnet_open(struct net_device *dev)
        if (ASTATUS() & RESETflag)
                ACOMMAND(CFLAGScmd | RESETclear);
 
-       /* we're started */
-       dev->start = 1;
-
        /* make sure we're ready to receive IRQ's. */
        AINTMASK(0);
        udelay(1);              /* give it time to set the mask before
@@ -453,6 +449,8 @@ static int arcnet_open(struct net_device *dev)
        lp->intmask = NORXflag | RECONflag;
        AINTMASK(lp->intmask);
 
+       netif_start_queue(dev);
+
        return 0;
 }
 
@@ -462,16 +460,14 @@ static int arcnet_close(struct net_device *dev)
 {
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
+       netif_stop_queue(dev);
+
        /* flush TX and disable RX */
        AINTMASK(0);
        ACOMMAND(NOTXcmd);      /* stop transmit */
        ACOMMAND(NORXcmd);      /* disable receive */
        mdelay(1);
 
-       dev->tbusy = 1;
-       dev->start = 0;
-       dev->interrupt = 0;
-
        /* shut down the card */
        ARCOPEN(0);
 
@@ -584,48 +580,6 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
               "transmit requested (status=%Xh, txbufs=%d/%d, len=%d)\n",
               ASTATUS(), lp->cur_tx, lp->next_tx, skb->len);
 
-       if (dev->tbusy) {
-               /*
-                * If we get here, some higher level has decided we are broken.
-                * There should really be a "kick me" function call instead. 
-                */
-               unsigned long flags;
-               int tickssofar = jiffies - dev->trans_start, status = ASTATUS();
-
-               if (tickssofar < TX_TIMEOUT) {
-                       BUGMSG(D_DURING, "premature kickme! (status=%Xh ticks=%d)\n",
-                              status, tickssofar);
-                       return 1;       /* means "try again" */
-               }
-               save_flags(flags);
-               cli();
-
-               if (status & TXFREEflag) {      /* transmit _DID_ finish */
-                       BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
-                              status, tickssofar, lp->intmask, lp->lasttrans_dest);
-                       lp->stats.tx_errors++;
-               } else {
-                       BUGMSG(D_EXTRA, "tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
-                              status, tickssofar, lp->intmask, lp->lasttrans_dest);
-                       lp->stats.tx_errors++;
-                       lp->stats.tx_aborted_errors++;
-
-                       ACOMMAND(NOTXcmd | (lp->cur_tx << 3));
-               }
-
-               /*
-                * interrupt handler will set dev->tbusy = 0 when it notices the
-                * transmit has been canceled.
-                */
-
-               /* make sure we didn't miss a TX IRQ */
-               AINTMASK(0);
-               lp->intmask |= TXFREEflag;
-               AINTMASK(lp->intmask);
-
-               restore_flags(flags);
-               return 1;
-       }
        pkt = (struct archdr *) skb->data;
        soft = &pkt->soft.rfc1201;
        proto = arc_proto_map[soft->proto];
@@ -638,18 +592,10 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
                dev_kfree_skb(skb);
                return 0;       /* don't try again */
        }
-       /*
-        * Block a timer-based transmit from overlapping.  This could better be
-        * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. 
-        */
-       if (test_and_set_bit(0, (int *) &dev->tbusy)) {
-               BUGMSG(D_NORMAL, "transmitter called with busy bit set! "
-                      "(status=%Xh, tickssofar=%ld)\n",
-                      ASTATUS(), jiffies - dev->trans_start);
-               lp->stats.tx_errors++;
-               lp->stats.tx_fifo_errors++;
-               return 0;       /* don't try again */
-       }
+
+       /* We're busy transmitting a packet... */
+       netif_stop_queue(dev);
+
        AINTMASK(0);
 
        txbuf = get_arcbuf(dev);
@@ -718,6 +664,37 @@ static int go_tx(struct net_device *dev)
 }
 
 
+/* Called by the kernel when transmit times out */
+static void arcnet_timeout(struct net_device *dev)
+{
+       unsigned long flags;
+       struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+       int status = ASTATUS();
+
+       save_flags(flags);
+       cli();
+
+       if (status & TXFREEflag) {      /* transmit _DID_ finish */
+               BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, mask=%Xh, dest=%02Xh)\n",
+                      status, lp->intmask, lp->lasttrans_dest);
+               lp->stats.tx_errors++;
+       } else {
+               BUGMSG(D_EXTRA, "tx timed out (status=%Xh, intmask=%Xh, dest=%02Xh)\n",
+                      status, lp->intmask, lp->lasttrans_dest);
+               lp->stats.tx_errors++;
+               lp->stats.tx_aborted_errors++;
+               ACOMMAND(NOTXcmd | (lp->cur_tx << 3));
+       }
+
+       /* make sure we didn't miss a TX IRQ */
+       AINTMASK(0);
+       lp->intmask |= TXFREEflag;
+       AINTMASK(lp->intmask);
+
+       restore_flags(flags);
+}
+
+
 /*
  * The typical workload of the driver: Handle the network interface
  * interrupts. Establish which device needs attention, and call the correct
@@ -743,25 +720,20 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                return;
        }
        /*
-        * RESET flag was enabled - if !dev->start, we must clear it right
+        * RESET flag was enabled - if device is not running, we must clear it right
         * away (but nothing else).
         */
-       if (!dev->start) {
+       if (!test_bit(LINK_STATE_START, &dev->state)) {
                if (ASTATUS() & RESETflag)
                        ACOMMAND(CFLAGScmd | RESETclear);
                AINTMASK(0);
                return;
        }
-       if (dev->interrupt) {
-               BUGMSG(D_NORMAL, "DRIVER PROBLEM!  Nested arcnet interrupts!\n");
-               return;         /* don't even try. */
-       }
-       dev->interrupt = 1;
 
        BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
               ASTATUS(), lp->intmask);
 
-       boguscount = 3;
+       boguscount = 5;
        do {
                status = ASTATUS();
                didsomething = 0;
@@ -839,17 +811,15 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                        if (lp->outgoing.proto->continue_tx(dev, txbuf)) {
                                                /* that was the last segment */
                                                lp->stats.tx_bytes += lp->outgoing.skb->len;
-                                               dev_kfree_skb(lp->outgoing.skb);
+                                               dev_kfree_skb_irq(lp->outgoing.skb);
                                                lp->outgoing.proto = NULL;
                                        }
                                        lp->next_tx = txbuf;
                                }
                        }
                        /* inform upper layers of idleness, if necessary */
-                       if (lp->cur_tx == -1) {
-                               dev->tbusy = 0;
-                               mark_bh(NET_BH);
-                       }
+                       if (lp->cur_tx == -1)
+                               netif_wake_queue(dev);
                }
                /* now process the received packet, if any */
                if (recbuf != -1) {
@@ -922,8 +892,6 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        AINTMASK(0);
        udelay(1);
        AINTMASK(lp->intmask);
-
-       dev->interrupt = 0;
 }
 
 
@@ -987,11 +955,6 @@ void arcnet_rx(struct net_device *dev, int bufnum)
        }
        /* call the protocol-specific receiver. */
        arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length);
-
-       /*
-        * If any worthwhile packets have been received, a mark_bh(NET_BH) has
-        * been done by netif_rx and Linux will handle them after we return.
-        */
 }
 
 
index 94c68901b747c49ca967dc0f9af88a1e87641b03..7bd06e2e48c7a6319e2e50f592dc3b6082eaac72 100644 (file)
@@ -3,7 +3,7 @@
  * 
  * Written 1997 by David Woodhouse.
  * Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
  * Derived from skeleton.c by Donald Becker.
  *
  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -176,12 +176,9 @@ void cleanup_module(void)
 {
        struct net_device *dev = my_dev;
 
-       if (dev->start)
-               dev->stop(dev);
-
+       unregister_netdev(dev);
        free_irq(dev->irq, dev);
        release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
-       unregister_netdev(dev);
        kfree(dev->priv);
        kfree(dev);
 }
index 585308c27d8b169852763c24ee7feae48456beed..b88203f543b1d53564dc7b40a833d093e901c639 100644 (file)
@@ -3,7 +3,7 @@
  * 
  * Written 1994-1999 by Avery Pennarun,
  *    based on an ISA version by David Woodhouse.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
  * Derived from skeleton.c by Donald Becker.
  *
  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -148,13 +148,9 @@ void cleanup_module(void)
 
        for (count = 0; count < numcards; count++) {
                dev = cards[count];
-
-               if (dev->start)
-                       dev->stop(dev);
-
+               unregister_netdev(dev);
                free_irq(dev->irq, dev);
                release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
-               unregister_netdev(dev);
                kfree(dev->priv);
                kfree(dev);
        }
index edd92ff2542678a1ecde89fe36381a2c6c040bae..79800883ff7253c3c65d33ed9d83aceaea5bc649 100644 (file)
@@ -3,7 +3,7 @@
  * 
  * Written 1997 by David Woodhouse.
  * Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
  * Derived from skeleton.c by Donald Becker.
  *
  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -406,20 +406,13 @@ void cleanup_module(void)
        struct net_device *dev = my_dev;
        int ioaddr = dev->base_addr;
 
-       if (dev->start)
-               dev->stop(dev);
-
-       /* Flush TX and disable RX */
-       AINTMASK(0);            /* disable IRQ's */
-       ACOMMAND(NOTXcmd);      /* stop transmit */
-       ACOMMAND(NORXcmd);      /* disable receive */
+       unregister_netdev(dev);
 
        /* Set the thing back to MMAP mode, in case the old driver is loaded later */
        outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
 
        free_irq(dev->irq, dev);
        release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
-       unregister_netdev(dev);
        kfree(dev->priv);
        kfree(dev);
 }
index 8431156090b8c1f113de4b489ba1edcd53b656d8..ac8790ef0139c0200971cbf8fdfeef43f04c23d9 100644 (file)
@@ -143,7 +143,7 @@ int __init com90xx_probe(struct net_device *dev)
                numprint %= 8;
                if (!numprint) {
                        BUGMSG2(D_INIT, "\n");
-                       BUGMSG(D_INIT, "S1: ");
+                       BUGMSG2(D_INIT, "S1: ");
                }
                BUGMSG2(D_INIT, "%Xh ", *port);
 
@@ -151,7 +151,7 @@ int __init com90xx_probe(struct net_device *dev)
 
                if (check_region(*port, ARCNET_TOTAL_SIZE)) {
                        BUGMSG2(D_INIT_REASONS, "(check_region)\n");
-                       BUGMSG(D_INIT_REASONS, "S1: ");
+                       BUGMSG2(D_INIT_REASONS, "S1: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
                        *port = ports[numports - 1];
                        numports--;
@@ -160,7 +160,7 @@ int __init com90xx_probe(struct net_device *dev)
                }
                if (ASTATUS() == 0xFF) {
                        BUGMSG2(D_INIT_REASONS, "(empty)\n");
-                       BUGMSG(D_INIT_REASONS, "S1: ");
+                       BUGMSG2(D_INIT_REASONS, "S1: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
                        *port = ports[numports - 1];
                        numports--;
@@ -170,13 +170,13 @@ int __init com90xx_probe(struct net_device *dev)
                inb(_RESET);    /* begin resetting card */
 
                BUGMSG2(D_INIT_REASONS, "\n");
-               BUGMSG(D_INIT_REASONS, "S1: ");
+               BUGMSG2(D_INIT_REASONS, "S1: ");
                BUGLVL(D_INIT_REASONS) numprint = 0;
        }
        BUGMSG2(D_INIT, "\n");
 
        if (!numports) {
-               BUGMSG(D_NORMAL, "S1: No ARCnet cards found.\n");
+               BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n");
                return -ENODEV;
        }
        /* Stage 2: we have now reset any possible ARCnet cards, so we can't
@@ -189,7 +189,7 @@ int __init com90xx_probe(struct net_device *dev)
                numprint %= 8;
                if (!numprint) {
                        BUGMSG2(D_INIT, "\n");
-                       BUGMSG(D_INIT, "S2: ");
+                       BUGMSG2(D_INIT, "S2: ");
                }
                BUGMSG2(D_INIT, "%Xh ", *port);
        }
@@ -207,13 +207,13 @@ int __init com90xx_probe(struct net_device *dev)
                numprint %= 8;
                if (!numprint) {
                        BUGMSG2(D_INIT, "\n");
-                       BUGMSG(D_INIT, "S3: ");
+                       BUGMSG2(D_INIT, "S3: ");
                }
                BUGMSG2(D_INIT, "%lXh ", *shmem);
 
                if (check_mem_region(*shmem, BUFFER_SIZE)) {
                        BUGMSG2(D_INIT_REASONS, "(check_mem_region)\n");
-                       BUGMSG(D_INIT_REASONS, "Stage 3: ");
+                       BUGMSG2(D_INIT_REASONS, "Stage 3: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
                        *shmem = shmems[numshmems - 1];
                        numshmems--;
@@ -223,7 +223,7 @@ int __init com90xx_probe(struct net_device *dev)
                if (isa_readb(ptr) != TESTvalue) {
                        BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
                                isa_readb(ptr), TESTvalue);
-                       BUGMSG(D_INIT_REASONS, "S3: ");
+                       BUGMSG2(D_INIT_REASONS, "S3: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
                        *shmem = shmems[numshmems - 1];
                        numshmems--;
@@ -238,20 +238,20 @@ int __init com90xx_probe(struct net_device *dev)
                isa_writeb(0x42, ptr);
                if (isa_readb(ptr) != 0x42) {
                        BUGMSG2(D_INIT_REASONS, "(read only)\n");
-                       BUGMSG(D_INIT_REASONS, "S3: ");
+                       BUGMSG2(D_INIT_REASONS, "S3: ");
                        *shmem = shmems[numshmems - 1];
                        numshmems--;
                        shmem--;
                        continue;
                }
                BUGMSG2(D_INIT_REASONS, "\n");
-               BUGMSG(D_INIT_REASONS, "S3: ");
+               BUGMSG2(D_INIT_REASONS, "S3: ");
                BUGLVL(D_INIT_REASONS) numprint = 0;
        }
        BUGMSG2(D_INIT, "\n");
 
        if (!numshmems) {
-               BUGMSG(D_NORMAL, "S3: No ARCnet cards found.\n");
+               BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n");
                return -ENODEV;
        }
        /* Stage 4: something of a dummy, to report the shmems that are
@@ -263,7 +263,7 @@ int __init com90xx_probe(struct net_device *dev)
                numprint %= 8;
                if (!numprint) {
                        BUGMSG2(D_INIT, "\n");
-                       BUGMSG(D_INIT, "S4: ");
+                       BUGMSG2(D_INIT, "S4: ");
                }
                BUGMSG2(D_INIT, "%lXh ", *shmem);
        }
@@ -282,7 +282,7 @@ int __init com90xx_probe(struct net_device *dev)
                numprint %= 8;
                if (!numprint) {
                        BUGMSG2(D_INIT, "\n");
-                       BUGMSG(D_INIT, "S5: ");
+                       BUGMSG2(D_INIT, "S5: ");
                }
                BUGMSG2(D_INIT, "%Xh ", *port);
 
@@ -292,7 +292,7 @@ int __init com90xx_probe(struct net_device *dev)
                if ((status & 0x9D)
                    != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
                        BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status);
-                       BUGMSG(D_INIT_REASONS, "S5: ");
+                       BUGMSG2(D_INIT_REASONS, "S5: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
                        *port = ports[numports - 1];
                        numports--;
@@ -304,7 +304,7 @@ int __init com90xx_probe(struct net_device *dev)
                if (status & RESETflag) {
                        BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
                                status);
-                       BUGMSG(D_INIT_REASONS, "S5: ");
+                       BUGMSG2(D_INIT_REASONS, "S5: ");
                        BUGLVL(D_INIT_REASONS) numprint = 0;
                        *port = ports[numports - 1];
                        numports--;
@@ -327,7 +327,7 @@ int __init com90xx_probe(struct net_device *dev)
 
                        if (airq <= 0) {
                                BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq);
-                               BUGMSG(D_INIT_REASONS, "S5: ");
+                               BUGMSG2(D_INIT_REASONS, "S5: ");
                                BUGLVL(D_INIT_REASONS) numprint = 0;
                                *port = ports[numports - 1];
                                numports--;
@@ -398,7 +398,7 @@ int __init com90xx_probe(struct net_device *dev)
                isa_writeb(TESTvalue, *shmem);
 
        if (retval && dev && !numcards)
-               BUGMSG(D_NORMAL, "S5: No ARCnet cards found.\n");
+               BUGMSG2(D_NORMAL, "S5: No ARCnet cards found.\n");
        return retval;
 }
 
@@ -416,7 +416,7 @@ static int __init com90xx_found(struct net_device *dev0, int ioaddr, int airq,
 
        /* allocate struct net_device if we don't have one yet */
        if (!dev && !(dev = dev_alloc("arc%d", &err))) {
-               BUGMSG(D_NORMAL, "Can't allocate device!\n");
+               BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n");
                return err;
        }
        lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
@@ -546,8 +546,7 @@ int com90xx_reset(struct net_device *dev, int really_reset)
        struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
        short ioaddr = dev->base_addr;
 
-       BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n",
-              dev->name, ASTATUS());
+       BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS());
 
        if (really_reset) {
                /* reset the card */
@@ -653,13 +652,11 @@ void cleanup_module(void)
                dev = cards[count];
                lp = (struct arcnet_local *) dev->priv;
 
-               if (dev->start)
-                       dev->stop(dev);
+               unregister_netdev(dev);
                free_irq(dev->irq, dev);
                iounmap(lp->mem_start);
                release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
                release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
-               unregister_netdev(dev);
                kfree(dev->priv);
                kfree(dev);
        }
index 759263ca04be5c8f76ae18f8b0442e26e6fad1aa..92d026ec807325b3fc267fdaea329321fefe8648 100644 (file)
@@ -171,7 +171,7 @@ static void rx(struct net_device *dev, int bufnum,
                        BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
                         in->sequence, soft->split_flag, soft->sequence);
                        lp->rfc1201.aborted_seq = soft->sequence;
-                       kfree_skb(in->skb);
+                       dev_kfree_skb_irq(in->skb);
                        lp->stats.rx_errors++;
                        lp->stats.rx_missed_errors++;
                        in->skb = NULL;
@@ -255,7 +255,7 @@ static void rx(struct net_device *dev, int bufnum,
                        BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
                               saddr, in->sequence, soft->sequence,
                               soft->split_flag);
-                       kfree_skb(in->skb);
+                       dev_kfree_skb_irq(in->skb);
                        in->skb = NULL;
                        lp->stats.rx_errors++;
                        lp->stats.rx_missed_errors++;
@@ -271,7 +271,7 @@ static void rx(struct net_device *dev, int bufnum,
                                       soft->sequence);
                                lp->stats.rx_errors++;
                                lp->stats.rx_missed_errors++;
-                               kfree_skb(in->skb);
+                               dev_kfree_skb_irq(in->skb);
                        }
                        in->sequence = soft->sequence;
                        in->numpackets = ((unsigned) soft->split_flag >> 1) + 2;
@@ -332,7 +332,7 @@ static void rx(struct net_device *dev, int bufnum,
                                       "(seq=%d) aborted (splitflag=%d, seq=%d)\n",
                                       in->sequence, soft->split_flag, soft->sequence);
                                lp->rfc1201.aborted_seq = soft->sequence;
-                               kfree_skb(in->skb);
+                               dev_kfree_skb_irq(in->skb);
                                in->skb = NULL;
                                lp->stats.rx_errors++;
                                lp->stats.rx_missed_errors++;
index 30aa851b86c42030332b582f50ae6818f5ba9f21..1c297dbec58e3943a4d3c85a0584e6da7b1478af 100644 (file)
@@ -65,6 +65,7 @@ struct bmac_data {
        volatile struct dbdma_cmd *tx_cmds;     /* xmit dma command list */
        volatile struct dbdma_cmd *rx_cmds;     /* recv dma command list */
        struct device_node *node;
+       int is_bmac_plus;
        struct sk_buff *rx_bufs[N_RX_RING];
        int rx_fill;
        int rx_empty;
@@ -80,6 +81,7 @@ struct bmac_data {
        int tx_allocated;
        unsigned short hash_use_count[64];
        unsigned short hash_table_mask[4];
+       struct net_device *next_bmac;
 };
 
 typedef struct bmac_reg_entry {
@@ -124,7 +126,6 @@ bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
 };
 
 struct net_device *bmac_devs = NULL;
-static int is_bmac_plus;
 
 #ifdef CONFIG_PMAC_PBOOK
 int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
@@ -133,13 +134,6 @@ static struct pmu_sleep_notifier bmac_sleep_notifier = {
 };
 #endif
 
-#if 0
-/*
- * If we can't get a skbuff when we need it, we use this area for DMA.
- */
-static unsigned char dummy_buf[RX_BUFLEN];
-#endif
-
 /*
  * Number of bytes of private data per BMAC: allow enough for
  * the rx and tx dma commands plus a branch dma command each,
@@ -151,6 +145,7 @@ static unsigned char dummy_buf[RX_BUFLEN];
        + sizeof(struct sk_buff_head))
 
 static unsigned char bitrev(unsigned char b);
+static void bmac_probe1(struct device_node *bmac, int is_bmac_plus);
 static int bmac_open(struct net_device *dev);
 static int bmac_close(struct net_device *dev);
 static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
@@ -192,9 +187,10 @@ dbdma_ld32(volatile unsigned long *a)
 void
 dbdma_stop(volatile struct dbdma_regs *dmap)
 {
-       dbdma_st32((volatile unsigned long *)&dmap->control, DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH));
+       dbdma_st32((volatile unsigned long *)&dmap->control,
+                  DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH));
        eieio();
-  
+
        while (dbdma_ld32((volatile unsigned long *)&dmap->status) & (ACTIVE|FLUSH))
                eieio();
 }
@@ -210,10 +206,11 @@ dbdma_continue(volatile struct dbdma_regs *dmap)
 static void
 dbdma_reset(volatile struct dbdma_regs *dmap)
 {
-       dbdma_st32((volatile unsigned long *)&dmap->control, 
-                  DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN));      
+       dbdma_st32((volatile unsigned long *)&dmap->control,
+                  DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN));
        eieio();
-       while (dbdma_ld32((volatile unsigned long *)&dmap->status) & RUN) eieio();
+       while (dbdma_ld32((volatile unsigned long *)&dmap->status) & RUN)
+               eieio();
 }
 
 static void
@@ -239,7 +236,7 @@ void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
 static __inline__
 volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
 {
-       return in_le16((void *)dev->base_addr + reg_offset); 
+       return in_le16((void *)dev->base_addr + reg_offset);
 }
 
 static void
@@ -248,7 +245,7 @@ bmac_reset_chip(struct net_device *dev)
        struct bmac_data *bp = (struct bmac_data *) dev->priv;
        volatile struct dbdma_regs *rd = bp->rx_dma;
        volatile struct dbdma_regs *td = bp->tx_dma;
-        
+
        dbdma_reset(rd);
        dbdma_reset(td);
 
@@ -349,7 +346,7 @@ bmac_init_registers(struct net_device *dev)
                regValue = bmread(dev, TXRST); /* wait for reset to clear..acknowledge */
        } while ((regValue & TxResetBit) && i > 0);
 
-       if (!is_bmac_plus) {
+       if (!bp->is_bmac_plus) {
                regValue = bmread(dev, XCVRIF);
                regValue |= ClkBit | SerialMode | COLActiveLow;
                bmwrite(dev, XCVRIF, regValue);
@@ -385,7 +382,7 @@ bmac_init_registers(struct net_device *dev)
 
        /* set rx fifo information */
        bmwrite(dev, RXFIFOCSR, 0);     /* first disable rxFIFO */
-       bmwrite(dev, RXFIFOCSR, RxFIFOEnable ); 
+       bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
 
        //bmwrite(dev, TXCFG, TxMACEnable);             /* TxNeverGiveUp maybe later */
        bmread(dev, STATUS);            /* read it just to clear it */
@@ -433,13 +430,13 @@ bmac_start_chip(struct net_device *dev)
 
        /* enable rx dma channel */
        dbdma_continue(rd);
+
        oldConfig = bmread(dev, TXCFG);         
-       bmwrite(dev, TXCFG, oldConfig | TxMACEnable );  
-  
+       bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
+
        /* turn on rx plus any other bits already on (promiscuous possibly) */
        oldConfig = bmread(dev, RXCFG);         
-       bmwrite(dev, RXCFG, oldConfig | RxMACEnable ); 
+       bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
        udelay(20000);
 }
 
@@ -447,6 +444,7 @@ static void
 bmac_init_phy(struct net_device *dev)
 {
        unsigned int addr;
+       struct bmac_data *bp = (struct bmac_data *) dev->priv;
 
        printk(KERN_DEBUG "phy registers:");
        for (addr = 0; addr < 32; ++addr) {
@@ -455,7 +453,7 @@ bmac_init_phy(struct net_device *dev)
                printk(" %.4x", bmac_mif_read(dev, addr));
        }
        printk("\n");
-       if (is_bmac_plus) {
+       if (bp->is_bmac_plus) {
                unsigned int capable, ctrl;
 
                ctrl = bmac_mif_read(dev, 0);
@@ -622,7 +620,8 @@ bmac_init_rx_ring(struct bmac_data *bp)
        if (!bp->rx_allocated) {
                for (i = 0; i < N_RX_RING; i++) {
                        bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
-                       if (bp->rx_bufs[i] == NULL) return 0;
+                       if (bp->rx_bufs[i] == NULL)
+                               return 0;
                        skb_reserve(bp->rx_bufs[i], 2);
                }
                bp->rx_allocated = 1;
@@ -657,9 +656,10 @@ static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev)
        /* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */
        /*           bp->tx_empty, bp->tx_fill)); */
        i = bp->tx_fill + 1;
-       if (i >= N_TX_RING) i = 0;
+       if (i >= N_TX_RING)
+               i = 0;
        if (i == bp->tx_empty) {
-               dev->tbusy = 1;
+               netif_stop_queue(dev);
                bp->tx_fullup = 1;
                XXDEBUG(("bmac_transmit_packet: tx ring full\n"));
                return -1;              /* can't take it at the moment */
@@ -776,16 +776,15 @@ static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 
                if (bp->tx_bufs[bp->tx_empty]) {
                        ++bp->stats.tx_packets;
-                       dev_kfree_skb(bp->tx_bufs[bp->tx_empty]);
+                       dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
                }
                bp->tx_bufs[bp->tx_empty] = NULL;
                bp->tx_fullup = 0;
-               dev->tbusy = 0;
-               /* XXDEBUG(("bmac_intr: cleared tbusy, empty=%d fill=%d\n", */
-               /*               i, bp->tx_fill)); */
-               mark_bh(NET_BH);
-               if (++bp->tx_empty >= N_TX_RING) bp->tx_empty = 0;
-               if (bp->tx_empty == bp->tx_fill) break;
+               netif_wake_queue(dev);
+               if (++bp->tx_empty >= N_TX_RING)
+                       bp->tx_empty = 0;
+               if (bp->tx_empty == bp->tx_fill)
+                       break;
        }
 
        restore_flags(flags);
@@ -831,7 +830,7 @@ crc416(unsigned int curval, unsigned short nxtval)
                /* is high CRC bit set? */
                if ((cur & 0x80000000) == 0) high_crc_set = 0;
                else high_crc_set = 1;
-      
+
                cur = cur << 1;
        
                if ((next & 0x0001) == 0) low_data_set = 0;
@@ -859,8 +858,8 @@ bmac_crc(unsigned short *address)
 }
 
 /*
- * Add requested mcast addr to BMac's hash table filter.  
- *  
+ * Add requested mcast addr to BMac's hash table filter.
+ *
  */
 
 static void
@@ -925,7 +924,7 @@ bmac_rx_on(struct net_device *dev, int hash_enable, int promisc_enable)
        else rx_cfg &= ~RxPromiscEnable;
        bmwrite(dev, RXRST, RxResetValue);
        bmwrite(dev, RXFIFOCSR, 0);     /* first disable rxFIFO */
-       bmwrite(dev, RXFIFOCSR, RxFIFOEnable ); 
+       bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
        bmwrite(dev, RXCFG, rx_cfg );
        return rx_cfg;
 }
@@ -1020,13 +1019,7 @@ static void bmac_set_multicast(struct net_device *dev)
        int i, j, bit, byte;
        unsigned short rx_cfg;
        u32 crc, poly = CRC_POLYNOMIAL_LE;
-    
-       /* Let the transmits drain. */
-       /*     while(dev->tbusy) schedule(); */
-    
-       /* Lock out others. */
-       /*     set_bit(0, (void *) &dev->tbusy); */
-    
+
        if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
                bmwrite(dev, BHASH0, 0xffff);
                bmwrite(dev, BHASH1, 0xffff);
@@ -1048,15 +1041,15 @@ static void bmac_set_multicast(struct net_device *dev)
                for(i = 0; i < dev->mc_count; i++) {
                        addrs = dmi->dmi_addr;
                        dmi = dmi->next;
-           
+
                        if(!(*addrs & 1))
                                continue;
-           
+
                        crc = 0xffffffffU;
                        for(byte = 0; byte < 6; byte++) {
                                for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
                                        int test;
-                   
+
                                        test = ((bit ^ crc) & 0x01);
                                        crc >>= 1;
                                        if(test)
@@ -1071,9 +1064,6 @@ static void bmac_set_multicast(struct net_device *dev)
                bmwrite(dev, BHASH2, hash_table[2]);
                bmwrite(dev, BHASH3, hash_table[3]);
        }
-    
-       /* Let us get going again. */
-       /*     dev->tbusy = 0; */
 }
 #endif /* SUNHME_MULTICAST */
 
@@ -1103,7 +1093,7 @@ static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 /*
- * Procedure for reading EEPROM 
+ * Procedure for reading EEPROM
  */
 #define SROMAddressLength      5
 #define DataInOn               0x0008
@@ -1126,28 +1116,28 @@ bmac_clock_out_bit(struct net_device *dev)
 
        bmwrite(dev, SROMCSR, ChipSelect | Clk);
        udelay(DelayValue);
-    
+
        data = bmread(dev, SROMCSR);
        udelay(DelayValue);
        val = (data >> SD0ShiftCount) & 1;
 
        bmwrite(dev, SROMCSR, ChipSelect);
        udelay(DelayValue);
-    
+
        return val;
 }
 
 static void
 bmac_clock_in_bit(struct net_device *dev, unsigned int val)
 {
-       unsigned short          data;    
+       unsigned short data;
 
        if (val != 0 && val != 1) return;
-    
+
        data = (val << SDIShiftCount);
        bmwrite(dev, SROMCSR, data | ChipSelect  );
        udelay(DelayValue);
-    
+
        bmwrite(dev, SROMCSR, data | ChipSelect | Clk );
        udelay(DelayValue);
 
@@ -1161,7 +1151,7 @@ reset_and_select_srom(struct net_device *dev)
        /* first reset */
        bmwrite(dev, SROMCSR, 0);
        udelay(DelayValue);
-    
+
        /* send it the read command (110) */
        bmac_clock_in_bit(dev, 1);
        bmac_clock_in_bit(dev, 1);
@@ -1173,13 +1163,13 @@ read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len)
 {
        unsigned short data, val;
        int i;
-    
+
        /* send out the address we want to read from */
        for (i = 0; i < addr_len; i++)  {
                val = addr >> (addr_len-i-1);
                bmac_clock_in_bit(dev, val & 1);
        }
-    
+
        /* Now read in the 16-bit data */
        data = 0;
        for (i = 0; i < 16; i++)        {
@@ -1188,24 +1178,24 @@ read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len)
                data |= val;
        }
        bmwrite(dev, SROMCSR, 0);
-    
+
        return data;
 }
 
 /*
  * It looks like Cogent and SMC use different methods for calculating
- * checksums. What a pain.. 
+ * checksums. What a pain..
  */
 
 static int
 bmac_verify_checksum(struct net_device *dev)
 {
        unsigned short data, storedCS;
-    
+
        reset_and_select_srom(dev);
        data = read_srom(dev, 3, SROMAddressBits);
        storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00);
-    
+
        return 0;
 }
 
@@ -1236,8 +1226,10 @@ static int bmac_reset_and_enable(struct net_device *dev, int enable)
        bp->reset_and_enabled = 0;
        bmac_reset_chip(dev);
        if (enable) {
-               if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp)) return 0;
-               if (!bmac_init_chip(dev)) return 0;
+               if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp))
+                       return 0;
+               if (!bmac_init_chip(dev))
+                       return 0;
                bmac_start_chip(dev);
                bmwrite(dev, INTDISABLE, EnableNormal);
                bp->reset_and_enabled = 1;
@@ -1257,70 +1249,55 @@ static int bmac_reset_and_enable(struct net_device *dev, int enable)
        return 1;
 }
 
-static int __init bmac_probe (void)
+static int __init bmac_probe(void)
 {
-       int j, rev;
-       struct bmac_data *bp;
-       struct device_node *bmacs;
-       unsigned char *addr;
-       static struct device_node *all_bmacs = NULL, *next_bmac;
-       struct net_device *dev = NULL;
+       struct device_node *bmac;
 
-#ifdef MODULE
-       if(bmac_devs != NULL)
-               return -EBUSY;
-#endif
-
-       if (all_bmacs == NULL) {
-               all_bmacs = find_devices("bmac");
-               is_bmac_plus = 0;
-               if (all_bmacs == NULL) {
-                       all_bmacs = find_compatible_devices("network", "bmac+");
-                       if (all_bmacs)
-                               is_bmac_plus = 1;
-               }
-               next_bmac = all_bmacs;
-       }
-       bmacs = next_bmac;
-       if (bmacs == NULL) return -ENODEV;
-       next_bmac = bmacs->next;
+       for (bmac = find_devices("bmac"); bmac != 0; bmac = bmac->next)
+               bmac_probe1(bmac, 0);
+       for (bmac = find_compatible_devices("network", "bmac+"); bmac != 0;
+            bmac = bmac->next)
+               bmac_probe1(bmac, 1);
 
-       if (bmac_devs == 0) {
-               bmac_devs = dev; /* KLUDGE!! */
+       if (bmac_devs != 0) {
+               proc_net_create ("bmac", 0, bmac_proc_info);
 #ifdef CONFIG_PMAC_PBOOK
                pmu_register_sleep_notifier(&bmac_sleep_notifier);
 #endif
        }
+       return 0;
+}
 
-       if (bmacs->n_addrs != 3 || bmacs->n_intrs != 3) {
-               printk(KERN_ERR "can't use BMAC %s: expect 3 addrs and 3 intrs\n",
-                      bmacs->full_name);
-               return -EINVAL;
+static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
+{
+       int j, rev;
+       struct bmac_data *bp;
+       unsigned char *addr;
+       struct net_device *dev;
+
+       if (bmac->n_addrs != 3 || bmac->n_intrs != 3) {
+               printk(KERN_ERR "can't use BMAC %s: need 3 addrs and 3 intrs\n",
+                      bmac->full_name);
+               return;
+       }
+       addr = get_property(bmac, "mac-address", NULL);
+       if (addr == NULL) {
+               addr = get_property(bmac, "local-mac-address", NULL);
+               if (addr == NULL) {
+                       printk(KERN_ERR "Can't get mac-address for BMAC %s\n",
+                              bmac->full_name);
+                       return;
+               }
        }
 
        dev = init_etherdev(NULL, PRIV_BYTES);
-       bmac_devs = dev;  /*KLUDGE!!*/
 
-#ifdef MODULE
-       bmac_devs = dev;
-#endif
-    
        dev->base_addr = (unsigned long)
-               ioremap(bmacs->addrs[0].address, bmacs->addrs[0].size);
-       dev->irq = bmacs->intrs[0].line;
+               ioremap(bmac->addrs[0].address, bmac->addrs[0].size);
+       dev->irq = bmac->intrs[0].line;
 
        bmwrite(dev, INTDISABLE, DisableAll);
-    
-       addr = get_property(bmacs, "mac-address", NULL);
-       if (addr == NULL) {
-               addr = get_property(bmacs, "local-mac-address", NULL);
-               if (addr == NULL) {
-                       printk(KERN_ERR "Can't get mac-address for BMAC at %lx\n",
-                              dev->base_addr);
-                       return -EAGAIN;
-               }
-       }
-    
+
        printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": ""));
        rev = addr[0] == 0 && addr[1] == 0xA0;
        for (j = 0; j < 6; ++j) {
@@ -1329,7 +1306,7 @@ static int __init bmac_probe (void)
        }
        XXDEBUG((", base_addr=%#0lx", dev->base_addr));
        printk("\n");
-    
+
        dev->open = bmac_open;
        dev->stop = bmac_close;
        dev->hard_start_xmit = bmac_output;
@@ -1338,61 +1315,55 @@ static int __init bmac_probe (void)
        dev->set_mac_address = bmac_set_address;
 
        bmac_get_station_address(dev, addr);
-       if (bmac_verify_checksum(dev) != 0) return -EINVAL;
-    
+       if (bmac_verify_checksum(dev) != 0)
+               return;
+
        ether_setup(dev);
-    
+
        bp = (struct bmac_data *) dev->priv;
        memset(bp, 0, sizeof(struct bmac_data));
+       bp->is_bmac_plus = is_bmac_plus;
        bp->tx_dma = (volatile struct dbdma_regs *)
-               ioremap(bmacs->addrs[1].address, bmacs->addrs[1].size);
-       bp->tx_dma_intr = bmacs->intrs[1].line;
+               ioremap(bmac->addrs[1].address, bmac->addrs[1].size);
+       bp->tx_dma_intr = bmac->intrs[1].line;
        bp->rx_dma = (volatile struct dbdma_regs *)
-               ioremap(bmacs->addrs[2].address, bmacs->addrs[2].size);
-       bp->rx_dma_intr = bmacs->intrs[2].line;
-    
+               ioremap(bmac->addrs[2].address, bmac->addrs[2].size);
+       bp->rx_dma_intr = bmac->intrs[2].line;
+
        bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
        bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;
 
        bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);
        skb_queue_head_init(bp->queue);
-    
-       bp->node = bmacs;
+
+       bp->node = bmac;
        memset(&bp->stats, 0, sizeof(bp->stats));
        memset((char *) bp->tx_cmds, 0,
               (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));
        /*     init_timer(&bp->tx_timeout); */
        /*     bp->timeout_active = 0; */
 
-       if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) {
+       if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev))
                printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq);
-               return -EAGAIN;
-       }
-       if (request_irq(bmacs->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma",
-                       dev)) {
-               printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[1].line);
-               return -EAGAIN;
-       }
-       if (request_irq(bmacs->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma",
-                       dev)) {
-               printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[2].line);
-               return -EAGAIN;
-       }
-    
-       if (!bmac_reset_and_enable(dev, 0)) return -ENOMEM;
-    
-       proc_net_create ("bmac", 0, bmac_proc_info);
-
-       return 0;
+       if (request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma",
+                       dev))
+               printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[1].line);
+       if (request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma",
+                       dev))
+               printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[2].line);
+
+       bp->next_bmac = bmac_devs;
+       bmac_devs = dev;
 }
 
 static int bmac_open(struct net_device *dev)
 {
        /* XXDEBUG(("bmac: enter open\n")); */
        /* reset the chip */
-       bmac_reset_and_enable(dev, 1);
+       if (!bmac_reset_and_enable(dev, 1))
+               return -ENOMEM;
 
-       dev->flags |= IFF_UP | IFF_RUNNING;
+       dev->flags |= IFF_RUNNING;
 
        MOD_INC_USE_COUNT;
        return 0;
@@ -1452,14 +1423,17 @@ bmac_start(struct net_device *dev)
        int i;
        struct sk_buff *skb;
        unsigned long flags;
-    
+
        save_flags(flags); cli();
        while (1) {
                i = bp->tx_fill + 1;
-               if (i >= N_TX_RING) i = 0;
-               if (i == bp->tx_empty) break;
+               if (i >= N_TX_RING)
+                       i = 0;
+               if (i == bp->tx_empty)
+                       break;
                skb = skb_dequeue(bp->queue);
-               if (skb == NULL) break;
+               if (skb == NULL)
+                       break;
                bmac_transmit_packet(skb, dev);
        }
        restore_flags(flags);
@@ -1525,9 +1499,7 @@ static void bmac_tx_timeout(unsigned long data)
                bp->tx_empty = i;
        }
        bp->tx_fullup = 0;
-       dev->tbusy = 0;
-       mark_bh(NET_BH);
-       XXDEBUG((KERN_DEBUG "bmac: clearing tbusy\n"));
+       netif_wake_queue(dev);
        if (i != bp->tx_fill) {
                cp = &bp->tx_cmds[i];
                out_le16(&cp->xfer_status, 0);
@@ -1540,9 +1512,9 @@ static void bmac_tx_timeout(unsigned long data)
 
        /* turn it back on */
        oldConfig = bmread(dev, RXCFG);         
-       bmwrite(dev, RXCFG, oldConfig | RxMACEnable ); 
+       bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
        oldConfig = bmread(dev, TXCFG);         
-       bmwrite(dev, TXCFG, oldConfig | TxMACEnable );  
+       bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
 
        restore_flags(flags);
 }
@@ -1573,7 +1545,8 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
        off_t begin = 0;
        int i;
 
-       if (bmac_devs == NULL) return (-ENOSYS);
+       if (bmac_devs == NULL)
+               return (-ENOSYS);
 
        len += sprintf(buffer, "BMAC counters & registers\n");
 
@@ -1582,20 +1555,20 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
                               reg_entries[i].name,
                               bmread(bmac_devs, reg_entries[i].reg_offset));
                pos = begin + len;
-    
+
                if (pos < offset) {
                        len = 0;
                        begin = pos;
                }
-    
+
                if (pos > offset+length) break;
        }
-  
+
        *start = buffer + (offset - begin);
        len -= (offset - begin);
-  
+
        if (len > length) len = length;
-  
+
        return len;
 }
 
@@ -1606,26 +1579,28 @@ MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
 
 static void __exit bmac_cleanup (void)
 {
-#ifdef MODULE
-    struct bmac_data *bp;
+       struct bmac_data *bp;
+       struct net_device *dev;
 
-    if (bmac_devs == 0)
-       return;
+       if (bmac_devs == 0)
+               return;
+#ifdef CONFIG_PMAC_PBOOK
+       pmu_unregister_sleep_notifier(&bmac_sleep_notifier);
+#endif
+       proc_net_remove("bmac");
 
-    bp = (struct bmac_data *) bmac_devs->priv;
-    unregister_netdev(bmac_devs);
-    proc_net_remove("bmac");
+       do {
+               dev = bmac_devs;
+               bp = (struct bmac_data *) dev->priv;
+               bmac_devs = bp->next_bmac;
 
-    free_irq(bmac_devs->irq, bmac_misc_intr);
-    free_irq(bp->tx_dma_intr, bmac_txdma_intr);
-    free_irq(bp->rx_dma_intr, bmac_rxdma_intr);
+               free_irq(dev->irq, dev);
+               free_irq(bp->tx_dma_intr, dev);
+               free_irq(bp->rx_dma_intr, dev);
 
-#ifdef CONFIG_PMAC_PBOOK
-    pmu_unregister_sleep_notifier(&bmac_sleep_notifier);
-#endif
-    kfree(bmac_devs);
-    bmac_devs = NULL;
-#endif
+               unregister_netdev(dev);
+               kfree(dev);
+       } while (bmac_devs != NULL);
 }
 
 module_init(bmac_probe);
index 8c997b3c2c66494077d4812a6be6a266d7f11019..a565d9eb8ef4877230f5add2dce5267f46f94c96 100644 (file)
@@ -1761,7 +1761,7 @@ de4x5_free_tx_buff(struct de4x5_private *lp, int entry)
     pci_unmap_single(lp->pdev, le32_to_cpu(lp->tx_ring[entry].buf),
                     le32_to_cpu(lp->tx_ring[entry].des1) & TD_TBS1);
     if ((u_long) lp->tx_skb[entry] > 1)
-       dev_kfree_skb(lp->tx_skb[entry]);
+       dev_kfree_skb_irq(lp->tx_skb[entry]);
     lp->tx_skb[entry] = NULL;
 }
 
index e651be8a8dda6ed67b2271aefca9d34e4dec0250..63b5405007f6ee00d803dd4eaa2028379dfb6c81 100644 (file)
@@ -73,10 +73,6 @@ static int debug = -1;                       /* The debug level */
 
 #include <linux/version.h>
 #include <linux/module.h>
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
-
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -84,14 +80,7 @@ static int debug = -1;                       /* The debug level */
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#ifdef HAS_PCI_NETIF
-#include "pci-netif.h"
-#else
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE < 0x20155
-#include <linux/bios32.h>              /* Ignore the bogus warning in 2.1.100+ */
-#endif
-#endif
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
@@ -118,26 +107,6 @@ MODULE_PARM(multicast_filter_limit, "i");
 
 #define RUN_AT(x) (jiffies + (x))
 
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#define le16_to_cpu(val) (val)
-#define cpu_to_le16(val) (val)
-#define le32_to_cpu(val) (val)
-#define cpu_to_le32(val) (val)
-#define spin_lock_irqsave(&sp->lock, flags)    save_flags(flags); cli();
-#define spin_unlock_irqrestore(&sp->lock, flags); restore_flags(flags);
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-#endif
-#if ! defined(CAP_NET_ADMIN)
-#define capable(CAP_XXX) (suser())
-#endif
-#if ! defined(HAS_NETIF_QUEUE)
-#define netif_wake_queue(dev)  mark_bh(NET_BH);
-#endif
 
 /* The total I/O port extent of the board.
    The registers beyond 0x18 only exist on the i82558. */
@@ -278,7 +247,8 @@ having to sign an Intel NDA when I'm helping Intel sell their own product!
 */
 
 /* This table drives the PCI probe routines. */
-static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+static struct net_device *speedo_found1(struct pci_dev *pdev, long ioaddr,
+                                       int irq, int chip_idx, int fnd_cnt);
 
 #ifdef USE_IO
 #define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1
@@ -288,14 +258,6 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr,
 #define SPEEDO_SIZE            0x1000
 #endif
 
-#if defined(HAS_PCI_NETIF)
-struct pci_id_info static pci_tbl[] = {
-       { "Intel PCI EtherExpress Pro100",
-         { 0x12298086, 0xffffffff,}, SPEEDO_IOTYPE, SPEEDO_SIZE,
-         0, speedo_found1 },
-       {0,},                                           /* 0 terminated list. */
-};
-#else
 enum pci_flags_bit {
        PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
        PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
@@ -304,13 +266,12 @@ struct pci_id_info {
        const char *name;
        u16     vendor_id, device_id, device_id_mask, flags;
        int io_size;
-       struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+       struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 } static pci_tbl[] = {
        { "Intel PCI EtherExpress Pro100",
          0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 },
        {0,},                                           /* 0 terminated list. */
 };
-#endif
 
 #ifndef USE_IO
 #define inb readb
@@ -456,7 +417,7 @@ struct speedo_private {
        struct enet_statistics stats;
        struct speedo_stats *lstats;
        int chip_id;
-       unsigned char pci_bus, pci_devfn, acpi_pwr;
+       unsigned char acpi_pwr;
        struct pci_dev *pdev;
        struct timer_list timer;        /* Media selection timer. */
        int mc_setup_frm_len;                           /* The length of an allocated.. */
@@ -529,65 +490,39 @@ static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
 /* A list of all installed Speedo devices, for removing the driver module. */
 static struct net_device *root_speedo_dev = NULL;
 
-#if ! defined(HAS_PCI_NETIF)
-int eepro100_init(void)
+static int __init eepro100_init (void)
 {
        int cards_found = 0;
-       static int pci_index = 0;
-
-       if (! pcibios_present())
-               return cards_found;
-
-       for (; pci_index < 8; pci_index++) {
-               unsigned char pci_bus, pci_device_fn, pci_latency;
-               long ioaddr;
-               int irq;
-
-               u16 pci_command, new_command;
+       struct pci_dev *pdev = NULL;
+       long ioaddr;
+       int irq;
 
-               if (pcibios_find_device(PCI_VENDOR_ID_INTEL,
-                                                               PCI_DEVICE_ID_INTEL_82557,
-                                                               pci_index, &pci_bus,
-                                                               &pci_device_fn))
-                       break;
-#if LINUX_VERSION_CODE >= 0x20155  ||  PCI_SUPPORT_1
-               {
-                       struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+       while ((pdev = pci_find_device (PCI_VENDOR_ID_INTEL,
+                                       PCI_DEVICE_ID_INTEL_82557, pdev))) {
 #ifdef USE_IO
-                       ioaddr = pdev->resource[1].start;
+               ioaddr = pdev->resource[1].start;
 #else
-                       ioaddr = pdev->resource[0].start;
-#endif
-                       irq = pdev->irq;
-               }
-#else
-               {
-                       u32 pciaddr;
-                       u8 pci_irq_line;
-                       pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                        PCI_INTERRUPT_LINE, &pci_irq_line);
-                       /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */
-#ifdef USE_IO
-                       pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                                         PCI_BASE_ADDRESS_1, &pciaddr);
-                       pciaddr &= ~3UL;
-#else
-                       pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                                         PCI_BASE_ADDRESS_0, &pciaddr);
-#endif
-                       ioaddr = pciaddr;
-                       irq = pci_irq_line;
-               }
+               ioaddr = pdev->resource[0].start;
 #endif
+               irq = pdev->irq;
+
                /* Remove I/O space marker in bit 0. */
 #ifdef USE_IO
-               if (check_region(ioaddr, 32))
+               if (check_region(ioaddr, 32)) {
+                       printk(KERN_ERR "eepro100: %ld mem region busy\n", ioaddr);
                        continue;
+               }
 #else
                {
                        unsigned long orig_ioaddr = ioaddr;
+                       
+                       if (check_mem_region(ioaddr, 32)) {
+                               printk(KERN_ERR "eepro100: %ld mem region busy\n",
+                                      ioaddr);
+                               continue;
+                       }
 
-                       if ((ioaddr = (long)ioremap(ioaddr & ~0xfUL, 0x1000)) == 0) {
+                       if ((ioaddr = (long)ioremap(orig_ioaddr, 0x1000)) == 0) {
                                printk(KERN_INFO "Failed to map PCI address %#lx.\n",
                                           orig_ioaddr);
                                continue;
@@ -598,54 +533,30 @@ int eepro100_init(void)
                        printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
                                   ioaddr, irq);
 
-               /* Get and check the bus-master and latency values. */
-               pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                PCI_COMMAND, &pci_command);
-               new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
-               if (pci_command != new_command) {
-                       printk(KERN_INFO "  The PCI BIOS has not enabled this"
-                                  " device!  Updating PCI command %4.4x->%4.4x.\n",
-                                  pci_command, new_command);
-                       pcibios_write_config_word(pci_bus, pci_device_fn,
-                                                                         PCI_COMMAND, new_command);
-               }
-               pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                PCI_LATENCY_TIMER, &pci_latency);
-               if (pci_latency < 32) {
-                       printk("  PCI latency timer (CFLT) is unreasonably low at %d."
-                                  "  Setting to 32 clocks.\n", pci_latency);
-                       pcibios_write_config_byte(pci_bus, pci_device_fn,
-                                                                         PCI_LATENCY_TIMER, 32);
-               } else if (speedo_debug > 1)
-                       printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
-
-               if(speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0,cards_found))
+               if(speedo_found1(pdev, ioaddr, irq, 0,cards_found))
                        cards_found++;
        }
 
        return cards_found;
 }
-#endif
 
-static struct net_device *speedo_found1(int pci_bus, int pci_devfn, 
+
+static struct net_device *speedo_found1(struct pci_dev *pdev,
                          long ioaddr, int irq, int chip_idx, int card_idx)
 {
        struct net_device *dev;
        struct speedo_private *sp;
-       struct pci_dev *pdev;
        unsigned char *tx_ring;
        dma_addr_t tx_ring_dma;
        const char *product;
        int i, option;
        u16 eeprom[0x100];
-       int acpi_idle_state = 0;
+       int acpi_idle_state = 0, pm;
 
        static int did_version = 0;                     /* Already printed version info. */
        if (speedo_debug > 0  &&  did_version++ == 0)
                printk(version);
 
-       pdev = pci_find_slot(pci_bus, pci_devfn);
-
        tx_ring = pci_alloc_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
                                             + sizeof(struct speedo_stats), &tx_ring_dma);
        if (!tx_ring) {
@@ -668,9 +579,16 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
        else
                option = 0;
 
-#if defined(HAS_PCI_NETIF)
-       acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0);
-#endif
+       /* save power state b4 pci_enable_device overwrites it */
+       pm = pci_find_capability(pdev, PCI_CAP_ID_PM);
+       if (pm) {
+               u16 pwr_command;
+               pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command);
+               acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
+       }
+
+       pci_enable_device (pdev);
+       pci_set_master (pdev);
 
        /* Read the station address EEPROM before doing the reset.
           Nominally his should even be done before accepting the device, but
@@ -724,7 +642,7 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
                printk("%2.2X:", dev->dev_addr[i]);
        printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq);
 
-#ifndef kernel_bloat
+#if 1
        /* OK, this is pure kernel bloat.  I don't like it when other drivers
           waste non-pageable kernel space to emit similar messages, but I need
           them for bug reports. */
@@ -793,13 +711,15 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
 #endif  /* kernel_bloat */
 
        outl(PortReset, ioaddr + SCBPort);
-#if defined(HAS_PCI_NETIF)
+
        /* Return the chip to its original power state. */
-       acpi_set_pwr_state(pci_bus, pci_devfn, acpi_idle_state);
-#endif
+       pci_set_power_state (pdev, acpi_idle_state);
 
-       /* We do a request_region() only to register /proc/ioports info. */
+#ifdef USE_IO
        request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet");
+#else
+       request_mem_region(ioaddr, 0x1000, "Intel Speedo3 Ethernet");
+#endif
 
        dev->base_addr = ioaddr;
        dev->irq = irq;
@@ -814,8 +734,6 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
        sp->next_module = root_speedo_dev;
        root_speedo_dev = dev;
 
-       sp->pci_bus = pci_bus;
-       sp->pci_devfn = pci_devfn;
        sp->pdev = pdev;
        sp->chip_id = chip_idx;
        sp->acpi_pwr = acpi_idle_state;
@@ -925,13 +843,11 @@ speedo_open(struct net_device *dev)
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
        long ioaddr = dev->base_addr;
 
-#if defined(HAS_PCI_NETIF)
-       acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
-#endif
-
        if (speedo_debug > 1)
                printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
 
+       pci_set_power_state(sp->pdev, 0);
+
        /* Set up the Tx queue early.. */
        sp->cur_tx = 0;
        sp->dirty_tx = 0;
@@ -940,9 +856,9 @@ speedo_open(struct net_device *dev)
        spin_lock_init(&sp->lock);
 
        /* .. we can safely take handler calls during init. */
-       if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) {
-               return -EAGAIN;
-       }
+       if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev))
+               return -EBUSY;
+
        MOD_INC_USE_COUNT;
 
        dev->if_port = sp->default_port;
@@ -1059,6 +975,8 @@ static void speedo_resume(struct net_device *dev)
             + (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD),
                 ioaddr + SCBPointer);
        outw(CUStart, ioaddr + SCBCmd);
+       
+       netif_start_queue (dev);
 }
 
 /* Media monitoring and control. */
@@ -1220,6 +1138,7 @@ static void speedo_tx_timeout(struct net_device *dev)
        }
        sp->stats.tx_errors++;
        dev->trans_start = jiffies;
+       netif_start_queue (dev);
        return;
 }
 
@@ -1230,6 +1149,8 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
        long ioaddr = dev->base_addr;
        int entry;
 
+       netif_stop_queue (dev);
+
        /* Caution: the write order is important here, set the base address
           with the "ownership" bits last. */
 
@@ -1270,13 +1191,15 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
                if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) {
                        sp->tx_full = 1;
-                       netif_stop_queue(dev);
                }
                spin_unlock_irqrestore(&sp->lock, flags);
        }
        wait_for_cmd_done(ioaddr + SCBCmd);
        outw(CUResume, ioaddr + SCBCmd);
        dev->trans_start = jiffies;
+       
+       if (! sp->tx_full)
+               netif_start_queue (dev);
 
        return 0;
 }
@@ -1300,6 +1223,8 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
        ioaddr = dev->base_addr;
        sp = (struct speedo_private *)dev->priv;
 
+       spin_lock (&sp->lock);
+
        do {
                status = inw(ioaddr + SCBStatus);
                /* Acknowledge all of the current interrupt sources ASAP. */
@@ -1330,7 +1255,6 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                /* User interrupt, Command/Tx unit interrupt or CU not active. */
                if (status & 0xA400) {
                        unsigned int dirty_tx;
-                       spin_lock(&sp->lock);
 
                        dirty_tx = sp->dirty_tx;
                        while (sp->cur_tx - dirty_tx > 0) {
@@ -1380,10 +1304,12 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                &&  sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) {
                                /* The ring is no longer full, clear tbusy. */
                                sp->tx_full = 0;
-                               spin_unlock(&sp->lock);
-                               netif_wake_queue(dev);
-                       } else
-                               spin_unlock(&sp->lock);
+                       }
+                       
+                       if (sp->tx_full)
+                               netif_stop_queue (dev);
+                       else
+                               netif_wake_queue (dev);
                }
 
                if (--boguscnt < 0) {
@@ -1399,7 +1325,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
                           dev->name, inw(ioaddr + SCBStatus));
 
-       return;
+       spin_unlock (&sp->lock);
 }
 
 static int
@@ -1546,7 +1472,7 @@ speedo_close(struct net_device *dev)
 #if LINUX_VERSION_CODE < 0x20100
                        skb->free = 1;
 #endif
-                       dev_free_skb(skb);
+                       dev_kfree_skb(skb);
                }
        }
 
@@ -1559,7 +1485,7 @@ speedo_close(struct net_device *dev)
                        pci_unmap_single(sp->pdev,
                                                         le32_to_cpu(sp->tx_ring[i].tx_buf_addr0),
                                                         skb->len);
-                       dev_free_skb(skb);
+                       dev_kfree_skb(skb);
                }
        }
        if (sp->mc_setup_frm) {
@@ -1571,10 +1497,9 @@ speedo_close(struct net_device *dev)
        if (speedo_debug > 3)
                speedo_show_state(dev);
 
-#if defined(HAS_PCI_NETIF)
        /* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */
-       acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D2);
-#endif
+       pci_set_power_state (sp->pdev, 2);
+
        MOD_DEC_USE_COUNT;
 
        return 0;
@@ -1626,32 +1551,22 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        long ioaddr = dev->base_addr;
        u16 *data = (u16 *)&rq->ifr_data;
        int phy = sp->phy[0] & 0x1f;
-#if defined(HAS_PCI_NETIF)
        int saved_acpi;
-#endif
 
     switch(cmd) {
        case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
                data[0] = phy;
        case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
-#if defined(HAS_PCI_NETIF)
-               saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
-               data[3] = mdio_read(ioaddr, data[0], data[1]);
-               acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
-#else
-               data[3] = mdio_read(ioaddr, data[0], data[1]);
-#endif
+               saved_acpi = pci_set_power_state (sp->pdev, 0);
+               data[3] = mdio_read (ioaddr, data[0], data[1]);
+               pci_set_power_state (sp->pdev, saved_acpi);
                return 0;
        case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-#if defined(HAS_PCI_NETIF)
-               saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
+               saved_acpi = pci_set_power_state(sp->pdev, 0);
                mdio_write(ioaddr, data[0], data[1], data[2]);
-               acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
-#else
-               mdio_write(ioaddr, data[0], data[1], data[2]);
-#endif
+               pci_set_power_state(sp->pdev, saved_acpi);
                return 0;
        default:
                return -EOPNOTSUPP;
@@ -1846,18 +1761,11 @@ static int __init eepro100_init_module(void)
        if (speedo_debug)
                printk(KERN_INFO "%s", version);
 
-#if defined(HAS_PCI_NETIF)
-       cards_found = netif_pci_probe(pci_tbl);
-       if (cards_found < 0)
-               printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
-       return cards_found;
-#else
        cards_found = eepro100_init();
        if (cards_found <= 0) {
                printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
                return -ENODEV;
        }
-#endif
        return 0;
 }
 
@@ -1872,11 +1780,10 @@ static void __exit eepro100_cleanup_module(void)
 #ifdef USE_IO
                release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE);
 #else
+               release_mem_region(root_speedo_dev->base_addr, 0x1000);
                iounmap((char *)root_speedo_dev->base_addr);
 #endif
-#if defined(HAS_PCI_NETIF)
-               acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, sp->acpi_pwr);
-#endif
+               pci_set_power_state(sp->pdev, sp->acpi_pwr);
                next_dev = sp->next_module;
                if (sp->priv_addr)
                        kfree(sp->priv_addr);
index c7dfb7a65e20967af300241ac4517a612181ca65..7d9cd2363cb28b9e6cccc843913ce874147c9636 100644 (file)
@@ -79,7 +79,6 @@ MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
 
 /* The I/O extent. */
 #define EPIC_TOTAL_SIZE 0x100
@@ -895,7 +894,7 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                }
 
                                /* Free the original skb. */
-                               DEV_FREE_SKB(ep->tx_skbuff[entry]);
+                               dev_kfree_skb_irq(ep->tx_skbuff[entry]);
                                ep->tx_skbuff[entry] = 0;
                        }
 
@@ -1073,12 +1072,12 @@ static int epic_close(struct net_device *dev)
                ep->rx_ring[i].buflength = 0;
                ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
                if (skb) {
-                       DEV_FREE_SKB(skb);
+                       dev_kfree_skb(skb);
                }
        }
        for (i = 0; i < TX_RING_SIZE; i++) {
                if (ep->tx_skbuff[i])
-                       DEV_FREE_SKB(ep->tx_skbuff[i]);
+                       dev_kfree_skb(ep->tx_skbuff[i]);
                ep->tx_skbuff[i] = 0;
        }
 
@@ -1224,13 +1223,14 @@ static dev_node_t *epic_attach(dev_locator_t *loc)
        struct net_device *dev;
        u16 dev_id;
        u32 io;
-       u8 bus, devfn, irq;
+       u8 irq;
        struct pci_dev *pdev;
 
        if (loc->bus != LOC_PCI) return NULL;
        pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
        if (!pdev) return NULL;
-       printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
+       printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n",
+              pdev->bus->number, pdev->devfn);
        io = pdev->resource[0].start;
        irq = pdev->irq;
        dev_id = pdev->device;
@@ -1241,7 +1241,7 @@ static dev_node_t *epic_attach(dev_locator_t *loc)
                           io == 0 ? "I/O address" : "IRQ");
                return NULL;
        }
-       dev = epic_probe1(bus, devfn, io, irq, 2, -1);
+       dev = epic_probe1(pdev, io, irq, 2, -1);
        if (dev) {
                dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
                strcpy(node->dev_name, dev->name);
index 7ee18bfe90fc035470426b3c50b2fcf3fb7587e1..b1a431499f944c38364f588881c65c16119f56bb 100644 (file)
@@ -51,6 +51,7 @@ struct gmac {
        int             phy_addr;
        int             full_duplex;
        struct net_device_stats stats;
+       struct net_device *next_gmac;
 };
 
 #define GM_OUT(r, v)   out_le32(gm->regs + (r)/4, (v))
@@ -80,6 +81,7 @@ static void gmac_receive(struct net_device *dev);
 static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static struct net_device_stats *gmac_stats(struct net_device *dev);
 static int gmac_probe(void);
+static void gmac_probe1(struct device_node *gmac);
 
 /* Stuff for talking to the physical-layer chip */
 static int
@@ -383,7 +385,7 @@ static int gmac_xmit_start(struct sk_buff *skb, struct net_device *dev)
        i = gm->next_tx;
        if (gm->tx_buff[i] != 0) {
                /* buffer is full, can't send this packet at the moment */
-               dev->tbusy = 1;
+               netif_stop_queue(dev);
                gm->tx_full = 1;
                restore_flags(flags);
                return 1;
@@ -421,7 +423,7 @@ static int gmac_tx_cleanup(struct gmac *gm)
                gm->stats.tx_bytes += skb->len;
                ++gm->stats.tx_packets;
                gm->tx_buff[i] = NULL;
-               dev_kfree_skb(skb);
+               dev_kfree_skb_irq(skb);
                if (++i >= NTX)
                        i = 0;
        }
@@ -452,7 +454,7 @@ static void gmac_receive(struct net_device *dev)
                        ++gm->stats.rx_dropped;
                } else if (ld_le32(&dp->status) & 0x40000000) {
                        ++gm->stats.rx_errors;
-                       dev_kfree_skb(skb);
+                       dev_kfree_skb_irq(skb);
                } else {
                        skb_put(skb, len);
                        skb->dev = dev;
@@ -486,14 +488,11 @@ static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        status = GM_IN(INTR_STATUS);
        GM_OUT(INTR_ACK, status);
        
-       if (status & GMAC_IRQ_MIF) {
+       if (status & GMAC_IRQ_MIF)
                mii_interrupt(gm);
-       }
        gmac_receive(dev);
-       if (gmac_tx_cleanup(gm)){
-               dev->tbusy = 0;
-               mark_bh(NET_BH);
-       }
+       if (gmac_tx_cleanup(gm))
+               netif_wake_queue(dev);
 }
 
 static struct net_device_stats *gmac_stats(struct net_device *dev)
@@ -505,33 +504,44 @@ static struct net_device_stats *gmac_stats(struct net_device *dev)
 
 static int __init gmac_probe(void)
 {
-       static int gmacs_found;
-       static struct device_node *next_gmac;
        struct device_node *gmac;
-       struct gmac *gm;
-       unsigned long descpage;
-       unsigned char *addr;
-       int i;
-
-       if (gmacs != NULL)
-               return -EBUSY;
 
        /*
         * We could (and maybe should) do this using PCI scanning
         * for vendor/net_device ID 0x106b/0x21.
         */
-       if (!gmacs_found) {
-               next_gmac = find_compatible_devices("network", "gmac");
-               gmacs_found = 1;
-       }
-       if ((gmac = next_gmac) == 0)
-               return -ENODEV;
-       next_gmac = gmac->next;
+       for (gmac = find_compatible_devices("network", "gmac"); gmac != 0;
+            gmac = gmac->next)
+               gmac_probe1(gmac);
+
+       return 0;
+}
+
+static void gmac_probe1(struct device_node *gmac)
+{
+       struct gmac *gm;
+       unsigned long descpage;
+       unsigned char *addr;
+       struct net_device *dev;
+       int i;
 
        if (gmac->n_addrs < 1 || gmac->n_intrs < 1) {
                printk(KERN_ERR "can't use GMAC %s: %d addrs and %d intrs\n",
                       gmac->full_name, gmac->n_addrs, gmac->n_intrs);
-               return -ENODEV;
+               return;
+       }
+
+       addr = get_property(gmac, "local-mac-address", NULL);
+       if (addr == NULL) {
+               printk(KERN_ERR "Can't get mac-address for GMAC %s\n",
+                      gmac->full_name);
+               return;
+       }
+
+       descpage = get_free_page(GFP_KERNEL);
+       if (descpage == 0) {
+               printk(KERN_ERR "GMAC: can't get a page for descriptors\n");
+               return;
        }
 
        dev = init_etherdev(0, sizeof(struct gmac));
@@ -544,13 +554,6 @@ static int __init gmac_probe(void)
        gm->sysregs = (volatile unsigned int *) ioremap(0xf8000000, 0x1000);
        dev->irq = gmac->intrs[0].line;
 
-       addr = get_property(gmac, "local-mac-address", NULL);
-       if (addr == NULL) {
-               printk(KERN_ERR "Can't get mac-address for GMAC %s\n",
-                      gmac->full_name);
-               return -EAGAIN;
-       }
-
        printk(KERN_INFO "%s: GMAC at", dev->name);
        for (i = 0; i < 6; ++i) {
                dev->dev_addr[i] = addr[i];
@@ -558,12 +561,6 @@ static int __init gmac_probe(void)
        }
        printk("\n");
 
-       descpage = get_free_page(GFP_KERNEL);
-       if (descpage == 0) {
-               printk(KERN_ERR "GMAC: can't get a page for descriptors\n");
-               return -EAGAIN;
-       }
-
        gm->desc_page = descpage;
        gm->rxring = (volatile struct gmac_dma_desc *) descpage;
        gm->txring = (volatile struct gmac_dma_desc *) (descpage + 0x800);
@@ -577,34 +574,29 @@ static int __init gmac_probe(void)
 
        ether_setup(dev);
 
-       if (request_irq(dev->irq, gmac_interrupt, 0, "GMAC", dev)) {
+       if (request_irq(dev->irq, gmac_interrupt, 0, "GMAC", dev))
                printk(KERN_ERR "GMAC: can't get irq %d\n", dev->irq);
-               return -EAGAIN;
-       }
 
+       gm->next_gmac = gmacs;
        gmacs = dev;
-
-       return 0;
 }
 
-MODULE_AUTHOR("Paul Mackerras");
+MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt");
 MODULE_DESCRIPTION("PowerMac GMAC driver.");
 
-
 static void __exit gmac_cleanup_module(void)
 {
        struct gmac *gm;
-
-       /* XXX should handle more than one */
-       if (gmacs == NULL)
-               return;
-
-       gm = (struct gmac *) gmacs->priv;
-       free_irq(gmacs->irq, gmac_interrupt);
-       free_page(gm->descpage);
-       unregister_netdev(gmacs);
-       kfree(gmacs);
-       gmacs = NULL;
+       struct net_device *dev;
+
+       while ((dev = gmacs) != NULL) {
+               gm = (struct gmac *) dev->priv;
+               gmacs = gm->next_gmac;
+               free_irq(dev->irq, dev);
+               free_page(gm->desc_page);
+               unregister_netdev(dev);
+               kfree(dev);
+       }
 }
 
 module_init(gmac_probe);
index 4840e1abfafdf6fceab1d40e2fac46860c925b4b..ac0771bd88e3f34b49228a2c7abd6e72943f771d 100644 (file)
@@ -20,9 +20,7 @@
 #include <asm/pgtable.h>
 #include "mace.h"
 
-#ifdef MODULE
 static struct net_device *mace_devs = NULL;
-#endif
 
 #define N_RX_RING      8
 #define N_TX_RING      6
@@ -55,6 +53,7 @@ struct mace_data {
     struct net_device_stats stats;
     struct timer_list tx_timeout;
     int timeout_active;
+    struct net_device *next_mace;
 };
 
 /*
@@ -67,6 +66,8 @@ struct mace_data {
        + (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
 
 static int bitrev(int);
+static int mace_probe(void);
+static void mace_probe1(struct device_node *mace);
 static int mace_open(struct net_device *dev);
 static int mace_close(struct net_device *dev);
 static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
@@ -99,34 +100,36 @@ bitrev(int b)
     return d;
 }
 
-static int __init mace_probe (void)
+static int __init mace_probe(void)
+{
+       struct device_node *mace;
+
+       for (mace = find_devices("mace"); mace != NULL; mace = mace->next)
+               mace_probe1(mace);
+       return 0;
+}
+
+static void __init mace_probe1(struct device_node *mace)
 {
        int j, rev;
        struct net_device *dev;
        struct mace_data *mp;
-       struct device_node *mace;
        unsigned char *addr;
-       static int maces_found = 0;
-       static struct device_node *next_mace;
-
-#ifdef MODULE
-       if(mace_devs != NULL)
-               return -EBUSY;
-#endif
-
-       if (!maces_found) {
-               next_mace = find_devices("mace");
-               maces_found = 1;
-       }
-       mace = next_mace;
-       if (mace == 0)
-               return -ENODEV;
-       next_mace = mace->next;
 
        if (mace->n_addrs != 3 || mace->n_intrs != 3) {
-               printk(KERN_ERR "can't use MACE %s: expect 3 addrs and 3 intrs\n",
+               printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
                       mace->full_name);
-               return -ENODEV;
+               return;
+       }
+
+       addr = get_property(mace, "mac-address", NULL);
+       if (addr == NULL) {
+               addr = get_property(mace, "local-mac-address", NULL);
+               if (addr == NULL) {
+                       printk(KERN_ERR "Can't get mac-address for MACE %s\n",
+                              mace->full_name);
+                       return;
+               }
        }
 
        dev = init_etherdev(0, PRIV_BYTES);
@@ -138,16 +141,6 @@ static int __init mace_probe (void)
                ioremap(mace->addrs[0].address, 0x1000);
        dev->irq = mace->intrs[0].line;
 
-       addr = get_property(mace, "mac-address", NULL);
-       if (addr == NULL) {
-               addr = get_property(mace, "local-mac-address", NULL);
-               if (addr == NULL) {
-                       printk(KERN_ERR "Can't get mac-address for MACE at %lx\n",
-                              dev->base_addr);
-                       return -EAGAIN;
-               }
-       }
-
        printk(KERN_INFO "%s: MACE at", dev->name);
        rev = addr[0] == 0 && addr[1] == 0xA0;
        for (j = 0; j < 6; ++j) {
@@ -186,22 +179,17 @@ static int __init mace_probe (void)
 
        mace_reset(dev);
 
-       if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
+       if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev))
                printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
-               return -EAGAIN;
-       }
        if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
-                       dev)) {
+                       dev))
                printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line);
-               return -EAGAIN;
-       }
        if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
-                       dev)) {
+                       dev))
                printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line);
-               return -EAGAIN;
-       }
 
-       return 0;
+       mp->next_mace = mace_devs;
+       mace_devs = dev;
 }
 
 static void dbdma_reset(volatile struct dbdma_regs *dma)
@@ -365,9 +353,7 @@ static int mace_open(struct net_device *dev)
     /* enable all interrupts except receive interrupts */
     out_8(&mb->imr, RCVINT);
 
-#ifdef MOD_INC_USE_COUNT
     MOD_INC_USE_COUNT;
-#endif
     return 0;
 }
 
@@ -406,9 +392,7 @@ static int mace_close(struct net_device *dev)
 
     mace_clean_rings(mp);
 
-#ifdef MOD_DEC_USE_COUNT
     MOD_DEC_USE_COUNT;
-#endif
 
     return 0;
 }
@@ -683,7 +667,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
            mp->stats.tx_bytes += mp->tx_bufs[i]->len;
            ++mp->stats.tx_packets;
        }
-       dev_kfree_skb(mp->tx_bufs[i]);
+       dev_kfree_skb_irq(mp->tx_bufs[i]);
        --mp->tx_active;
        if (++i >= N_TX_RING)
            i = 0;
@@ -895,23 +879,25 @@ static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
     }
 }
 
-
 MODULE_AUTHOR("Paul Mackerras");
 MODULE_DESCRIPTION("PowerMac MACE driver.");
 
 static void __exit mace_cleanup (void)
 {
-#ifdef MODULE
-    struct mace_data *mp = (struct mace_data *) mace_devs->priv;
-    unregister_netdev(mace_devs);
+    struct net_device *dev;
+    struct mace_data *mp;
 
-    free_irq(mace_devs->irq, mace_interrupt);
-    free_irq(mp->tx_dma_intr, mace_txdma_intr);
-    free_irq(mp->rx_dma_intr, mace_rxdma_intr);
+    while ((dev = mace_devs) != 0) {
+       mp = (struct mace_data *) mace_devs->priv;
+       mace_devs = mp->next_mace;
 
-    kfree(mace_devs);
-    mace_devs = NULL;
-#endif
+       free_irq(dev->irq, dev);
+       free_irq(mp->tx_dma_intr, dev);
+       free_irq(mp->rx_dma_intr, dev);
+
+       unregister_netdev(dev);
+       kfree(dev);
+    }
 }
 
 module_init(mace_probe);
index fd120de2b6a4ca6491405a473f3569cfb47dec32..6a8c8b4129a61c320e415ea01d59433d94ea6cbd 100644 (file)
  */
 
 static const char *version =
-"ncr885e.c:v0.8 11/30/98 dan@synergymicro.com\n";
+"ncr885e.c:v1.0 02/10/00 dan@synergymicro.com, cort@fsmlabs.com\n";
 
 #include <linux/config.h>
+
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
@@ -81,8 +82,6 @@ static const char *chipname = "ncr885e";
 
 int ncr885e_debug = NCR885E_DEBUG;
 static int print_version = 0;
-static int debug = NCR885E_DEBUG; /* module parm */
-
 
 struct ncr885e_private {
 
@@ -426,7 +425,6 @@ ncr885e_tx( struct net_device *dev )
        if ( xfer ) {
 
                dev_kfree_skb( sp->tx_skbufs[i] );
-               mark_bh( NET_BH );
 
                if ( txbits & TX_STATUS_TXOK ) {
                        sp->stats.tx_packets++;
@@ -443,7 +441,7 @@ ncr885e_tx( struct net_device *dev )
 
        }
 
-       dev->tbusy = 0;
+       netif_start_queue(dev);
   
        return;
 }
@@ -626,12 +624,6 @@ ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs )
        sp = (struct ncr885e_private *) dev->priv;
        spin_lock( &sp->lock );
   
-       if ( dev->interrupt ) {
-               printk( KERN_ERR "%s: Re-entering interrupt handler...\n", 
-                       dev->name );
-       }
-
-       dev->interrupt = 1;
        status = inw( ioaddr + INTERRUPT_CLEAR );
 
        if (ncr885e_debug > 2)
@@ -671,7 +663,6 @@ ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs )
                ncr885e_rx( dev );
        }
   
-       dev->interrupt = 0;
        spin_unlock( &sp->lock );
 
        return;
@@ -779,8 +770,7 @@ ncr885e_tx_timeout( unsigned long data )
 
        /* start anew from the beginning of the ring buffer (why not?) */
        sp->tx_current = 0;
-       dev->tbusy = 0;
-       mark_bh( NET_BH );
+       netif_wake_queue(dev);
 
        /* restart rx dma */
        outl( (RX_DBDMA_ENABLE << 16) | RX_CHANNEL_RUN,
@@ -958,9 +948,7 @@ ncr885e_open( struct net_device *dev )
        outl( (RX_DBDMA_ENABLE << 16)|RX_CHANNEL_RUN,
              ioaddr + RX_CHANNEL_CONTROL );
 
-       dev->start = 1;
-       dev->tbusy = 0;
-       dev->interrupt = 0;
+       netif_start_queue(dev);
 
        MOD_INC_USE_COUNT;
 
@@ -990,7 +978,7 @@ ncr885e_xmit_start( struct sk_buff *skb, struct net_device *dev )
                next = 0;
 
        /* mark ourselves as busy, even if we have too many packets waiting */
-       dev->tbusy = 1;
+       netif_stop_queue(dev);
 
        /* see if it's necessary to defer this packet */
        if ( sp->tx_active >= MAX_TX_ACTIVE ) {
@@ -1058,8 +1046,7 @@ ncr885e_close(struct net_device *dev)
        struct ncr885e_private *np = (struct ncr885e_private *) dev->priv;
        unsigned long ioaddr = dev->base_addr;
 
-       dev->start = 0;
-       dev->tbusy = 1;
+       netif_stop_queue(dev);
 
        spin_lock( &np->lock );
 
@@ -1148,8 +1135,7 @@ ncr885e_stats( struct net_device *dev )
  *  configuration.
  */
 
-static int
-ncr885e_probe1(unsigned long ioaddr, unsigned char irq )
+static int __init ncr885e_probe1(unsigned long ioaddr, unsigned char irq )
 
 {
        struct net_device *dev;
@@ -1158,9 +1144,6 @@ ncr885e_probe1(unsigned long ioaddr, unsigned char irq )
        unsigned char *p;
        int  i;
 
-       if (!request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name))
-               return -EBUSY;
-
        dev = init_etherdev(NULL, 0 );
 
        /* construct private data for the 885 ethernet */
@@ -1413,12 +1396,16 @@ write_mii( unsigned long ioaddr, int reg, int data )
 
 #endif /* NCR885E_DEBUG_MII */
 
-MODULE_AUTHOR("dan@synergymicro.com");
-MODULE_DESCRIPTION("Symbios 53C885 Ethernet driver");
-MODULE_PARM(debug, "i");
+int
+init_module(void)
+{
+       if ( debug >= 0)
+               ncr885e_debug = debug;
 
+       return ncr885e_probe();
+}
 
-static void __exit ncr885e_cleanup (void)
+static void __exit cleanup_module(void)
 {
        struct ncr885e_private *np;
 
@@ -1435,7 +1422,6 @@ static void __exit ncr885e_cleanup (void)
 module_init(ncr885e_probe);
 module_exit(ncr885e_cleanup);
 
-
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O6 -c symba.c"
index 4e4fc4157a0cb777e7e1ba264eb290c3d8ab7b08..1e53dc964f3127ef6bc58f3db3ec7bd54e0769bd 100644 (file)
@@ -220,6 +220,7 @@ struct el3_private {
        u_short media_status;
        u_short fast_poll;
        u_long last_irq;
+       spinlock_t lock;
 };
 
 /* Set iff a MII transceiver on any interface requires mdio preamble.
@@ -261,6 +262,7 @@ static int el3_rx(struct net_device *dev, int worklimit);
 static int el3_close(struct net_device *dev);
 static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
+static void el3_tx_timeout(struct net_device *dev);
 
 static dev_info_t dev_info = "3c574_cs";
 
@@ -320,6 +322,8 @@ static dev_link_t *tc574_attach(void)
        lp = kmalloc(sizeof(*lp), GFP_KERNEL);
        if (!lp) return NULL;
        memset(lp, 0, sizeof(*lp));
+       
+       lp->lock = SPIN_LOCK_UNLOCKED;
        link = &lp->link; dev = &lp->dev;
        link->priv = dev->priv = link->irq.Instance = lp;
        
@@ -351,7 +355,10 @@ static dev_link_t *tc574_attach(void)
        dev->init = &tc574_init;
        dev->open = &el3_open;
        dev->stop = &el3_close;
-       dev->tbusy = 1;
+       dev->tx_timeout = el3_tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
+       
+       netif_start_queue (dev);
 
        /* Register with Card Services */
        link->next = dev_list;
@@ -398,13 +405,12 @@ static void tc574_detach(dev_link_t *link)
        if (*linkp == NULL)
        return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&lp->lock, flags);
        if (link->state & DEV_RELEASE_PENDING) {
                del_timer(&link->release);
                link->state &= ~DEV_RELEASE_PENDING;
        }
-       restore_flags(flags);
+       spin_unlock_irqrestore(&lp->lock, flags);
 
        if (link->state & DEV_CONFIG) {
                tc574_release((u_long)link);
@@ -502,7 +508,7 @@ static void tc574_config(dev_link_t *link)
        dev->irq = link->irq.AssignedIRQ;
        dev->base_addr = link->io.BasePort1;
 
-       dev->tbusy = 0;
+       netif_start_queue (dev);
        if (register_netdev(dev) != 0) {
                printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
                goto failed;
@@ -667,7 +673,7 @@ static int tc574_event(event_t event, int priority,
        case CS_EVENT_CARD_REMOVAL:
                link->state &= ~DEV_PRESENT;
                if (link->state & DEV_CONFIG) {
-                       dev->tbusy = 1; dev->start = 0;
+                       netif_stop_queue (dev);
                        link->release.expires = jiffies + HZ/20;
                        add_timer(&link->release);
                }
@@ -682,7 +688,7 @@ static int tc574_event(event_t event, int priority,
        case CS_EVENT_RESET_PHYSICAL:
                if (link->state & DEV_CONFIG) {
                        if (link->open) {
-                               dev->tbusy = 1; dev->start = 0;
+                               netif_stop_queue (dev);
                        }
                        CardServices(ReleaseConfiguration, link->handle);
                }
@@ -695,7 +701,7 @@ static int tc574_event(event_t event, int priority,
                        CardServices(RequestConfiguration, link->handle, &link->conf);
                        if (link->open) {
                                tc574_reset(dev);
-                               dev->tbusy = 0; dev->start = 1;
+                               netif_start_queue (dev);
                        }
                }
                break;
@@ -913,7 +919,7 @@ static int el3_open(struct net_device *dev)
        
        link->open++;
        MOD_INC_USE_COUNT;
-       dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+       netif_start_queue (dev);
        
        tc574_reset(dev);
        lp->media.function = &media_check;
@@ -939,7 +945,7 @@ static void el3_tx_timeout(struct net_device *dev)
        /* Issue TX_RESET and TX_START commands. */
        wait_for_completion(dev, TxReset);
        outw(TxEnable, ioaddr + EL3_CMD);
-       dev->tbusy = 0;
+       netif_start_queue (dev);
 }
 
 static void pop_tx_status(struct net_device *dev)
@@ -972,22 +978,16 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        long flags = 0;
 #endif
 
-       /* Transmitter timeout, serious problems. */
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-               if (jiffies - dev->trans_start < TX_TIMEOUT)
-                       return 1;
-               el3_tx_timeout(dev);
-       }
-
        DEBUG(3, "%s: el3_start_xmit(length = %ld) called, "
                  "status %4.4x.\n", dev->name, (long)skb->len,
                  inw(ioaddr + EL3_STATUS));
 
+       netif_stop_queue (dev);
+       
 #ifdef BROKEN_FEATURES
        if (use_fifo_buffer) {
                /* Avoid other accesses to the chip while RunnerWrCtrl is non-zero. */
-               save_flags(flags);
-               cli();
+               spin_lock_irqsave(&lp->lock, flags);
                outw((((skb->len + 7)>>2)<<1), ioaddr + RunnerWrCtrl);
                DEBUG(0, "TxFree %x, tx length %x, RunnerWrCtrl is %4.4x.\n",
                          inw(ioaddr+TxFree), skb->len, inw(ioaddr+RunnerWrCtrl));
@@ -1009,7 +1009,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                DEBUG(0, " RunnerWr/RdCtrl is %4.4x/%4.4x, TxFree %x.\n",
                          inw(ioaddr + RunnerWrCtrl), inw(ioaddr + RunnerRdCtrl),
                          inw(ioaddr + TxFree));
-               restore_flags(flags);
+               spin_unlock_irqrestore (&lp->lock, flags);
        }
 #else
        outw(skb->len, ioaddr + TX_FIFO);
@@ -1021,7 +1021,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* TxFree appears only in Window 1, not offset 0x1c. */
        if (inw(ioaddr + TxFree) > 1536) {
-               dev->tbusy = 0;
+               netif_start_queue (dev);
        } else
                /* Interrupt us when the FIFO has room for max-sized packet. 
                   The threshold is in units of dwords. */
@@ -1041,26 +1041,27 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        ioaddr_t ioaddr, status;
        int work_budget = max_interrupt_work;
 
-       if ((lp == NULL) || !dev->start)
+       if (lp == NULL)
                return;
+
+       spin_lock (&lp->lock);
+
        ioaddr = dev->base_addr;
 
 #ifdef PCMCIA_DEBUG
-       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-               printk(KERN_NOTICE "%s: re-entering the interrupt handler.\n",
-                          dev->name);
-               return;
-       }
        DEBUG(3, "%s: interrupt, status %4.4x.\n",
                  dev->name, inw(ioaddr + EL3_STATUS));
 #endif
 
        while ((status = inw(ioaddr + EL3_STATUS)) &
                   (IntLatch | RxComplete | RxEarly | StatsFull)) {
+
+#if 0
                if ((dev->start == 0) || ((status & 0xe000) != 0x2000)) {
                        DEBUG(1, "%s: Interrupt from dead card\n", dev->name);
                        break;
                }
+#endif
 
                if (status & RxComplete)
                        work_budget = el3_rx(dev, work_budget);
@@ -1069,8 +1070,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        DEBUG(3, "  TX room bit was handled.\n");
                        /* There's room in the FIFO for a full-sized packet. */
                        outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);
+                       netif_wake_queue (dev);
+               } else {
+                       netif_stop_queue (dev);
                }
 
                if (status & TxComplete)
@@ -1120,9 +1122,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #ifdef PCMCIA_DEBUG
        DEBUG(3, "%s: exiting interrupt, status %4.4x.\n",
                  dev->name, inw(ioaddr + EL3_STATUS));
-       dev->interrupt = 0;
 #endif
-       return;
+
+       spin_unlock (&lp->lock);
 }
 
 /*
@@ -1138,7 +1140,9 @@ static void media_check(u_long arg)
     u_long flags;
        u_short /* cable, */ media, partner;
        
+#if 0
     if (dev->start == 0) goto reschedule;
+#endif
        
     /* Check for pending interrupt with expired latency timer: with
        this, we can limp along even if the interrupt is blocked */
@@ -1208,7 +1212,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
 {
        struct el3_private *lp = (struct el3_private *)dev->priv;
 
-       if (dev->start)
+       if (test_bit(LINK_STATE_START, &dev->state))
                update_stats(dev);
        return &lp->stats;
 }
@@ -1404,6 +1408,8 @@ static int el3_close(struct net_device *dev)
 
        DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
        
+       netif_stop_queue (dev);
+       
        if (DEV_OK(link)) {
                /* Turn off statistics ASAP.  We update lp->stats below. */
                outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1419,7 +1425,6 @@ static int el3_close(struct net_device *dev)
        }
 
        link->open--;
-       dev->start = 0;
        del_timer(&lp->media);
        if (link->state & DEV_STALE_CONFIG) {
                link->release.expires = jiffies + HZ/20;
index 82f534f0c68e4fcd9be3024374d05bf3e53b1fd9..18cb312e4d14ba015ad9d39142379a5c0385867d 100644 (file)
@@ -53,18 +53,7 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
 #error You must compile this driver with "-O".
 #endif
 
-#include <linux/config.h>
-#include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -89,13 +78,6 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
 
 #include <linux/delay.h>
 
-#define PCI_SUPPORT_VER2
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#if ! defined(CAP_NET_ADMIN)
-#define capable(CAP_XXX) (suser())
-#endif
-
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
 MODULE_PARM(debug, "i");
@@ -106,7 +88,6 @@ MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(compaq_ioaddr, "i");
 MODULE_PARM(compaq_irq, "i");
 MODULE_PARM(compaq_device_id, "i");
-#endif
 
 /* Operational parameter that usually are not changed. */
 
@@ -209,15 +190,15 @@ struct pci_id_info {
        const char *name;
        u16     vendor_id, device_id, device_id_mask, flags;
        int drv_flags, io_size;
-       struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
-                                                        long ioaddr, int irq, int chip_idx, int fnd_cnt);
+       struct net_device *(*probe1)(struct pci_dev *pdev, struct net_device *dev,
+                                    long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
 enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
           HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
-                                                                       struct net_device *dev, long ioaddr,
-                                                                       int irq, int dev_id, int card_idx);
+static struct net_device *vortex_probe1(struct pci_dev *pdev,
+                                       struct net_device *dev, long ioaddr,
+                                       int irq, int dev_id, int card_idx);
 static struct pci_id_info pci_tbl[] = {
        {"3c590 Vortex 10Mbps",                 0x10B7, 0x5900, 0xffff,
         PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
@@ -427,7 +408,7 @@ struct vortex_private {
        struct sk_buff *tx_skb;         /* Packet being eaten by bus master ctrl.  */
 
        /* PCI configuration space information. */
-       u8 pci_bus, pci_devfn;          /* PCI bus location, for power management. */
+       struct pci_dev *pdev;
        char *cb_fn_base;                       /* CardBus function status addr space. */
        int chip_id;
 
@@ -451,6 +432,7 @@ struct vortex_private {
        u16 advertising;                                        /* NWay media advertisement */
        unsigned char phys[2];                          /* MII device addresses. */
        u16 deferred;
+       spinlock_t lock;
 };
 
 /* The action to take with a media selection timer tick.
@@ -501,7 +483,8 @@ static void update_stats(long ioaddr, struct net_device *dev);
 static struct net_device_stats *vortex_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void acpi_wake(int pci_bus, int pci_devfn);
+static void vortex_tx_timeout(struct net_device *dev);
+static void acpi_wake(struct pci_dev *pdev);
 static void acpi_set_WOL(struct net_device *dev);
 \f
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
@@ -542,20 +525,21 @@ static dev_node_t *vortex_attach(dev_locator_t *loc)
 {
        u16 dev_id, vendor_id;
        u32 io;
-       u8 bus, devfn, irq;
+       u8 irq;
        struct net_device *dev;
        int chip_idx;
+       struct pci_dev *pdev;
 
        vortex_reap();
        if (loc->bus != LOC_PCI) return NULL;
-       bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
-       pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-       pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
-       pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
-       pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+       pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+       if (!pdev) return NULL;
+       io = pci_resource_start (pdev, 0);
+       irq = pdev->irq;
+       vendor_id = pdev->vendor;
+       dev_id = pdev->device;
        printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
-                  bus, devfn, dev_id);
-       io &= ~3;
+                  pdev->bus->number, pdev->devfn, dev_id);
        if (io == 0 || irq == 0) {
                printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
                           "assigned an %s.\n" KERN_ERR "  It will not be activated.\n",
@@ -572,7 +556,7 @@ static dev_node_t *vortex_attach(dev_locator_t *loc)
                           "vortex_attach().\n", vendor_id, dev_id);
                return NULL;
        }
-       dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
+       dev = vortex_probe1(pdev, NULL, io, irq, chip_idx, MAX_UNITS+1);
        if (dev) {
                dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
                strcpy(node->dev_name, dev->name);
@@ -663,44 +647,6 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
        int cards_found = 0;
 
        /* Allow an EISA-only driver. */
-#if defined(CONFIG_PCI) || (defined(MODULE) && !defined(NO_PCI))
-       /* Ideally we would detect all cards in slot order.  That would
-          be best done a central PCI probe dispatch, which wouldn't work
-          well with the current structure.  So instead we detect 3Com cards
-          in slot order. */
-       if (pcibios_present()) {
-               static int pci_index = 0;
-               unsigned char pci_bus, pci_device_fn;
-
-               for (;pci_index < 0xff; pci_index++) {
-                       u16 vendor, device, pci_command, new_command;
-                       int chip_idx, irq;
-                       long ioaddr;
-
-                       if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
-                                                                       &pci_bus, &pci_device_fn)
-                               != PCIBIOS_SUCCESSFUL)
-                               break;
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_VENDOR_ID, &vendor);
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_DEVICE_ID, &device);
-                       for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
-                               if (vendor == pci_tbl[chip_idx].vendor_id
-                                       && (device & pci_tbl[chip_idx].device_id_mask) ==
-                                       pci_tbl[chip_idx].device_id)
-                                       break;
-                       if (pci_tbl[chip_idx].vendor_id == 0)           /* Compiled out! */
-                               continue;
-
-                       /* The Cyclone requires config space re-write if powered down. */
-                       acpi_wake(pci_bus, pci_device_fn);
-
-                       {
-                               struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-                               ioaddr = pdev->resource[0].start;
-                               irq = pdev->irq;
-#elif LINUX_VERSION_CODE >= 0x20155
                                struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
                                ioaddr = pdev->base_address[0] & ~3;
                                irq = pdev->irq;
@@ -751,7 +697,6 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
                        }
                }
        }
-#endif /* NO_PCI */
 
        /* Now check all slots of the EISA bus. */
        if (EISA_bus) {
@@ -787,9 +732,9 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
 }
 #endif  /* ! Cardbus */
 
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
-                                                                       struct net_device *dev, long ioaddr,
-                                                                       int irq, int chip_idx, int card_idx)
+static struct net_device *vortex_probe1(struct pci_dev *pdev,
+                                       struct net_device *dev, long ioaddr,
+                                       int irq, int chip_idx, int card_idx)
 {
        struct vortex_private *vp;
        int option;
@@ -817,9 +762,9 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
        vp->next_module = root_vortex_dev;
        root_vortex_dev = dev;
 
+       vp->lock = SPIN_LOCK_UNLOCKED;
        vp->chip_id = chip_idx;
-       vp->pci_bus = pci_bus;
-       vp->pci_devfn = pci_devfn;
+       vp->pdev = pdev;
 
        /* The lower four bits are the media type. */
        if (dev->mem_start)
@@ -892,10 +837,9 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
 
        if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
                u32 fn_st_addr;                 /* Cardbus function status space */
-               pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
-                                                                 &fn_st_addr);
+               fn_st_addr = pci_resource_start (pdev, 2);
                if (fn_st_addr)
-                       vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
+                       vp->cb_fn_base = ioremap(fn_st_addr, 128);
                printk(KERN_INFO "%s: CardBus functions mapped %8.8x->%p\n",
                           dev->name, fn_st_addr, vp->cb_fn_base);
        }
@@ -988,6 +932,8 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
        dev->get_stats = &vortex_get_stats;
        dev->do_ioctl = &vortex_ioctl;
        dev->set_multicast_list = &set_rx_mode;
+       dev->tx_timeout = vortex_tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
 
        return dev;
 }
@@ -1013,7 +959,7 @@ vortex_up(struct net_device *dev)
        int i;
        
        /* Should be if(HAS_ACPI) */
-       acpi_wake(vp->pci_bus, vp->pci_devfn);
+       acpi_wake(vp->pdev);
 
        /* Before initializing select the active media port. */
        EL3WINDOW(3);
@@ -1157,9 +1103,7 @@ vortex_up(struct net_device *dev)
        outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
        vp->in_interrupt = 0;
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
+       netif_start_queue (dev);
 
        outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
        outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -1377,8 +1321,10 @@ static void vortex_tx_timeout(struct net_device *dev)
                                 ioaddr + DownListPtr);
                if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {
                        vp->tx_full = 0;
-                       clear_bit(0, (void*)&dev->tbusy);
+                       netif_start_queue (dev);
                }
+               if (vp->tx_full)
+                       netif_stop_queue (dev);
                outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
                outw(DownUnstall, ioaddr + EL3_CMD);
        } else
@@ -1478,12 +1424,8 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct vortex_private *vp = (struct vortex_private *)dev->priv;
        long ioaddr = dev->base_addr;
 
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-               if (jiffies - dev->trans_start >= TX_TIMEOUT)
-                       vortex_tx_timeout(dev);
-               return 1;
-       }
-
+       netif_stop_queue (dev);
+       
        /* Put out the doubleword header... */
        outl(skb->len, ioaddr + TX_FIFO);
        if (vp->bus_master) {
@@ -1496,9 +1438,9 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
        } else {
                /* ... and the packet rounded to a doubleword. */
                outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-               DEV_FREE_SKB(skb);
+               dev_kfree_skb (skb);
                if (inw(ioaddr + TxFree) > 1536) {
-                       clear_bit(0, (void*)&dev->tbusy);
+                       netif_start_queue (dev);
                } else
                        /* Interrupt us when the FIFO has room for max-sized packet. */
                        outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
@@ -1535,11 +1477,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct vortex_private *vp = (struct vortex_private *)dev->priv;
        long ioaddr = dev->base_addr;
 
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-               if (jiffies - dev->trans_start >= TX_TIMEOUT)
-                       vortex_tx_timeout(dev);
-               return 1;
-       } else {
+       netif_stop_queue (dev);
+       if (1) {
                /* Calculate the next Tx descriptor entry. */
                int entry = vp->cur_tx % TX_RING_SIZE;
                struct boom_tx_desc *prev_entry =
@@ -1561,8 +1500,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
                vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
                vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
 
-               save_flags(flags);
-               cli();
+               spin_lock_irqsave(&vp->lock, flags);
                /* Wait for the stall to complete. */
                wait_for_completion(dev, DownStall);
                prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
@@ -1571,16 +1509,17 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        queued_packet++;
                }
                outw(DownUnstall, ioaddr + EL3_CMD);
-               restore_flags(flags);
+               spin_unlock_irqrestore(&vp->lock, flags);
 
                vp->cur_tx++;
-               if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
+               if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
                        vp->tx_full = 1;
-               else {                                  /* Clear previous interrupt enable. */
+                       netif_stop_queue (dev);
+               } else {                                        /* Clear previous interrupt enable. */
 #if defined(tx_interrupt_mitigation)
                        prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
 #endif
-                       clear_bit(0, (void*)&dev->tbusy);
+                       netif_start_queue (dev);
                }
                dev->trans_start = jiffies;
                return 0;
@@ -1597,23 +1536,8 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        int latency, status;
        int work_done = max_interrupt_work;
 
-#if defined(__i386__)
-       /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-               printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-                          dev->name);
-               dev->interrupt = 0;     /* Avoid halting machine. */
-               return;
-       }
-#else
-       if (dev->interrupt) {
-               printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-               return;
-       }
-       dev->interrupt = 1;
-#endif
-
-       dev->interrupt = 1;
+       spin_lock (&vp->lock);
+       
        ioaddr = dev->base_addr;
        latency = inb(ioaddr + Timer);
        status = inw(ioaddr + EL3_STATUS);
@@ -1643,8 +1567,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                printk(KERN_DEBUG "     TX room bit was handled.\n");
                        /* There's room in the FIFO for a full-sized packet. */
                        outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-                       clear_bit(0, (void*)&dev->tbusy);
-                       mark_bh(NET_BH);
+                       netif_wake_queue (dev);
                }
 
                if (status & DownComplete) {
@@ -1657,7 +1580,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                        virt_to_bus(&vp->tx_ring[entry]))
                                        break;                  /* It still hasn't been processed. */
                                if (vp->tx_skbuff[entry]) {
-                                       DEV_FREE_SKB(vp->tx_skbuff[entry]);
+                                       dev_kfree_skb_irq(vp->tx_skbuff[entry]);
                                        vp->tx_skbuff[entry] = 0;
                                }
                                /* vp->stats.tx_packets++;  Counted below. */
@@ -1666,19 +1589,21 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        vp->dirty_tx = dirty_tx;
                        if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
                                vp->tx_full = 0;
-                               clear_bit(0, (void*)&dev->tbusy);
-                               mark_bh(NET_BH);
+                               netif_wake_queue (dev);
                        }
                }
+               if (vp->tx_full)
+                       netif_stop_queue (dev);
                if (status & DMADone) {
                        if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
                                outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-                               DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+                               dev_kfree_skb_irq(vp->tx_skb); /* Release the transfered buffer */
                                if (inw(ioaddr + TxFree) > 1536) {
-                                       clear_bit(0, (void*)&dev->tbusy);
-                                       mark_bh(NET_BH);
-                               } else /* Interrupt when FIFO has room for max-sized packet. */
+                                       netif_wake_queue (dev);
+                               } else { /* Interrupt when FIFO has room for max-sized packet. */
                                        outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+                                       netif_stop_queue (dev);
+                               }
                        }
                }
                /* Check for all uncommon interrupts at once. */
@@ -1715,12 +1640,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
                           dev->name, status);
 handler_exit:
-#if defined(__i386__)
-       clear_bit(0, (void*)&dev->interrupt);
-#else
-       dev->interrupt = 0;
-#endif
-       return;
+       spin_unlock (&vp->lock);
 }
 
 static int vortex_rx(struct net_device *dev)
@@ -1891,8 +1811,7 @@ vortex_down(struct net_device *dev)
        struct vortex_private *vp = (struct vortex_private *)dev->priv;
        long ioaddr = dev->base_addr;
 
-       dev->start = 0;
-       dev->tbusy = 1;
+       netif_stop_queue (dev);
 
        del_timer(&vp->timer);
 
@@ -1926,7 +1845,7 @@ vortex_close(struct net_device *dev)
        long ioaddr = dev->base_addr;
        int i;
 
-       if (dev->start)
+       if (test_bit(LINK_STATE_START, &dev->state))
                vortex_down(dev);
 
        if (vortex_debug > 1) {
@@ -1942,14 +1861,14 @@ vortex_close(struct net_device *dev)
        if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
                for (i = 0; i < RX_RING_SIZE; i++)
                        if (vp->rx_skbuff[i]) {
-                               DEV_FREE_SKB(vp->rx_skbuff[i]);
+                               dev_kfree_skb(vp->rx_skbuff[i]);
                                vp->rx_skbuff[i] = 0;
                        }
        }
        if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
                for (i = 0; i < TX_RING_SIZE; i++)
                        if (vp->tx_skbuff[i]) {
-                               DEV_FREE_SKB(vp->tx_skbuff[i]);
+                               dev_kfree_skb(vp->tx_skbuff[i]);
                                vp->tx_skbuff[i] = 0;
                        }
        }
@@ -1964,11 +1883,10 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev)
        struct vortex_private *vp = (struct vortex_private *)dev->priv;
        unsigned long flags;
 
-       if (dev->start) {
-               save_flags(flags);
-               cli();
+       if (test_bit(LINK_STATE_START, &dev->state)) {
+               spin_lock_irqsave (&vp->lock, flags);
                update_stats(dev->base_addr, dev);
-               restore_flags(flags);
+               spin_unlock_irqrestore (&vp->lock, flags);
        }
        return &vp->stats;
 }
@@ -2168,35 +2086,35 @@ static void acpi_set_WOL(struct net_device *dev)
        outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
        outw(RxEnable, ioaddr + EL3_CMD);
        /* Change the power state to D3; RxEnable doesn't take effect. */
-       pcibios_write_config_word(vp->pci_bus, vp->pci_devfn, 0xe0, 0x8103);
+       pci_write_config_word(vp->pdev, 0xe0, 0x8103);
 }
 /* Change from D3 (sleep) to D0 (active).
    Problem: The Cyclone forgets all PCI config info during the transition! */
-static void acpi_wake(int bus, int devfn)
+static void acpi_wake(struct pci_dev *pdev)
 {
        u32 base0, base1, romaddr;
        u16 pci_command, pwr_command;
        u8  pci_latency, pci_cacheline, irq;
 
-       pcibios_read_config_word(bus, devfn, 0xe0, &pwr_command);
+       pci_read_config_word(pdev, 0xe0, &pwr_command);
        if ((pwr_command & 3) == 0)
                return;
-       pcibios_read_config_word( bus, devfn, PCI_COMMAND, &pci_command);
-       pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &base0);
-       pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, &base1);
-       pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr);
-       pcibios_read_config_byte( bus, devfn, PCI_LATENCY_TIMER, &pci_latency);
-       pcibios_read_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, &pci_cacheline);
-       pcibios_read_config_byte( bus, devfn, PCI_INTERRUPT_LINE, &irq);
-
-       pcibios_write_config_word( bus, devfn, 0xe0, 0x0000);
-       pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, base0);
-       pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, base1);
-       pcibios_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, romaddr);
-       pcibios_write_config_byte( bus, devfn, PCI_INTERRUPT_LINE, irq);
-       pcibios_write_config_byte( bus, devfn, PCI_LATENCY_TIMER, pci_latency);
-       pcibios_write_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, pci_cacheline);
-       pcibios_write_config_word( bus, devfn, PCI_COMMAND, pci_command | 5);
+       pci_read_config_word( pdev, PCI_COMMAND, &pci_command);
+       pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base0);
+       pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, &base1);
+       pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &romaddr);
+       pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &pci_latency);
+       pci_read_config_byte( pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+       pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq);
+
+       pci_write_config_word( pdev, 0xe0, 0x0000);
+       pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, base0);
+       pci_write_config_dword(pdev, PCI_BASE_ADDRESS_1, base1);
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS, romaddr);
+       pci_write_config_byte( pdev, PCI_INTERRUPT_LINE, irq);
+       pci_write_config_byte( pdev, PCI_LATENCY_TIMER, pci_latency);
+       pci_write_config_byte( pdev, PCI_CACHE_LINE_SIZE, pci_cacheline);
+       pci_write_config_word( pdev, PCI_COMMAND, pci_command | 5);
 }
 
 #ifdef MODULE
index e95b871043738c24631af4fd1ade8f030b86399e..b819be85616e28b0adca9db4456088fbed5130e6 100644 (file)
@@ -155,6 +155,7 @@ static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
+static void el3_tx_timeout(struct net_device *dev);
 
 static void set_multicast_list(struct net_device *dev);
 
@@ -257,7 +258,10 @@ static dev_link_t *tc589_attach(void)
     dev->init = &tc589_init;
     dev->open = &el3_open;
     dev->stop = &el3_close;
-    dev->tbusy = 1;
+    dev->tx_timeout = el3_tx_timeout;
+    dev->watchdog_timeo = TX_TIMEOUT;
+    
+    netif_start_queue (dev);
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -399,7 +403,7 @@ static void tc589_config(dev_link_t *link)
        
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
-    dev->tbusy = 0;
+    netif_start_queue (dev);
     if (register_netdev(dev) != 0) {
        printk(KERN_NOTICE "3c589_cs: register_netdev() failed\n");
        goto failed;
@@ -508,7 +512,7 @@ static int tc589_event(event_t event, int priority,
     case CS_EVENT_CARD_REMOVAL:
        link->state &= ~DEV_PRESENT;
        if (link->state & DEV_CONFIG) {
-           dev->tbusy = 1; dev->start = 0;
+           netif_stop_queue (dev);
            link->release.expires = jiffies + HZ/20;
            add_timer(&link->release);
        }
@@ -523,7 +527,7 @@ static int tc589_event(event_t event, int priority,
     case CS_EVENT_RESET_PHYSICAL:
        if (link->state & DEV_CONFIG) {
            if (link->open) {
-               dev->tbusy = 1; dev->start = 0;
+               netif_stop_queue (dev);
            }
            CardServices(ReleaseConfiguration, link->handle);
        }
@@ -536,7 +540,7 @@ static int tc589_event(event_t event, int priority,
            CardServices(RequestConfiguration, link->handle, &link->conf);
            if (link->open) {
                tc589_reset(dev);
-               dev->tbusy = 0; dev->start = 1;
+               netif_start_queue (dev);
            }
        }
        break;
@@ -683,7 +687,7 @@ static int el3_open(struct net_device *dev)
 
     link->open++;
     MOD_INC_USE_COUNT;
-    dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+    netif_start_queue (dev);
     
     tc589_reset(dev);
     lp->media.function = &media_check;
@@ -709,7 +713,7 @@ static void el3_tx_timeout(struct net_device *dev)
     /* Issue TX_RESET and TX_START commands. */
     wait_for_completion(dev, TxReset);
     outw(TxEnable, ioaddr + EL3_CMD);
-    dev->tbusy = 0;
+    netif_start_queue (dev);
 }
 
 static void pop_tx_status(struct net_device *dev)
@@ -739,22 +743,12 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     ioaddr_t ioaddr = dev->base_addr;
 
-    /* Transmitter timeout, serious problems. */
-    if (dev->tbusy) {
-       if (jiffies - dev->trans_start < TX_TIMEOUT)
-           return 1;
-       el3_tx_timeout(dev);
-    }
-
     DEBUG(3, "%s: el3_start_xmit(length = %ld) called, "
          "status %4.4x.\n", dev->name, (long)skb->len,
          inw(ioaddr + EL3_STATUS));
 
-    /* Avoid timer-based retransmission conflicts. */
-    if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-       printk(KERN_NOTICE "%s: transmitter access conflict.\n",
-              dev->name);
-    else {
+    netif_stop_queue (dev);
+    if (1) {
        struct el3_private *lp = (struct el3_private *)dev->priv;
        lp->stats.tx_bytes += skb->len;
        /* Put out the doubleword header... */
@@ -765,7 +759,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        
        dev->trans_start = jiffies;
        if (inw(ioaddr + TX_FREE) > 1536) {
-           dev->tbusy = 0;
+           netif_start_queue (dev);
        } else
            /* Interrupt us when the FIFO has room for max-sized packet. */
            outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
@@ -785,7 +779,7 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     ioaddr_t ioaddr, status;
     int i = 0;
     
-    if ((lp == NULL) || !dev->start)
+    if (lp == NULL)
        return;
     ioaddr = dev->base_addr;
 
@@ -802,10 +796,12 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     
     while ((status = inw(ioaddr + EL3_STATUS)) &
        (IntLatch | RxComplete | StatsFull)) {
+#if 0
        if ((dev->start == 0) || ((status & 0xe000) != 0x2000)) {
            DEBUG(1, "%s: interrupt from dead card\n", dev->name);
            break;
        }
+#endif
        
        if (status & RxComplete)
            el3_rx(dev);
@@ -814,8 +810,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
            DEBUG(3, "    TX room bit was handled.\n");
            /* There's room in the FIFO for a full-sized packet. */
            outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-           dev->tbusy = 0;
-           mark_bh(NET_BH);
+           netif_wake_queue (dev);
+       } else {
+           netif_stop_queue (dev);
        }
        
        if (status & TxComplete)
@@ -879,7 +876,9 @@ static void media_check(u_long arg)
     u_short media, errs;
     u_long flags;
 
+#if 0
     if (dev->start == 0) goto reschedule;
+#endif
 
     EL3WINDOW(1);
     /* Check for pending interrupt with expired latency timer: with
@@ -1093,6 +1092,8 @@ static int el3_close(struct net_device *dev)
     ioaddr_t ioaddr = dev->base_addr;
     
     DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
+    
+    netif_stop_queue (dev);
 
     if (DEV_OK(link)) {
        /* Turn off statistics ASAP.  We update lp->stats below. */
@@ -1122,7 +1123,6 @@ static int el3_close(struct net_device *dev)
     }
 
     link->open--;
-    dev->start = 0;
     del_timer(&lp->media);
     if (link->state & DEV_STALE_CONFIG) {
        link->release.expires = jiffies + HZ/20;
index 3dbb9923fc3b81e559aa266742e8bc52dc06e5ff..1e96e668c881f7047e78577f5f06d5d2b164d6dc 100644 (file)
@@ -231,8 +231,7 @@ static dev_link_t *awc_attach(void)
        dev->init = &awc_pcmcia_init;
        dev->open = &awc_pcmcia_open;
        dev->stop = &awc_pcmcia_close;
-       dev->tbusy = 1;
-       dev->start  = 0;
+       netif_start_queue (dev);
        
        link->priv = dev;
 #if CS_RELEASE_CODE > 0x2911
@@ -567,7 +566,7 @@ static int awc_event(event_t event, int priority,
        case CS_EVENT_CARD_REMOVAL:
                link->state &= ~DEV_PRESENT;
                if (link->state & DEV_CONFIG) {
-                       dev->tbusy = 1; dev->start = 0;
+                       netif_stop_queue (dev);
                        link->release.expires = RUN_AT( HZ/20 );
                        add_timer(&link->release);
                }
@@ -582,7 +581,7 @@ static int awc_event(event_t event, int priority,
        case CS_EVENT_RESET_PHYSICAL:
                if (link->state & DEV_CONFIG) {
                        if (link->open) {
-                               dev->tbusy = 1; dev->start = 0;
+                               netif_stop_queue (dev);
                        }
                        CardServices(ReleaseConfiguration, link->handle);
                }
@@ -595,7 +594,7 @@ static int awc_event(event_t event, int priority,
                        CardServices(RequestConfiguration, link->handle, &link->conf);
                        if (link->open) {
                                // awc_reset(dev);
-                               dev->tbusy = 0; dev->start = 1;
+                               netif_start_queue (dev);
                        }
                }
                break;
index 74928fd27576b6bc3263baceeb4fa018e9ff249a..dd99d84acef9b4932de075c9e146b4700368bd56 100644 (file)
@@ -151,7 +151,7 @@ static const unsigned int txConfEUD    = 0x10; /* Enable Uni-Data packets */
 static const unsigned int txConfKey    = 0x02; /* Scramble data packets */
 static const unsigned int txConfLoop   = 0x01; /* Loopback mode */
 
-/*static int netwave_debug = 0;*/
+static int netwave_debug = 0;
 
 /*
    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
@@ -223,6 +223,7 @@ static void netwave_reset(struct net_device *dev);
 static int netwave_open(struct net_device *dev);  /* Open the device */
 static int netwave_close(struct net_device *dev); /* Close the device */
 static int netwave_config(struct net_device *dev, struct ifmap *map);
+static void netwave_tx_timeout (struct net_device *dev);
 
 /* Packet transmission and Packet reception */
 static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev);
@@ -308,6 +309,7 @@ typedef struct netwave_private {
     u_char     *ramBase;
     int        timeoutCounter;
     int        lastExec;
+    spinlock_t lock;
     struct timer_list      watchdog;   /* To avoid blocking state */
     struct site_survey     nss;
     struct enet_statistics stats;
@@ -454,6 +456,7 @@ static dev_link_t *netwave_attach(void)
     priv = kmalloc(sizeof(*priv), GFP_KERNEL);
     if (!priv) return NULL;
     memset(priv, 0, sizeof(*priv));
+    priv->lock = SPIN_LOCK_UNLOCKED;
     link = &priv->link; dev = &priv->dev;
     link->priv = dev->priv = priv;
     link->release.function = &netwave_release;
@@ -503,7 +506,9 @@ static dev_link_t *netwave_attach(void)
     dev->init = &netwave_init;
     dev->open = &netwave_open;
     dev->stop = &netwave_close;
-    dev->tbusy = 1;
+    dev->tx_timeout = netwave_tx_timeout;
+    dev->watchdog_timeo = TX_TIMEOUT;
+    netif_start_queue (dev);
     link->irq.Instance = dev;
     
     /* Register with Card Services */
@@ -835,7 +840,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
     struct net_device *dev = &priv->dev;
     tuple_t tuple;
     cisparse_t parse;
-    int i, j, last_ret, last_fn;
+    int i=0, j, last_ret, last_fn;
     u_char buf[64];
     win_req_t req;
     memreq_t mem;
@@ -910,7 +915,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
     
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
-    dev->tbusy = 0;
+    netif_start_queue (dev);
     if (register_netdev(dev) != 0) {
        printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
        goto failed;
@@ -1014,7 +1019,7 @@ static int netwave_event(event_t event, int priority,
     case CS_EVENT_CARD_REMOVAL:
        link->state &= ~DEV_PRESENT;
        if (link->state & DEV_CONFIG) {
-           dev->tbusy = 1; dev->start = 0;
+           netif_stop_queue (dev);
            link->release.expires = jiffies + 5;
            add_timer(&link->release);
        }
@@ -1029,7 +1034,7 @@ static int netwave_event(event_t event, int priority,
     case CS_EVENT_RESET_PHYSICAL:
        if (link->state & DEV_CONFIG) {
            if (link->open) {
-               dev->tbusy = 1; dev->start = 0;
+               netif_stop_queue (dev);
            }
            CardServices(ReleaseConfiguration, link->handle);
        }
@@ -1042,7 +1047,7 @@ static int netwave_event(event_t event, int priority,
            CardServices(RequestConfiguration, link->handle, &link->conf);
            if (link->open) {
                netwave_reset(dev);
-               dev->tbusy = 0; dev->start = 1;
+               netif_start_queue (dev);
            }
        }
        break;
@@ -1229,6 +1234,18 @@ static int netwave_hw_xmit(unsigned char* data, int len,
     return 0;
 }
 
+
+static void netwave_tx_timeout (struct net_device *dev)
+{
+       if (netwave_debug > 0)
+               printk (KERN_DEBUG "%s timed out.\n", dev->name);
+       netwave_reset (dev);
+       dev->trans_start = jiffies;
+       netif_start_queue (dev);
+}
+
+
+
 static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
        /* This flag indicate that the hardware can't perform a transmission.
         * Theoritically, NET3 check it before sending a packet to the driver,
@@ -1236,29 +1253,6 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
         * As the watchdog will abort too long transmissions, we are quite safe...
         */
 
-    if (dev->tbusy) {
-       /* Handled by watchdog */
-       return 1;
-               
-       /* If we get here, some higher level has decided we are broken.
-          There should really be a 'kick me' function call instead.
-          */
-       /*int tickssofar = jiffies - dev->trans_start;*/
-       /* printk("xmit called with busy. tickssofar %d\n", tickssofar); */
-       /*if (tickssofar < TX_TIMEOUT) 
-         return 1;
-         */
-       /* Should also detect if the kernel tries to xmit
-        * on a stopped card. 
-        */
-       
-       /*if (netwave_debug > 0)
-         printk(KERN_DEBUG "%s timed out.\n", dev->name);
-         netwave_reset(dev); 
-         dev->trans_start = jiffies;
-         dev->tbusy = 0;*/
-    }
-
     /* Sending a NULL skb means some higher layer thinks we've missed an
      * tx-done interrupt. Caution: dev_tint() handles the cli()/sti()
      * itself. 
@@ -1268,15 +1262,14 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
      * better be done with atomic_swap(1, dev->tbusy, but set_bit()
      * works as well 
      */
-    if ( test_and_set_bit(0, (void*)&dev->tbusy) != 0) 
-       printk("%s: Transmitter access conflict.\n", dev->name);
-    else {
+    netif_stop_queue (dev);
+    if (1) {
        short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        unsigned char* buf = skb->data;
        
        if (netwave_hw_xmit( buf, length, dev) == 1) {
            /* Some error, let's make them call us another time? */
-           dev->tbusy = 0;
+           netif_start_queue (dev);
        }
        dev->trans_start = jiffies;
     }
@@ -1303,14 +1296,10 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
     dev_link_t *link = &priv->link;
     int i;
     
-    if ((dev == NULL) | (!dev->start))
+    if (dev == NULL)
        return;
     
-    if (dev->interrupt) {
-       printk("%s: re-entering the interrupt handler.\n", dev->name);
-       return;
-    }
-    dev->interrupt = 1;
+    spin_lock (&priv->lock);
     
     iobase = dev->base_addr;
     ramBase = priv->ramBase;
@@ -1409,8 +1398,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
            /* If watchdog was activated, kill it ! */
            del_timer(&priv->watchdog);
 
-           dev->tbusy = 0;
-           mark_bh(NET_BH);
+           netif_wake_queue (dev);
        }
        /* TxBA, this would trigger on all error packets received */
        /* if (status & 0x01) {
@@ -1420,8 +1408,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
           */
     }
     /* done.. */
-    dev->interrupt = 0;
-    return;
+    spin_unlock (&priv->lock);
 } /* netwave_interrupt */
 
 /*
@@ -1444,7 +1431,7 @@ static void netwave_watchdog(u_long a) {
     netwave_reset(dev); 
        
     /* We are not waiting anymore... */
-    dev->tbusy = 0;
+    netif_start_queue (dev);
        
 } /* netwave_watchdog */
 
@@ -1584,7 +1571,7 @@ static int netwave_open(struct net_device *dev) {
     link->open++;
     MOD_INC_USE_COUNT;
        
-    dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+    netif_start_queue (dev);
     netwave_reset(dev);
        
     return 0;
@@ -1596,11 +1583,12 @@ static int netwave_close(struct net_device *dev) {
 
     DEBUG(1, "netwave_close: finishing.\n");
 
+    netif_stop_queue (dev);
+
     /* If watchdog was activated, kill it ! */
     del_timer(&priv->watchdog);
        
     link->open--;
-    dev->start = 0;
     if (link->state & DEV_STALE_CONFIG) {
        link->release.expires = jiffies + 5;
        link->state |= DEV_RELEASE_PENDING;
index 2fb3772a55a48700d145b523b3210d4c6ec0393a..a3c22cc7a4b141e423cbd2ffd0f8e77c19e4f1e3 100644 (file)
@@ -307,6 +307,10 @@ four transmit and 12 receive frames at a time.
 #undef MACE_IMR_DEFAULT
 #define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */
 
+#define TX_TIMEOUT (5*HZ)
+
+
+
 /* ----------------------------------------------------------------------------
 Type Definitions
 ---------------------------------------------------------------------------- */
@@ -360,6 +364,7 @@ typedef struct _mace_private {
     dev_link_t link;
     struct net_device dev;
     dev_node_t node;
+    spinlock_t lock;
     struct net_device_stats linux_stats; /* Linux statistics counters */
     mace_statistics mace_stats; /* MACE chip statistics counters */
 
@@ -432,6 +437,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static struct net_device_stats *mace_get_stats(struct net_device *dev);
 static int mace_rx(struct net_device *dev, unsigned char RxCnt);
 static void restore_multicast_list(struct net_device *dev);
+static void mace_tx_timeout (struct net_device *dev);
 
 static void set_multicast_list(struct net_device *dev);
 
@@ -498,6 +504,8 @@ static dev_link_t *nmclan_attach(void)
     lp = kmalloc(sizeof(*lp), GFP_KERNEL);
     if (!lp) return NULL;
     memset(lp, 0, sizeof(*lp));
+    
+    lp->lock = SPIN_LOCK_UNLOCKED;
     link = &lp->link; dev = &lp->dev;
     link->priv = dev->priv = link->irq.Instance = lp;
 
@@ -531,7 +539,10 @@ static dev_link_t *nmclan_attach(void)
     dev->init = &nmclan_init;
     dev->open = &mace_open;
     dev->stop = &mace_close;
-    dev->tbusy = 0xFF;
+    dev->tx_timeout = mace_tx_timeout;
+    dev->watchdog_timeo = TX_TIMEOUT;
+
+    netif_start_queue (dev);
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -752,7 +763,7 @@ static void nmclan_config(dev_link_t *link)
   CS_CHECK(RequestConfiguration, handle, &link->conf);
   dev->irq = link->irq.AssignedIRQ;
   dev->base_addr = link->io.BasePort1;
-  dev->tbusy = 0;
+  netif_start_queue (dev);
   i = register_netdev(dev);
   if (i != 0) {
     printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
@@ -859,7 +870,7 @@ static int nmclan_event(event_t event, int priority,
     case CS_EVENT_CARD_REMOVAL:
       link->state &= ~DEV_PRESENT;
       if (link->state & DEV_CONFIG) {
-       dev->tbusy = 0xFF; dev->start = 0;
+       netif_stop_queue (dev);
        link->release.expires = jiffies + HZ/20;
        add_timer(&link->release);
       }
@@ -874,7 +885,7 @@ static int nmclan_event(event_t event, int priority,
     case CS_EVENT_RESET_PHYSICAL:
       if (link->state & DEV_CONFIG) {
        if (link->open) {
-         dev->tbusy = 0xFF; dev->start = 0;
+         netif_stop_queue (dev);
        }
        CardServices(ReleaseConfiguration, link->handle);
       }
@@ -886,9 +897,8 @@ static int nmclan_event(event_t event, int priority,
       if (link->state & DEV_CONFIG) {
        CardServices(RequestConfiguration, link->handle, &link->conf);
        if (link->open) {
-         dev->tbusy = 0;
-         dev->start = 1;
          nmclan_reset(dev);
+         netif_start_queue (dev);
        }
       }
       break;
@@ -987,10 +997,7 @@ static int mace_open(struct net_device *dev)
 
   MACEBANK(0);
 
-  dev->interrupt = 0;
-  dev->tbusy = 0;
-  dev->start = 1;
-
+  netif_start_queue (dev);
   nmclan_reset(dev);
 
   return 0; /* Always succeed */
@@ -1007,12 +1014,13 @@ static int mace_close(struct net_device *dev)
   dev_link_t *link = &lp->link;
 
   DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
+  
+  netif_stop_queue (dev);
 
   /* Mask off all interrupts from the MACE chip. */
   outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR);
 
   link->open--;
-  dev->start = 0;
   if (link->state & DEV_STALE_CONFIG) {
     link->release.expires = jiffies + HZ/20;
     link->state |= DEV_RELEASE_PENDING;
@@ -1024,6 +1032,24 @@ static int mace_close(struct net_device *dev)
   return 0;
 } /* mace_close */
 
+
+static void mace_tx_timeout (struct net_device *dev)
+{
+       mace_private *lp = (mace_private *)dev->priv;
+       dev_link_t *link = &lp->link;
+
+       printk (KERN_NOTICE "%s: transmit timed out -- ", dev->name);
+#if RESET_ON_TIMEOUT
+       printk ("resetting card\n");
+       CardServices (ResetCard, link->handle);
+#else                          /* #if RESET_ON_TIMEOUT */
+       printk ("NOT resetting card\n");
+#endif                         /* #if RESET_ON_TIMEOUT */
+       dev->trans_start = jiffies;
+       netif_start_queue (dev);
+}
+
+
 /* ----------------------------------------------------------------------------
 mace_start_xmit
        This routine begins the packet transmit function.  When completed,
@@ -1038,39 +1064,11 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
   mace_private *lp = (mace_private *)dev->priv;
   ioaddr_t ioaddr = dev->base_addr;
-  dev_link_t *link = &lp->link;
-
-#if TIMEOUT_TX
-  /* Transmitter timeout. */
-  if (dev->tbusy) {
-    int tickssofar = jiffies - dev->trans_start;
-
-    if (tickssofar < (HZ/5))
-      return 1;
-    printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
-#if RESET_ON_TIMEOUT
-    printk("resetting card\n");
-    CardServices(ResetCard, link->handle);
-#else /* #if RESET_ON_TIMEOUT */
-    printk("NOT resetting card\n");
-#endif /* #if RESET_ON_TIMEOUT */
-    dev->trans_start = jiffies;
-    return 1;
-  }
-#else /* #if TIMEOUT_TX */
-  if (dev->tbusy)
-    return 1;
-#endif /* #if TIMEOUT_TX */
 
   DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n",
        dev->name, (long)skb->len);
 
-  /* Avoid timer-based retransmission conflicts. */
-  if (test_and_set_bit(TBUSY_UNSPECIFIED, (void*)&dev->tbusy) != 0) {
-    printk(KERN_NOTICE "%s: transmitter access conflict.\n",
-          dev->name);
-    return 1;
-  }
+  netif_stop_queue (dev);
 
 #if (!TX_INTERRUPTABLE)
   /* Disable MACE TX interrupts. */
@@ -1085,11 +1083,9 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
        the upper layers.  The interrupt handler is guaranteed never to
        service a transmit interrupt while we are in here.
     */
-    set_bit(TBUSY_PARTIAL_TX_FRAME, (void*)&dev->tbusy);
 
     lp->linux_stats.tx_bytes += skb->len;
     lp->tx_free_frames--;
-    set_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy);
 
     /* WARNING: Write the _exact_ number of bytes written in the header! */
     /* Put out the word header [must be an outw()] . . . */
@@ -1105,11 +1101,10 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
     if (lp->tx_free_frames > 0) {
 #if MULTI_TX
-      clear_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy);
+      netif_start_queue (dev);
 #endif /* #if MULTI_TX */
     }
 
-    clear_bit(TBUSY_PARTIAL_TX_FRAME, (void*)&dev->tbusy);
   }
 
 #if (!TX_INTERRUPTABLE)
@@ -1140,8 +1135,10 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
          irq);
     return;
   }
+  
+  spin_lock (&lp->lock);
 
-  if (dev->interrupt || lp->tx_irq_disabled) {
+  if (lp->tx_irq_disabled) {
     printk(
       (lp->tx_irq_disabled?
        KERN_NOTICE "%s: Interrupt with tx_irq_disabled "
@@ -1155,12 +1152,6 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     /* WARNING: MACE_IR has been read! */
     return;
   }
-  dev->interrupt = 1;
-
-  if (dev->start == 0) {
-    DEBUG(2, "%s: interrupt from dead card\n", dev->name);
-    goto exception;
-  }
 
   do {
     /* WARNING: MACE_IR is a READ/CLEAR port! */
@@ -1230,8 +1221,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
       lp->linux_stats.tx_packets++;
       lp->tx_free_frames++;
-      clear_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy);
-      mark_bh(NET_BH);
+      netif_wake_queue (dev);
     } /* if (status & MACE_IR_XMTINT) */
 
     if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) {
@@ -1266,8 +1256,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
   } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));
 
 exception:
-  dev->interrupt = 0;
-  return;
+  spin_unlock (&lp->lock);
 } /* mace_interrupt */
 
 /* ----------------------------------------------------------------------------
index 4a58706f6efc92aba3a5b47a30a37d51bc2335a7..897e93d03fcbe3fb8e19c78e6866404e70c991c4 100644 (file)
@@ -125,6 +125,8 @@ struct smc_private {
     u_short                    media_status;
     u_short                    fast_poll;
     u_long                     last_rx;
+    
+    spinlock_t                 lock;
 };
 
 /* Special definitions for Megahertz multifunction cards */
@@ -281,6 +283,7 @@ static void smc91c92_release(u_long arg);
 static int smc91c92_event(event_t event, int priority,
                          event_callback_args_t *args);
 
+static void smc91c92_tx_timeout (struct net_device *dev);
 static int smc91c92_open(struct net_device *dev);
 static int smc91c92_close(struct net_device *dev);
 static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -379,9 +382,12 @@ static dev_link_t *smc91c92_attach(void)
     dev->init = &smc91c92_init;
     dev->open = &smc91c92_open;
     dev->stop = &smc91c92_close;
-    dev->tbusy = 1;
+    dev->tx_timeout = smc91c92_tx_timeout;
+    dev->watchdog_timeo = TX_TIMEOUT;
     dev->priv = link->priv = link->irq.Instance = smc;
     
+    netif_start_queue (dev);
+    
     /* Register with Card Services */
     link->next = dev_list;
     dev_list = link;
@@ -663,7 +669,7 @@ static int mot_setup(dev_link_t *link) {
     struct smc_private *smc = link->priv;
     struct net_device *dev = &smc->dev;
     ioaddr_t ioaddr = dev->base_addr;
-    int i, wait, loop;
+    int i, wait=0, loop;
     unsigned int addr;
 
     /* Read Ethernet address from Serial EEPROM */
@@ -775,7 +781,7 @@ static int osi_config(dev_link_t *link)
     struct smc_private *smc = link->priv;
     struct net_device *dev = &smc->dev;
     static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
-    int i, j;
+    int i=0, j;
     
     link->conf.Attributes |= CONF_ENABLE_SPKR;
     link->conf.Status = CCSR_AUDIO_ENA;
@@ -977,7 +983,7 @@ static void smc91c92_config(dev_link_t *link)
        dev->if_port = if_port;
     else
        printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
-    dev->tbusy = 0;
+    netif_start_queue (dev);
     
     if (register_netdev(dev) != 0) {
        printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
@@ -1106,8 +1112,7 @@ static int smc91c92_event(event_t event, int priority,
     case CS_EVENT_CARD_REMOVAL:
        link->state &= ~DEV_PRESENT;
        if (link->state & DEV_CONFIG) {
-           dev->tbusy = 1;
-           dev->start = 0;
+           netif_stop_queue (dev);
            link->release.expires = jiffies + HZ/20;
            link->state |= DEV_RELEASE_PENDING;
            add_timer(&link->release);
@@ -1123,7 +1128,7 @@ static int smc91c92_event(event_t event, int priority,
     case CS_EVENT_RESET_PHYSICAL:
        if (link->state & DEV_CONFIG) {
            if (link->open) {
-               dev->tbusy = 1; dev->start = 0;
+               netif_stop_queue (dev);
            }
            CardServices(ReleaseConfiguration, link->handle);
        }
@@ -1147,7 +1152,7 @@ static int smc91c92_event(event_t event, int priority,
            }
            if (link->open) {
                smc_reset(dev);
-               dev->tbusy = 0; dev->start = 1;
+               netif_start_queue (dev);
            }
        }
        break;
@@ -1201,7 +1206,7 @@ static int smc91c92_open(struct net_device *dev)
     link->open++;
     MOD_INC_USE_COUNT;
     
-    dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+    netif_start_queue (dev);
     smc->saved_skb = 0;
     smc->packets_waiting = 0;
     
@@ -1225,8 +1230,7 @@ static int smc91c92_close(struct net_device *dev)
     DEBUG(0, "%s: smc91c92_close(), status %4.4x.\n",
          dev->name, inw(ioaddr + BANK_SELECT));
     
-    dev->tbusy = 1;
-    dev->start = 0;
+    netif_stop_queue (dev);
     
     /* Shut off all interrupts, and turn off the Tx and Rx sections.
        Don't bother to check for chip present. */
@@ -1240,7 +1244,7 @@ static int smc91c92_close(struct net_device *dev)
     SMC_SELECT_BANK( 1 );
     outw(CTL_POWERDOWN, ioaddr + CONTROL  );
     
-    link->open--; dev->start = 0;
+    link->open--;
     del_timer(&smc->media);
     if (link->state & DEV_STALE_CONFIG) {
        link->release.expires = jiffies + HZ/20;
@@ -1281,7 +1285,7 @@ static void smc_hardware_send_packet( struct net_device * dev )
               " failed, status %#2.2x.\n", dev->name, packet_no);
        dev_kfree_skb (skb);
        smc->saved_skb = NULL;
-       dev->tbusy = 0;
+       netif_start_queue (dev);
        return;
     }
     
@@ -1329,10 +1333,28 @@ static void smc_hardware_send_packet( struct net_device * dev )
     smc->saved_skb = NULL;
     dev_kfree_skb (skb);
     dev->trans_start = jiffies;
-    dev->tbusy = 0;
+    netif_start_queue (dev);
     return;
 }
 
+/*====================================================================*/
+
+static void smc91c92_tx_timeout (struct net_device *dev)
+{
+       struct smc_private *smc = dev->priv;
+       ioaddr_t ioaddr = dev->base_addr;
+
+       printk (KERN_NOTICE "%s: SMC91c92 transmit timed out, "
+               "Tx_status %2.2x status %4.4x.\n",
+               dev->name, inw (ioaddr) & 0xff, inw (ioaddr + 2));
+       smc->stats.tx_errors++;
+       smc_reset (dev);
+       dev->trans_start = jiffies;
+       smc->saved_skb = NULL;
+       netif_start_queue (dev);
+}
+
+
 /*====================================================================*/
 
 static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1342,29 +1364,10 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
     unsigned short num_pages;
     short time_out, ir;
     
-    /* Transmitter timeout, serious problems. */
-    if (dev->tbusy) {
-       int tickssofar = jiffies - dev->trans_start;
-       if (tickssofar < TX_TIMEOUT)
-           return 1;
-       printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
-              "Tx_status %2.2x status %4.4x.\n",
-              dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
-       smc->stats.tx_errors++;
-       smc_reset(dev);
-       dev->trans_start = jiffies;
-       dev->tbusy = 0;
-       smc->saved_skb = NULL;
-    }
-
     DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called,"
          " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
-    
-    /* Avoid timer-based retransmission conflicts. */
-    if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-       printk(KERN_ERR "%s: transmitter access conflict.\n", dev->name);
-       return 1;
-    }
+
+    netif_stop_queue (dev);
     
     if ( smc->saved_skb) {
        /* THIS SHOULD NEVER HAPPEN. */
@@ -1500,18 +1503,13 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     u_short saved_bank, saved_pointer, mask, status;
     char bogus_cnt = INTR_WORK;                /* Work we are willing to do. */
 
-    if ((smc == NULL) || !dev->start)
+    if (smc == NULL)
        return;
     ioaddr = dev->base_addr;
     
-#ifdef PCMCIA_DEBUG
-    if (dev->interrupt) {
-       printk(KERN_ERR "%s: re-entering the interrupt handler.\n",
-              dev->name);
-       return;
-    }
-    dev->interrupt = 1;
+    spin_lock (&smc->lock);
 
+#ifdef PCMCIA_DEBUG
     DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
          irq, ioaddr);
 #endif
@@ -1569,7 +1567,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
            mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
            
            /* and let the card send more packets to me */
-           mark_bh( NET_BH );
+           netif_wake_queue (dev);
        }
        if (status & IM_RX_OVRN_INT) {
            smc->stats.rx_errors++;
@@ -1588,8 +1586,9 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     outw(saved_pointer, ioaddr + POINTER);
     SMC_SELECT_BANK( saved_bank );
 
+    spin_unlock (&smc->lock);
+
 #ifdef PCMCIA_DEBUG
-    dev->interrupt = 0;
     DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);
 #endif
 
@@ -1913,8 +1912,10 @@ static void media_check(u_long arg)
     ioaddr_t ioaddr = dev->base_addr;
     u_short i, media, saved_bank;
 
+#if 0
     if (dev->start == 0) goto reschedule;
-    
+#endif
+
     saved_bank = inw(ioaddr + BANK_SELECT);
     SMC_SELECT_BANK(2);
     i = inw(ioaddr + INTERRUPT);
index ee49f58ebecc122da43f79415fc848ee1f661357..25ffb1c2c3ed8dbda908583c0d17ee54d5e9f735 100644 (file)
@@ -128,7 +128,6 @@ static int csr0 = 0x00A00000 | 0x4800;
 /* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
    This is only in the support-all-kernels source code. */
 
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
 MODULE_PARM(debug, "i");
@@ -138,13 +137,11 @@ MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(csr0, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
 
 #define RUN_AT(x) (jiffies + (x))
 
 #define NETSTATS_VER2
 #define PCI_SUPPORT_VER3
-#define dev_free_skb(skb) dev_kfree_skb(skb);
 
 #define tulip_debug debug
 #ifdef TULIP_DEBUG
@@ -438,7 +435,8 @@ struct tulip_private {
        struct mediatable *mtable;
        int cur_index;                                          /* Current media index. */
        int saved_if_port;
-       unsigned char pci_bus, pci_devfn;
+       struct pci_dev *pdev;
+       spinlock_t lock;
        int pad0, pad1;                                         /* Used for 8-byte alignment */
 };
 
@@ -515,9 +513,9 @@ static void outl_CSR6 (u32 newcsr6, long ioaddr, int chip_idx)
     restore_flags(flags);
 }
 \f
-static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
-                                                                  struct net_device *dev, long ioaddr, int irq,
-                                                                  int chip_idx, int board_idx)
+static struct net_device *tulip_probe1(struct pci_dev *pdev,
+                                      struct net_device *dev, long ioaddr, int irq,
+                                      int chip_idx, int board_idx)
 {
        static int did_version = 0;                     /* Already printed version info. */
        struct tulip_private *tp;
@@ -534,11 +532,11 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
 
        dev = init_etherdev(dev, 0);
 
-       pcibios_read_config_byte(pci_bus, pci_devfn, PCI_REVISION_ID, &chip_rev);
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
        /* Bring the 21143 out of sleep mode.
           Caution: Snooze mode does not work with some boards! */
        if (tulip_tbl[chip_idx].flags & HAS_ACPI)
-               pcibios_write_config_dword(pci_bus, pci_devfn, 0x40, 0x00000000);
+               pci_write_config_dword(pdev, 0x40, 0x00000000);
 
        printk(KERN_INFO "%s: %s rev %d at %#3lx,",
                   dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
@@ -691,8 +689,8 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
        memset(tp, 0, sizeof(*tp));
        dev->priv = tp;
 
-       tp->pci_bus = pci_bus;
-       tp->pci_devfn = pci_devfn;
+       tp->lock = SPIN_LOCK_UNLOCKED;
+       tp->pdev = pdev;
        tp->chip_id = chip_idx;
        tp->revision = chip_rev;
        tp->csr0 = csr0;
@@ -807,6 +805,8 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
 #ifdef HAVE_MULTICAST
        dev->set_multicast_list = &set_rx_mode;
 #endif
+       dev->tx_timeout = tulip_tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
 
        /* Reset the xcvr interface and turn on heartbeat. */
        switch (chip_idx) {
@@ -1302,7 +1302,7 @@ tulip_up(struct net_device *dev)
        udelay(2);
 
        if (tulip_tbl[tp->chip_id].flags & HAS_ACPI)
-               pcibios_write_config_dword(tp->pci_bus, tp->pci_devfn, 0x40, 0x00000000);
+               pci_write_config_dword(tp->pdev, 0x40, 0x00000000);
 
        /* Clear the tx ring */
        for (i = 0; i < TX_RING_SIZE; i++) {
@@ -1461,15 +1461,13 @@ media_picked:
        outl_CSR6(tp->csr6, ioaddr, tp->chip_id);
        outl_CSR6(tp->csr6 | 0x2000, ioaddr, tp->chip_id);
 
-       dev->tbusy = 0;
-       tp->interrupt = 0;
-       dev->start = 1;
-
        /* Enable interrupts by setting the interrupt mask. */
        outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
        outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
        outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
        outl(0, ioaddr + CSR2);         /* Rx poll demand */
+       
+       netif_start_queue (dev);
 
        if (tulip_debug > 2) {
                printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
@@ -2413,15 +2411,6 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int entry;
        u32 flag;
 
-       /* Block a timer-based transmit from overlapping.  This could better be
-          done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-               if (jiffies - dev->trans_start < TX_TIMEOUT)
-                       return 1;
-               tulip_tx_timeout(dev);
-               return 1;
-       }
-
        /* Caution: the write order is important here, set the base address
           with the "ownership" bits last. */
 
@@ -2454,8 +2443,10 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tp->tx_ring[entry].length = skb->len | flag;
        tp->tx_ring[entry].status = DescOwned;  /* Pass ownership to the chip. */
        tp->cur_tx++;
-       if ( ! tp->tx_full)
-               clear_bit(0, (void*)&dev->tbusy);
+       if (tp->tx_full)
+               netif_stop_queue (dev);
+       else
+               netif_wake_queue (dev);
 
        /* Trigger an immediate transmit demand. */
        outl(0, dev->base_addr + CSR1);
@@ -2474,21 +2465,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
        long ioaddr = dev->base_addr;
        int csr5, work_budget = max_interrupt_work;
 
-#if defined(__i386__) && defined(SMP_CHECK)
-       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-               printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by "
-                          "processor %d.\n",
-                          dev->name, smp_processor_id());
-               dev->interrupt = 0;
-               return;
-       }
-#else
-       if (dev->interrupt) {
-               printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-               return;
-       }
-       dev->interrupt = 1;
-#endif
+       spin_lock (&tp->lock);
 
        do {
                csr5 = inl(ioaddr + CSR5);
@@ -2549,7 +2526,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                }
 
                                /* Free the original skb. */
-                               dev_free_skb(tp->tx_skbuff[entry]);
+                               dev_kfree_skb_irq(tp->tx_skbuff[entry]);
                                tp->tx_skbuff[entry] = 0;
                        }
 
@@ -2561,13 +2538,15 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        }
 #endif
 
-                       if (tp->tx_full && dev->tbusy
-                               && tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2) {
-                               /* The ring is no longer full, clear tbusy. */
+                       if (tp->tx_full && 
+                           tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2)
+                               /* The ring is no longer full */
                                tp->tx_full = 0;
-                               dev->tbusy = 0;
-                               mark_bh(NET_BH);
-                       }
+                       
+                       if (tp->tx_full)
+                               netif_stop_queue (dev);
+                       else
+                               netif_wake_queue (dev);
 
                        tp->dirty_tx = dirty_tx;
                        if (csr5 & TxDied) {
@@ -2630,12 +2609,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
                           dev->name, inl(ioaddr + CSR5));
 
-#if defined(__i386__)
-       clear_bit(0, (void*)&dev->interrupt);
-#else
-       dev->interrupt = 0;
-#endif
-       return;
+       spin_unlock (&tp->lock);
 }
 
 static int
@@ -2751,8 +2725,7 @@ tulip_down(struct net_device *dev)
        long ioaddr = dev->base_addr;
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
 
-       dev->start = 0;
-       dev->tbusy = 1;
+       netif_stop_queue (dev);
 
        /* Disable interrupts by clearing the interrupt mask. */
        outl(0x00000000, ioaddr + CSR7);
@@ -2781,7 +2754,7 @@ tulip_close(struct net_device *dev)
                printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
                           dev->name, inl(ioaddr + CSR5));
 
-       if (dev->start)
+       if (test_bit(LINK_STATE_START, &dev->state))
                tulip_down(dev);
 
        free_irq(dev->irq, dev);
@@ -2794,12 +2767,12 @@ tulip_close(struct net_device *dev)
                tp->rx_ring[i].length = 0;
                tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
                if (skb) {
-                       dev_free_skb(skb);
+                       dev_kfree_skb(skb);
                }
        }
        for (i = 0; i < TX_RING_SIZE; i++) {
                if (tp->tx_skbuff[i])
-                       dev_free_skb(tp->tx_skbuff[i]);
+                       dev_kfree_skb(tp->tx_skbuff[i]);
                tp->tx_skbuff[i] = 0;
        }
 
@@ -2813,7 +2786,7 @@ static struct net_device_stats *tulip_get_stats(struct net_device *dev)
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
        long ioaddr = dev->base_addr;
 
-       if (dev->start)
+       if (test_bit(LINK_STATE_START, &dev->state))
                tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
 
        return &tp->stats;
@@ -3075,8 +3048,8 @@ static void set_rx_mode(struct net_device *dev)
                                tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
                        tp->tx_ring[entry].status = DescOwned;
                        if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
-                               set_bit(0, (void*)&dev->tbusy);
                                tp->tx_full = 1;
+                               netif_stop_queue (dev);
                        }
                        if (dummy >= 0)
                                tp->tx_ring[dummy].status = DescOwned;
@@ -3114,10 +3087,11 @@ static int __devinit tulip_pci_probe(struct pci_dev *pdev, const struct pci_devi
 
        printk(KERN_INFO "tulip_attach(%s)\n", pdev->slot_name);
 
-       pci_set_master(pdev);
-       dev = tulip_probe1(pdev->bus->number, pdev->devfn, NULL,
-                                      pdev->resource[0].start, pdev->irq,
-                                      id->driver_data, board_idx++);
+       pci_enable_device (pdev);
+       pci_set_master (pdev);
+       dev = tulip_probe1(pdev, NULL,
+                          pci_resource_start (pdev, 0), pdev->irq,
+                          id->driver_data, board_idx++);
        if (dev) {
                pdev->driver_data = dev;
                return 0;
index c1c38aa2855089ca5587c82c8f788e194a76fc64..b8ec9510429b225a7641a8942a6316af780a7718 100644 (file)
  * (wavelan modem or i82593)
  */
 
-/*------------------------------------------------------------------*/
-/*
- * Wrapper for disabling interrupts.
- */
-static inline unsigned long
-wv_splhi(void)
-{
-  unsigned long flags;
-
-  save_flags(flags);
-  cli();
-
-  return(flags);
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Wrapper for re-enabling interrupts.
- */
-static inline void
-wv_splx(unsigned long  flags)
-{
-  restore_flags(flags);
-}
-
 /*------------------------------------------------------------------*/
 /*
  * Wrapper for reporting error to cardservices
@@ -581,20 +556,20 @@ void wv_roam_cleanup(struct net_device *dev)
 void wv_nwid_filter(unsigned char mode, net_local *lp)
 {
   mm_t                  m;
-  unsigned long         x;
+  unsigned long         flags;
   
 #ifdef WAVELAN_ROAMING_DEBUG
   printk(KERN_DEBUG "WaveLAN: NWID promisc %s, device %s\n",(mode==NWID_PROMISC) ? "on" : "off", lp->dev->name);
 #endif
   
   /* Disable interrupts & save flags */
-  x = wv_splhi();
+  spin_lock_irqsave (&lp->lock, flags);
   
   m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00;
   mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1);
   
   /* ReEnable interrupts & restore flags */
-  wv_splx(x);
+  spin_unlock_irqrestore (&lp->lock, flags);
   
   if(mode==NWID_PROMISC)
     lp->cell_search=1;
@@ -755,7 +730,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
 {
   ioaddr_t              base = lp->dev->base_addr;  
   mm_t                  m;
-  unsigned long         x;
+  unsigned long         flags;
   
   if(wavepoint==lp->curr_point)          /* Sanity check... */
     {
@@ -768,7 +743,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
 #endif
        
   /* Disable interrupts & save flags */
-  x = wv_splhi();
+  spin_lock_irqsave(&lp->lock, flags);
   
   m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF;
   m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8;
@@ -776,7 +751,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
   mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2);
   
   /* ReEnable interrupts & restore flags */
-  wv_splx(x);
+  spin_unlock_irqrestore (&lp->lock, flags);
   
   wv_nwid_filter(!NWID_PROMISC,lp);
   lp->curr_point=wavepoint;
@@ -863,15 +838,15 @@ wv_82593_cmd(device *     dev,
   net_local *  lp = (net_local *)dev->priv;
   int          status;
   long         spin;
-  u_long       opri;
+  u_long       flags;
 
   /* Spin until the chip finishes executing its current command (if any) */
   do
     {
-      opri = wv_splhi();
+      spin_lock_irqsave (&lp->lock, flags);
       outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
       status = inb(LCSR(base));
-      wv_splx(opri);
+      spin_unlock_irqrestore (&lp->lock, flags);
     }
   while((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE);
 
@@ -1009,27 +984,25 @@ read_ringbuf(device *    dev,
  * wavelan_interrupt is not an option...), so you may experience
  * some delay sometime...
  */
-static inline void
-wv_82593_reconfig(device *     dev)
+static inline void wv_82593_reconfig (device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
-  dev_link_t * link = ((net_local *) dev->priv)->link;
+       net_local *lp = (net_local *) dev->priv;
+       dev_link_t *link = ((net_local *) dev->priv)->link;
 
-  /* Check if we can do it now ! */
-  if(!(link->open) || (test_and_set_bit(0, (void *)&dev->tbusy) != 0))
-    {
-      lp->reconfig_82593 = TRUE;
+       /* Check if we can do it now ! */
+       if (!(link->open)) {
+               lp->reconfig_82593 = TRUE;
 #ifdef DEBUG_IOCTL_INFO
-      printk(KERN_DEBUG "%s: wv_82593_reconfig(): delayed (busy = %ld, link = %d)\n",
-            dev->name, dev->tbusy, link->open);
+               printk (KERN_DEBUG "%s: wv_82593_reconfig(): delayed (link = %d)\n",
+                       dev->name, link->open);
 #endif
-    }
-  else
-    {
-      lp->reconfig_82593 = FALSE;
-      wv_82593_config(dev);
-      dev->tbusy = 0;
-    }
+       } else {
+               netif_stop_queue (dev);
+
+               lp->reconfig_82593 = FALSE;
+               wv_82593_config (dev);
+               netif_start_queue (dev);
+       }
 }
 
 #ifdef OLDIES
@@ -1286,9 +1259,6 @@ static void
 wv_dev_show(device *   dev)
 {
   printk(KERN_DEBUG "dev:");
-  printk(" start=%d,", dev->start);
-  printk(" tbusy=%ld,", dev->tbusy);
-  printk(" interrupt=%d,", dev->interrupt);
   printk(" trans_start=%ld,", dev->trans_start);
   printk(" flags=0x%x,", dev->flags);
   printk("\n");
@@ -1908,7 +1878,7 @@ wavelan_ioctl(struct net_device * dev,    /* Device on wich the ioctl apply */
   struct iwreq *       wrq = (struct iwreq *) rq;
   psa_t                        psa;
   mm_t                 m;
-  unsigned long                x;
+  unsigned long                flags;
   int                  ret = 0;
 
 #ifdef DEBUG_IOCTL_TRACE
@@ -1916,7 +1886,7 @@ wavelan_ioctl(struct net_device * dev,    /* Device on wich the ioctl apply */
 #endif
 
   /* Disable interrupts & save flags */
-  x = wv_splhi();
+  spin_lock_irqsave (&lp->lock, flags);
 
   /* Look what is the request */
   switch(cmd)
@@ -2528,7 +2498,7 @@ wavelan_ioctl(struct net_device * dev,    /* Device on wich the ioctl apply */
     }
 
   /* ReEnable interrupts & restore flags */
-  wv_splx(x);
+  spin_unlock_irqrestore (&lp->lock, flags);
 
 #ifdef DEBUG_IOCTL_TRACE
   printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
@@ -2548,14 +2518,14 @@ wavelan_get_wireless_stats(device *     dev)
   net_local *          lp = (net_local *) dev->priv;
   mmr_t                        m;
   iw_stats *           wstats;
-  unsigned long                x;
+  unsigned long                flags;
 
 #ifdef DEBUG_IOCTL_TRACE
   printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);
 #endif
 
   /* Disable interrupts & save flags */
-  x = wv_splhi();
+  spin_lock_irqsave (&lp->lock, flags);
 
   if(lp == (net_local *) NULL)
     return (iw_stats *) NULL;
@@ -2583,7 +2553,7 @@ wavelan_get_wireless_stats(device *       dev)
   wstats->discard.misc = 0L;
 
   /* ReEnable interrupts & restore flags */
-  wv_splx(x);
+  spin_unlock_irqrestore (&lp->lock, flags);
 
 #ifdef DEBUG_IOCTL_TRACE
   printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);
@@ -2917,7 +2887,7 @@ wv_packet_write(device *  dev,
 {
   net_local *          lp = (net_local *) dev->priv;
   ioaddr_t             base = dev->base_addr;
-  unsigned long                x;
+  unsigned long                flags;
   int                  clen = length;
   register u_short     xmtdata_base = TX_BASE;
 
@@ -2925,7 +2895,7 @@ wv_packet_write(device *  dev,
   printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length);
 #endif
 
-  x = wv_splhi();
+  spin_lock_irqsave (&lp->lock, flags);
 
   /* Check if we need some padding */
   if(clen < ETH_ZLEN)
@@ -2963,7 +2933,7 @@ wv_packet_write(device *  dev,
       add_timer(&lp->watchdog);
     }
 
-  wv_splx(x); 
+  spin_unlock_irqrestore (&lp->lock, flags);
 
 #ifdef DEBUG_TX_INFO
   wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write");
@@ -2972,6 +2942,8 @@ wv_packet_write(device *  dev,
 #ifdef DEBUG_TX_TRACE
   printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
 #endif
+
+  netif_start_queue (dev);
 }
 
 /*------------------------------------------------------------------*/
@@ -2981,60 +2953,45 @@ wv_packet_write(device *        dev,
  * the packet. We also prevent reentrance. Then, we call the function
  * to send the packet...
  */
-static int
-wavelan_packet_xmit(struct sk_buff *   skb,
-                   device *            dev)
+static int wavelan_packet_xmit (struct sk_buff *skb,
+                               device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
+       net_local *lp = (net_local *) dev->priv;
 
 #ifdef DEBUG_TX_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
-        (unsigned) skb);
+       printk (KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
+               (unsigned) skb);
 #endif
 
-  /* This flag indicate that the hardware can't perform a transmission.
-   * Theoritically, NET3 check it before sending a packet to the driver,
-   * but in fact it never do that and pool continuously.
-   * As the watchdog will abort too long transmissions, we are quite safe...
-   */
-  if(dev->tbusy)
-    return(1);
+       /*
+        * For ethernet, fill in the header.
+        */
 
-  /*
-   * For ethernet, fill in the header.
-   */
-
-  /*
-   * Block a timer-based transmit from overlapping a previous transmit.
-   * In other words, prevent reentering this routine.
-   */
-  if(test_and_set_bit(0, (void *)&dev->tbusy) != 0)
-#ifdef DEBUG_TX_ERROR
-    printk(KERN_INFO "%s: Transmitter access conflict.\n", dev->name);
-#endif
-  else
-    {
-      /* If somebody has asked to reconfigure the controler, we can do it now */
-      if(lp->reconfig_82593)
-       {
-         lp->reconfig_82593 = FALSE;
-         wv_82593_config(dev);
-       }
+       netif_stop_queue (dev);
 
+       /*
+        * Block a timer-based transmit from overlapping a previous transmit.
+        * In other words, prevent reentering this routine.
+        */
+       if (1) {
+               /* If somebody has asked to reconfigure the controler, we can do it now */
+               if (lp->reconfig_82593) {
+                       lp->reconfig_82593 = FALSE;
+                       wv_82593_config (dev);
+               }
 #ifdef DEBUG_TX_ERROR
-      if(skb->next)
-       printk(KERN_INFO "skb has next\n");
+               if (skb->next)
+                       printk (KERN_INFO "skb has next\n");
 #endif
-      wv_packet_write(dev, skb->data, skb->len);
-    }
 
-  dev_kfree_skb(skb);
+               wv_packet_write (dev, skb->data, skb->len);
+       }
+       dev_kfree_skb (skb);
 
 #ifdef DEBUG_TX_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
+       printk (KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
 #endif
-  return(0);
+       return (0);
 }
 
 /********************** HARDWARE CONFIGURATION **********************/
@@ -3245,7 +3202,8 @@ static int
 wv_ru_stop(device *    dev)
 {
   ioaddr_t     base = dev->base_addr;
-  unsigned long        opri;
+  net_local *lp = (net_local *) dev->priv;
+  unsigned long        flags;
   int          status;
   int          spin;
 
@@ -3262,10 +3220,10 @@ wv_ru_stop(device *     dev)
   do
     {
       udelay(10);
-      opri = wv_splhi();
+      spin_lock_irqsave (&lp->lock, flags);
       outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
       status = inb(LCSR(base));
-      wv_splx(opri);
+      spin_unlock_irqrestore (&lp->lock, flags);
     }
   while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin++ < 300));
 
@@ -3273,10 +3231,10 @@ wv_ru_stop(device *     dev)
   do
     {
       udelay(10);
-      opri = wv_splhi();
+      spin_lock_irqsave (&lp->lock, flags);
       outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
       status = inb(LCSR(base));
-      wv_splx(opri);
+      spin_unlock_irqrestore (&lp->lock, flags);
     }
   while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin++ < 300));
 
@@ -3347,16 +3305,16 @@ wv_ru_start(device *    dev)
 #ifdef DEBUG_I82593_SHOW
   {
     int        status;
-    int        opri;
+    unsigned long flags;
     int        i = 0;
 
     /* spin until the chip starts receiving */
     do
       {
-       opri = wv_splhi();
+       spin_lock_irqsave (&lp->lock, flags);
        outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
        status = inb(LCSR(base));
-       wv_splx(opri);
+       spin_unlock_irqrestore (&lp->lock, flags);
        if(i++ > 10000)
          break;
       }
@@ -3838,7 +3796,7 @@ wv_pcmcia_config(dev_link_t *     link)
       /* Feed device with this info... */
       dev->irq = link->irq.AssignedIRQ;
       dev->base_addr = link->io.BasePort1;
-      dev->tbusy = 0;
+      netif_start_queue (dev);
 
 #ifdef DEBUG_CONFIG_INFO
       printk(KERN_DEBUG "wv_pcmcia_config: MEMSTART 0x%x IRQ %d IOPORT 0x%x\n",
@@ -3991,13 +3949,7 @@ wavelan_interrupt(int            irq,
   lp = (net_local *) dev->priv;
   base = dev->base_addr;
 
-  /* Prevent reentrance. What should we do here ? */
-#ifdef DEBUG_INTERRUPT_ERROR
-  if(dev->interrupt)
-    printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n",
-          dev->name);
-#endif
-  dev->interrupt = 1;
+  spin_lock (&lp->lock);
 
   /* Treat all pending interrupts */
   while(1)
@@ -4201,8 +4153,7 @@ wavelan_interrupt(int             irq,
          lp->stats.collisions += (tx_status & TX_NCOL_MASK);
          lp->stats.tx_packets++;
 
-         dev->tbusy = FALSE;
-         mark_bh(NET_BH);
+         netif_wake_queue (dev);
          outb(CR0_INT_ACK | OP0_NOP, LCCR(base));      /* Acknowledge the interrupt */
        } 
       else     /* if interrupt = transmit done or retransmit done */
@@ -4214,7 +4165,8 @@ wavelan_interrupt(int             irq,
          outb(CR0_INT_ACK | OP0_NOP, LCCR(base));      /* Acknowledge the interrupt */
        }
     }
-  dev->interrupt = FALSE;
+
+  spin_unlock_irq (&lp->lock);
 
 #ifdef DEBUG_INTERRUPT_TRACE
   printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
@@ -4296,7 +4248,7 @@ wavelan_watchdog(u_long           a)
 #endif
 
   /* We are no more waiting for something... */
-  dev->tbusy = 0;
+  netif_start_queue (dev);
 
 #ifdef DEBUG_INTERRUPT_TRACE
   printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
@@ -4349,9 +4301,7 @@ wavelan_open(device *     dev)
     return FALSE;
   if(!wv_ru_start(dev))
     wv_hw_reset(dev);          /* If problem : reset */
-  dev->interrupt = 0;
-  dev->start = 1;
-  dev->tbusy = 0;   
+  netif_start_queue (dev);
 
   /* Mark the device as used */
   link->open++;
@@ -4385,6 +4335,8 @@ wavelan_close(device *    dev)
         (unsigned int) dev);
 #endif
 
+  netif_stop_queue (dev);
+
   /* If the device isn't open, then nothing to do */
   if(!link->open)
     {
@@ -4408,10 +4360,9 @@ wavelan_close(device *   dev)
   MOD_DEC_USE_COUNT;
 
   /* If the card is still present */
-  if(dev->start)
+  if (test_bit(LINK_STATE_START, &dev->state))
     {
-      dev->tbusy = 1;
-      dev->start = 0;
+      netif_stop_queue (dev);
 
       /* Stop receiving new messages and wait end of transmission */
       wv_ru_stop(dev);
@@ -4549,7 +4500,7 @@ wavelan_attach(void)
   /* Other specific data */
   /* Provide storage area for device name */
   dev->name = ((net_local *)dev->priv)->node.dev_name;
-  dev->tbusy = 1;
+  netif_start_queue (dev);
   dev->mtu = WAVELAN_MTU;
 
   /* Register with Card Services */
@@ -4711,7 +4662,7 @@ wavelan_event(event_t             event,          /* The event received */
        if(link->state & DEV_CONFIG)
          {
            /* Accept no more transmissions */
-           dev->tbusy = 1; dev->start = 0;
+           netif_stop_queue (dev);
 
            /* Release the card */
            wv_pcmcia_release((u_long) link);
@@ -4749,8 +4700,7 @@ wavelan_event(event_t             event,          /* The event received */
          {
            if(link->open)
              {
-               dev->tbusy = 1;
-               dev->start = 0;
+               netif_stop_queue (dev);
              }
            CardServices(ReleaseConfiguration, link->handle);
          }
@@ -4766,8 +4716,7 @@ wavelan_event(event_t             event,          /* The event received */
            if(link->open)      /* If RESET -> True, If RESUME -> False ??? */
              {
                wv_hw_reset(dev);
-               dev->tbusy = 0;
-               dev->start = 1;
+               netif_start_queue (dev);
              }
          }
        break;
index 0f5be4f37423d8886bf10079951c469f8c8e7c58..f35a81ac972c8703aeae0792656c1cb5f281d0e1 100644 (file)
@@ -550,6 +550,7 @@ typedef u_char              mac_addr[WAVELAN_ADDR_SIZE];    /* Hardware address */
  */
 struct net_local
 {
+  spinlock_t   lock;
   dev_node_t   node;           /* ???? What is this stuff ???? */
   device *     dev;            /* Reverse link... */
   dev_link_t * link;           /* pcmcia structure */
@@ -609,10 +610,6 @@ void wv_roam_cleanup(struct net_device *dev);
 #endif /* WAVELAN_ROAMING */
 
 /* ----------------------- MISC SUBROUTINES ------------------------ */
-static inline unsigned long    /* flags */
-       wv_splhi(void);         /* Disable interrupts */
-static inline void
-       wv_splx(unsigned long); /* ReEnable interrupts : flags */
 static void
        cs_error(client_handle_t, /* Report error to cardmgr */
                 int,
index 0c4f72ae7af0b13fa5fea7adb915b19ff3d54a1c..b424f9e9914f0d4e183bd7896418e1b65d50b648 100644 (file)
@@ -410,6 +410,7 @@ typedef struct local_info_t {
     int suspended;
     unsigned last_ptr_value; /* last packets transmitted value */
     const char *manf_str;
+    spinlock_t lock;
 } local_info_t;
 
 /****************
@@ -429,6 +430,7 @@ static void do_reset(struct net_device *dev, int full);
 static int init_mii(struct net_device *dev);
 static void do_powerdown(struct net_device *dev);
 static int do_stop(struct net_device *dev);
+static void xirc_tx_timeout (struct net_device *dev);
 
 /*=============== Helper functions =========================*/
 static void
@@ -691,6 +693,8 @@ xirc2ps_attach(void)
     local = kmalloc(sizeof(*local), GFP_KERNEL);
     if (!local) return NULL;
     memset(local, 0, sizeof(*local));
+    
+    local->lock = SPIN_LOCK_UNLOCKED;
     link = &local->link; dev = &local->dev;
     link->priv = dev->priv = local;
 
@@ -717,7 +721,9 @@ xirc2ps_attach(void)
     dev->init = &do_init;
     dev->open = &do_open;
     dev->stop = &do_stop;
-    dev->tbusy = 1;
+    dev->tx_timeout = xirc_tx_timeout;
+    dev->watchdog_timeo = TX_TIMEOUT;
+    netif_start_queue (dev);
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -1233,7 +1239,7 @@ xirc2ps_config(dev_link_t * link)
     /* we can now register the device with the net subsystem */
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
-    dev->tbusy = 0;
+    netif_start_queue (dev);
     if ((err=register_netdev(dev))) {
        printk(KNOT_XIRC "register_netdev() failed\n");
        goto config_error;
@@ -1334,7 +1340,7 @@ xirc2ps_event(event_t event, int priority,
       case CS_EVENT_CARD_REMOVAL:
          link->state &= ~DEV_PRESENT;
          if (link->state & DEV_CONFIG) {
-             dev->tbusy = 1; dev->start = 0;
+             netif_stop_queue (dev);
              link->release.expires = jiffies + HZ / 20;
              add_timer(&link->release);
          }
@@ -1349,7 +1355,7 @@ xirc2ps_event(event_t event, int priority,
       case CS_EVENT_RESET_PHYSICAL:
          if (link->state & DEV_CONFIG) {
              if (link->open) {
-                 dev->tbusy = 1; dev->start = 0;
+                 netif_stop_queue (dev);
                  lp->suspended=1;
                  do_powerdown(dev);
              }
@@ -1365,7 +1371,7 @@ xirc2ps_event(event_t event, int priority,
             if (link->open) {
                 do_reset(dev,1);
                 lp->suspended=0;
-                dev->tbusy = 0; dev->start = 1;
+                netif_start_queue (dev);
             }
          }
          break;
@@ -1393,14 +1399,8 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                  * -- on a laptop?
                                  */
 
-    if (!dev->start)
-       return;
+    spin_lock (&lp->lock);
 
-    if (dev->interrupt) {
-       printk(KERR_XIRC "re-entering isr on irq %d (dev=%p)\n", irq, dev);
-       return;
-    }
-    dev->interrupt = 1;
     ioaddr = dev->base_addr;
     if (lp->mohawk) { /* must disable the interrupt */
        PutByte(XIRCREG_CR, 0);
@@ -1555,8 +1555,7 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
            DEBUG(0, "PTR not changed?\n");
        } else
            lp->stats.tx_packets += lp->last_ptr_value - n;
-       dev->tbusy = 0;
-       mark_bh(NET_BH);  /* Inform upper layers. */
+       netif_wake_queue (dev);
     }
     if (tx_status & 0x0002) {  /* Execessive collissions */
        DEBUG(0, "tx restarted due to execssive collissions\n");
@@ -1595,7 +1594,9 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
            goto loop_entry;
     }
     SelectPage(saved_page);
-    dev->interrupt = 0;
+
+    spin_unlock (&lp->lock);
+
     PutByte(XIRCREG_CR, EnableIntr);  /* re-enable interrupts */
     /* Instead of dropping packets during a receive, we could
      * force an interrupt with this command:
@@ -1605,44 +1606,39 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 /*====================================================================*/
 
-static int
-do_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void xirc_tx_timeout (struct net_device *dev)
 {
-    local_info_t *lp = dev->priv;
-    ioaddr_t ioaddr = dev->base_addr;
-    int okay;
-    unsigned freespace;
-    unsigned pktlen = skb? skb->len : 0;
-
-    DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
-         skb, dev, pktlen);
-
-    /* Transmitter timeout, serious problems */
-    if (dev->tbusy) {
-       int tickssofar = jiffies - dev->trans_start;
+       local_info_t *lp = dev->priv;
 
        if (lp->suspended) {
-           dev_kfree_skb (skb);
            dev->trans_start = jiffies;
            lp->stats.tx_dropped++;
-           return 0;
+           netif_start_queue (dev);
+           return;
        }
-       if (tickssofar < TX_TIMEOUT)
-           return 1;
 
        printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
        lp->stats.tx_errors++;
        /* reset the card */
        do_reset(dev,1);
        dev->trans_start = jiffies;
-       dev->tbusy = 0;
-    }
+       netif_start_queue (dev);
+}
 
-    if (test_and_set_bit(0, (void*)&dev->tbusy)) {
-       printk(KWRN_XIRC "transmitter access conflict\n");
-       dev_kfree_skb (skb);
-       return 0;
-    }
+
+static int
+do_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+    local_info_t *lp = dev->priv;
+    ioaddr_t ioaddr = dev->base_addr;
+    int okay;
+    unsigned freespace;
+    unsigned pktlen = skb? skb->len : 0;
+
+    DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
+         skb, dev, pktlen);
+
+    netif_stop_queue (dev);
 
     /* adjust the packet length to min. required
      * and hope that the buffer is large enough
@@ -1664,7 +1660,6 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
     DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n",
          dev->name, freespace, okay ? " (okay)":" (not enough)");
     if (!okay) { /* not enough space */
-       dev->tbusy = 1;
        return 1;  /* upper layer may decide to requeue this packet */
     }
     /* send the packet */
@@ -1678,7 +1673,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
     dev_kfree_skb (skb);
     dev->trans_start = jiffies;
-    dev->tbusy = 0;
+    netif_start_queue (dev);
     lp->stats.tx_bytes += pktlen;
     return 0;
 }
@@ -1823,7 +1818,7 @@ do_open(struct net_device *dev)
     link->open++;
     MOD_INC_USE_COUNT;
 
-    dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+    netif_start_queue (dev);
     lp->suspended = 0;
     do_reset(dev,1);
 
@@ -2141,8 +2136,7 @@ do_stop(struct net_device *dev)
     if (!link)
        return -ENODEV;
 
-    dev->tbusy = 1;
-    dev->start = 0;
+    netif_stop_queue (dev);
 
     SelectPage(0);
     PutByte(XIRCREG_CR, 0);  /* disable interrupts */
@@ -2152,7 +2146,7 @@ do_stop(struct net_device *dev)
     PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */
     SelectPage(0);
 
-    link->open--; dev->start = 0;
+    link->open--;
     if (link->state & DEV_STALE_CONFIG) {
        link->release.expires = jiffies + HZ/20;
        link->state |= DEV_RELEASE_PENDING;
index 396e783c59d9237f0eb05ed7670b795b84e68be4..27b0c6474bcd65c04de7f66756f77665713be0eb 100644 (file)
@@ -309,7 +309,6 @@ RCfound_device(int memaddr, int irq,
 #endif
     dev->base_addr = (unsigned long)vaddr;
     dev->irq = irq;
-    dev->interrupt = 0;
 
     /*
      * Request a shared interrupt line.
@@ -430,6 +429,7 @@ RCopen(struct net_device *dev)
     printk("rc: RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);
 #endif
     MOD_INC_USE_COUNT;
+    netif_start_queue(dev);
     return 0;
 }
 
@@ -441,29 +441,26 @@ RC_xmit_packet(struct sk_buff *skb, struct net_device *dev)
     singleTCB tcb;
     psingleTCB ptcb = &tcb;
     RC_RETURN status = 0;
-    
-        if (dev->tbusy || pDpa->shutdown || pDpa->reboot)
-        {
+   
+    netif_stop_queue(dev);
+     
+    if (pDpa->shutdown || pDpa->reboot)
+    {
 #ifdef RCDEBUG
             printk("rc: RC_xmit_packet: tbusy!\n");
 #endif
-            dev->tbusy = 1;
             return 1;
-        }
-      
-    if ( skb->len <= 0 ) 
-    {
-        printk("RC_xmit_packet: skb->len less than 0!\n");
-        return 0;
     }
-
+      
     /*
      * The user is free to reuse the TCB after RCI2OSendPacket() returns, since
      * the function copies the necessary info into its own private space.  Thus,
      * our TCB can be a local structure.  The skb, on the other hand, will be
      * freed up in our interrupt handler.
      */
+
     ptcb->bcount = 1;
+
     /* 
      * we'll get the context when the adapter interrupts us to tell us that
      * the transmision is done. At that time, we can free skb.
@@ -483,13 +480,12 @@ RC_xmit_packet(struct sk_buff *skb, struct net_device *dev)
 #ifdef RCDEBUG
         printk("rc: RC send error 0x%x\n", (uint)status);
 #endif
-        dev->tbusy = 1;
         return 1;
     }
     else
     {
         dev->trans_start = jiffies;
-        //       dev->tbusy = 0;
+        netif_wake_queue(dev);
     }
     /*
      * That's it!
@@ -546,10 +542,9 @@ RCxmit_callback(U32 Status,
             printk("rc: skb = 0x%x\n", (uint)skb);
 #endif
             BufferContext++;
-            dev_kfree_skb (skb);
+            dev_kfree_skb_irq(skb);
         }
-        dev->tbusy = 0;
-
+       netif_wake_queue(dev);
 }
 
 static void
@@ -811,14 +806,8 @@ RCinterrupt(int irq, void *dev_id, struct pt_regs *regs)
            (uint)pDpa, (uint)dev, (uint)pDpa->id);
     printk("dev = 0x%x\n", (uint)dev);
 #endif
-    if (dev->interrupt)
-        printk("%s: Re-entering the interrupt handler.\n", dev->name);
-    dev->interrupt = 1;
 
     RCProcI2OMsgQ(pDpa->id);
-    dev->interrupt = 0;
-
-    return;
 }
 
 
@@ -870,7 +859,7 @@ static void rc_timer(unsigned long data)
                        (uint)pDpa->numOutRcvBuffers);
             }
             printk("rc: Initialization done.\n");
-            dev->tbusy=0;
+            netif_wake_queue(dev);
             retry=0;
             return;
         case RC_RTN_FREE_Q_EMPTY:
@@ -913,6 +902,8 @@ RCclose(struct net_device *dev)
 
     PDPA pDpa = (PDPA) dev->priv;
 
+    netif_stop_queue(dev);
+    
 #ifdef RCDEBUG
     printk("rc: RCclose\r\n");
 #endif
diff --git a/drivers/net/rtl8129.c b/drivers/net/rtl8129.c
new file mode 100644 (file)
index 0000000..fad5b90
--- /dev/null
@@ -0,0 +1,1476 @@
+/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
+/*
+       Written 1997-1999 by Donald Becker.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+    All other rights reserved.
+
+       This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet
+       chips.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+       Support and updates available at
+       http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html
+
+       Twister-tuning table provided by Kinston <shangh@realtek.com.tw>.
+*/
+
+static const char *version =
+"rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
+
+/* A few user-configurable values. */
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+#define rtl8129_debug debug
+static int rtl8129_debug = 1;
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
+static int multicast_filter_limit = 32;
+
+/* Used to pass the full-duplex flag, etc. */
+#define MAX_UNITS 8            /* More are supported, limit only on options */
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+/* Size of the in-memory receive ring. */
+#define RX_BUF_LEN_IDX 3                       /* 0==8K, 1==16K, 2==32K, 3==64K */
+#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
+/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
+#define TX_BUF_SIZE    1536
+
+/* PCI Tuning Parameters
+   Threshold is bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 256     /* In bytes, rounded down to 32 byte units. */
+
+/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024. */
+#define RX_FIFO_THRESH 4               /* Rx buffer level before first PCI xfer.  */
+#define RX_DMA_BURST   4               /* Maximum PCI burst, '4' is 256 bytes */
+#define TX_DMA_BURST   4               /* Calculate as 16<<val. */
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (4*HZ)
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+/* Kernel compatibility defines, some common to David Hind's PCMCIA package.
+   This is only in the support-all-kernels source code. */
+
+#define RUN_AT(x) (jiffies + (x))
+
+#include <linux/delay.h>
+
+#if LINUX_VERSION_CODE < 0x20123
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#endif
+#if LINUX_VERSION_CODE <= 0x20139
+#define        net_device_stats enet_statistics
+#else
+#define NETSTATS_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
+/* Grrrr, the PCI code changed, but did not consider CardBus... */
+#include <linux/bios32.h>
+#define PCI_SUPPORT_VER1
+#else
+#define PCI_SUPPORT_VER2
+#endif
+
+/* The I/O extent. */
+#define RTL8129_TOTAL_SIZE 0x80
+
+/*
+                               Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the RealTek RTL8129, the RealTek Fast
+Ethernet controllers for PCI.  This chip is used on a few clone boards.
+
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+Note: Kernel versions earlier than 1.3.73 do not support shared PCI
+interrupt lines.
+
+III. Driver operation
+
+IIIa. Rx Ring buffers
+
+The receive unit uses a single linear ring buffer rather than the more
+common (and more efficient) descriptor-based architecture.  Incoming frames
+are sequentially stored into the Rx region, and the host copies them into
+skbuffs.
+
+Comment: While it is theoretically possible to process many frames in place,
+any delay in Rx processing would cause us to drop frames.  More importantly,
+the Linux protocol stack is not designed to operate in this manner.
+
+IIIb. Tx operation
+
+The RTL8129 uses a fixed set of four Tx descriptors in register space.
+In a stunningly bad design choice, Tx frames must be 32 bit aligned.  Linux
+aligns the IP header on word boundaries, and 14 byte ethernet header means
+that almost all frames will need to be copied to an alignment buffer.
+
+IVb. References
+
+http://www.realtek.com.tw/cn/cn.html
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+
+IVc. Errata
+
+*/
+\f
+
+/* This table drives the PCI probe routines.  It's mostly boilerplate in all
+   of the drivers, and will likely be provided by some future kernel.
+   Note the matching code -- the first table entry matchs all 56** cards but
+   second only the 1234 card.
+*/
+enum pci_flags_bit {
+       PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+       PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+       const char *name;
+       u16     vendor_id, device_id, device_id_mask, flags;
+       int io_size;
+       struct net_device *(*probe1)(struct pci_dev *pdev, int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+};
+
+static struct net_device * rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
+                                                                                 int pci_devfn, long ioaddr,
+                                                                                 int irq, int chp_idx, int fnd_cnt);
+
+static struct pci_id_info pci_tbl[] =
+{{ "RealTek RTL8129 Fast Ethernet",
+   0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+#ifdef USE_8139_SUPPORT_ALSO
+ { "RealTek RTL8139 Fast Ethernet",
+   0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+ { "SMC1211TX EZCard 10/100 (RealTek RTL8139)",
+   0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+ { "Accton MPX5030 (RealTek RTL8139)",
+   0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+#endif
+ {0,},                                         /* 0 terminated list. */
+};
+
+/* The capability table matches the chip table above. */
+enum {HAS_MII_XCVR=0x01, HAS_CHIP_XCVR=0x02, HAS_LNK_CHNG=0x04};
+static int rtl_cap_tbl[] = {
+       HAS_MII_XCVR, HAS_CHIP_XCVR|HAS_LNK_CHNG, HAS_CHIP_XCVR|HAS_LNK_CHNG,
+};
+
+
+/* The rest of these values should never change. */
+#define NUM_TX_DESC    4                       /* Number of Tx descriptor registers. */
+
+/* Symbolic offsets to registers. */
+enum RTL8129_registers {
+       MAC0=0,                                         /* Ethernet hardware address. */
+       MAR0=8,                                         /* Multicast filter. */
+       TxStatus0=0x10,                         /* Transmit status (Four 32bit registers). */
+       TxAddr0=0x20,                           /* Tx descriptors (also four 32bit). */
+       RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36,
+       ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A,
+       IntrMask=0x3C, IntrStatus=0x3E,
+       TxConfig=0x40, RxConfig=0x44,
+       Timer=0x48,                                     /* A general-purpose counter. */
+       RxMissed=0x4C,                          /* 24 bits valid, write clears. */
+       Cfg9346=0x50, Config0=0x51, Config1=0x52,
+       FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B,
+       MultiIntr=0x5C, TxSummary=0x60,
+       MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68,
+       NWayExpansion=0x6A,
+       /* Undocumented registers, but required for proper operation. */
+       FIFOTMS=0x70,   /* FIFO Test Mode Select */
+       CSCR=0x74,      /* Chip Status and Configuration Register. */
+       PARA78=0x78, PARA7c=0x7c,       /* Magic transceiver parameter register. */
+};
+
+enum ChipCmdBits {
+       CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, };
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatusBits {
+       PCIErr=0x8000, PCSTimeout=0x4000,
+       RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10,
+       TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01,
+};
+enum TxStatusBits {
+       TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000,
+       TxOutOfWindow=0x20000000, TxAborted=0x40000000, TxCarrierLost=0x80000000,
+};
+enum RxStatusBits {
+       RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000,
+       RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004,
+       RxBadAlign=0x0002, RxStatusOK=0x0001,
+};
+
+/* Twister tuning parameters from RealTek.
+   Completely undocumented, but required to tune bad links. */
+enum CSCRBits {
+       CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
+       CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
+       CSCR_LinkDownCmd=0x0f3c0,
+};
+unsigned long param[4][4]={
+       {0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43},
+       {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
+       {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
+       {0x0bb39de43,0x0bb39ce43,0x0bb39ce83,0x0bb39ce83}
+};
+
+struct ring_info {
+       struct sk_buff *skb;
+       dma_addr_t mapping;
+};
+
+struct rtl8129_private {
+       char devname[8];                        /* Used only for kernel debugging. */
+       const char *product_name;
+       struct net_device *next_module;
+       struct pci_dev *pdev;
+       int chip_id;
+       int chip_revision;
+       unsigned char pci_bus, pci_devfn;
+#if LINUX_VERSION_CODE > 0x20139
+       struct net_device_stats stats;
+#else
+       struct enet_statistics stats;
+#endif
+       struct timer_list timer;        /* Media selection timer. */
+       unsigned int cur_rx;            /* Index into the Rx buffer of next Rx pkt. */
+       unsigned int cur_tx, dirty_tx, tx_flag;
+       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+       struct ring_info tx_info[NUM_TX_DESC];
+       unsigned char *tx_buf[NUM_TX_DESC];     /* Tx bounce buffers */
+       unsigned char *rx_ring;
+       unsigned char *tx_bufs;                         /* Tx bounce buffer region. */
+       dma_addr_t rx_ring_dma;
+       dma_addr_t tx_bufs_dma;
+       char phys[4];                                           /* MII device addresses. */
+       char twistie, twist_cnt;                        /* Twister tune state. */
+       unsigned int tx_full:1;                         /* The Tx queue is full. */
+       unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
+       unsigned int duplex_lock:1;
+       unsigned int default_port:4;            /* Last dev->if_port value. */
+       unsigned int media2:4;                          /* Secondary monitored media port. */
+       unsigned int medialock:1;                       /* Don't sense media type. */
+       unsigned int mediasense:1;                      /* Media sensing in progress. */
+};
+
+#ifdef MODULE
+#if LINUX_VERSION_CODE > 0x20115
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(multicast_filter_limit, "i");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(debug, "i");
+#endif
+#endif
+
+static int rtl8129_open(struct net_device *dev);
+static int read_eeprom(long ioaddr, int location);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int val);
+static void rtl8129_timer(unsigned long data);
+static void rtl8129_tx_timeout(struct net_device *dev);
+static void rtl8129_init_ring(struct net_device *dev);
+static int rtl8129_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int rtl8129_rx(struct net_device *dev);
+static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int rtl8129_close(struct net_device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct enet_statistics *rtl8129_get_stats(struct net_device *dev);
+static inline u32 ether_crc(int length, unsigned char *data);
+static void set_rx_mode(struct net_device *dev);
+\f
+
+/* A list of all installed RTL8129 devices, for removing the driver module. */
+static struct net_device *root_rtl8129_dev = NULL;
+
+/* Ideally we would detect all network cards in slot order.  That would
+   be best done a central PCI probe dispatch, which wouldn't work
+   well when dynamically adding drivers.  So instead we detect just the
+   Rtl81*9 cards in slot order. */
+
+int rtl8139_probe(void)
+{
+       int cards_found = 0;
+       int pci_index = 0;
+       unsigned char pci_bus, pci_device_fn;
+       struct net_device *dev;
+
+       if ( ! pcibios_present())
+               return -ENODEV;
+
+       for (; pci_index < 0xff; pci_index++) {
+               struct pci_dev *pdev;
+               u16 vendor, device, pci_command, new_command;
+               int chip_idx, irq;
+               long ioaddr;
+
+               if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
+                                                               &pci_bus, &pci_device_fn)
+                       != PCIBIOS_SUCCESSFUL)
+                       break;
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_VENDOR_ID, &vendor);
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_DEVICE_ID, &device);
+
+               for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+                       if (vendor == pci_tbl[chip_idx].vendor_id
+                               && (device & pci_tbl[chip_idx].device_id_mask) ==
+                               pci_tbl[chip_idx].device_id)
+                               break;
+               if (pci_tbl[chip_idx].vendor_id == 0)           /* Compiled out! */
+                       continue;
+
+               pdev = pci_find_slot(pci_bus, pci_device_fn);
+               ioaddr = pdev->resource[0].start;
+               irq = pdev->irq;
+
+               if ((pci_tbl[chip_idx].flags & PCI_USES_IO) &&
+                       check_region(ioaddr, pci_tbl[chip_idx].io_size))
+                       continue;
+
+               /* Activate the card: fix for brain-damaged Win98 BIOSes. */
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_COMMAND, &pci_command);
+               new_command = pci_command | (pci_tbl[chip_idx].flags & 7);
+               if (pci_command != new_command) {
+                       printk(KERN_INFO "  The PCI BIOS has not enabled the"
+                                  " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
+                                  pci_bus, pci_device_fn, pci_command, new_command);
+                       pcibios_write_config_word(pci_bus, pci_device_fn,
+                                                                         PCI_COMMAND, new_command);
+               }
+
+               dev = pci_tbl[chip_idx].probe1(pdev, pci_bus, pci_device_fn, ioaddr, irq, chip_idx, cards_found);
+
+               if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
+                       u8 pci_latency;
+                       pcibios_read_config_byte(pci_bus, pci_device_fn,
+                                                                        PCI_LATENCY_TIMER, &pci_latency);
+                       if (pci_latency < 32) {
+                               printk(KERN_NOTICE "  PCI latency timer (CFLT) is "
+                                          "unreasonably low at %d.  Setting to 64 clocks.\n",
+                                          pci_latency);
+                               pcibios_write_config_byte(pci_bus, pci_device_fn,
+                                                                                 PCI_LATENCY_TIMER, 64);
+                       }
+               }
+               dev = 0;
+               cards_found++;
+       }
+
+       return cards_found ? 0 : -ENODEV;
+}
+
+static struct net_device *rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
+                                                                                int pci_devfn, long ioaddr,
+                                                                                int irq, int chip_idx, int found_cnt)
+{
+       static int did_version = 0;                     /* Already printed version info. */
+       struct rtl8129_private *tp;
+       int i, option = found_cnt < MAX_UNITS ? options[found_cnt] : 0;
+       struct net_device *dev;
+
+       if (rtl8129_debug > 0  &&  did_version++ == 0)
+               printk(KERN_INFO "%s", version);
+
+       dev = init_etherdev(NULL, 0);
+
+       printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
+                  dev->name, pci_tbl[chip_idx].name, ioaddr, irq);
+
+       /* Bring the chip out of low-power mode. */
+       outb(0x00, ioaddr + Config1);
+
+       if (read_eeprom(ioaddr, 0) != 0xffff) {
+               for (i = 0; i < 3; i++) {
+                       ((u16 *)(dev->dev_addr))[i] =
+                               le16_to_cpu(read_eeprom(ioaddr, i + 7));
+               }
+       } else {
+               for (i = 0; i < 6; i++)
+                       dev->dev_addr[i] = inb(ioaddr + MAC0 + i);
+       }
+       for (i = 0; i < 5; i++)
+               printk("%2.2x:", dev->dev_addr[i]);
+       printk("%2.2x.\n", dev->dev_addr[i]);
+
+       /* We do a request_region() to register /proc/ioports info. */
+       request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
+
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+
+       /* Some data structures must be quadword aligned. */
+       tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
+       memset(tp, 0, sizeof(*tp));
+       dev->priv = tp;
+
+       tp->next_module = root_rtl8129_dev;
+       root_rtl8129_dev = dev;
+
+       tp->pdev = pdev;
+       tp->chip_id = chip_idx;
+       tp->pci_bus = pci_bus;
+       tp->pci_devfn = pci_devfn;
+
+       /* Find the connected MII xcvrs.
+          Doing this in open() would allow detecting external xcvrs later, but
+          takes too much time. */
+       if (rtl_cap_tbl[chip_idx] & HAS_MII_XCVR) {
+               int phy, phy_idx;
+               for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+                        phy++) {
+                       int mii_status = mdio_read(dev, phy, 1);
+                       if (mii_status != 0xffff  && mii_status != 0x0000) {
+                               tp->phys[phy_idx++] = phy;
+                               printk(KERN_INFO "%s: MII transceiver found at address %d.\n",
+                                          dev->name, phy);
+                       }
+               }
+               if (phy_idx == 0) {
+                       printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "
+                                  "transceiver.\n",
+                                  dev->name);
+                       tp->phys[0] = -1;
+               }
+       } else
+               tp->phys[0] = 32;
+
+       /* Put the chip into low-power mode. */
+       outb(0xC0, ioaddr + Cfg9346);
+       outb(0x03, ioaddr + Config1);
+       outb('H', ioaddr + HltClk);             /* 'R' would leave the clock running. */
+
+       /* The lower four bits are the media type. */
+       if (option > 0) {
+               tp->full_duplex = (option & 0x200) ? 1 : 0;
+               tp->default_port = option & 15;
+               if (tp->default_port)
+                       tp->medialock = 1;
+       }
+
+       if (found_cnt < MAX_UNITS  &&  full_duplex[found_cnt] > 0)
+               tp->full_duplex = full_duplex[found_cnt];
+
+       if (tp->full_duplex) {
+               printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
+               mdio_write(dev, tp->phys[0], 4, 0x141);
+               tp->duplex_lock = 1;
+       }
+
+       /* The Rtl8129-specific entries in the device structure. */
+       dev->open = &rtl8129_open;
+       dev->hard_start_xmit = &rtl8129_start_xmit;
+       dev->tx_timeout = &rtl8129_tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
+       dev->stop = &rtl8129_close;
+       dev->get_stats = &rtl8129_get_stats;
+       dev->set_multicast_list = &set_rx_mode;
+       dev->do_ioctl = &mii_ioctl;
+
+       return dev;
+}
+\f
+/* Serial EEPROM section. */
+
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK   0x04    /* EEPROM shift clock. */
+#define EE_CS                  0x08    /* EEPROM chip select. */
+#define EE_DATA_WRITE  0x02    /* EEPROM chip data in. */
+#define EE_WRITE_0             0x00
+#define EE_WRITE_1             0x02
+#define EE_DATA_READ   0x01    /* EEPROM chip data out. */
+#define EE_ENB                 (0x80 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
+ */
+
+#define eeprom_delay() inl(ee_addr)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD   (5 << 6)
+#define EE_READ_CMD            (6 << 6)
+#define EE_ERASE_CMD   (7 << 6)
+
+static int read_eeprom(long ioaddr, int location)
+{
+       int i;
+       unsigned retval = 0;
+       long ee_addr = ioaddr + Cfg9346;
+       int read_cmd = location | EE_READ_CMD;
+
+       outb(EE_ENB & ~EE_CS, ee_addr);
+       outb(EE_ENB, ee_addr);
+
+       /* Shift the read command bits out. */
+       for (i = 10; i >= 0; i--) {
+               int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+               outb(EE_ENB | dataval, ee_addr);
+               eeprom_delay();
+               outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+               eeprom_delay();
+       }
+       outb(EE_ENB, ee_addr);
+       eeprom_delay();
+
+       for (i = 16; i > 0; i--) {
+               outb(EE_ENB | EE_SHIFT_CLK, ee_addr);
+               eeprom_delay();
+               retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0);
+               outb(EE_ENB, ee_addr);
+               eeprom_delay();
+       }
+
+       /* Terminate the EEPROM access. */
+       outb(~EE_CS, ee_addr);
+       return retval;
+}
+
+/* MII serial management: mostly bogus for now. */
+/* Read and write the MII management registers using software-generated
+   serial MDIO protocol.
+   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+   "overclocking" issues. */
+#define MDIO_DIR               0x80
+#define MDIO_DATA_OUT  0x04
+#define MDIO_DATA_IN   0x02
+#define MDIO_CLK               0x01
+#define MDIO_WRITE0 (MDIO_DIR)
+#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
+
+#define mdio_delay()   inb(mdio_addr)
+
+static char mii_2_8139_map[8] = {MII_BMCR, MII_BMSR, 0, 0, NWayAdvert,
+                                                                NWayLPAR, NWayExpansion, 0 };
+
+/* Syncronize the MII management interface by shifting 32 one bits out. */
+static void mdio_sync(long mdio_addr)
+{
+       int i;
+
+       for (i = 32; i >= 0; i--) {
+               outb(MDIO_WRITE1, mdio_addr);
+               mdio_delay();
+               outb(MDIO_WRITE1 | MDIO_CLK, mdio_addr);
+               mdio_delay();
+       }
+       return;
+}
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+       long mdio_addr = dev->base_addr + MII_SMI;
+       int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+       int retval = 0;
+       int i;
+
+       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
+               return location < 8 && mii_2_8139_map[location] ?
+                       inw(dev->base_addr + mii_2_8139_map[location]) : 0;
+       }
+       mdio_sync(mdio_addr);
+       /* Shift the read command bits out. */
+       for (i = 15; i >= 0; i--) {
+               int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
+
+               outb(MDIO_DIR | dataval, mdio_addr);
+               mdio_delay();
+               outb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
+               mdio_delay();
+       }
+
+       /* Read the two transition, 16 data, and wire-idle bits. */
+       for (i = 19; i > 0; i--) {
+               outb(0, mdio_addr);
+               mdio_delay();
+               retval = (retval << 1) | ((inb(mdio_addr) & MDIO_DATA_IN) ? 1 : 0);
+               outb(MDIO_CLK, mdio_addr);
+               mdio_delay();
+       }
+       return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
+{
+       long mdio_addr = dev->base_addr + MII_SMI;
+       int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+       int i;
+
+       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
+               if (location < 8  &&  mii_2_8139_map[location])
+                       outw(value, dev->base_addr + mii_2_8139_map[location]);
+               return;
+       }
+       mdio_sync(mdio_addr);
+
+       /* Shift the command bits out. */
+       for (i = 31; i >= 0; i--) {
+               int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+               outb(dataval, mdio_addr);
+               mdio_delay();
+               outb(dataval | MDIO_CLK, mdio_addr);
+               mdio_delay();
+       }
+       /* Clear out extra bits. */
+       for (i = 2; i > 0; i--) {
+               outb(0, mdio_addr);
+               mdio_delay();
+               outb(MDIO_CLK, mdio_addr);
+               mdio_delay();
+       }
+       return;
+}
+
+\f
+static int
+rtl8129_open(struct net_device *dev)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int i;
+
+       /* Soft reset the chip. */
+       outb(CmdReset, ioaddr + ChipCmd);
+
+       if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev)) {
+               return -EAGAIN;
+       }
+
+       MOD_INC_USE_COUNT;
+
+       tp->tx_bufs = pci_alloc_consistent(tp->pdev,
+                                                                          TX_BUF_SIZE * NUM_TX_DESC,
+                                                                          &tp->tx_bufs_dma);
+       tp->rx_ring = pci_alloc_consistent(tp->pdev,
+                                                                          RX_BUF_LEN + 16,
+                                                                          &tp->rx_ring_dma);
+       if (tp->tx_bufs == NULL ||  tp->rx_ring == NULL) {
+               free_irq(dev->irq, dev);
+               if (tp->tx_bufs)
+                       pci_free_consistent(tp->pdev,
+                                                               TX_BUF_SIZE * NUM_TX_DESC,
+                                                               tp->tx_bufs, tp->tx_bufs_dma);
+               if (tp->rx_ring)
+                       pci_free_consistent(tp->pdev,
+                                                               RX_BUF_LEN + 16,
+                                                               tp->rx_ring, tp->rx_ring_dma);
+               if (rtl8129_debug > 0)
+                       printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n",
+                                  dev->name, RX_BUF_LEN);
+               return -ENOMEM;
+       }
+       rtl8129_init_ring(dev);
+
+       /* Check that the chip has finished the reset. */
+       for (i = 1000; i > 0; i--)
+               if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
+                       break;
+
+       for (i = 0; i < 6; i++)
+               outb(dev->dev_addr[i], ioaddr + MAC0 + i);
+
+       /* Must enable Tx/Rx before setting transfer thresholds! */
+       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),
+                ioaddr + RxConfig);
+       outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig);
+       tp->tx_flag = (TX_FIFO_THRESH<<11) & 0x003f0000;
+
+       tp->full_duplex = tp->duplex_lock;
+       if (tp->phys[0] >= 0  ||  (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)) {
+               u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
+               if (mii_reg5 == 0xffff)
+                       ;                                       /* Not there */
+               else if ((mii_reg5 & 0x0100) == 0x0100
+                                || (mii_reg5 & 0x00C0) == 0x0040)
+                       tp->full_duplex = 1;
+               if (rtl8129_debug > 1)
+                       printk(KERN_INFO"%s: Setting %s%s-duplex based on"
+                                  " auto-negotiated partner ability %4.4x.\n", dev->name,
+                                  mii_reg5 == 0 ? "" :
+                                  (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
+                                  tp->full_duplex ? "full" : "half", mii_reg5);
+       }
+
+       outb(0xC0, ioaddr + Cfg9346);
+       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+       outb(0x00, ioaddr + Cfg9346);
+
+       outl(tp->rx_ring_dma, ioaddr + RxBuf);
+
+       /* Start the chip's Tx and Rx process. */
+       outl(0, ioaddr + RxMissed);
+       set_rx_mode(dev);
+
+       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+
+       /* Enable all known interrupts by setting the interrupt mask. */
+       outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
+                | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
+
+       if (rtl8129_debug > 1)
+               printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d"
+                          " GP Pins %2.2x %s-duplex.\n",
+                          dev->name, ioaddr, dev->irq, inb(ioaddr + GPPinData),
+                          tp->full_duplex ? "full" : "half");
+
+       /* Set the timer to switch to check for link beat and perhaps switch
+          to an alternate media type. */
+       init_timer(&tp->timer);
+       tp->timer.expires = RUN_AT((24*HZ)/10);                 /* 2.4 sec. */
+       tp->timer.data = (unsigned long)dev;
+       tp->timer.function = &rtl8129_timer;
+       add_timer(&tp->timer);
+
+       return 0;
+}
+
+static void rtl8129_timer(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int next_tick = 60*HZ;
+       int mii_reg5 = mdio_read(dev, tp->phys[0], 5);
+
+       if (! tp->duplex_lock  &&  mii_reg5 != 0xffff) {
+               int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
+               if (tp->full_duplex != duplex) {
+                       tp->full_duplex = duplex;
+                       printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
+                                  " partner ability of %4.4x.\n", dev->name,
+                                  tp->full_duplex ? "full" : "half", tp->phys[0], mii_reg5);
+                       outb(0xC0, ioaddr + Cfg9346);
+                       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+                       outb(0x00, ioaddr + Cfg9346);
+               }
+       }
+       /* Check for bogusness. */
+       if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) {
+               int status = inw(ioaddr + IntrStatus);
+               if (status & (TxOK | RxOK)) {   /* Double check */
+                       printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n",
+                                  dev->name, status);
+                       rtl8129_interrupt(dev->irq, dev, 0);
+               }
+       }
+       if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+               (jiffies - dev->trans_start) >= 2*TX_TIMEOUT)
+               rtl8129_tx_timeout(dev);
+
+#if 0
+       if (tp->twistie) {
+               unsigned int CSCRval = inw(ioaddr + CSCR);              /* Read link status. */
+               if (tp->twistie == 1) {
+                       if (CSCRval & CSCR_LinkOKBit) {
+                               outw(CSCR_LinkDownOffCmd, ioaddr + CSCR);
+                               tp->twistie = 2;
+                               next_tick = HZ/10;
+                       } else {
+                               outw(CSCR_LinkDownCmd, ioaddr + CSCR);
+                               outl(FIFOTMS_default,ioaddr + FIFOTMS);
+                               outl(PARA78_default ,ioaddr + PARA78);
+                               outl(PARA7c_default ,ioaddr + PARA7c);
+                               tp->twistie = 0;
+                       }
+               } else if (tp->twistie == 2) {
+                       int linkcase = (CSCRval & CSCR_LinkStatusBits) >> 12;
+                       int row;
+                       if (linkcase >= 0x7000) row = 3;
+                       else if (linkcase >= 0x3000) row = 2;
+                       else if (linkcase >= 0x1000) row = 1;
+                       else row = 0;
+                       tp->twistie == row + 3;
+                       outw(0,ioaddr+FIFOTMS);
+                       outl(param[row][0], ioaddr+PARA7c);
+                       tp->twist_cnt = 1;
+               } else {
+                       outl(param[tp->twistie-3][tp->twist_cnt], ioaddr+PARA7c);
+                       if (++tp->twist_cnt < 4) {
+                               next_tick = HZ/10;
+                       } else if (tp->twistie-3 == 3) {
+                               if ((CSCRval & CSCR_LinkStatusBits) != 0x7000) {
+                                       outl(PARA7c_xxx, ioaddr+PARA7c);
+                                       next_tick = HZ/10;              /* 100ms. */
+                                       outl(FIFOTMS_default, ioaddr+FIFOTMS);
+                                       outl(PARA78_default,  ioaddr+PARA78);
+                                       outl(PARA7c_default,  ioaddr+PARA7c);
+                                       tp->twistie == 3 + 3;
+                                       outw(0,ioaddr+FIFOTMS);
+                                       outl(param[3][0], ioaddr+PARA7c);
+                                       tp->twist_cnt = 1;
+                               }
+                       }
+               }
+       }
+#endif
+
+       if (rtl8129_debug > 2) {
+               if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)
+                       printk(KERN_DEBUG"%s: Media selection tick, GP pins %2.2x.\n",
+                                  dev->name, inb(ioaddr + GPPinData));
+               else
+                       printk(KERN_DEBUG"%s: Media selection tick, Link partner %4.4x.\n",
+                                  dev->name, inw(ioaddr + NWayLPAR));
+               printk(KERN_DEBUG"%s:  Other registers are IntMask %4.4x IntStatus %4.4x"
+                          " RxStatus %4.4x.\n",
+                          dev->name, inw(ioaddr + IntrMask), inw(ioaddr + IntrStatus),
+                          inl(ioaddr + RxEarlyStatus));
+               printk(KERN_DEBUG"%s:  Chip config %2.2x %2.2x.\n",
+                          dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1));
+       }
+
+       tp->timer.expires = RUN_AT(next_tick);
+       add_timer(&tp->timer);
+}
+
+static void rtl8129_tx_timeout(struct net_device *dev)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int mii_reg, i;
+
+       if (rtl8129_debug > 0)
+               printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x "
+                          "media %2.2x.\n",
+                          dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus),
+                          inb(ioaddr + GPPinData));
+
+       /* Disable interrupts by clearing the interrupt mask. */
+       outw(0x0000, ioaddr + IntrMask);
+       /* Emit info to figure out what went wrong. */
+       printk("%s: Tx queue start entry %d  dirty entry %d.\n",
+                  dev->name, tp->cur_tx, tp->dirty_tx);
+       for (i = 0; i < NUM_TX_DESC; i++)
+               printk(KERN_DEBUG"%s:  Tx descriptor %d is %8.8x.%s\n",
+                          dev->name, i, inl(ioaddr + TxStatus0 + i*4),
+                          i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : "");
+       printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]);
+       for (mii_reg = 0; mii_reg < 8; mii_reg++)
+               printk(" %4.4x", mdio_read(dev, tp->phys[0], mii_reg));
+       printk(".\n");
+
+       /* Soft reset the chip. */
+       outb(CmdReset, ioaddr + ChipCmd);
+       /* Check that the chip has finished the reset. */
+       for (i = 1000; i > 0; i--)
+               if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
+                       break;
+       for (i = 0; i < 6; i++)
+               outb(dev->dev_addr[i], ioaddr + MAC0 + i);
+
+       outb(0x00, ioaddr + Cfg9346);
+       tp->cur_rx = 0;
+       /* Must enable Tx/Rx before setting transfer thresholds! */
+       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),
+                ioaddr + RxConfig);
+       outl((TX_DMA_BURST<<8), ioaddr + TxConfig);
+       set_rx_mode(dev);
+       {                                                       /* Save the unsent Tx packets. */
+               struct sk_buff *saved_skb[NUM_TX_DESC], *skb;
+               int j;
+               for (j = 0; tp->cur_tx - tp->dirty_tx > 0 ; j++, tp->dirty_tx++) {
+                       struct ring_info *rp = &tp->tx_info[tp->dirty_tx % NUM_TX_DESC];
+
+                       saved_skb[j] = rp->skb;
+                       if (rp->mapping != 0) {
+                               pci_unmap_single(tp->pdev, rp->mapping, rp->skb->len);
+                               rp->mapping = 0;
+                       }
+               }
+               tp->dirty_tx = tp->cur_tx = 0;
+
+               for (i = 0; i < j; i++) {
+                       skb = tp->tx_info[i].skb = saved_skb[i];
+                       if ((long)skb->data & 3) {              /* Must use alignment buffer. */
+                               memcpy(tp->tx_buf[i], skb->data, skb->len);
+                               outl(tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs),
+                                        ioaddr + TxAddr0 + i*4);
+                       } else {
+                               tp->tx_info[i].mapping =
+                                       pci_map_single(tp->pdev, skb->data, skb->len);
+                               outl(tp->tx_info[i].mapping, ioaddr + TxAddr0 + i*4);
+                       }
+                       /* Note: the chip doesn't have auto-pad! */
+                       outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
+                                ioaddr + TxStatus0 + i*4);
+               }
+               tp->cur_tx = i;
+               while (i < NUM_TX_DESC) {
+                       tp->tx_info[i].skb = NULL;
+                       tp->tx_info[i].mapping = 0;
+                       i++;
+               }
+               if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
+                       netif_wake_queue(dev);
+                       tp->tx_full = 0;
+               } else {
+                       tp->tx_full = 1;
+                       netif_stop_queue(dev);
+               }
+       }
+
+       dev->trans_start = jiffies;
+       tp->stats.tx_errors++;
+       /* Enable all known interrupts by setting the interrupt mask. */
+       outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
+                | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
+       return;
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void
+rtl8129_init_ring(struct net_device *dev)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       int i;
+
+       tp->tx_full = 0;
+       tp->cur_rx = 0;
+       tp->dirty_tx = tp->cur_tx = 0;
+
+       for (i = 0; i < NUM_TX_DESC; i++) {
+               tp->tx_buf[i] = &tp->tx_bufs[i*TX_BUF_SIZE];
+               tp->tx_info[i].skb = NULL;
+               tp->tx_info[i].mapping = 0;
+       }
+}
+
+static int
+rtl8129_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int entry;
+
+       netif_stop_queue(dev);
+
+       /* Calculate the next Tx descriptor entry. */
+       entry = tp->cur_tx % NUM_TX_DESC;
+
+       tp->tx_info[entry].skb = skb;
+       if ((long)skb->data & 3) {                      /* Must use alignment buffer. */
+               tp->tx_info[entry].mapping = 0;
+               memcpy(tp->tx_buf[entry], skb->data, skb->len);
+               outl(tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs),
+                        ioaddr + TxAddr0 + entry*4);
+       } else {
+               tp->tx_info[entry].mapping =
+                       pci_map_single(tp->pdev, skb->data, skb->len);
+               outl(tp->tx_info[entry].mapping, ioaddr + TxAddr0 + entry*4);
+       }
+       /* Note: the chip doesn't have auto-pad! */
+       outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
+                ioaddr + TxStatus0 + entry*4);
+
+       if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {        /* Typical path */
+               netif_start_queue(dev);
+       } else {
+               tp->tx_full = 1;
+       }
+
+       dev->trans_start = jiffies;
+       if (rtl8129_debug > 4)
+               printk(KERN_DEBUG"%s: Queued Tx packet at %p size %d to slot %d.\n",
+                          dev->name, skb->data, (int)skb->len, entry);
+
+       return 0;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)dev_instance;
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       int boguscnt = max_interrupt_work;
+       int status, link_changed = 0;
+       long ioaddr = dev->base_addr;
+
+       do {
+               status = inw(ioaddr + IntrStatus);
+               /* Acknowledge all of the current interrupt sources ASAP, but
+                  an first get an additional status bit from CSCR. */
+               if ((status & RxUnderrun)  &&  inw(ioaddr+CSCR) & CSCR_LinkChangeBit)
+                       link_changed = 1;
+               outw(status, ioaddr + IntrStatus);
+
+               if (rtl8129_debug > 4)
+                       printk(KERN_DEBUG"%s: interrupt  status=%#4.4x new intstat=%#4.4x.\n",
+                                  dev->name, status, inw(ioaddr + IntrStatus));
+
+               if ((status & (PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver
+                                          |TxErr|TxOK|RxErr|RxOK)) == 0)
+                       break;
+
+               if (status & (RxOK|RxUnderrun|RxOverflow|RxFIFOOver))/* Rx interrupt */
+                       rtl8129_rx(dev);
+
+               if (status & (TxOK | TxErr)) {
+                       unsigned int dirty_tx = tp->dirty_tx;
+
+                       while (tp->cur_tx - dirty_tx > 0) {
+                               int entry = dirty_tx % NUM_TX_DESC;
+                               int txstatus = inl(ioaddr + TxStatus0 + entry*4);
+
+                               if ( ! (txstatus & (TxStatOK | TxUnderrun | TxAborted)))
+                                       break;                  /* It still hasn't been Txed */
+
+                               /* Note: TxCarrierLost is always asserted at 100mbps. */
+                               if (txstatus & (TxOutOfWindow | TxAborted)) {
+                                       /* There was an major error, log it. */
+                                       if (rtl8129_debug > 1)
+                                               printk(KERN_NOTICE"%s: Transmit error, Tx status %8.8x.\n",
+                                                          dev->name, txstatus);
+                                       tp->stats.tx_errors++;
+                                       if (txstatus&TxAborted) {
+                                               tp->stats.tx_aborted_errors++;
+                                               outl((TX_DMA_BURST<<8)|0x03000001, ioaddr + TxConfig);
+                                       }
+                                       if (txstatus&TxCarrierLost) tp->stats.tx_carrier_errors++;
+                                       if (txstatus&TxOutOfWindow) tp->stats.tx_window_errors++;
+#ifdef ETHER_STATS
+                                       if ((txstatus & 0x0f000000) == 0x0f000000)
+                                               tp->stats.collisions16++;
+#endif
+                               } else {
+                                       if (txstatus & TxUnderrun) {
+                                               /* Add 64 to the Tx FIFO threshold. */
+                                               if (tp->tx_flag <  0x00300000)
+                                                       tp->tx_flag += 0x00020000;
+                                               tp->stats.tx_fifo_errors++;
+                                       }
+                                       tp->stats.collisions += (txstatus >> 24) & 15;
+#if LINUX_VERSION_CODE > 0x20119
+                                       tp->stats.tx_bytes += txstatus & 0x7ff;
+#endif
+                                       tp->stats.tx_packets++;
+                               }
+
+                               if (tp->tx_info[entry].mapping != 0) {
+                                       pci_unmap_single(tp->pdev,
+                                                                        tp->tx_info[entry].mapping,
+                                                                        tp->tx_info[entry].skb->len);
+                                       tp->tx_info[entry].mapping = 0;
+                               }
+
+                               /* Free the original skb. */
+                               dev_kfree_skb_irq(tp->tx_info[entry].skb);
+                               tp->tx_info[entry].skb = NULL;
+                               if (tp->tx_full) {
+                                       /* The ring is no longer full, wake the queue. */
+                                       tp->tx_full = 0;
+                                       netif_wake_queue(dev);
+                               }
+                               dirty_tx++;
+                       }
+
+#ifndef final_version
+                       if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
+                               printk(KERN_ERR"%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+                                          dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
+                               dirty_tx += NUM_TX_DESC;
+                       }
+#endif
+                       tp->dirty_tx = dirty_tx;
+               }
+
+               /* Check uncommon events with one test. */
+               if (status & (PCIErr|PCSTimeout |RxUnderrun|RxOverflow|RxFIFOOver
+                                         |TxErr|RxErr)) {
+                       if (rtl8129_debug > 2)
+                               printk(KERN_NOTICE"%s: Abnormal interrupt, status %8.8x.\n",
+                                          dev->name, status);
+
+                       if (status == 0xffffffff)
+                               break;
+                       /* Update the error count. */
+                       tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
+                       outl(0, ioaddr + RxMissed);
+
+                       if ((status & RxUnderrun)  &&  link_changed  &&
+                               (rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) {
+                               /* Really link-change on new chips. */
+                               int lpar = inw(ioaddr + NWayLPAR);
+                               int duplex = (lpar&0x0100)||(lpar & 0x01C0) == 0x0040; 
+                               if (tp->full_duplex != duplex) {
+                                       tp->full_duplex = duplex;
+                                       outb(0xC0, ioaddr + Cfg9346);
+                                       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+                                       outb(0x00, ioaddr + Cfg9346);
+                               }
+                               status &= ~RxUnderrun;
+                       }
+                       if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
+                               tp->stats.rx_errors++;
+
+                       if (status & (PCSTimeout)) tp->stats.rx_length_errors++;
+                       if (status & (RxUnderrun|RxFIFOOver)) tp->stats.rx_fifo_errors++;
+                       if (status & RxOverflow) {
+                               tp->stats.rx_over_errors++;
+                               tp->cur_rx = inw(ioaddr + RxBufAddr) % RX_BUF_LEN;
+                               outw(tp->cur_rx - 16, ioaddr + RxBufPtr);
+                       }
+                       if (status & PCIErr) {
+                               u32 pci_cmd_status;
+                               pcibios_read_config_dword(tp->pci_bus, tp->pci_devfn,
+                                                                                 PCI_COMMAND, &pci_cmd_status);
+
+                               printk(KERN_ERR "%s: PCI Bus error %4.4x.\n",
+                                          dev->name, pci_cmd_status);
+                       }
+               }
+               if (--boguscnt < 0) {
+                       printk(KERN_WARNING"%s: Too much work at interrupt, "
+                                  "IntrStatus=0x%4.4x.\n",
+                                  dev->name, status);
+                       /* Clear all interrupt sources. */
+                       outw(0xffff, ioaddr + IntrStatus);
+                       break;
+               }
+       } while (1);
+
+       if (rtl8129_debug > 3)
+               printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n",
+                          dev->name, inl(ioaddr + IntrStatus));
+       return;
+}
+
+/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
+   field alignments and semantics. */
+static int rtl8129_rx(struct net_device *dev)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       unsigned char *rx_ring = tp->rx_ring;
+       u16 cur_rx = tp->cur_rx;
+
+       if (rtl8129_debug > 4)
+               printk(KERN_DEBUG"%s: In rtl8129_rx(), current %4.4x BufAddr %4.4x,"
+                          " free to %4.4x, Cmd %2.2x.\n",
+                          dev->name, cur_rx, inw(ioaddr + RxBufAddr),
+                          inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd));
+
+       while ((inb(ioaddr + ChipCmd) & 1) == 0) {
+               int ring_offset = cur_rx % RX_BUF_LEN;
+               u32 rx_status = le32_to_cpu(*(u32*)(rx_ring + ring_offset));
+               int rx_size = rx_status >> 16;
+
+               if (rtl8129_debug > 4) {
+                       int i;
+                       printk(KERN_DEBUG"%s:  rtl8129_rx() status %4.4x, size %4.4x, cur %4.4x.\n",
+                                  dev->name, rx_status, rx_size, cur_rx);
+                       printk(KERN_DEBUG"%s: Frame contents ", dev->name);
+                       for (i = 0; i < 70; i++)
+                               printk(" %2.2x", le32_to_cpu(rx_ring[ring_offset + i]));
+                       printk(".\n");
+               }
+               if (rx_status & RxTooLong) {
+                       if (rtl8129_debug > 0)
+                               printk(KERN_NOTICE"%s: Oversized Ethernet frame, status %4.4x!\n",
+                                          dev->name, rx_status);
+                       tp->stats.rx_length_errors++;
+               } else if (rx_status &
+                                  (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) {
+                       if (rtl8129_debug > 1)
+                               printk(KERN_DEBUG"%s: Ethernet frame had errors,"
+                                          " status %4.4x.\n", dev->name, rx_status);
+                       tp->stats.rx_errors++;
+                       if (rx_status & (RxBadSymbol|RxBadAlign))
+                               tp->stats.rx_frame_errors++;
+                       if (rx_status & (RxRunt|RxTooLong)) tp->stats.rx_length_errors++;
+                       if (rx_status & RxCRCErr) tp->stats.rx_crc_errors++;
+                       /* Reset the receiver, based on RealTek recommendation. (Bug?) */
+                       tp->cur_rx = 0;
+                       outb(CmdTxEnb, ioaddr + ChipCmd);
+                       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+                       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) |
+                                (RX_DMA_BURST<<8), ioaddr + RxConfig);
+               } else {
+                       /* Malloc up new buffer, compatible with net-2e. */
+                       /* Omit the four octet CRC from the length. */
+                       struct sk_buff *skb;
+
+                       skb = dev_alloc_skb(rx_size + 2);
+                       if (skb == NULL) {
+                               printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n",
+                                          dev->name);
+                               /* We should check that some rx space is free.
+                                  If not, free one and mark stats->rx_dropped++. */
+                               tp->stats.rx_dropped++;
+                               break;
+                       }
+                       skb->dev = dev;
+                       skb_reserve(skb, 2);    /* 16 byte align the IP fields. */
+                       if (ring_offset+rx_size+4 > RX_BUF_LEN) {
+                               int semi_count = RX_BUF_LEN - ring_offset - 4;
+                               memcpy(skb_put(skb, semi_count), &rx_ring[ring_offset + 4],
+                                          semi_count);
+                               memcpy(skb_put(skb, rx_size-semi_count), rx_ring,
+                                          rx_size-semi_count);
+                               if (rtl8129_debug > 4) {
+                                       int i;
+                                       printk(KERN_DEBUG"%s:  Frame wrap @%d",
+                                                  dev->name, semi_count);
+                                       for (i = 0; i < 16; i++)
+                                               printk(" %2.2x", le32_to_cpu(rx_ring[i]));
+                                       printk(".\n");
+                                       memset(rx_ring, 0xcc, 16);
+                               }
+                       } else {
+#if 1  /* USE_IP_COPYSUM */
+                               eth_copy_and_sum(skb, &rx_ring[ring_offset + 4],
+                                                                rx_size, 0);
+                               skb_put(skb, rx_size);
+#else
+                               memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4],
+                                          rx_size);
+#endif
+                       }
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);
+#if LINUX_VERSION_CODE > 0x20119
+                       tp->stats.rx_bytes += rx_size;
+#endif
+                       tp->stats.rx_packets++;
+               }
+
+               cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
+               outw(cur_rx - 16, ioaddr + RxBufPtr);
+       }
+       if (rtl8129_debug > 4)
+               printk(KERN_DEBUG"%s: Done rtl8129_rx(), current %4.4x BufAddr %4.4x,"
+                          " free to %4.4x, Cmd %2.2x.\n",
+                          dev->name, cur_rx, inw(ioaddr + RxBufAddr),
+                          inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd));
+       tp->cur_rx = cur_rx;
+       return 0;
+}
+
+static int
+rtl8129_close(struct net_device *dev)
+{
+       long ioaddr = dev->base_addr;
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       int i;
+
+       netif_stop_queue(dev);
+
+       if (rtl8129_debug > 1)
+               printk(KERN_DEBUG"%s: Shutting down ethercard, status was 0x%4.4x.\n",
+                          dev->name, inw(ioaddr + IntrStatus));
+
+       /* Disable interrupts by clearing the interrupt mask. */
+       outw(0x0000, ioaddr + IntrMask);
+
+       /* Stop the chip's Tx and Rx DMA processes. */
+       outb(0x00, ioaddr + ChipCmd);
+
+       /* Update the error counts. */
+       tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
+       outl(0, ioaddr + RxMissed);
+
+       del_timer(&tp->timer);
+
+       free_irq(dev->irq, dev);
+
+       for (i = 0; i < NUM_TX_DESC; i++) {
+               struct sk_buff *skb = tp->tx_info[i].skb;
+               dma_addr_t mapping = tp->tx_info[i].mapping;
+
+               if (skb) {
+                       if (mapping)
+                               pci_unmap_single(tp->pdev, mapping, skb->len);
+                       dev_kfree_skb(skb);
+               }
+               tp->tx_info[i].skb = NULL;
+               tp->tx_info[i].mapping = 0;
+       }
+       pci_free_consistent(tp->pdev, RX_BUF_LEN + 16,
+                                               tp->rx_ring, tp->rx_ring_dma);
+       pci_free_consistent(tp->pdev, TX_BUF_SIZE * NUM_TX_DESC,
+                                               tp->tx_bufs, tp->tx_bufs_dma);
+       tp->rx_ring = NULL;
+       tp->tx_bufs = NULL;
+
+       /* Green! Put the chip in low-power mode. */
+       outb(0xC0, ioaddr + Cfg9346);
+       outb(0x03, ioaddr + Config1);
+       outb('H', ioaddr + HltClk);             /* 'R' would leave the clock running. */
+
+       MOD_DEC_USE_COUNT;
+
+       return 0;
+}
+
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       u16 *data = (u16 *)&rq->ifr_data;
+
+       switch(cmd) {
+       case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
+               data[0] = tp->phys[0] & 0x3f;
+               /* Fall Through */
+       case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
+               data[3] = mdio_read(dev, data[0], data[1] & 0x1f);
+               return 0;
+       case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               mdio_write(dev, data[0], data[1] & 0x1f, data[2]);
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+static struct enet_statistics *
+rtl8129_get_stats(struct net_device *dev)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+
+       if (test_bit(LINK_STATE_START, &dev->state)) {
+               tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
+               outl(0, ioaddr + RxMissed);
+       }
+
+       return &tp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+   This routine is not state sensitive and need not be SMP locked. */
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+    int crc = -1;
+
+    while (--length >= 0) {
+               unsigned char current_octet = *data++;
+               int bit;
+               for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+                       crc = (crc << 1) ^
+                               ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+    }
+    return crc;
+}
+
+/* Bits in RxConfig. */
+enum rx_mode_bits {
+       AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08,
+       AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01,
+};
+
+static void set_rx_mode(struct net_device *dev)
+{
+       long ioaddr = dev->base_addr;
+       u32 mc_filter[2];                /* Multicast hash filter */
+       int i, rx_mode;
+
+       if (rtl8129_debug > 3)
+               printk(KERN_DEBUG"%s:   set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
+                          dev->name, dev->flags, inl(ioaddr + RxConfig));
+
+       /* Note: do not reorder, GCC is clever about common statements. */
+       if (dev->flags & IFF_PROMISC) {
+               /* Unconditionally log net taps. */
+               printk(KERN_NOTICE"%s: Promiscuous mode enabled.\n", dev->name);
+               rx_mode = AcceptBroadcast|AcceptMulticast|AcceptMyPhys|AcceptAllPhys;
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+       } else if ((dev->mc_count > multicast_filter_limit)
+                          ||  (dev->flags & IFF_ALLMULTI)) {
+               /* Too many to filter perfectly -- accept all multicasts. */
+               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+       } else {
+               struct dev_mc_list *mclist;
+               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+               mc_filter[1] = mc_filter[0] = 0;
+               for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+                        i++, mclist = mclist->next)
+                       set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter);
+       }
+       /* We can safely update without stopping the chip. */
+       outb(rx_mode, ioaddr + RxConfig);
+       outl(mc_filter[0], ioaddr + MAR0 + 0);
+       outl(mc_filter[1], ioaddr + MAR0 + 4);
+       return;
+}
+\f
+#ifdef MODULE
+int init_module(void)
+{
+       return rtl8139_probe();
+}
+
+void
+cleanup_module(void)
+{
+       struct net_device *next_dev;
+
+       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+       while (root_rtl8129_dev) {
+               struct rtl8129_private *tp =
+                       (struct rtl8129_private *)root_rtl8129_dev->priv;
+               next_dev = tp->next_module;
+               unregister_netdev(root_rtl8129_dev);
+               release_region(root_rtl8129_dev->base_addr,
+                                          pci_tbl[tp->chip_id].io_size);
+               kfree(tp);
+               kfree(root_rtl8129_dev);
+               root_rtl8129_dev = next_dev;
+       }
+}
+
+#endif  /* MODULE */
+\f
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
deleted file mode 100644 (file)
index 25efb4a..0000000
+++ /dev/null
@@ -1,1473 +0,0 @@
-/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
-/*
-       Written 1997-1999 by Donald Becker.
-
-       This software may be used and distributed according to the terms
-       of the GNU Public License, incorporated herein by reference.
-    All other rights reserved.
-
-       This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet
-       chips.
-
-       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-       Center of Excellence in Space Data and Information Sciences
-          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-
-       Support and updates available at
-       http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html
-
-       Twister-tuning table provided by Kinston <shangh@realtek.com.tw>.
-*/
-
-static const char *version =
-"rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
-
-/* A few user-configurable values. */
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-#define rtl8129_debug debug
-static int rtl8129_debug = 1;
-
-/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
-   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
-static int multicast_filter_limit = 32;
-
-/* Used to pass the full-duplex flag, etc. */
-#define MAX_UNITS 8            /* More are supported, limit only on options */
-static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* Size of the in-memory receive ring. */
-#define RX_BUF_LEN_IDX 3                       /* 0==8K, 1==16K, 2==32K, 3==64K */
-#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
-/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
-#define TX_BUF_SIZE    1536
-
-/* PCI Tuning Parameters
-   Threshold is bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 256     /* In bytes, rounded down to 32 byte units. */
-
-/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024. */
-#define RX_FIFO_THRESH 4               /* Rx buffer level before first PCI xfer.  */
-#define RX_DMA_BURST   4               /* Maximum PCI burst, '4' is 256 bytes */
-#define TX_DMA_BURST   4               /* Calculate as 16<<val. */
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (4*HZ)
-
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/malloc.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <asm/processor.h>             /* Processor type for cache alignment. */
-#include <asm/bitops.h>
-#include <asm/io.h>
-
-/* Kernel compatibility defines, some common to David Hind's PCMCIA package.
-   This is only in the support-all-kernels source code. */
-
-#define RUN_AT(x) (jiffies + (x))
-
-#include <linux/delay.h>
-
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define        net_device_stats enet_statistics
-#else
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
-/* Grrrr, the PCI code changed, but did not consider CardBus... */
-#include <linux/bios32.h>
-#define PCI_SUPPORT_VER1
-#else
-#define PCI_SUPPORT_VER2
-#endif
-
-/* The I/O extent. */
-#define RTL8129_TOTAL_SIZE 0x80
-
-/*
-                               Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the RealTek RTL8129, the RealTek Fast
-Ethernet controllers for PCI.  This chip is used on a few clone boards.
-
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS will assign the
-PCI INTA signal to a (preferably otherwise unused) system IRQ line.
-Note: Kernel versions earlier than 1.3.73 do not support shared PCI
-interrupt lines.
-
-III. Driver operation
-
-IIIa. Rx Ring buffers
-
-The receive unit uses a single linear ring buffer rather than the more
-common (and more efficient) descriptor-based architecture.  Incoming frames
-are sequentially stored into the Rx region, and the host copies them into
-skbuffs.
-
-Comment: While it is theoretically possible to process many frames in place,
-any delay in Rx processing would cause us to drop frames.  More importantly,
-the Linux protocol stack is not designed to operate in this manner.
-
-IIIb. Tx operation
-
-The RTL8129 uses a fixed set of four Tx descriptors in register space.
-In a stunningly bad design choice, Tx frames must be 32 bit aligned.  Linux
-aligns the IP header on word boundaries, and 14 byte ethernet header means
-that almost all frames will need to be copied to an alignment buffer.
-
-IVb. References
-
-http://www.realtek.com.tw/cn/cn.html
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-
-IVc. Errata
-
-*/
-\f
-
-/* This table drives the PCI probe routines.  It's mostly boilerplate in all
-   of the drivers, and will likely be provided by some future kernel.
-   Note the matching code -- the first table entry matchs all 56** cards but
-   second only the 1234 card.
-*/
-enum pci_flags_bit {
-       PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-       PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
-};
-struct pci_id_info {
-       const char *name;
-       u16     vendor_id, device_id, device_id_mask, flags;
-       int io_size;
-       struct net_device *(*probe1)(struct pci_dev *pdev, int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
-};
-
-static struct net_device * rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
-                                                                                 int pci_devfn, long ioaddr,
-                                                                                 int irq, int chp_idx, int fnd_cnt);
-
-static struct pci_id_info pci_tbl[] =
-{{ "RealTek RTL8129 Fast Ethernet",
-   0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
- { "RealTek RTL8139 Fast Ethernet",
-   0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
- { "SMC1211TX EZCard 10/100 (RealTek RTL8139)",
-   0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
- { "Accton MPX5030 (RealTek RTL8139)",
-   0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
- {0,},                                         /* 0 terminated list. */
-};
-
-/* The capability table matches the chip table above. */
-enum {HAS_MII_XCVR=0x01, HAS_CHIP_XCVR=0x02, HAS_LNK_CHNG=0x04};
-static int rtl_cap_tbl[] = {
-       HAS_MII_XCVR, HAS_CHIP_XCVR|HAS_LNK_CHNG, HAS_CHIP_XCVR|HAS_LNK_CHNG,
-};
-
-
-/* The rest of these values should never change. */
-#define NUM_TX_DESC    4                       /* Number of Tx descriptor registers. */
-
-/* Symbolic offsets to registers. */
-enum RTL8129_registers {
-       MAC0=0,                                         /* Ethernet hardware address. */
-       MAR0=8,                                         /* Multicast filter. */
-       TxStatus0=0x10,                         /* Transmit status (Four 32bit registers). */
-       TxAddr0=0x20,                           /* Tx descriptors (also four 32bit). */
-       RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36,
-       ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A,
-       IntrMask=0x3C, IntrStatus=0x3E,
-       TxConfig=0x40, RxConfig=0x44,
-       Timer=0x48,                                     /* A general-purpose counter. */
-       RxMissed=0x4C,                          /* 24 bits valid, write clears. */
-       Cfg9346=0x50, Config0=0x51, Config1=0x52,
-       FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B,
-       MultiIntr=0x5C, TxSummary=0x60,
-       MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68,
-       NWayExpansion=0x6A,
-       /* Undocumented registers, but required for proper operation. */
-       FIFOTMS=0x70,   /* FIFO Test Mode Select */
-       CSCR=0x74,      /* Chip Status and Configuration Register. */
-       PARA78=0x78, PARA7c=0x7c,       /* Magic transceiver parameter register. */
-};
-
-enum ChipCmdBits {
-       CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, };
-
-/* Interrupt register bits, using my own meaningful names. */
-enum IntrStatusBits {
-       PCIErr=0x8000, PCSTimeout=0x4000,
-       RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10,
-       TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01,
-};
-enum TxStatusBits {
-       TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000,
-       TxOutOfWindow=0x20000000, TxAborted=0x40000000, TxCarrierLost=0x80000000,
-};
-enum RxStatusBits {
-       RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000,
-       RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004,
-       RxBadAlign=0x0002, RxStatusOK=0x0001,
-};
-
-/* Twister tuning parameters from RealTek.
-   Completely undocumented, but required to tune bad links. */
-enum CSCRBits {
-       CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
-       CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
-       CSCR_LinkDownCmd=0x0f3c0,
-};
-unsigned long param[4][4]={
-       {0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43},
-       {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
-       {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
-       {0x0bb39de43,0x0bb39ce43,0x0bb39ce83,0x0bb39ce83}
-};
-
-struct ring_info {
-       struct sk_buff *skb;
-       dma_addr_t mapping;
-};
-
-struct rtl8129_private {
-       char devname[8];                        /* Used only for kernel debugging. */
-       const char *product_name;
-       struct net_device *next_module;
-       struct pci_dev *pdev;
-       int chip_id;
-       int chip_revision;
-       unsigned char pci_bus, pci_devfn;
-#if LINUX_VERSION_CODE > 0x20139
-       struct net_device_stats stats;
-#else
-       struct enet_statistics stats;
-#endif
-       struct timer_list timer;        /* Media selection timer. */
-       unsigned int cur_rx;            /* Index into the Rx buffer of next Rx pkt. */
-       unsigned int cur_tx, dirty_tx, tx_flag;
-       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
-       struct ring_info tx_info[NUM_TX_DESC];
-       unsigned char *tx_buf[NUM_TX_DESC];     /* Tx bounce buffers */
-       unsigned char *rx_ring;
-       unsigned char *tx_bufs;                         /* Tx bounce buffer region. */
-       dma_addr_t rx_ring_dma;
-       dma_addr_t tx_bufs_dma;
-       char phys[4];                                           /* MII device addresses. */
-       char twistie, twist_cnt;                        /* Twister tune state. */
-       unsigned int tx_full:1;                         /* The Tx queue is full. */
-       unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
-       unsigned int duplex_lock:1;
-       unsigned int default_port:4;            /* Last dev->if_port value. */
-       unsigned int media2:4;                          /* Secondary monitored media port. */
-       unsigned int medialock:1;                       /* Don't sense media type. */
-       unsigned int mediasense:1;                      /* Media sensing in progress. */
-};
-
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20115
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(multicast_filter_limit, "i");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(debug, "i");
-#endif
-#endif
-
-static int rtl8129_open(struct net_device *dev);
-static int read_eeprom(long ioaddr, int location);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int val);
-static void rtl8129_timer(unsigned long data);
-static void rtl8129_tx_timeout(struct net_device *dev);
-static void rtl8129_init_ring(struct net_device *dev);
-static int rtl8129_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int rtl8129_rx(struct net_device *dev);
-static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int rtl8129_close(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct enet_statistics *rtl8129_get_stats(struct net_device *dev);
-static inline u32 ether_crc(int length, unsigned char *data);
-static void set_rx_mode(struct net_device *dev);
-\f
-
-/* A list of all installed RTL8129 devices, for removing the driver module. */
-static struct net_device *root_rtl8129_dev = NULL;
-
-/* Ideally we would detect all network cards in slot order.  That would
-   be best done a central PCI probe dispatch, which wouldn't work
-   well when dynamically adding drivers.  So instead we detect just the
-   Rtl81*9 cards in slot order. */
-
-int rtl8139_probe(void)
-{
-       int cards_found = 0;
-       int pci_index = 0;
-       unsigned char pci_bus, pci_device_fn;
-       struct net_device *dev;
-
-       if ( ! pcibios_present())
-               return -ENODEV;
-
-       for (; pci_index < 0xff; pci_index++) {
-               struct pci_dev *pdev;
-               u16 vendor, device, pci_command, new_command;
-               int chip_idx, irq;
-               long ioaddr;
-
-               if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
-                                                               &pci_bus, &pci_device_fn)
-                       != PCIBIOS_SUCCESSFUL)
-                       break;
-               pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                PCI_VENDOR_ID, &vendor);
-               pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                PCI_DEVICE_ID, &device);
-
-               for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
-                       if (vendor == pci_tbl[chip_idx].vendor_id
-                               && (device & pci_tbl[chip_idx].device_id_mask) ==
-                               pci_tbl[chip_idx].device_id)
-                               break;
-               if (pci_tbl[chip_idx].vendor_id == 0)           /* Compiled out! */
-                       continue;
-
-               pdev = pci_find_slot(pci_bus, pci_device_fn);
-               ioaddr = pdev->resource[0].start;
-               irq = pdev->irq;
-
-               if ((pci_tbl[chip_idx].flags & PCI_USES_IO) &&
-                       check_region(ioaddr, pci_tbl[chip_idx].io_size))
-                       continue;
-
-               /* Activate the card: fix for brain-damaged Win98 BIOSes. */
-               pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                PCI_COMMAND, &pci_command);
-               new_command = pci_command | (pci_tbl[chip_idx].flags & 7);
-               if (pci_command != new_command) {
-                       printk(KERN_INFO "  The PCI BIOS has not enabled the"
-                                  " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
-                                  pci_bus, pci_device_fn, pci_command, new_command);
-                       pcibios_write_config_word(pci_bus, pci_device_fn,
-                                                                         PCI_COMMAND, new_command);
-               }
-
-               dev = pci_tbl[chip_idx].probe1(pdev, pci_bus, pci_device_fn, ioaddr, irq, chip_idx, cards_found);
-
-               if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
-                       u8 pci_latency;
-                       pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                        PCI_LATENCY_TIMER, &pci_latency);
-                       if (pci_latency < 32) {
-                               printk(KERN_NOTICE "  PCI latency timer (CFLT) is "
-                                          "unreasonably low at %d.  Setting to 64 clocks.\n",
-                                          pci_latency);
-                               pcibios_write_config_byte(pci_bus, pci_device_fn,
-                                                                                 PCI_LATENCY_TIMER, 64);
-                       }
-               }
-               dev = 0;
-               cards_found++;
-       }
-
-       return cards_found ? 0 : -ENODEV;
-}
-
-static struct net_device *rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
-                                                                                int pci_devfn, long ioaddr,
-                                                                                int irq, int chip_idx, int found_cnt)
-{
-       static int did_version = 0;                     /* Already printed version info. */
-       struct rtl8129_private *tp;
-       int i, option = found_cnt < MAX_UNITS ? options[found_cnt] : 0;
-       struct net_device *dev;
-
-       if (rtl8129_debug > 0  &&  did_version++ == 0)
-               printk(KERN_INFO "%s", version);
-
-       dev = init_etherdev(NULL, 0);
-
-       printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
-                  dev->name, pci_tbl[chip_idx].name, ioaddr, irq);
-
-       /* Bring the chip out of low-power mode. */
-       outb(0x00, ioaddr + Config1);
-
-       if (read_eeprom(ioaddr, 0) != 0xffff) {
-               for (i = 0; i < 3; i++) {
-                       ((u16 *)(dev->dev_addr))[i] =
-                               le16_to_cpu(read_eeprom(ioaddr, i + 7));
-               }
-       } else {
-               for (i = 0; i < 6; i++)
-                       dev->dev_addr[i] = inb(ioaddr + MAC0 + i);
-       }
-       for (i = 0; i < 5; i++)
-               printk("%2.2x:", dev->dev_addr[i]);
-       printk("%2.2x.\n", dev->dev_addr[i]);
-
-       /* We do a request_region() to register /proc/ioports info. */
-       request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
-
-       dev->base_addr = ioaddr;
-       dev->irq = irq;
-
-       /* Some data structures must be quadword aligned. */
-       tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
-       memset(tp, 0, sizeof(*tp));
-       dev->priv = tp;
-
-       tp->next_module = root_rtl8129_dev;
-       root_rtl8129_dev = dev;
-
-       tp->pdev = pdev;
-       tp->chip_id = chip_idx;
-       tp->pci_bus = pci_bus;
-       tp->pci_devfn = pci_devfn;
-
-       /* Find the connected MII xcvrs.
-          Doing this in open() would allow detecting external xcvrs later, but
-          takes too much time. */
-       if (rtl_cap_tbl[chip_idx] & HAS_MII_XCVR) {
-               int phy, phy_idx;
-               for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
-                        phy++) {
-                       int mii_status = mdio_read(dev, phy, 1);
-                       if (mii_status != 0xffff  && mii_status != 0x0000) {
-                               tp->phys[phy_idx++] = phy;
-                               printk(KERN_INFO "%s: MII transceiver found at address %d.\n",
-                                          dev->name, phy);
-                       }
-               }
-               if (phy_idx == 0) {
-                       printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "
-                                  "transceiver.\n",
-                                  dev->name);
-                       tp->phys[0] = -1;
-               }
-       } else
-               tp->phys[0] = 32;
-
-       /* Put the chip into low-power mode. */
-       outb(0xC0, ioaddr + Cfg9346);
-       outb(0x03, ioaddr + Config1);
-       outb('H', ioaddr + HltClk);             /* 'R' would leave the clock running. */
-
-       /* The lower four bits are the media type. */
-       if (option > 0) {
-               tp->full_duplex = (option & 0x200) ? 1 : 0;
-               tp->default_port = option & 15;
-               if (tp->default_port)
-                       tp->medialock = 1;
-       }
-
-       if (found_cnt < MAX_UNITS  &&  full_duplex[found_cnt] > 0)
-               tp->full_duplex = full_duplex[found_cnt];
-
-       if (tp->full_duplex) {
-               printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
-               mdio_write(dev, tp->phys[0], 4, 0x141);
-               tp->duplex_lock = 1;
-       }
-
-       /* The Rtl8129-specific entries in the device structure. */
-       dev->open = &rtl8129_open;
-       dev->hard_start_xmit = &rtl8129_start_xmit;
-       dev->tx_timeout = &rtl8129_tx_timeout;
-       dev->watchdog_timeo = TX_TIMEOUT;
-       dev->stop = &rtl8129_close;
-       dev->get_stats = &rtl8129_get_stats;
-       dev->set_multicast_list = &set_rx_mode;
-       dev->do_ioctl = &mii_ioctl;
-
-       return dev;
-}
-\f
-/* Serial EEPROM section. */
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK   0x04    /* EEPROM shift clock. */
-#define EE_CS                  0x08    /* EEPROM chip select. */
-#define EE_DATA_WRITE  0x02    /* EEPROM chip data in. */
-#define EE_WRITE_0             0x00
-#define EE_WRITE_1             0x02
-#define EE_DATA_READ   0x01    /* EEPROM chip data out. */
-#define EE_ENB                 (0x80 | EE_CS)
-
-/* Delay between EEPROM clock transitions.
-   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
- */
-
-#define eeprom_delay() inl(ee_addr)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD   (5 << 6)
-#define EE_READ_CMD            (6 << 6)
-#define EE_ERASE_CMD   (7 << 6)
-
-static int read_eeprom(long ioaddr, int location)
-{
-       int i;
-       unsigned retval = 0;
-       long ee_addr = ioaddr + Cfg9346;
-       int read_cmd = location | EE_READ_CMD;
-
-       outb(EE_ENB & ~EE_CS, ee_addr);
-       outb(EE_ENB, ee_addr);
-
-       /* Shift the read command bits out. */
-       for (i = 10; i >= 0; i--) {
-               int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-               outb(EE_ENB | dataval, ee_addr);
-               eeprom_delay();
-               outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay();
-       }
-       outb(EE_ENB, ee_addr);
-       eeprom_delay();
-
-       for (i = 16; i > 0; i--) {
-               outb(EE_ENB | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay();
-               retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0);
-               outb(EE_ENB, ee_addr);
-               eeprom_delay();
-       }
-
-       /* Terminate the EEPROM access. */
-       outb(~EE_CS, ee_addr);
-       return retval;
-}
-
-/* MII serial management: mostly bogus for now. */
-/* Read and write the MII management registers using software-generated
-   serial MDIO protocol.
-   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
-   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
-   "overclocking" issues. */
-#define MDIO_DIR               0x80
-#define MDIO_DATA_OUT  0x04
-#define MDIO_DATA_IN   0x02
-#define MDIO_CLK               0x01
-#define MDIO_WRITE0 (MDIO_DIR)
-#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
-
-#define mdio_delay()   inb(mdio_addr)
-
-static char mii_2_8139_map[8] = {MII_BMCR, MII_BMSR, 0, 0, NWayAdvert,
-                                                                NWayLPAR, NWayExpansion, 0 };
-
-/* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_sync(long mdio_addr)
-{
-       int i;
-
-       for (i = 32; i >= 0; i--) {
-               outb(MDIO_WRITE1, mdio_addr);
-               mdio_delay();
-               outb(MDIO_WRITE1 | MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-       return;
-}
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-       long mdio_addr = dev->base_addr + MII_SMI;
-       int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-       int retval = 0;
-       int i;
-
-       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
-               return location < 8 && mii_2_8139_map[location] ?
-                       inw(dev->base_addr + mii_2_8139_map[location]) : 0;
-       }
-       mdio_sync(mdio_addr);
-       /* Shift the read command bits out. */
-       for (i = 15; i >= 0; i--) {
-               int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
-
-               outb(MDIO_DIR | dataval, mdio_addr);
-               mdio_delay();
-               outb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-
-       /* Read the two transition, 16 data, and wire-idle bits. */
-       for (i = 19; i > 0; i--) {
-               outb(0, mdio_addr);
-               mdio_delay();
-               retval = (retval << 1) | ((inb(mdio_addr) & MDIO_DATA_IN) ? 1 : 0);
-               outb(MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-       return (retval>>1) & 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-       long mdio_addr = dev->base_addr + MII_SMI;
-       int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
-       int i;
-
-       if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */
-               if (location < 8  &&  mii_2_8139_map[location])
-                       outw(value, dev->base_addr + mii_2_8139_map[location]);
-               return;
-       }
-       mdio_sync(mdio_addr);
-
-       /* Shift the command bits out. */
-       for (i = 31; i >= 0; i--) {
-               int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
-               outb(dataval, mdio_addr);
-               mdio_delay();
-               outb(dataval | MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-       /* Clear out extra bits. */
-       for (i = 2; i > 0; i--) {
-               outb(0, mdio_addr);
-               mdio_delay();
-               outb(MDIO_CLK, mdio_addr);
-               mdio_delay();
-       }
-       return;
-}
-
-\f
-static int
-rtl8129_open(struct net_device *dev)
-{
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       long ioaddr = dev->base_addr;
-       int i;
-
-       /* Soft reset the chip. */
-       outb(CmdReset, ioaddr + ChipCmd);
-
-       if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev)) {
-               return -EAGAIN;
-       }
-
-       MOD_INC_USE_COUNT;
-
-       tp->tx_bufs = pci_alloc_consistent(tp->pdev,
-                                                                          TX_BUF_SIZE * NUM_TX_DESC,
-                                                                          &tp->tx_bufs_dma);
-       tp->rx_ring = pci_alloc_consistent(tp->pdev,
-                                                                          RX_BUF_LEN + 16,
-                                                                          &tp->rx_ring_dma);
-       if (tp->tx_bufs == NULL ||  tp->rx_ring == NULL) {
-               free_irq(dev->irq, dev);
-               if (tp->tx_bufs)
-                       pci_free_consistent(tp->pdev,
-                                                               TX_BUF_SIZE * NUM_TX_DESC,
-                                                               tp->tx_bufs, tp->tx_bufs_dma);
-               if (tp->rx_ring)
-                       pci_free_consistent(tp->pdev,
-                                                               RX_BUF_LEN + 16,
-                                                               tp->rx_ring, tp->rx_ring_dma);
-               if (rtl8129_debug > 0)
-                       printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n",
-                                  dev->name, RX_BUF_LEN);
-               return -ENOMEM;
-       }
-       rtl8129_init_ring(dev);
-
-       /* Check that the chip has finished the reset. */
-       for (i = 1000; i > 0; i--)
-               if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
-                       break;
-
-       for (i = 0; i < 6; i++)
-               outb(dev->dev_addr[i], ioaddr + MAC0 + i);
-
-       /* Must enable Tx/Rx before setting transfer thresholds! */
-       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
-       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),
-                ioaddr + RxConfig);
-       outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig);
-       tp->tx_flag = (TX_FIFO_THRESH<<11) & 0x003f0000;
-
-       tp->full_duplex = tp->duplex_lock;
-       if (tp->phys[0] >= 0  ||  (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)) {
-               u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
-               if (mii_reg5 == 0xffff)
-                       ;                                       /* Not there */
-               else if ((mii_reg5 & 0x0100) == 0x0100
-                                || (mii_reg5 & 0x00C0) == 0x0040)
-                       tp->full_duplex = 1;
-               if (rtl8129_debug > 1)
-                       printk(KERN_INFO"%s: Setting %s%s-duplex based on"
-                                  " auto-negotiated partner ability %4.4x.\n", dev->name,
-                                  mii_reg5 == 0 ? "" :
-                                  (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
-                                  tp->full_duplex ? "full" : "half", mii_reg5);
-       }
-
-       outb(0xC0, ioaddr + Cfg9346);
-       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
-       outb(0x00, ioaddr + Cfg9346);
-
-       outl(tp->rx_ring_dma, ioaddr + RxBuf);
-
-       /* Start the chip's Tx and Rx process. */
-       outl(0, ioaddr + RxMissed);
-       set_rx_mode(dev);
-
-       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
-
-       /* Enable all known interrupts by setting the interrupt mask. */
-       outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
-                | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
-
-       if (rtl8129_debug > 1)
-               printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d"
-                          " GP Pins %2.2x %s-duplex.\n",
-                          dev->name, ioaddr, dev->irq, inb(ioaddr + GPPinData),
-                          tp->full_duplex ? "full" : "half");
-
-       /* Set the timer to switch to check for link beat and perhaps switch
-          to an alternate media type. */
-       init_timer(&tp->timer);
-       tp->timer.expires = RUN_AT((24*HZ)/10);                 /* 2.4 sec. */
-       tp->timer.data = (unsigned long)dev;
-       tp->timer.function = &rtl8129_timer;
-       add_timer(&tp->timer);
-
-       return 0;
-}
-
-static void rtl8129_timer(unsigned long data)
-{
-       struct net_device *dev = (struct net_device *)data;
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       long ioaddr = dev->base_addr;
-       int next_tick = 60*HZ;
-       int mii_reg5 = mdio_read(dev, tp->phys[0], 5);
-
-       if (! tp->duplex_lock  &&  mii_reg5 != 0xffff) {
-               int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
-               if (tp->full_duplex != duplex) {
-                       tp->full_duplex = duplex;
-                       printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
-                                  " partner ability of %4.4x.\n", dev->name,
-                                  tp->full_duplex ? "full" : "half", tp->phys[0], mii_reg5);
-                       outb(0xC0, ioaddr + Cfg9346);
-                       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
-                       outb(0x00, ioaddr + Cfg9346);
-               }
-       }
-       /* Check for bogusness. */
-       if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) {
-               int status = inw(ioaddr + IntrStatus);
-               if (status & (TxOK | RxOK)) {   /* Double check */
-                       printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n",
-                                  dev->name, status);
-                       rtl8129_interrupt(dev->irq, dev, 0);
-               }
-       }
-       if (test_bit(LINK_STATE_XOFF, &dev->state) &&
-               (jiffies - dev->trans_start) >= 2*TX_TIMEOUT)
-               rtl8129_tx_timeout(dev);
-
-#if 0
-       if (tp->twistie) {
-               unsigned int CSCRval = inw(ioaddr + CSCR);              /* Read link status. */
-               if (tp->twistie == 1) {
-                       if (CSCRval & CSCR_LinkOKBit) {
-                               outw(CSCR_LinkDownOffCmd, ioaddr + CSCR);
-                               tp->twistie = 2;
-                               next_tick = HZ/10;
-                       } else {
-                               outw(CSCR_LinkDownCmd, ioaddr + CSCR);
-                               outl(FIFOTMS_default,ioaddr + FIFOTMS);
-                               outl(PARA78_default ,ioaddr + PARA78);
-                               outl(PARA7c_default ,ioaddr + PARA7c);
-                               tp->twistie = 0;
-                       }
-               } else if (tp->twistie == 2) {
-                       int linkcase = (CSCRval & CSCR_LinkStatusBits) >> 12;
-                       int row;
-                       if (linkcase >= 0x7000) row = 3;
-                       else if (linkcase >= 0x3000) row = 2;
-                       else if (linkcase >= 0x1000) row = 1;
-                       else row = 0;
-                       tp->twistie == row + 3;
-                       outw(0,ioaddr+FIFOTMS);
-                       outl(param[row][0], ioaddr+PARA7c);
-                       tp->twist_cnt = 1;
-               } else {
-                       outl(param[tp->twistie-3][tp->twist_cnt], ioaddr+PARA7c);
-                       if (++tp->twist_cnt < 4) {
-                               next_tick = HZ/10;
-                       } else if (tp->twistie-3 == 3) {
-                               if ((CSCRval & CSCR_LinkStatusBits) != 0x7000) {
-                                       outl(PARA7c_xxx, ioaddr+PARA7c);
-                                       next_tick = HZ/10;              /* 100ms. */
-                                       outl(FIFOTMS_default, ioaddr+FIFOTMS);
-                                       outl(PARA78_default,  ioaddr+PARA78);
-                                       outl(PARA7c_default,  ioaddr+PARA7c);
-                                       tp->twistie == 3 + 3;
-                                       outw(0,ioaddr+FIFOTMS);
-                                       outl(param[3][0], ioaddr+PARA7c);
-                                       tp->twist_cnt = 1;
-                               }
-                       }
-               }
-       }
-#endif
-
-       if (rtl8129_debug > 2) {
-               if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)
-                       printk(KERN_DEBUG"%s: Media selection tick, GP pins %2.2x.\n",
-                                  dev->name, inb(ioaddr + GPPinData));
-               else
-                       printk(KERN_DEBUG"%s: Media selection tick, Link partner %4.4x.\n",
-                                  dev->name, inw(ioaddr + NWayLPAR));
-               printk(KERN_DEBUG"%s:  Other registers are IntMask %4.4x IntStatus %4.4x"
-                          " RxStatus %4.4x.\n",
-                          dev->name, inw(ioaddr + IntrMask), inw(ioaddr + IntrStatus),
-                          inl(ioaddr + RxEarlyStatus));
-               printk(KERN_DEBUG"%s:  Chip config %2.2x %2.2x.\n",
-                          dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1));
-       }
-
-       tp->timer.expires = RUN_AT(next_tick);
-       add_timer(&tp->timer);
-}
-
-static void rtl8129_tx_timeout(struct net_device *dev)
-{
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       long ioaddr = dev->base_addr;
-       int mii_reg, i;
-
-       if (rtl8129_debug > 0)
-               printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x "
-                          "media %2.2x.\n",
-                          dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus),
-                          inb(ioaddr + GPPinData));
-
-       /* Disable interrupts by clearing the interrupt mask. */
-       outw(0x0000, ioaddr + IntrMask);
-       /* Emit info to figure out what went wrong. */
-       printk("%s: Tx queue start entry %d  dirty entry %d.\n",
-                  dev->name, tp->cur_tx, tp->dirty_tx);
-       for (i = 0; i < NUM_TX_DESC; i++)
-               printk(KERN_DEBUG"%s:  Tx descriptor %d is %8.8x.%s\n",
-                          dev->name, i, inl(ioaddr + TxStatus0 + i*4),
-                          i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : "");
-       printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]);
-       for (mii_reg = 0; mii_reg < 8; mii_reg++)
-               printk(" %4.4x", mdio_read(dev, tp->phys[0], mii_reg));
-       printk(".\n");
-
-       /* Soft reset the chip. */
-       outb(CmdReset, ioaddr + ChipCmd);
-       /* Check that the chip has finished the reset. */
-       for (i = 1000; i > 0; i--)
-               if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
-                       break;
-       for (i = 0; i < 6; i++)
-               outb(dev->dev_addr[i], ioaddr + MAC0 + i);
-
-       outb(0x00, ioaddr + Cfg9346);
-       tp->cur_rx = 0;
-       /* Must enable Tx/Rx before setting transfer thresholds! */
-       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
-       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),
-                ioaddr + RxConfig);
-       outl((TX_DMA_BURST<<8), ioaddr + TxConfig);
-       set_rx_mode(dev);
-       {                                                       /* Save the unsent Tx packets. */
-               struct sk_buff *saved_skb[NUM_TX_DESC], *skb;
-               int j;
-               for (j = 0; tp->cur_tx - tp->dirty_tx > 0 ; j++, tp->dirty_tx++) {
-                       struct ring_info *rp = &tp->tx_info[tp->dirty_tx % NUM_TX_DESC];
-
-                       saved_skb[j] = rp->skb;
-                       if (rp->mapping != 0) {
-                               pci_unmap_single(tp->pdev, rp->mapping, rp->skb->len);
-                               rp->mapping = 0;
-                       }
-               }
-               tp->dirty_tx = tp->cur_tx = 0;
-
-               for (i = 0; i < j; i++) {
-                       skb = tp->tx_info[i].skb = saved_skb[i];
-                       if ((long)skb->data & 3) {              /* Must use alignment buffer. */
-                               memcpy(tp->tx_buf[i], skb->data, skb->len);
-                               outl(tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs),
-                                        ioaddr + TxAddr0 + i*4);
-                       } else {
-                               tp->tx_info[i].mapping =
-                                       pci_map_single(tp->pdev, skb->data, skb->len);
-                               outl(tp->tx_info[i].mapping, ioaddr + TxAddr0 + i*4);
-                       }
-                       /* Note: the chip doesn't have auto-pad! */
-                       outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
-                                ioaddr + TxStatus0 + i*4);
-               }
-               tp->cur_tx = i;
-               while (i < NUM_TX_DESC) {
-                       tp->tx_info[i].skb = NULL;
-                       tp->tx_info[i].mapping = 0;
-                       i++;
-               }
-               if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
-                       netif_wake_queue(dev);
-                       tp->tx_full = 0;
-               } else {
-                       tp->tx_full = 1;
-               }
-       }
-
-       dev->trans_start = jiffies;
-       tp->stats.tx_errors++;
-       /* Enable all known interrupts by setting the interrupt mask. */
-       outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
-                | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
-       return;
-}
-
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void
-rtl8129_init_ring(struct net_device *dev)
-{
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int i;
-
-       tp->tx_full = 0;
-       tp->cur_rx = 0;
-       tp->dirty_tx = tp->cur_tx = 0;
-
-       for (i = 0; i < NUM_TX_DESC; i++) {
-               tp->tx_buf[i] = &tp->tx_bufs[i*TX_BUF_SIZE];
-               tp->tx_info[i].skb = NULL;
-               tp->tx_info[i].mapping = 0;
-       }
-}
-
-static int
-rtl8129_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       long ioaddr = dev->base_addr;
-       int entry;
-
-       netif_stop_queue(dev);
-
-       /* Calculate the next Tx descriptor entry. */
-       entry = tp->cur_tx % NUM_TX_DESC;
-
-       tp->tx_info[entry].skb = skb;
-       if ((long)skb->data & 3) {                      /* Must use alignment buffer. */
-               tp->tx_info[entry].mapping = 0;
-               memcpy(tp->tx_buf[entry], skb->data, skb->len);
-               outl(tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs),
-                        ioaddr + TxAddr0 + entry*4);
-       } else {
-               tp->tx_info[entry].mapping =
-                       pci_map_single(tp->pdev, skb->data, skb->len);
-               outl(tp->tx_info[entry].mapping, ioaddr + TxAddr0 + entry*4);
-       }
-       /* Note: the chip doesn't have auto-pad! */
-       outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
-                ioaddr + TxStatus0 + entry*4);
-
-       if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {        /* Typical path */
-               netif_start_queue(dev);
-       } else {
-               tp->tx_full = 1;
-       }
-
-       dev->trans_start = jiffies;
-       if (rtl8129_debug > 4)
-               printk(KERN_DEBUG"%s: Queued Tx packet at %p size %d to slot %d.\n",
-                          dev->name, skb->data, (int)skb->len, entry);
-
-       return 0;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct net_device *dev = (struct net_device *)dev_instance;
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int boguscnt = max_interrupt_work;
-       int status, link_changed = 0;
-       long ioaddr = dev->base_addr;
-
-       do {
-               status = inw(ioaddr + IntrStatus);
-               /* Acknowledge all of the current interrupt sources ASAP, but
-                  an first get an additional status bit from CSCR. */
-               if ((status & RxUnderrun)  &&  inw(ioaddr+CSCR) & CSCR_LinkChangeBit)
-                       link_changed = 1;
-               outw(status, ioaddr + IntrStatus);
-
-               if (rtl8129_debug > 4)
-                       printk(KERN_DEBUG"%s: interrupt  status=%#4.4x new intstat=%#4.4x.\n",
-                                  dev->name, status, inw(ioaddr + IntrStatus));
-
-               if ((status & (PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver
-                                          |TxErr|TxOK|RxErr|RxOK)) == 0)
-                       break;
-
-               if (status & (RxOK|RxUnderrun|RxOverflow|RxFIFOOver))/* Rx interrupt */
-                       rtl8129_rx(dev);
-
-               if (status & (TxOK | TxErr)) {
-                       unsigned int dirty_tx = tp->dirty_tx;
-
-                       while (tp->cur_tx - dirty_tx > 0) {
-                               int entry = dirty_tx % NUM_TX_DESC;
-                               int txstatus = inl(ioaddr + TxStatus0 + entry*4);
-
-                               if ( ! (txstatus & (TxStatOK | TxUnderrun | TxAborted)))
-                                       break;                  /* It still hasn't been Txed */
-
-                               /* Note: TxCarrierLost is always asserted at 100mbps. */
-                               if (txstatus & (TxOutOfWindow | TxAborted)) {
-                                       /* There was an major error, log it. */
-                                       if (rtl8129_debug > 1)
-                                               printk(KERN_NOTICE"%s: Transmit error, Tx status %8.8x.\n",
-                                                          dev->name, txstatus);
-                                       tp->stats.tx_errors++;
-                                       if (txstatus&TxAborted) {
-                                               tp->stats.tx_aborted_errors++;
-                                               outl((TX_DMA_BURST<<8)|0x03000001, ioaddr + TxConfig);
-                                       }
-                                       if (txstatus&TxCarrierLost) tp->stats.tx_carrier_errors++;
-                                       if (txstatus&TxOutOfWindow) tp->stats.tx_window_errors++;
-#ifdef ETHER_STATS
-                                       if ((txstatus & 0x0f000000) == 0x0f000000)
-                                               tp->stats.collisions16++;
-#endif
-                               } else {
-                                       if (txstatus & TxUnderrun) {
-                                               /* Add 64 to the Tx FIFO threshold. */
-                                               if (tp->tx_flag <  0x00300000)
-                                                       tp->tx_flag += 0x00020000;
-                                               tp->stats.tx_fifo_errors++;
-                                       }
-                                       tp->stats.collisions += (txstatus >> 24) & 15;
-#if LINUX_VERSION_CODE > 0x20119
-                                       tp->stats.tx_bytes += txstatus & 0x7ff;
-#endif
-                                       tp->stats.tx_packets++;
-                               }
-
-                               if (tp->tx_info[entry].mapping != 0) {
-                                       pci_unmap_single(tp->pdev,
-                                                                        tp->tx_info[entry].mapping,
-                                                                        tp->tx_info[entry].skb->len);
-                                       tp->tx_info[entry].mapping = 0;
-                               }
-
-                               /* Free the original skb. */
-                               dev_kfree_skb_irq(tp->tx_info[entry].skb);
-                               tp->tx_info[entry].skb = NULL;
-                               if (tp->tx_full) {
-                                       /* The ring is no longer full, wake the queue. */
-                                       tp->tx_full = 0;
-                                       netif_wake_queue(dev);
-                               }
-                               dirty_tx++;
-                       }
-
-#ifndef final_version
-                       if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
-                               printk(KERN_ERR"%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-                                          dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
-                               dirty_tx += NUM_TX_DESC;
-                       }
-#endif
-                       tp->dirty_tx = dirty_tx;
-               }
-
-               /* Check uncommon events with one test. */
-               if (status & (PCIErr|PCSTimeout |RxUnderrun|RxOverflow|RxFIFOOver
-                                         |TxErr|RxErr)) {
-                       if (rtl8129_debug > 2)
-                               printk(KERN_NOTICE"%s: Abnormal interrupt, status %8.8x.\n",
-                                          dev->name, status);
-
-                       if (status == 0xffffffff)
-                               break;
-                       /* Update the error count. */
-                       tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
-                       outl(0, ioaddr + RxMissed);
-
-                       if ((status & RxUnderrun)  &&  link_changed  &&
-                               (rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) {
-                               /* Really link-change on new chips. */
-                               int lpar = inw(ioaddr + NWayLPAR);
-                               int duplex = (lpar&0x0100)||(lpar & 0x01C0) == 0x0040; 
-                               if (tp->full_duplex != duplex) {
-                                       tp->full_duplex = duplex;
-                                       outb(0xC0, ioaddr + Cfg9346);
-                                       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
-                                       outb(0x00, ioaddr + Cfg9346);
-                               }
-                               status &= ~RxUnderrun;
-                       }
-                       if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
-                               tp->stats.rx_errors++;
-
-                       if (status & (PCSTimeout)) tp->stats.rx_length_errors++;
-                       if (status & (RxUnderrun|RxFIFOOver)) tp->stats.rx_fifo_errors++;
-                       if (status & RxOverflow) {
-                               tp->stats.rx_over_errors++;
-                               tp->cur_rx = inw(ioaddr + RxBufAddr) % RX_BUF_LEN;
-                               outw(tp->cur_rx - 16, ioaddr + RxBufPtr);
-                       }
-                       if (status & PCIErr) {
-                               u32 pci_cmd_status;
-                               pcibios_read_config_dword(tp->pci_bus, tp->pci_devfn,
-                                                                                 PCI_COMMAND, &pci_cmd_status);
-
-                               printk(KERN_ERR "%s: PCI Bus error %4.4x.\n",
-                                          dev->name, pci_cmd_status);
-                       }
-               }
-               if (--boguscnt < 0) {
-                       printk(KERN_WARNING"%s: Too much work at interrupt, "
-                                  "IntrStatus=0x%4.4x.\n",
-                                  dev->name, status);
-                       /* Clear all interrupt sources. */
-                       outw(0xffff, ioaddr + IntrStatus);
-                       break;
-               }
-       } while (1);
-
-       if (rtl8129_debug > 3)
-               printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n",
-                          dev->name, inl(ioaddr + IntrStatus));
-       return;
-}
-
-/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
-   field alignments and semantics. */
-static int rtl8129_rx(struct net_device *dev)
-{
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       long ioaddr = dev->base_addr;
-       unsigned char *rx_ring = tp->rx_ring;
-       u16 cur_rx = tp->cur_rx;
-
-       if (rtl8129_debug > 4)
-               printk(KERN_DEBUG"%s: In rtl8129_rx(), current %4.4x BufAddr %4.4x,"
-                          " free to %4.4x, Cmd %2.2x.\n",
-                          dev->name, cur_rx, inw(ioaddr + RxBufAddr),
-                          inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd));
-
-       while ((inb(ioaddr + ChipCmd) & 1) == 0) {
-               int ring_offset = cur_rx % RX_BUF_LEN;
-               u32 rx_status = le32_to_cpu(*(u32*)(rx_ring + ring_offset));
-               int rx_size = rx_status >> 16;
-
-               if (rtl8129_debug > 4) {
-                       int i;
-                       printk(KERN_DEBUG"%s:  rtl8129_rx() status %4.4x, size %4.4x, cur %4.4x.\n",
-                                  dev->name, rx_status, rx_size, cur_rx);
-                       printk(KERN_DEBUG"%s: Frame contents ", dev->name);
-                       for (i = 0; i < 70; i++)
-                               printk(" %2.2x", le32_to_cpu(rx_ring[ring_offset + i]));
-                       printk(".\n");
-               }
-               if (rx_status & RxTooLong) {
-                       if (rtl8129_debug > 0)
-                               printk(KERN_NOTICE"%s: Oversized Ethernet frame, status %4.4x!\n",
-                                          dev->name, rx_status);
-                       tp->stats.rx_length_errors++;
-               } else if (rx_status &
-                                  (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) {
-                       if (rtl8129_debug > 1)
-                               printk(KERN_DEBUG"%s: Ethernet frame had errors,"
-                                          " status %4.4x.\n", dev->name, rx_status);
-                       tp->stats.rx_errors++;
-                       if (rx_status & (RxBadSymbol|RxBadAlign))
-                               tp->stats.rx_frame_errors++;
-                       if (rx_status & (RxRunt|RxTooLong)) tp->stats.rx_length_errors++;
-                       if (rx_status & RxCRCErr) tp->stats.rx_crc_errors++;
-                       /* Reset the receiver, based on RealTek recommendation. (Bug?) */
-                       tp->cur_rx = 0;
-                       outb(CmdTxEnb, ioaddr + ChipCmd);
-                       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
-                       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) |
-                                (RX_DMA_BURST<<8), ioaddr + RxConfig);
-               } else {
-                       /* Malloc up new buffer, compatible with net-2e. */
-                       /* Omit the four octet CRC from the length. */
-                       struct sk_buff *skb;
-
-                       skb = dev_alloc_skb(rx_size + 2);
-                       if (skb == NULL) {
-                               printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n",
-                                          dev->name);
-                               /* We should check that some rx space is free.
-                                  If not, free one and mark stats->rx_dropped++. */
-                               tp->stats.rx_dropped++;
-                               break;
-                       }
-                       skb->dev = dev;
-                       skb_reserve(skb, 2);    /* 16 byte align the IP fields. */
-                       if (ring_offset+rx_size+4 > RX_BUF_LEN) {
-                               int semi_count = RX_BUF_LEN - ring_offset - 4;
-                               memcpy(skb_put(skb, semi_count), &rx_ring[ring_offset + 4],
-                                          semi_count);
-                               memcpy(skb_put(skb, rx_size-semi_count), rx_ring,
-                                          rx_size-semi_count);
-                               if (rtl8129_debug > 4) {
-                                       int i;
-                                       printk(KERN_DEBUG"%s:  Frame wrap @%d",
-                                                  dev->name, semi_count);
-                                       for (i = 0; i < 16; i++)
-                                               printk(" %2.2x", le32_to_cpu(rx_ring[i]));
-                                       printk(".\n");
-                                       memset(rx_ring, 0xcc, 16);
-                               }
-                       } else {
-#if 1  /* USE_IP_COPYSUM */
-                               eth_copy_and_sum(skb, &rx_ring[ring_offset + 4],
-                                                                rx_size, 0);
-                               skb_put(skb, rx_size);
-#else
-                               memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4],
-                                          rx_size);
-#endif
-                       }
-                       skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);
-#if LINUX_VERSION_CODE > 0x20119
-                       tp->stats.rx_bytes += rx_size;
-#endif
-                       tp->stats.rx_packets++;
-               }
-
-               cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
-               outw(cur_rx - 16, ioaddr + RxBufPtr);
-       }
-       if (rtl8129_debug > 4)
-               printk(KERN_DEBUG"%s: Done rtl8129_rx(), current %4.4x BufAddr %4.4x,"
-                          " free to %4.4x, Cmd %2.2x.\n",
-                          dev->name, cur_rx, inw(ioaddr + RxBufAddr),
-                          inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd));
-       tp->cur_rx = cur_rx;
-       return 0;
-}
-
-static int
-rtl8129_close(struct net_device *dev)
-{
-       long ioaddr = dev->base_addr;
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int i;
-
-       netif_stop_queue(dev);
-
-       if (rtl8129_debug > 1)
-               printk(KERN_DEBUG"%s: Shutting down ethercard, status was 0x%4.4x.\n",
-                          dev->name, inw(ioaddr + IntrStatus));
-
-       /* Disable interrupts by clearing the interrupt mask. */
-       outw(0x0000, ioaddr + IntrMask);
-
-       /* Stop the chip's Tx and Rx DMA processes. */
-       outb(0x00, ioaddr + ChipCmd);
-
-       /* Update the error counts. */
-       tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
-       outl(0, ioaddr + RxMissed);
-
-       del_timer(&tp->timer);
-
-       free_irq(dev->irq, dev);
-
-       for (i = 0; i < NUM_TX_DESC; i++) {
-               struct sk_buff *skb = tp->tx_info[i].skb;
-               dma_addr_t mapping = tp->tx_info[i].mapping;
-
-               if (skb) {
-                       if (mapping)
-                               pci_unmap_single(tp->pdev, mapping, skb->len);
-                       dev_kfree_skb(skb);
-               }
-               tp->tx_info[i].skb = NULL;
-               tp->tx_info[i].mapping = 0;
-       }
-       pci_free_consistent(tp->pdev, RX_BUF_LEN + 16,
-                                               tp->rx_ring, tp->rx_ring_dma);
-       pci_free_consistent(tp->pdev, TX_BUF_SIZE * NUM_TX_DESC,
-                                               tp->tx_bufs, tp->tx_bufs_dma);
-       tp->rx_ring = NULL;
-       tp->tx_bufs = NULL;
-
-       /* Green! Put the chip in low-power mode. */
-       outb(0xC0, ioaddr + Cfg9346);
-       outb(0x03, ioaddr + Config1);
-       outb('H', ioaddr + HltClk);             /* 'R' would leave the clock running. */
-
-       MOD_DEC_USE_COUNT;
-
-       return 0;
-}
-
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       u16 *data = (u16 *)&rq->ifr_data;
-
-       switch(cmd) {
-       case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
-               data[0] = tp->phys[0] & 0x3f;
-               /* Fall Through */
-       case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
-               data[3] = mdio_read(dev, data[0], data[1] & 0x1f);
-               return 0;
-       case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
-               mdio_write(dev, data[0], data[1] & 0x1f, data[2]);
-               return 0;
-       default:
-               return -EOPNOTSUPP;
-       }
-}
-
-static struct enet_statistics *
-rtl8129_get_stats(struct net_device *dev)
-{
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       long ioaddr = dev->base_addr;
-
-       if (test_bit(LINK_STATE_START, &dev->state)) {
-               tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
-               outl(0, ioaddr + RxMissed);
-       }
-
-       return &tp->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   This routine is not state sensitive and need not be SMP locked. */
-
-static unsigned const ethernet_polynomial = 0x04c11db7U;
-static inline u32 ether_crc(int length, unsigned char *data)
-{
-    int crc = -1;
-
-    while (--length >= 0) {
-               unsigned char current_octet = *data++;
-               int bit;
-               for (bit = 0; bit < 8; bit++, current_octet >>= 1)
-                       crc = (crc << 1) ^
-                               ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
-    }
-    return crc;
-}
-
-/* Bits in RxConfig. */
-enum rx_mode_bits {
-       AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08,
-       AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01,
-};
-
-static void set_rx_mode(struct net_device *dev)
-{
-       long ioaddr = dev->base_addr;
-       u32 mc_filter[2];                /* Multicast hash filter */
-       int i, rx_mode;
-
-       if (rtl8129_debug > 3)
-               printk(KERN_DEBUG"%s:   set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
-                          dev->name, dev->flags, inl(ioaddr + RxConfig));
-
-       /* Note: do not reorder, GCC is clever about common statements. */
-       if (dev->flags & IFF_PROMISC) {
-               /* Unconditionally log net taps. */
-               printk(KERN_NOTICE"%s: Promiscuous mode enabled.\n", dev->name);
-               rx_mode = AcceptBroadcast|AcceptMulticast|AcceptMyPhys|AcceptAllPhys;
-               mc_filter[1] = mc_filter[0] = 0xffffffff;
-       } else if ((dev->mc_count > multicast_filter_limit)
-                          ||  (dev->flags & IFF_ALLMULTI)) {
-               /* Too many to filter perfectly -- accept all multicasts. */
-               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
-               mc_filter[1] = mc_filter[0] = 0xffffffff;
-       } else {
-               struct dev_mc_list *mclist;
-               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
-               mc_filter[1] = mc_filter[0] = 0;
-               for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-                        i++, mclist = mclist->next)
-                       set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter);
-       }
-       /* We can safely update without stopping the chip. */
-       outb(rx_mode, ioaddr + RxConfig);
-       outl(mc_filter[0], ioaddr + MAR0 + 0);
-       outl(mc_filter[1], ioaddr + MAR0 + 4);
-       return;
-}
-\f
-#ifdef MODULE
-int init_module(void)
-{
-       return rtl8139_probe();
-}
-
-void
-cleanup_module(void)
-{
-       struct net_device *next_dev;
-
-       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-       while (root_rtl8129_dev) {
-               struct rtl8129_private *tp =
-                       (struct rtl8129_private *)root_rtl8129_dev->priv;
-               next_dev = tp->next_module;
-               unregister_netdev(root_rtl8129_dev);
-               release_region(root_rtl8129_dev->base_addr,
-                                          pci_tbl[tp->chip_id].io_size);
-               kfree(tp);
-               kfree(root_rtl8129_dev);
-               root_rtl8129_dev = next_dev;
-       }
-}
-
-#endif  /* MODULE */
-\f
-/*
- * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */
index d2756c92fda5e6e03685218fbf2d5909fde57bb2..f7d86c10336e523241705940f30307fbe877afe5 100644 (file)
@@ -83,6 +83,7 @@ extern int seeq8005_probe(struct net_device *dev);
 
 static int seeq8005_probe1(struct net_device *dev, int ioaddr);
 static int seeq8005_open(struct net_device *dev);
+static void seeq8005_timeout(struct net_device *dev);
 static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void seeq8005_rx(struct net_device *dev);
@@ -324,9 +325,11 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
 
        dev->open               = seeq8005_open;
        dev->stop               = seeq8005_close;
-       dev->hard_start_xmit = seeq8005_send_packet;
-       dev->get_stats  = seeq8005_get_stats;
-       dev->set_multicast_list = &set_multicast_list;
+       dev->hard_start_xmit    = seeq8005_send_packet;
+       dev->tx_timeout         = seeq8005_timeout;
+       dev->watchdog_timeo     = HZ/20;
+       dev->get_stats          = seeq8005_get_stats;
+       dev->set_multicast_list = set_multicast_list;
 
        /* Fill in the fields of the device structure with ethernet values. */
        ether_setup(dev);
@@ -344,8 +347,7 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
    registers that "should" only need to be set once at boot, so that
    there is non-reboot way to recover if something goes wrong.
    */
-static int
-seeq8005_open(struct net_device *dev)
+static int seeq8005_open(struct net_device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
 
@@ -363,46 +365,34 @@ seeq8005_open(struct net_device *dev)
 
        lp->open_time = jiffies;
 
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
+       netif_start_queue(dev);
        return 0;
 }
 
-static int
-seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void seeq8005_timeout(struct net_device *dev)
 {
        int ioaddr = dev->base_addr;
-       struct net_local *lp = (struct net_local *)dev->priv;
+       printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+                  tx_done(dev) ? "IRQ conflict" : "network cable problem");
+       /* Try to restart the adaptor. */
+       seeq8005_init(dev, 1);
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+}
 
-       if (dev->tbusy) {
-               /* If we get here, some higher level has decided we are broken.
-                  There should really be a "kick me" function call instead. */
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 5)
-                       return 1;
-               printk("%s: transmit timed out, %s?\n", dev->name,
-                          tx_done(dev) ? "IRQ conflict" : "network cable problem");
-               /* Try to restart the adaptor. */
-               seeq8005_init(dev, 1);
-               dev->tbusy=0;
-               dev->trans_start = jiffies;
-       }
+static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+       struct net_local *lp = (struct net_local *)dev->priv;
+       short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+       unsigned char *buf = skb->data;
 
-       /* Block a timer-based transmit from overlapping.  This could better be
-          done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-               printk("%s: Transmitter access conflict.\n", dev->name);
-       else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-               unsigned char *buf = skb->data;
-
-               hardware_send_packet(dev, buf, length); 
-               dev->trans_start = jiffies;
-               lp->stats.tx_bytes += length;
-       }
+       /* Block a timer-based transmit from overlapping */
+       netif_stop_queue(dev);
+       
+       hardware_send_packet(dev, buf, length); 
+       dev->trans_start = jiffies;
+       lp->stats.tx_bytes += length;
        dev_kfree_skb (skb);
-
        /* You might need to clean up and record Tx statistics here. */
 
        return 0;
@@ -410,22 +400,12 @@ seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
 \f
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static void
-seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        struct net_device *dev = dev_id;
        struct net_local *lp;
        int ioaddr, status, boguscount = 0;
 
-       if (dev == NULL) {
-               printk ("net_interrupt(): irq %d for unknown device.\n", irq);
-               return;
-       }
-       
-       if (dev->interrupt)
-               printk ("%s: Re-entering the interrupt handler.\n", dev->name);
-       dev->interrupt = 1;
-
        ioaddr = dev->base_addr;
        lp = (struct net_local *)dev->priv;
 
@@ -444,8 +424,7 @@ seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                if (status & SEEQSTAT_TX_INT) {
                        outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
                        lp->stats.tx_packets++;
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);        /* Inform upper layers. */
+                       netif_wake_queue(dev);  /* Inform upper layers. */
                }
                if (status & SEEQSTAT_RX_INT) {
                        /* Got a packet(s). */
@@ -457,13 +436,10 @@ seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        if(net_debug>2) {
                printk("%s: eoi\n",dev->name);
        }
-       dev->interrupt = 0;
-       return;
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
-static void
-seeq8005_rx(struct net_device *dev)
+static void seeq8005_rx(struct net_device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
        int boguscount = 10;
@@ -561,17 +537,15 @@ seeq8005_rx(struct net_device *dev)
 }
 
 /* The inverse routine to net_open(). */
-static int
-seeq8005_close(struct net_device *dev)
+static int seeq8005_close(struct net_device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
        int ioaddr = dev->base_addr;
 
        lp->open_time = 0;
 
-       dev->tbusy = 1;
-       dev->start = 0;
-
+       netif_stop_queue(dev);
+       
        /* Flush the Tx and disable Rx here. */
        outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
 
@@ -598,8 +572,7 @@ static struct net_device_stats *seeq8005_get_stats(struct net_device *dev)
    num_addrs > 0       Multicast mode, receive normal and MC packets, and do
                        best-effort filtering.
  */
-static void
-set_multicast_list(struct net_device *dev)
+static void set_multicast_list(struct net_device *dev)
 {
 /*
  * I _could_ do up to 6 addresses here, but won't (yet?)
index 23644ef1d3b2518fa35f41a79d9b28cbc3bdcddf..ab1664fecd0f8f1d494ba7a00647e6ec846c2990 100644 (file)
@@ -414,9 +414,8 @@ static int ultramca_close_card(struct net_device *dev)
 {
        int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 
-       dev->start = 0;
-       dev->tbusy = 1;
-
+       netif_stop_queue(dev);
+       
        if (ei_debug > 1)
                printk("%s: Shutting down ethercard.\n", dev->name);
 
index 944ad87c3aa9746df6ecff38e91797a3fbd8e807..661c1b36355f8bb2eaab42b83f1e1f5efaf767d3 100644 (file)
 static const char *version =
        "smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n";
 
-#ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -81,22 +78,6 @@ static const char *version =
  .
  -------------------------------------------------------------------------*/
 
-/*
- . this is for kernels > 1.2.70
-*/
-#define REALLY_NEW_KERNEL
-#ifndef REALLY_NEW_KERNEL
-#define free_irq( x, y ) free_irq( x )
-#define request_irq( x, y, z, u, v ) request_irq( x, y, z, u )
-#endif
-
-/*
- . Do you want to use this with old kernels.
- . WARNING: this is not well tested.
-#define SUPPORT_OLD_KERNEL
-*/
-
-
 /*
  . Do you want to use 32 bit xfers?  This should work on all chips, as
  . the chipset is designed to accommodate them.
@@ -108,9 +89,10 @@ static const char *version =
  .for a slightly different card, you can add it to the array.  Keep in
  .mind that the array must end in zero.
 */
-static unsigned int smc_portlist[] __initdata =
-   { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
-         0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0};
+static unsigned int smc_portlist[] __initdata = { 
+       0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+       0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
+};
 
 /*
  . Wait time for memory to be free.  This probably shouldn't be
@@ -149,12 +131,6 @@ static unsigned int smc_portlist[] __initdata =
 #endif
 
 
-/* the older versions of the kernel cannot support autoprobing */
-#ifdef SUPPORT_OLD_KERNEL
-#define NO_AUTOPROBE
-#endif
-
-
 /*------------------------------------------------------------------------
  .
  . The internal workings of the driver.  If you are changing anything
@@ -164,9 +140,6 @@ static unsigned int smc_portlist[] __initdata =
  -------------------------------------------------------------------------*/
 #define CARDNAME "SMC9194"
 
-#ifdef SUPPORT_OLD_KERNEL
-char kernel_version[] = UTS_RELEASE;
-#endif
 
 /* store this information for the driver.. */
 struct smc_local {
@@ -216,6 +189,11 @@ int smc_init(struct net_device *dev);
 */
 static int smc_open(struct net_device *dev);
 
+/*
+ . Our watchdog timed out. Called by the networking layer
+*/
+static void smc_timeout(struct net_device *dev);
+
 /*
  . This is called by the kernel to send a packet out into the net.  it's
  . responsible for doing a best-effort send, but if it's simply not possible
@@ -240,12 +218,12 @@ static struct net_device_stats * smc_query_statistics( struct net_device *dev);
  . Finally, a call to set promiscuous mode ( for TCPDUMP and related
  . programs ) and multicast modes.
 */
-#ifdef SUPPORT_OLD_KERNEL
-static void smc_set_multicast_list(struct net_device *dev, int num_addrs,
-                                void *addrs);
-#else
 static void smc_set_multicast_list(struct net_device *dev);
-#endif
+
+/*
+ . CRC compute
+ */
+static int crc32( char * s, int length );
 
 /*---------------------------------------------------------------
  .
@@ -256,11 +234,7 @@ static void smc_set_multicast_list(struct net_device *dev);
 /*
  . Handles the actual interrupt
 */
-#ifdef REALLY_NEW_KERNEL
 static void smc_interrupt(int irq, void *, struct pt_regs *regs);
-#else
-static void smc_interrupt(int irq, struct pt_regs *regs);
-#endif
 /*
  . This is a separate procedure to handle the receipt of a packet, to
  . leave the interrupt code looking slightly cleaner
@@ -321,25 +295,9 @@ static void smc_enable( int ioaddr );
 /* this puts the device in an inactive state */
 static void smc_shutdown( int ioaddr );
 
-#ifndef NO_AUTOPROBE
 /* This routine will find the IRQ of the driver if one is not
  . specified in the input to the device.  */
 static int smc_findirq( int ioaddr );
-#endif
-
-/*
-  this routine will set the hardware multicast table to the specified
-  values given it by the higher level routines
-*/
-#ifndef SUPPORT_OLD_KERNEL
-static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list *  );
-static int crc32( char *, int );
-#endif
-
-#ifdef SUPPORT_OLD_KERNEL
-extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private,
-                       unsigned long *mem_startp );
-#endif
 
 /*
  . Function: smc_reset( int ioaddr )
@@ -442,7 +400,6 @@ static void smc_shutdown( int ioaddr )
 }
 
 
-#ifndef SUPPORT_OLD_KERNEL
 /*
  . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds )
  . Purpose:
@@ -525,8 +482,6 @@ static int crc32( char * s, int length ) {
        return  crc_value;
 }
 
-#endif
-
 
 /*
  . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
@@ -575,6 +530,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de
                dev_kfree_skb (skb);
                lp->saved_skb = NULL;
                /* this IS an error, but, i don't want the skb saved */
+               netif_wake_queue(dev);
                return 0;
        }
        /* either way, a packet is waiting now */
@@ -616,7 +572,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de
        }
        /* or YES! I can send the packet now.. */
        smc_hardware_send_packet(dev);
-
+       netif_wake_queue(dev);
        return 0;
 }
 
@@ -663,7 +619,7 @@ static void smc_hardware_send_packet( struct net_device * dev )
                printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n");
                kfree(skb);
                lp->saved_skb = NULL;
-               dev->tbusy = 0;
+               netif_wake_queue(dev);
                return;
        }
 
@@ -729,8 +685,7 @@ static void smc_hardware_send_packet( struct net_device * dev )
        dev->trans_start = jiffies;
 
        /* we can send another packet */
-       dev->tbusy = 0;
-
+       netif_wake_queue(dev);
 
        return;
 }
@@ -787,7 +742,6 @@ int __init smc_init(struct net_device *dev)
        return -ENODEV;
 }
 
-#ifndef NO_AUTOPROBE
 /*----------------------------------------------------------------------
  . smc_findirq
  .
@@ -860,7 +814,6 @@ int __init smc_findirq( int ioaddr )
        /* and return what I found */
        return autoirq_report( 0 );
 }
-#endif
 
 /*----------------------------------------------------------------------
  . Function: smc_probe( int ioaddr )
@@ -962,14 +915,7 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
 
        /* see if I need to initialize the ethernet card structure */
        if (dev == NULL) {
-#ifdef SUPPORT_OLD_KERNEL
-#ifndef MODULE
-/* note: the old module interface does not support this call */
-               dev = init_etherdev( 0, sizeof( struct smc_local ), 0 );
-#endif
-#else
                dev = init_etherdev(0, 0);
-#endif
                if (dev == NULL)
                        return -ENOMEM;
        }
@@ -1043,7 +989,6 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
         . what (s)he is doing.  No checking is done!!!!
         .
        */
-#ifndef NO_AUTOPROBE
        if ( dev->irq < 2 ) {
                int     trials;
 
@@ -1060,13 +1005,6 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
                printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");
                return -ENODEV;
        }
-#else
-       if (dev->irq == 0 ) {
-               printk(CARDNAME
-               ": Autoprobing IRQs is not supported for old kernels.\n");
-               return -ENODEV;
-       }
-#endif
        if (dev->irq == 2) {
                /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
                 * or don't know which one to set.
@@ -1114,10 +1052,10 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
        dev->open                       = smc_open;
        dev->stop                       = smc_close;
        dev->hard_start_xmit            = smc_send_packet;
+       dev->tx_timeout                 = smc_timeout;
+       dev->watchdog_timeo             = HZ/20;
        dev->get_stats                  = smc_query_statistics;
-#ifdef HAVE_MULTICAST
-       dev->set_multicast_list         = &smc_set_multicast_list;
-#endif
+       dev->set_multicast_list         = smc_set_multicast_list;
 
        return 0;
 }
@@ -1174,12 +1112,7 @@ static int smc_open(struct net_device *dev)
        /* clear out all the junk that was put here before... */
        memset(dev->priv, 0, sizeof(struct smc_local));
 
-       dev->tbusy      = 0;
-       dev->interrupt  = 0;
-       dev->start      = 1;
-#ifdef MODULE
        MOD_INC_USE_COUNT;
-#endif
 
        /* reset the hardware */
 
@@ -1211,6 +1144,8 @@ static int smc_open(struct net_device *dev)
                address  |= dev->dev_addr[ i ];
                outw( address, ioaddr + ADDR0 + i );
        }
+       
+       netif_start_queue(dev);
        return 0;
 }
 
@@ -1220,38 +1155,29 @@ static int smc_open(struct net_device *dev)
  . skeleton.c, from Becker.
  .--------------------------------------------------------
 */
-static int smc_send_packet(struct sk_buff *skb, struct net_device *dev)
+
+static void smc_timeout(struct net_device *dev)
 {
-       if (dev->tbusy) {
-               /* If we get here, some higher level has decided we are broken.
-                  There should really be a "kick me" function call instead. */
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 5)
-                       return 1;
-               printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
-                       tx_done(dev) ? "IRQ conflict" :
-                       "network cable problem");
-               /* "kick" the adaptor */
-               smc_reset( dev->base_addr );
-               smc_enable( dev->base_addr );
-
-               dev->tbusy = 0;
-               dev->trans_start = jiffies;
-               /* clear anything saved */
-               ((struct smc_local *)dev->priv)->saved_skb = NULL;
-       }
+       /* If we get here, some higher level has decided we are broken.
+          There should really be a "kick me" function call instead. */
+       printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
+               tx_done(dev) ? "IRQ conflict" :
+               "network cable problem");
+       /* "kick" the adaptor */
+       smc_reset( dev->base_addr );
+       smc_enable( dev->base_addr );
+       dev->trans_start = jiffies;
+       /* clear anything saved */
+       ((struct smc_local *)dev->priv)->saved_skb = NULL;
+       netif_wake_queue(dev);
+}
 
-       /* Block a timer-based transmit from overlapping.  This could better be
-          done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-               printk(KERN_WARNING CARDNAME": Transmitter access conflict.\n");
-               dev_kfree_skb (skb);
-       } else {
-               /* Well, I want to send the packet.. but I don't know
-                  if I can send it right now...  */
-               return smc_wait_to_send_packet( skb, dev );
-       }
-       return 0;
+static int smc_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+       netif_stop_queue(dev);
+       /* Well, I want to send the packet.. but I don't know
+          if I can send it right now...  */
+       return smc_wait_to_send_packet( skb, dev );
 }
 
 /*--------------------------------------------------------------------
@@ -1266,11 +1192,8 @@ static int smc_send_packet(struct sk_buff *skb, struct net_device *dev)
  .   and finally restore state.
  .
  ---------------------------------------------------------------------*/
-#ifdef REALLY_NEW_KERNEL
+
 static void smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
-#else
-static void smc_interrupt(int irq, struct pt_regs * regs)
-#endif
 {
        struct net_device *dev  = dev_id;
        int ioaddr              = dev->base_addr;
@@ -1288,20 +1211,6 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
 
        PRINTK3((CARDNAME": SMC interrupt started \n"));
 
-       if (dev == NULL) {
-               printk(KERN_WARNING  CARDNAME": irq %d for unknown device.\n",
-                       irq);
-               return;
-       }
-
-/* will Linux let this happen ??  If not, this costs some speed */
-       if ( dev->interrupt ) {
-               printk(KERN_WARNING CARDNAME": interrupt inside interrupt.\n");
-               return;
-       }
-
-       dev->interrupt = 1;
-
        saved_bank = inw( ioaddr + BANK_SELECT );
 
        SMC_SELECT_BANK(2);
@@ -1346,12 +1255,7 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
                        lp->stats.collisions += card_stats & 0xF;
 
                        /* these are for when linux supports these statistics */
-#if 0
-                       card_stats >>= 4;
-                       /* deferred */
-                       card_stats >>= 4;
-                       /* excess deferred */
-#endif
+
                        SMC_SELECT_BANK( 2 );
                        PRINTK2((KERN_WARNING CARDNAME
                                ": TX_BUFFER_EMPTY handled\n"));
@@ -1372,8 +1276,8 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
                        mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
 
                        /* and let the card send more packets to me */
-                       mark_bh( NET_BH );
-
+                       netif_wake_queue(dev);
+                       
                        PRINTK2((CARDNAME": Handoff done successfully.\n"));
                } else if (status & IM_RX_OVRN_INT ) {
                        lp->stats.rx_errors++;
@@ -1397,7 +1301,6 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
 
        SMC_SELECT_BANK( saved_bank );
 
-       dev->interrupt = 0;
        PRINTK3((CARDNAME ": Interrupt done\n"));
        return;
 }
@@ -1462,11 +1365,7 @@ static void smc_rcv(struct net_device *dev)
                if ( status & RS_MULTICAST )
                        lp->stats.multicast++;
 
-#ifdef SUPPORT_OLD_KERNEL
-               skb = alloc_skb( packet_length + 5, GFP_ATOMIC );
-#else
                skb = dev_alloc_skb( packet_length + 5);
-#endif
 
                if ( skb == NULL ) {
                        printk(KERN_NOTICE CARDNAME
@@ -1478,18 +1377,12 @@ static void smc_rcv(struct net_device *dev)
                 ! This should work without alignment, but it could be
                 ! in the worse case
                */
-#ifndef SUPPORT_OLD_KERNEL
-               /* TODO: Should I use 32bit alignment here ? */
+
                skb_reserve( skb, 2 );   /* 16 bit alignment */
-#endif
 
                skb->dev = dev;
-#ifdef SUPPORT_OLD_KERNEL
-               skb->len = packet_length;
-               data = skb->data;
-#else
                data = skb_put( skb, packet_length);
-#endif
+
 #ifdef USE_32_BIT
                /* QUESTION:  Like in the TX routine, do I want
                   to send the DWORDs or the bytes first, or some
@@ -1516,9 +1409,7 @@ static void smc_rcv(struct net_device *dev)
                        print_packet( data, packet_length );
 #endif
 
-#ifndef SUPPORT_OLD_KERNEL
                skb->protocol = eth_type_trans(skb, dev );
-#endif
                netif_rx(skb);
                lp->stats.rx_packets++;
        } else {
@@ -1616,17 +1507,12 @@ static void smc_tx( struct net_device * dev )
  -----------------------------------------------------*/
 static int smc_close(struct net_device *dev)
 {
-       dev->tbusy = 1;
-       dev->start = 0;
-
+       netif_stop_queue(dev);
        /* clear everything */
        smc_shutdown( dev->base_addr );
 
        /* Update the statistics here. */
-#ifdef MODULE
        MOD_DEC_USE_COUNT;
-#endif
-
        return 0;
 }
 
@@ -1648,21 +1534,12 @@ static struct net_device_stats* smc_query_statistics(struct net_device *dev) {
  . promiscuous mode ( for TCPDUMP and cousins ) or accept
  . a select set of multicast packets
 */
-#ifdef SUPPORT_OLD_KERNEL
-static void smc_set_multicast_list( struct net_device * dev,
-                       int num_addrs, void * addrs )
-#else
 static void smc_set_multicast_list(struct net_device *dev)
-#endif
 {
        short ioaddr = dev->base_addr;
 
        SMC_SELECT_BANK(0);
-#ifdef  SUPPORT_OLD_KERNEL
-       if ( num_addrs < 0 )
-#else
        if ( dev->flags & IFF_PROMISC )
-#endif
                outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR );
 
 /* BUG?  I never disable promiscuous mode if multicasting was turned on.
@@ -1674,27 +1551,12 @@ static void smc_set_multicast_list(struct net_device *dev)
           I don't need to zero the multicast table, because the flag is
           checked before the table is
        */
-#ifdef  SUPPORT_OLD_KERNEL
-       else if ( num_addrs > 20 )      /* arbitrary constant */
-#else
        else if (dev->flags & IFF_ALLMULTI)
-#endif
                outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR );
 
        /* We just get all multicast packets even if we only want them
         . from one source.  This will be changed at some future
         . point. */
-#ifdef  SUPPORT_OLD_KERNEL
-       else if (num_addrs > 0 ) {
-/* the old kernel support will not have hardware multicast support. It would
-   involve more kludges, and make the multicast setting code even worse.
-   Instead, just use the ALMUL method.   This is reasonable, considering that
-   it is seldom used
-*/
-               outw( inw( ioaddr + RCR ) & ~RCR_PROMISC, ioaddr + RCR );
-               outw( inw( ioadddr + RCR ) | RCR_ALMUL, ioadddr + RCR );
-       }
-#else
        else if (dev->mc_count )  {
                /* support hardware multicasting */
 
@@ -1705,7 +1567,6 @@ static void smc_set_multicast_list(struct net_device *dev)
                   last thing called.  The bank is set to zero at the top */
                smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
        }
-#endif
        else  {
                outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
                        ioaddr + RCR );
index 2f3eb9076782554e4a31b345856ff7ec901bc8ae..ee31cb4ca3149348d3a8994a31f15a25d1ae9d0a 100644 (file)
@@ -1036,9 +1036,7 @@ static void strip_unlock(struct strip *strip_info)
      */
     strip_info->idle_timer.expires = jiffies + 1*HZ;
     add_timer(&strip_info->idle_timer);
-    if (!test_and_clear_bit(0, (void *)&strip_info->dev.tbusy))
-        printk(KERN_ERR "%s: trying to unlock already unlocked device!\n",
-            strip_info->dev.name);
+    netif_wake_queue(&strip_info->dev);
 }
 
 
@@ -1355,7 +1353,8 @@ static void strip_write_some_more(struct tty_struct *tty)
     struct strip *strip_info = (struct strip *) tty->disc_data;
 
     /* First make sure we're connected. */
-    if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start)
+    if (!strip_info || strip_info->magic != STRIP_MAGIC || 
+       !test_bit(LINK_STATE_START, &strip_info->dev.state))
         return;
 
     if (strip_info->tx_left > 0)
@@ -1387,7 +1386,6 @@ static void strip_write_some_more(struct tty_struct *tty)
     {
         tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
         strip_unlock(strip_info);
-        mark_bh(NET_BH);
     }
 }
 
@@ -1646,12 +1644,14 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     struct strip *strip_info = (struct strip *)(dev->priv);
 
-    if (!dev->start)
+    if (!test_bit(LINK_STATE_START, &dev->state))
     {
         printk(KERN_ERR "%s: xmit call when iface is down\n", dev->name);
         return(1);
     }
-    if (test_and_set_bit(0, (void *) &strip_info->dev.tbusy)) return(1);
+
+    netif_stop_queue(dev);
+    
     del_timer(&strip_info->idle_timer);
 
     /* See if someone has been ifconfigging */
@@ -1687,7 +1687,8 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
 
     strip_send(strip_info, skb);
 
-    if (skb) dev_kfree_skb(skb);
+    if (skb)
+       dev_kfree_skb(skb);
     return(0);
 }
 
@@ -2336,7 +2337,8 @@ strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int
     struct strip *strip_info = (struct strip *) tty->disc_data;
     const unsigned char *end = cp + count;
 
-    if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start)
+    if (!strip_info || strip_info->magic != STRIP_MAGIC 
+       || !test_bit(LINK_STATE_START, &strip_info->dev.state))
         return;
 
     /* Argh! mtu change time! - costs us the packet part received at the change */
@@ -2507,13 +2509,11 @@ static int strip_open_low(struct net_device *dev)
     if (in_dev->ifa_list->ifa_address == 0)
         in_dev->ifa_list->ifa_address = ntohl(0xC0A80001);
 #endif
-    dev->tbusy  = 0;
-    dev->start  = 1;
-
     printk(KERN_INFO "%s: Initializing Radio.\n", strip_info->dev.name);
     ResetRadio(strip_info);
     strip_info->idle_timer.expires = jiffies + 1*HZ;
     add_timer(&strip_info->idle_timer);
+    netif_wake_queue(dev);
     return(0);
 }
 
@@ -2529,9 +2529,9 @@ static int strip_close_low(struct net_device *dev)
     if (strip_info->tty == NULL)
         return -EBUSY;
     strip_info->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-    dev->tbusy = 1;
-    dev->start = 0;
 
+    netif_stop_queue(dev);
+    
     /*
      * Free all STRIP frame buffers.
      */
index e11c9bcfe5f643d174a5073b6ec8cde35e75b76c..47196db9c7fb23ac2cfe8ae79423e526ec140ccf 100644 (file)
@@ -502,12 +502,10 @@ static int if_open (struct net_device *dev)
        x25_channel_t *chan = dev->priv;
        cycx_t *card = chan->card;
 
-       if (dev->start)
+       if (test_bit(LINK_STATE_START, &dev->state))
                return -EBUSY; /* only one open is allowed */ 
 
-       dev->interrupt = 0;
-       dev->tbusy = 0;
-       dev->start = 1;
+       netif_start_queue(dev);
        cyclomx_mod_inc_use_count(card);
 
        return 0;
@@ -521,8 +519,8 @@ static int if_close (struct net_device *dev)
        x25_channel_t *chan = dev->priv;
        cycx_t *card = chan->card;
 
-       dev->start = 0;
-
+       netif_stop_queue(dev);
+       
        if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
                chan_disconnect(dev);
                
@@ -556,7 +554,7 @@ static int if_rebuild_hdr (struct sk_buff *skb)
 }
 
 /* Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission).
+ * o set busy flag (marks start of the transmission).
  * o check link state. If link is not up, then drop the packet.
  * o check channel status. If it's down then initiate a call.
  * o pass a packet to corresponding WAN device.
@@ -575,11 +573,6 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
        x25_channel_t *chan = dev->priv;
        cycx_t *card = chan->card;
 
-       if (dev->tbusy) {
-               ++chan->ifstats.rx_dropped;     
-               return -EBUSY;  
-       }
-
        if (!chan->svc)
                chan->protocol = skb->protocol;
 
@@ -595,14 +588,14 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
                switch (chan->state) {
                        case WAN_DISCONNECTED:
                                if (chan_connect(dev)) {
-                                       dev->tbusy = 1;
+                                       netif_stop_queue(dev);
                                        return -EBUSY;
                                }
                                /* fall thru */
                        case WAN_CONNECTED:
                                reset_timer(dev);
                                dev->trans_start = jiffies;
-                               dev->tbusy = 1;
+                               netif_stop_queue(dev);
 
                                if (chan_send(dev, skb))
                                        return -EBUSY;
@@ -632,8 +625,8 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
                skb_pull(skb, 1); /* Remove control byte */
                reset_timer(dev);
                dev->trans_start = jiffies;
-               dev->tbusy = 1;
-
+               netif_stop_queue(dev);
+               
                if (chan_send(dev, skb)) {
                        /* prepare for future retransmissions */
                        skb_push(skb, 1);
@@ -705,9 +698,6 @@ static void cyx_isr (cycx_t *card)
        cycx_poke(&card->hw, 0, &z, sizeof(z));
        cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
        card->in_isr = 0;
-
-       if (card->buff_int_mode_unbusy)
-               mark_bh(NET_BH);
 }
 
 /* Transmit interrupt handler.
@@ -724,7 +714,7 @@ static void tx_intr (cycx_t *card, TX25Cmd *cmd)
        /* unbusy device and then dev_tint(); */
        if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
                card->buff_int_mode_unbusy = 1;
-               dev->tbusy = 0;
+               netif_wake_queue(dev);
        } else
                printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
                                 card->devname, lcn);
@@ -1357,7 +1347,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
                        case WAN_CONNECTED:
                                string_state = "connected!";
                                *(u16*)dev->dev_addr = htons(chan->lcn);
-                               dev->tbusy = 0;
+                               netif_wake_queue(dev);
                                reset_timer(dev);
 
                                if (chan->protocol == ETH_P_X25)
@@ -1384,7 +1374,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
                                if (chan->protocol == ETH_P_X25)
                                        chan_x25_send_event(dev, 2);
 
-                               dev->tbusy = 0;
+                               netif_wake_queue(dev);
                                break;
                }
 
@@ -1560,14 +1550,14 @@ static void x25_dump_devs(wan_device_t *wandev)
        struct net_device *dev = wandev->dev;
 
        printk(KERN_INFO "X.25 dev states\n");
-       printk(KERN_INFO "name: addr:           tbusy:  protocol:\n");
+       printk(KERN_INFO "name: addr:           txoff:  protocol:\n");
        printk(KERN_INFO "---------------------------------------\n");
 
        for (; dev; dev = dev->slave) {
                x25_channel_t *chan = dev->priv;
 
-               printk(KERN_INFO "%-5.5s %-15.15s   %ld     ETH_P_%s\n",
-                                chan->name, chan->addr, dev->tbusy,
+               printk(KERN_INFO "%-5.5s %-15.15s   %d     ETH_P_%s\n",
+                                chan->name, chan->addr, test_bit(LINK_STATE_XOFF, &dev->state),
                                 chan->protocol == ETH_P_IP ? "IP" : "X25");
        }
 }
index a4564afcb0643985530e0b390005c9acf0eb5b72..56e4f372242f42b29010dc431bf162e0fa3c848f 100644 (file)
@@ -163,7 +163,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
        
        dev = lapbeth_get_x25_dev(dev);
 
-       if (dev == NULL || dev->start == 0) {
+       if (dev == NULL || test_bit(LINK_STATE_START, &dev->state) == 0) {
                kfree_skb(skb);
                return 0;
        }
@@ -215,7 +215,7 @@ static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
         * Just to be *really* sure not to send anything if the interface
         * is down, the ethernet device may have gone.
         */
-       if (!dev->start) {
+       if (!test_bit(LINK_STATE_START, &dev->state)) {
                lapbeth_check_devices(dev);
                kfree_skb(skb);
                return -ENODEV;
@@ -360,9 +360,6 @@ static int lapbeth_open(struct net_device *dev)
        if (lapbeth_check_devices(dev))
                return -ENODEV;         /* oops, it's gone */
        
-       dev->tbusy = 0;
-       dev->start = 1;
-
        lapbeth = (struct lapbethdev *)dev->priv;
 
        lapbeth_callbacks.connect_confirmation    = lapbeth_connected;
@@ -374,12 +371,11 @@ static int lapbeth_open(struct net_device *dev)
 
        if ((err = lapb_register(lapbeth, &lapbeth_callbacks)) != LAPB_OK) {
                printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
-               dev->tbusy = 1;
-               dev->start = 0;
                return -ENODEV;
        }
 
        MOD_INC_USE_COUNT;
+       netif_start_queue(dev);
 
        return 0;
 }
@@ -389,9 +385,8 @@ static int lapbeth_close(struct net_device *dev)
        struct lapbethdev *lapbeth;
        int err;
 
-       dev->tbusy = 1;
-       dev->start = 0;
-
+       netif_stop_queue(dev);
+       
        lapbeth = (struct lapbethdev *)dev->priv;
 
        if ((err = lapb_unregister(lapbeth)) != LAPB_OK)
index 4cf0c05a1c3458289345ee52fe3c38fc4c56ed3d..1aa7afc2087a4bdafba7a17467fb236f5ae7cd0c 100644 (file)
 
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE >=0x020200
-#define v22
-#endif
-
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -74,6 +69,7 @@
 #include <linux/malloc.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/spinlock.h>
 
 #include <asm/io.h>
 #include <asm/types.h>
 
 #include <net/arp.h>
 
-
-
-#ifdef v22
 #include <asm/uaccess.h>
 #include <linux/init.h>
-#endif
 
 #include "sbni.h"
 
@@ -523,6 +515,7 @@ static int __init sbni_probe1(struct net_device *dev, int ioaddr)
        dev->hard_header_cache = sbni_header_cache;
        dev->header_cache_update = sbni_header_cache_update;
   
+       spin_lock_init(&lp->lock);
        lp->m=dev;
        lp->me=dev;
        lp->next_lp=NULL;
@@ -538,15 +531,15 @@ static int sbni_open(struct net_device *dev)
 {
        struct net_local* lp = (struct net_local*)dev->priv;
        struct timer_list* watchdog = &lp->watchdog;
-   
+       unsigned long flags;   
       
        DP( printk("%s: sbni_open\n", dev->name); )
      
+       save_flags(flags);
        cli();
        lp->currframe = NULL;
    
        card_start(dev);
-       dev->start = 1;
        /* set timer  watchdog */
        init_timer(watchdog);
        watchdog->expires = jiffies + SBNI_TIMEOUT;
@@ -555,8 +548,9 @@ static int sbni_open(struct net_device *dev)
        add_timer(watchdog);
        DP( printk("%s: sbni timer watchdog initialized\n", dev->name); );
    
-       sti();
-   
+       restore_flags(flags);
+          
+       netif_start_queue(dev);
        MOD_INC_USE_COUNT;
        return 0;
 }
@@ -566,21 +560,18 @@ static int sbni_close(struct net_device *dev)
        int ioaddr = dev->base_addr;
        struct net_local* lp = (struct net_local*) dev->priv;
        struct timer_list* watchdog = &lp->watchdog;
-
-   
+       unsigned long flags;
+       
        DP( printk("%s: sbni_close\n", dev->name); )
 
+       netif_stop_queue(dev);
+
+       save_flags(flags);
        cli();
-   
        sbni_drop_tx_queue(dev);        
-   
-       dev->tbusy = 1;
-       dev->start = 0;
-
        del_timer(watchdog);
-
        outb(0, ioaddr + CSR0);
-       sti();
+       restore_flags(flags);
 
        MOD_DEC_USE_COUNT;
        return 0;
@@ -590,6 +581,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_local *lp = (struct net_local*)dev->priv;
        struct sbni_hard_header *hh=(struct sbni_hard_header *)skb->data;
+       unsigned long flags;
   
 #ifdef KATYUSHA   
        struct net_local *nl;
@@ -602,13 +594,6 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if(lp->me != dev)
                panic("sbni: lp->me != dev !!!\nMail to developer (xenon@granch.ru) if you noticed this error\n");
   
-       if(dev->interrupt)
-       {
-               DP( printk("sbni_xmit_start: interrupt\n"); )
-               /* May be unloading, don't stamp on */  
-               return 1;       /* the packet buffer this time      */
-       }
-  
        hh->number = 1;
        hh->reserv = 0;
   
@@ -623,6 +608,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
                       skb->len - sizeof(struct sbni_hard_header),
                       hh->crc);
   
+       spin_lock_irqsave(&lp->lock, flags);
 #ifdef KATYUSHA
        /* looking for first idle device */
        for (stop=0,nl=lp; nl && !stop; nl=nl->next_lp)
@@ -657,6 +643,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* set request for transmit */
        outb(inb(dev->base_addr + CSR0) | TR_REQ, dev->base_addr + CSR0);
 #endif
+       spin_unlock_irqrestore(&lp->lock, flags);
        return 0;
 }
 
@@ -677,9 +664,6 @@ void card_start(struct net_device *dev)
        lp->waitack=0;
        skb_queue_head_init(&lp->queue);
        sbni_drop_tx_queue(dev);
-       dev->tbusy = 0;
-   
-       dev->interrupt = 0;
        /* Reset the card and set start parameters */
        outb(PR_RES | *(char*)&lp->csr1, dev->base_addr + CSR1);
        outb(EN_INT, dev->base_addr + CSR0);
@@ -776,8 +760,7 @@ static inline unsigned short sbni_recv(struct net_device *dev)
                                        /*
                                         * reset output active flags
                                         */
-                                       dev->tbusy = 0;
-                                       mark_bh(NET_BH);
+                                       netif_wake_queue(dev);
                                        /*} if */
                                }
                                case PACKET_RESEND:
@@ -920,17 +903,12 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                return;
        }
    
-       if(dev->interrupt)
-       {
-               printk("%s: Reentering the interrupt driver!\n", dev->name);
-               return;
-       }
-       dev->interrupt = 1;
-   
        csr0 = inb(dev->base_addr + CSR0);
        DP( printk("%s: entering interrupt handler, CSR0 = %02x\n", dev->name, csr0); )
      
        lp=dev->priv;
+
+       spin_lock(&lp->lock);
   
        if(!lp->carrier)
                lp->carrier=1;
@@ -971,7 +949,7 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         */
   
        outb(csr0 | EN_INT, dev->base_addr + CSR0);
-       dev->interrupt = 0;
+       spin_unlock(&lp->lock);
 }
 
 static struct enet_statistics *sbni_get_stats(struct net_device *dev)
@@ -1103,7 +1081,7 @@ static void sbni_watchdog(unsigned long arg)
        }
        sti();
        outb(csr0 | RC_CHK, dev->base_addr + CSR0);
-       if(dev->start)
+       if(test_bit(LINK_STATE_START, &dev->state))
        {
                struct timer_list* watchdog = &lp->watchdog; 
                init_timer(watchdog);
@@ -1167,9 +1145,8 @@ static void sbni_drop_tx_queue(struct net_device *dev)
                }
        }
        lp->waitack=0;
-       dev->tbusy = 0;
-  
-       mark_bh(NET_BH);
+       netif_wake_queue(dev);
+       
        DP( printk("%s: queue dropping stoped\n",dev->name); ); 
 }
 
@@ -1194,7 +1171,7 @@ static int sbni_set_mac_address(struct net_device *dev, void *addr)
        /* struct net_local *lp = (struct net_local *)dev->priv; */
        struct sockaddr *saddr = addr;
        
-       if(dev->start)
+       if(test_bit(LINK_STATE_START, &dev->state))
        {
                /* Only possible while card isn't started */
                return -EBUSY;
@@ -1400,13 +1377,11 @@ static int rxl[SBNI_MAX_NUM_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 static int baud[SBNI_MAX_NUM_CARDS] = { 0 };
 static long mac[SBNI_MAX_NUM_CARDS] = { 0 };
 
-#ifdef v22
 MODULE_PARM(io, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
 MODULE_PARM(rxl, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
 MODULE_PARM(baud, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
 MODULE_PARM(mac, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
-#endif
 
 
 static int sbniautodetect = -1;
index 2e34d8d3451d8a3fdb1912d9a6d50c8e947b6d23..56550d8f2812880eb13caed7c1ff7d4df7e97dcb 100644 (file)
@@ -146,7 +146,7 @@ struct net_local {
 
        int carrier;
 
-
+       spinlock_t lock;
 };
 
 
index e50865d97907a56743ee227b038604bcc170ceae..be92deae42fa05b235d997ae5478f5203d5a1a65 100644 (file)
@@ -205,8 +205,7 @@ static void x25_asy_changed_mtu(struct x25_asy *sl)
 
 static inline void x25_asy_lock(struct x25_asy *sl)
 {
-       if (test_and_set_bit(0, (void *) &sl->dev->tbusy))
-               printk("%s: trying to lock already locked device!\n", sl->dev->name);
+       netif_stop_queue(sl->dev);
 }
 
 
@@ -214,8 +213,7 @@ static inline void x25_asy_lock(struct x25_asy *sl)
 
 static inline void x25_asy_unlock(struct x25_asy *sl)
 {
-       if (!test_and_clear_bit(0, (void *)&sl->dev->tbusy))
-               printk("%s: trying to unlock already unlocked device!\n", sl->dev->name);
+       netif_wake_queue(sl->dev);
 }
 
 /* Send one completely decapsulated IP datagram to the IP layer. */
@@ -303,7 +301,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
        struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
 
        /* First make sure we're connected. */
-       if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start)
+       if (!sl || sl->magic != X25_ASY_MAGIC || !test_bit(LINK_STATE_START, &sl->dev->state))
                return;
 
        if (sl->xleft <= 0)  
@@ -313,7 +311,6 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
                sl->tx_packets++;
                tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
                x25_asy_unlock(sl);
-               mark_bh(NET_BH);
                return;
        }
 
@@ -322,6 +319,20 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
        sl->xhead += actual;
 }
 
+static void x25_asy_timeout(struct net_device *dev)
+{
+       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       /* May be we must check transmitter timeout here ?
+        *      14 Oct 1994 Dmitry Gorodchanin.
+        */
+       printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+              (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
+              "bad line quality" : "driver error");
+       sl->xleft = 0;
+       sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+       x25_asy_unlock(sl);
+}
+
 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 
 static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -329,7 +340,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
        struct x25_asy *sl = (struct x25_asy*)(dev->priv);
        int err;
 
-       if (!dev->start)  
+       if (!test_bit(LINK_STATE_START, &sl->dev->state))
        {
                printk("%s: xmit call when iface is down\n", dev->name);
                return 1;
@@ -361,25 +372,6 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
         * So, no queues !
         *        14 Oct 1994  Dmitry Gorodchanin.
         */
-       if (dev->tbusy) {
-               /* May be we must check transmitter timeout here ?
-                *      14 Oct 1994 Dmitry Gorodchanin.
-                */
-#ifdef SL_CHECK_TRANSMIT
-               if (jiffies - dev->trans_start  < 20 * HZ)  {
-                       /* 20 sec timeout not reached */
-                       return 1;
-               }
-               printk("%s: transmit timed out, %s?\n", dev->name,
-                      (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
-                      "bad line quality" : "driver error");
-               sl->xleft = 0;
-               sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-               x25_asy_unlock(sl);
-#else
-               return 1;
-#endif
-       }
        
        if((err=lapb_data_request(sl,skb))!=LAPB_OK)
        {
@@ -414,7 +406,7 @@ static void x25_asy_data_indication(void *token, struct sk_buff *skb)
 static void x25_asy_data_transmit(void *token, struct sk_buff *skb)
 {
        struct x25_asy *sl=token;
-       if(sl->dev->tbusy)
+       if(test_bit(LINK_STATE_XOFF, &sl->dev->state))
        {
                printk(KERN_ERR "x25_asy: tbusy drop\n");
                kfree_skb(skb);
@@ -514,10 +506,8 @@ static int x25_asy_open(struct net_device *dev)
        sl->xleft    = 0;
        sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */
 
-       dev->tbusy  = 0;
-/*     dev->flags |= IFF_UP; */
-       dev->start  = 1;
-       
+       netif_start_queue(dev);
+                       
        /*
         *      Now attach LAPB
         */
@@ -551,12 +541,9 @@ static int x25_asy_close(struct net_device *dev)
                return -EBUSY;
 
        sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-       dev->tbusy = 1;
-       dev->start = 0;
+       netif_stop_queue(dev);
        if((err=lapb_unregister(sl))!=LAPB_OK)
                printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
-
-/*     dev->flags &= ~IFF_UP; */
        return 0;
 }
 
@@ -576,7 +563,7 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 {
        struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
 
-       if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start)
+       if (!sl || sl->magic != X25_ASY_MAGIC || !test_bit(LINK_STATE_START, &sl->dev->state))
                return;
 
        /*
@@ -876,6 +863,8 @@ int x25_asy_init(struct net_device *dev)
         
        dev->mtu                = SL_MTU;
        dev->hard_start_xmit    = x25_asy_xmit;
+       dev->tx_timeout         = x25_asy_timeout;
+       dev->watchdog_timeo     = HZ*20;
        dev->open               = x25_asy_open_dev;
        dev->stop               = x25_asy_close;
        dev->get_stats          = x25_asy_get_stats;
@@ -914,7 +903,7 @@ cleanup_module(void)
                                 * VSV = if dev->start==0, then device
                                 * unregistered while close proc.
                                 */
-                               if (x25_asy_ctrls[i]->dev.start)
+                               if (test_bit(LINK_STATE_START, &x25_asy_ctrls[i]->dev.state))
                                        unregister_netdev(&(x25_asy_ctrls[i]->dev));
 
                                kfree(x25_asy_ctrls[i]);
index c5e1c4bd52b646fab06a339f7dfd801846efef0f..2ff818b04eb9265464c1a4aab6c90d4f9382ce08 100644 (file)
 
 static spinlock_t z8530_buffer_lock = SPIN_LOCK_UNLOCKED;
 
-/*
+/**
+ *     z8530_read_port:
+ *     @p: port to read
+ *
  *     Provided port access methods. The Comtrol SV11 requires no delays
  *     between accesses and uses PC I/O. Some drivers may need a 5uS delay
+ *     
+ *     In the longer term this should become an architecture specific
+ *     section so that this can become a generic driver interface for all
+ *     platforms. For now we only handle PC I/O ports with or without the
+ *     dread 5uS sanity delay.
+ *
+ *     The caller must hold sufficient locks to avoid violating the horrible
+ *     5uS delay rule.
  */
 
-extern __inline__ int z8530_read_port(int p)
+extern __inline__ int z8530_read_port(unsigned long p)
 {
        u8 r=inb(Z8530_PORT_OF(p));
        if(p&Z8530_PORT_SLEEP)  /* gcc should figure this out efficiently ! */
@@ -67,7 +78,23 @@ extern __inline__ int z8530_read_port(int p)
        return r;
 }
 
-extern __inline__ void z8530_write_port(int p, u8 d)
+/**
+ *     z8530_write_port:
+ *     @p: port to write
+ *     @d: value to write
+ *
+ *     Write a value to a port with delays if need be. Note that the
+ *     caller must hold locks to avoid read/writes from other contexts
+ *     violating the 5uS rule
+ *
+ *     In the longer term this should become an architecture specific
+ *     section so that this can become a generic driver interface for all
+ *     platforms. For now we only handle PC I/O ports with or without the
+ *     dread 5uS sanity delay.
+ */
+
+
+extern __inline__ void z8530_write_port(unsigned long p, u8 d)
 {
        outb(d,Z8530_PORT_OF(p));
        if(p&Z8530_PORT_SLEEP)
@@ -80,8 +107,16 @@ static void z8530_rx_done(struct z8530_channel *c);
 static void z8530_tx_done(struct z8530_channel *c);
 
 
-/*
- *     Port accesses
+/**
+ *     read_zsreg:
+ *     @c: Z8530 channel to read from (2 per chip)
+ *     @reg: Register to read
+ *     FIXME: Use a spinlock.
+ *     
+ *     Most of the Z8530 registers are indexed off the control registers.
+ *     A read is done by writing to the control register and reading the
+ *     register back. We do the locking needed to protect this 
+ *     operation.
  */
  
 extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg)
@@ -97,6 +132,14 @@ extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg)
        return r;
 }
 
+/**
+ *     read_zsdata:
+ *     @c: The Z8530 channel to read the data port from
+ *
+ *     The data port provides fast access to some things. We still
+ *     have all the 5uS delays to worry about.
+ */
+
 extern inline u8 read_zsdata(struct z8530_channel *c)
 {
        u8 r;
@@ -104,6 +147,17 @@ extern inline u8 read_zsdata(struct z8530_channel *c)
        return r;
 }
 
+/**
+ *     write_zsreg:
+ *     @c: The Z8530 channel
+ *     @reg: Register number
+ *     @val: Value to write
+ *
+ *     Write a value to an indexed register. Perform the locking needed
+ *     to honour the irritating delay rules. We know about register 0
+ *     being fast to access.
+ */
 extern inline void write_zsreg(struct z8530_channel *c, u8 reg, u8 val)
 {
        unsigned long flags;
@@ -194,8 +248,16 @@ u8 z8530_hdlc_kilostream_85230[]=
 
 EXPORT_SYMBOL(z8530_hdlc_kilostream_85230);
 
-/*
- *     Flush the FIFO
+/**
+ *     z8530_flush_fifo:
+ *     @c: Channel to flush
+ *
+ *     Flush the receive FIFO. There is no specific option for this, we 
+ *     blindly read bytes and discard them. Reading when there is no data
+ *     is harmless. The 8530 has a 4 byte FIFO, the 85230 has 8 bytes.
+ *     
+ *     All locking is handled for the caller. On return data may still be
+ *     present if it arrived during the flush.
  */
  
 static void z8530_flush_fifo(struct z8530_channel *c)
@@ -213,7 +275,16 @@ static void z8530_flush_fifo(struct z8530_channel *c)
        }
 }      
 
-/* Sets or clears DTR/RTS on the requested line */
+/**
+ *     z8530_rtsdtr:
+ *     @c: The Z8530 channel to contro;
+ *     @set: 1 to set, 0 to clear
+ *
+ *     Sets or clears DTR/RTS on the requested line. All locking is handled
+ *     for the caller. For now we assume all boards use the actual RTS/DTR
+ *     on the chip. Apparently one or two don't. We'll scream about them
+ *     later.
+ */
 
 static void z8530_rtsdtr(struct z8530_channel *c, int set)
 {
@@ -224,9 +295,12 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set)
        write_zsreg(c, R5, c->regs[5]);
 }
 
-/*
- *     Receive handler. This is much like the async one but not quite the
- *     same or as complex
+/**
+ *     z8530_rx:
+ *     @c: Z8530 channel to process
+ *
+ *     Receive handler for receiving in PIO mode. This is much like the 
+ *     async one but not quite the same or as complex
  *
  *     Note: Its intended that this handler can easily be separated from
  *     the main code to run realtime. That'll be needed for some machines
@@ -238,9 +312,9 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set)
  *     other code - this is true in the RT case too.
  *
  *     We only cover the sync cases for this. If you want 2Mbit async
- *     do it yourself but consider medical assistance first.
- *
- *     This non DMA synchronous mode is portable code.
+ *     do it yourself but consider medical assistance first. This non DMA 
+ *     synchronous mode is portable code. The DMA mode assumes PCI like 
+ *     ISA DMA
  */
  
 static void z8530_rx(struct z8530_channel *c)
@@ -303,8 +377,14 @@ static void z8530_rx(struct z8530_channel *c)
 }
 
 
-/*
- *     Z8530 transmit interrupt handler
+/**
+ *     z8530_tx:
+ *     @c: Z8530 channel to process
+ *
+ *     Z8530 transmit interrupt handler for the PIO mode. The basic
+ *     idea is to attempt to keep the FIFO fed. We fill as many bytes
+ *     in as possible, its quite possible that we won't keep up with the
+ *     data rate otherwise.
  */
  
 static void z8530_tx(struct z8530_channel *c)
@@ -340,6 +420,17 @@ static void z8530_tx(struct z8530_channel *c)
        write_zsctrl(c, RES_H_IUS);
 }
 
+/**
+ *     z8530_status:
+ *     @chan: Z8530 channel to process
+ *
+ *     A status event occured in PIO synchronous mode. There are several
+ *     reasons the chip will bother us here. A transmit underrun means we
+ *     failed to feed the chip fast enough and just broke a packet. A DCD
+ *     change is a line up or down. We communicate that back to the protocol
+ *     layer for synchronous PPP to renegotiate.
+ */
+
 static void z8530_status(struct z8530_channel *chan)
 {
        u8 status=read_zsreg(chan, R0);
@@ -387,9 +478,14 @@ struct z8530_irqhandler z8530_sync=
 
 EXPORT_SYMBOL(z8530_sync);
 
-/*
+/**
+ *     z8530_dma_rx:
+ *     @chan: Channel to handle
+ *
  *     Non bus mastering DMA interfaces for the Z8x30 devices. This
- *     is really pretty PC specific.
+ *     is really pretty PC specific. The DMA mode means that most receive
+ *     events are handled by the DMA hardware. We get a kick here only if
+ *     a frame ended.
  */
  
 static void z8530_dma_rx(struct z8530_channel *chan)
@@ -417,6 +513,14 @@ static void z8530_dma_rx(struct z8530_channel *chan)
        }       
 }
 
+/**
+ *     z8530_dma_tx:
+ *     @chan:  The Z8530 channel to handle
+ *
+ *     We have received an interrupt while doing DMA transmissions. It
+ *     shouldn't happen. Scream loudly if it does.
+ */
 static void z8530_dma_tx(struct z8530_channel *chan)
 {
        if(!chan->dma_tx)
@@ -430,6 +534,17 @@ static void z8530_dma_tx(struct z8530_channel *chan)
        z8530_tx(chan);
 }
 
+/**
+ *     z8530_dma_status:
+ *     @chan: Z8530 channel to process
+ *     
+ *     A status event occured on the Z8530. We receive these for two reasons
+ *     when in DMA mode. Firstly if we finished a packet transfer we get one
+ *     and kick the next packet out. Secondly we may see a DCD change and
+ *     have to poke the protocol layer.
+ *
+ */
 static void z8530_dma_status(struct z8530_channel *chan)
 {
        unsigned long flags;
@@ -490,8 +605,11 @@ struct z8530_irqhandler z8530_txdma_sync=
 
 EXPORT_SYMBOL(z8530_txdma_sync);
 
-/*
- *     Interrupt vectors for a Z8530 that is in 'parked' mode.
+/**
+ *     z8530_rx_clear:
+ *     @c: Z8530 channel to shut up
+ *
+ *     Receive interrupt vectors for a Z8530 that is in 'parked' mode.
  *     For machines with PCI Z85x30 cards, or level triggered interrupts
  *     (eg the MacII) we must clear the interrupt cause or die.
  */
@@ -516,12 +634,30 @@ static void z8530_rx_clear(struct z8530_channel *c)
        write_zsctrl(c, RES_H_IUS);
 }
 
+/**
+ *     z8530_tx_clear:
+ *     @c: Z8530 channel to shut up
+ *
+ *     Transmit interrupt vectors for a Z8530 that is in 'parked' mode.
+ *     For machines with PCI Z85x30 cards, or level triggered interrupts
+ *     (eg the MacII) we must clear the interrupt cause or die.
+ */
+
 static void z8530_tx_clear(struct z8530_channel *c)
 {
        write_zsctrl(c, RES_Tx_P);
        write_zsctrl(c, RES_H_IUS);
 }
 
+/**
+ *     z8530_status_clear:
+ *     @chan: Z8530 channel to shut up
+ *
+ *     Status interrupt vectors for a Z8530 that is in 'parked' mode.
+ *     For machines with PCI Z85x30 cards, or level triggered interrupts
+ *     (eg the MacII) we must clear the interrupt cause or die.
+ */
+
 static void z8530_status_clear(struct z8530_channel *chan)
 {
        u8 status=read_zsreg(chan, R0);
@@ -541,8 +677,17 @@ struct z8530_irqhandler z8530_nop=
 
 EXPORT_SYMBOL(z8530_nop);
 
-/*
- *     A Z85[2]30 device has stuck its hand in the air for attention
+/**
+ *     z8530_interrupt:
+ *     @irq:   Interrupt number
+ *     @dev_id: The Z8530 device that is interrupting.
+ *     @regs: unused
+ *
+ *     A Z85[2]30 device has stuck its hand in the air for attention.
+ *     We scan both the channels on the chip for events and then call
+ *     the channel specific call backs for each channel that has events.
+ *     We have to use callback functions because the two channels can be
+ *     in different modes.
  */
 
 void z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -612,6 +757,15 @@ static char reg_init[16]=
 };
 
 
+/**
+ *     z8530_sync_open:
+ *     @dev:   The network interface we are using
+ *     @c:     The Z8530 channel to open in synchronous PIO mode
+ *
+ *     Switch a Z8530 into synchronous mode without DMA assist. We
+ *     raise the RTS/DTR and commence network operation.
+ */
 int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
 {
        c->sync = 1;
@@ -634,6 +788,15 @@ int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
 
 EXPORT_SYMBOL(z8530_sync_open);
 
+/**
+ *     z8530_sync_close:
+ *     @dev: Network device to close
+ *     @c: Z8530 channel to disassociate and move to idle
+ *
+ *     Close down a Z8530 interface and switch its interrupt handlers
+ *     to discard future events.
+ */
 int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
 {
        u8 chk;
@@ -650,6 +813,16 @@ int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
 
 EXPORT_SYMBOL(z8530_sync_close);
 
+/**
+ *     z8530_sync_dma_open:
+ *     @dev: The network device to attach
+ *     @c: The Z8530 channel to configure in sync DMA mode.
+ *
+ *     Set up a Z85x30 device for synchronous DMA in both directions. Two
+ *     ISA DMA channels must be available for this to work. We assume ISA
+ *     DMA driven I/O and PC limits on access.
+ */
 int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
 {
        unsigned long flags;
@@ -760,6 +933,15 @@ int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
 
 EXPORT_SYMBOL(z8530_sync_dma_open);
 
+/**
+ *     z8530_sync_dma_close:
+ *     @dev: Network device to detach
+ *     @c: Z8530 channel to move into discard mode
+ *
+ *     Shut down a DMA mode synchronous interface. Halt the DMA, and
+ *     free the buffers.
+ */
 int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
 {
        u8 chk;
@@ -816,6 +998,16 @@ int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
 
 EXPORT_SYMBOL(z8530_sync_dma_close);
 
+/**
+ *     z8530_sync_txdma_open:
+ *     @dev: The network device to attach
+ *     @c: The Z8530 channel to configure in sync DMA mode.
+ *
+ *     Set up a Z85x30 device for synchronous DMA tranmission. One
+ *     ISA DMA channel must be available for this to work. The receive
+ *     side is run in PIO mode, but then it has the bigger FIFO.
+ */
+
 int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
 {
        unsigned long flags;
@@ -905,7 +1097,16 @@ int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
 }
 
 EXPORT_SYMBOL(z8530_sync_txdma_open);
-       
+
+/**
+ *     z8530_sync_txdma_close:
+ *     @dev: Network device to detach
+ *     @c: Z8530 channel to move into discard mode
+ *
+ *     Shut down a DMA/PIO split mode synchronous interface. Halt the DMA, 
+ *     and  free the buffers.
+ */
+
 int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
 {
        unsigned long flags;
@@ -954,21 +1155,32 @@ int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
 
 EXPORT_SYMBOL(z8530_sync_txdma_close);
 
+
 /*
- *     Describe a Z8530 in a standard format. We must pass the I/O as
- *     the port offset isnt predictable. The main reason for this function
- *     is to try and get a common format of report.
+ *     Name strings for Z8530 chips. SGI claim to have a 130, Zilog deny
+ *     it exists...
  */
-
 static char *z8530_type_name[]={
        "Z8530",
        "Z85C30",
        "Z85230"
 };
 
-void z8530_describe(struct z8530_dev *dev, char *mapping, int io)
+/**
+ *     z8530_describe:
+ *     @dev: Z8530 device to describe
+ *     @mapping: string holding mapping type (eg "I/O" or "Mem")
+ *     @io: the port value in question
+ *
+ *     Describe a Z8530 in a standard format. We must pass the I/O as
+ *     the port offset isnt predictable. The main reason for this function
+ *     is to try and get a common format of report.
+ */
+
+void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io)
 {
-       printk(KERN_INFO "%s: %s found at %s 0x%X, IRQ %d.\n",
+       printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n",
                dev->name, 
                z8530_type_name[dev->type],
                mapping,
@@ -978,8 +1190,21 @@ void z8530_describe(struct z8530_dev *dev, char *mapping, int io)
 
 EXPORT_SYMBOL(z8530_describe);
 
-/*
- *     Configure up a Z8530
+/**
+ *     z8530_init:
+ *     @dev: Z8530 device to initialise.
+ *
+ *     Configure up a Z8530/Z85C30 or Z85230 chip. We check the device
+ *     is present, identify the type and then program it to hopefully
+ *     keep quite and behave. This matters a lot, a Z8530 in the wrong
+ *     state will sometimes get into stupid modes generating 10Khz
+ *     interrupt streams and the like.
+ *
+ *     We set the interrupt handler up to discard any events, in case
+ *     we get them during reset or setp.
+ *
+ *     Return 0 for success, or a negative value indicating the problem
+ *     in errno form.
  */
 
  
@@ -1047,6 +1272,15 @@ int z8530_init(struct z8530_dev *dev)
 
 EXPORT_SYMBOL(z8530_init);
 
+/**
+ *     z8530_shutdown:
+ *     @dev: The Z8530 chip to shutdown
+ *
+ *     We set the interrupt handlers to silence any interrupts. We then 
+ *     reset the chip and wait 100uS to be sure the reset completed. Just
+ *     in case the caller then tries to do stuff.
+ */
 int z8530_shutdown(struct z8530_dev *dev)
 {
        /* Reset the chip */
@@ -1059,9 +1293,15 @@ int z8530_shutdown(struct z8530_dev *dev)
 
 EXPORT_SYMBOL(z8530_shutdown);
 
-/*
- *     Load a Z8530 channel up from the system data
- *     We use +16 to indicate the 'prime' registers
+/**
+ *     z8530_channel_load:
+ *     @c: Z8530 channel to configure
+ *     @rtable: Table of register, value pairs
+ *     FIXME: ioctl to allow user uploaded tables
+ *
+ *     Load a Z8530 channel up from the system data> We use +16 to 
+ *     indicate the 'prime' registers. The value 255 terminates the
+ *     table
  */
 
 int z8530_channel_load(struct z8530_channel *c, u8 *rtable)
@@ -1092,8 +1332,16 @@ int z8530_channel_load(struct z8530_channel *c, u8 *rtable)
 EXPORT_SYMBOL(z8530_channel_load);
 
 
-/*
- *     Higher level shovelling - transmit chains
+/**
+ *     z8530_tx_begin:
+ *     @c: The Z8530 channel to kick
+ *
+ *     This is the speed sensitive side of transmission. If we are called
+ *     and no buffer is being transmitted we commence the next buffer. If
+ *     nothing is queued we idle the sync. 
+ *
+ *     Note: We are handling this code path in the interrupt path, keep it
+ *     fast or bad things will happen.
  */
 
 static void z8530_tx_begin(struct z8530_channel *c)
@@ -1180,7 +1428,15 @@ static void z8530_tx_begin(struct z8530_channel *c)
                }
        }
 }
+
+/**
+ *     z8530_tx_done:
+ *     @c: The channel that completed a transmit.
+ *
+ *     This is called when we complete a packet send. We wake the queue,
+ *     start the next packet going and then free the buffer of the existing
+ *     packet. This code is fairly timing sensitive.
+ */ 
  
 static void z8530_tx_done(struct z8530_channel *c)
 {
@@ -1201,11 +1457,16 @@ static void z8530_tx_done(struct z8530_channel *c)
        spin_unlock_irqrestore(&z8530_buffer_lock, flags);
        c->stats.tx_packets++;
        c->stats.tx_bytes+=skb->len;
-       dev_kfree_skb(skb);
+       dev_kfree_skb_irq(skb);
 }
 
-/*
- *     Higher level shovelling - receive chains
+/**
+ *     z8530_null_rx:
+ *     @c: The channel the packet arrived on
+ *     @skb: The buffer
+ *
+ *     We point the receive handler at this function when idle. Instead
+ *     of syncppp processing the frames we get to throw them away.
  */
  
 void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb)
@@ -1215,6 +1476,17 @@ void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb)
 
 EXPORT_SYMBOL(z8530_null_rx);
 
+/**
+ *     z8530_rx_done:
+ *     @c: The channel that completed a receive
+ *
+ *     A new packet is complete. Our goal here is to get back into receive
+ *     mode as fast as possible. On the Z85230 we could change to using
+ *     ESCC mode, but on the older chips we have no choice. We flip to the
+ *     new buffer immediately in DMA mode so that the DMA of the next
+ *     frame can occur while we are copying the previous buffer to an sk_buff
+ */
 static void z8530_rx_done(struct z8530_channel *c)
 {
        struct sk_buff *skb;
@@ -1269,7 +1541,7 @@ static void z8530_rx_done(struct z8530_channel *c)
                else
                        /* Can't occur as we dont reenable the DMA irq until
                           after the flip is done */
-                       printk("DMA flip overrun!\n");
+                       printk(KERN_WARNING "%s: DMA flip overrun!\n", c->netdevice->name);
                        
                release_dma_lock(flags);
                
@@ -1357,8 +1629,12 @@ static void z8530_rx_done(struct z8530_channel *c)
        }
 }
 
-/*
- *     Cannot DMA over a 64K boundary on a PC
+/**
+ *     spans_boundary:
+ *     @skb: The buffer to check
+ *
+ *     Returns true if the buffer cross a DMA boundary on a PC. The poor
+ *     thing can only DMA within a 64K block not across the edges of it.
  */
  
 extern inline int spans_boundary(struct sk_buff *skb)
@@ -1373,7 +1649,11 @@ extern inline int spans_boundary(struct sk_buff *skb)
        return 0;
 }
 
-/*
+/**
+ *     z8530_queue_xmit:
+ *     @c: The channel to use
+ *     @skb: The packet to kick down the channel
+ *
  *     Queue a packet for transmission. Because we have rather
  *     hard to hit interrupt latencies for the Z85230 per packet 
  *     even in DMA mode we do the flip to DMA buffer if needed here
@@ -1426,6 +1706,14 @@ int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb)
 
 EXPORT_SYMBOL(z8530_queue_xmit);
 
+/**
+ *     z8530_get_stats:
+ *     @c: The channel to use
+ *
+ *     Get the statistics block. We keep the statistics in software as
+ *     the chip doesn't do it for us.
+ */
 struct net_device_stats *z8530_get_stats(struct z8530_channel *c)
 {
        return &c->stats;
index dcad711b07b37e95ac483b71cb9750367ef0e25e..8dc92a5356005773d45acb1c80b949c2988317b5 100644 (file)
@@ -304,8 +304,8 @@ struct z8530_channel
         */
         
        struct z8530_dev *dev;          /* Z85230 chip instance we are from */
-       int             ctrlio;         /* I/O ports */
-       int             dataio;
+       unsigned long   ctrlio;         /* I/O ports */
+       unsigned long   dataio;
 
        /*
         *      For PC we encode this way.
@@ -395,7 +395,7 @@ extern u8 z8530_dead_port[];
 extern u8 z8530_hdlc_kilostream_85230[];
 extern u8 z8530_hdlc_kilostream[];
 extern void z8530_interrupt(int, void *, struct pt_regs *);
-extern void z8530_describe(struct z8530_dev *, char *mapping,int io);
+extern void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io);
 extern int z8530_init(struct z8530_dev *);
 extern int z8530_shutdown(struct z8530_dev *);
 extern int z8530_sync_open(struct net_device *, struct z8530_channel *);
index 73771fc96ce1189351d07bf5c50e30a225285f42..59d8621ca04abe79a759b38aa4fd4bd353a9e2c5 100644 (file)
@@ -6,9 +6,9 @@
  * Reorganisation and extension of the driver.
  * Original copyright follows (also see the end of this file).
  * See wavelan.p.h for details.
- */
-
-/*
+ *
+ *
+ *
  * AT&T GIS (nee NCR) WaveLAN card:
  *     An Ethernet-like radio transceiver
  *     controlled by an Intel 82586 coprocessor.
 /*
  * Wrapper for disabling interrupts.
  */
-static inline unsigned long
-wv_splhi(void)
-{
-  unsigned long flags;
 
-  save_flags(flags);
-  cli();
-
-  return(flags);
+static inline unsigned long wv_splhi(void)
+{
+       unsigned long flags;
+       save_flags(flags);
+       cli();
+       return (flags);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Wrapper for re-enabling interrupts.
  */
-static inline void
-wv_splx(unsigned long  flags)
+static inline void wv_splx(unsigned long flags)
 {
-  restore_flags(flags);
+       restore_flags(flags);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Translate irq number to PSA irq parameter
  */
-static u_char
-wv_irq_to_psa(int      irq)
+static u8 wv_irq_to_psa(int irq)
 {
-  if(irq < 0 || irq >= NELS(irqvals))
-    return 0;
+       if (irq < 0 || irq >= NELS(irqvals))
+               return 0;
 
-  return irqvals[irq];
+       return irqvals[irq];
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Translate PSA irq parameter to irq number 
  */
-static int __init 
-wv_psa_to_irq(u_char irqval)
+static int __init wv_psa_to_irq(u8 irqval)
 {
-  int  irq;
+       int irq;
 
-  for(irq = 0; irq < NELS(irqvals); irq++)
-    if(irqvals[irq] == irqval)
-      return irq;
+       for (irq = 0; irq < NELS(irqvals); irq++)
+               if (irqvals[irq] == irqval)
+                       return irq;
 
-  return -1;
+       return -1;
 }
 
 #ifdef STRUCT_CHECK
@@ -82,21 +77,20 @@ wv_psa_to_irq(u_char irqval)
  * Sanity routine to verify the sizes of the various WaveLAN interface
  * structures.
  */
-static char *
-wv_struct_check(void)
+static char *wv_struct_check(void)
 {
 #define        SC(t,s,n)       if (sizeof(t) != s) return(n);
 
-  SC(psa_t, PSA_SIZE, "psa_t");
-  SC(mmw_t, MMW_SIZE, "mmw_t");
-  SC(mmr_t, MMR_SIZE, "mmr_t");
-  SC(ha_t, HA_SIZE, "ha_t");
+       SC(psa_t, PSA_SIZE, "psa_t");
+       SC(mmw_t, MMW_SIZE, "mmw_t");
+       SC(mmr_t, MMR_SIZE, "mmr_t");
+       SC(ha_t, HA_SIZE, "ha_t");
 
 #undef SC
 
-  return((char *) NULL);
-} /* wv_struct_check */
-#endif /* STRUCT_CHECK */
+       return ((char *) NULL);
+}                              /* wv_struct_check */
+#endif                         /* STRUCT_CHECK */
 
 /********************* HOST ADAPTER SUBROUTINES *********************/
 /*
@@ -111,120 +105,106 @@ wv_struct_check(void)
 /*
  * Read from card's Host Adaptor Status Register.
  */
-static inline u_short
-hasr_read(u_long       ioaddr)
+static inline u16 hasr_read(unsigned long ioaddr)
 {
-  return(inw(HASR(ioaddr)));
-} /* hasr_read */
+       return (inw(HASR(ioaddr)));
+}                              /* hasr_read */
 
 /*------------------------------------------------------------------*/
 /*
  * Write to card's Host Adapter Command Register.
  */
-static inline void
-hacr_write(u_long      ioaddr,
-          u_short      hacr)
+static inline void hacr_write(unsigned long ioaddr, u16 hacr)
 {
-  outw(hacr, HACR(ioaddr));
-} /* hacr_write */
+       outw(hacr, HACR(ioaddr));
+}                              /* hacr_write */
 
 /*------------------------------------------------------------------*/
 /*
  * Write to card's Host Adapter Command Register. Include a delay for
  * those times when it is needed.
  */
-static inline void
-hacr_write_slow(u_long ioaddr,
-               u_short hacr)
+static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr)
 {
-  hacr_write(ioaddr, hacr);
-  /* delay might only be needed sometimes */
-  mdelay(1);
-} /* hacr_write_slow */
+       hacr_write(ioaddr, hacr);
+       /* delay might only be needed sometimes */
+       mdelay(1);
+}                              /* hacr_write_slow */
 
 /*------------------------------------------------------------------*/
 /*
  * Set the channel attention bit.
  */
-static inline void
-set_chan_attn(u_long   ioaddr,
-             u_short   hacr)
+static inline void set_chan_attn(unsigned long ioaddr, u16 hacr)
 {
-  hacr_write(ioaddr, hacr | HACR_CA);
-} /* set_chan_attn */
+       hacr_write(ioaddr, hacr | HACR_CA);
+}                              /* set_chan_attn */
 
 /*------------------------------------------------------------------*/
 /*
  * Reset, and then set host adaptor into default mode.
  */
-static inline void
-wv_hacr_reset(u_long   ioaddr)
+static inline void wv_hacr_reset(unsigned long ioaddr)
 {
-  hacr_write_slow(ioaddr, HACR_RESET);
-  hacr_write(ioaddr, HACR_DEFAULT);
-} /* wv_hacr_reset */
+       hacr_write_slow(ioaddr, HACR_RESET);
+       hacr_write(ioaddr, HACR_DEFAULT);
+}                              /* wv_hacr_reset */
 
 /*------------------------------------------------------------------*/
 /*
  * Set the I/O transfer over the ISA bus to 8-bit mode
  */
-static inline void
-wv_16_off(u_long       ioaddr,
-         u_short       hacr)
+static inline void wv_16_off(unsigned long ioaddr, u16 hacr)
 {
-  hacr &= ~HACR_16BITS;
-  hacr_write(ioaddr, hacr);
-} /* wv_16_off */
+       hacr &= ~HACR_16BITS;
+       hacr_write(ioaddr, hacr);
+}                              /* wv_16_off */
 
 /*------------------------------------------------------------------*/
 /*
  * Set the I/O transfer over the ISA bus to 8-bit mode
  */
-static inline void
-wv_16_on(u_long                ioaddr,
-        u_short        hacr)
+static inline void wv_16_on(unsigned long ioaddr, u16 hacr)
 {
-  hacr |= HACR_16BITS;
-  hacr_write(ioaddr, hacr);
-} /* wv_16_on */
+       hacr |= HACR_16BITS;
+       hacr_write(ioaddr, hacr);
+}                              /* wv_16_on */
 
 /*------------------------------------------------------------------*/
 /*
  * Disable interrupts on the WaveLAN hardware.
  */
-static inline void
-wv_ints_off(device *   dev)
+static inline void wv_ints_off(device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  u_long       x;
-
-  x = wv_splhi();
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       unsigned long flags;
 
-  lp->hacr &= ~HACR_INTRON;
-  hacr_write(ioaddr, lp->hacr);
+       save_flags(flags);
+       cli();
+       
+       lp->hacr &= ~HACR_INTRON;
+       hacr_write(ioaddr, lp->hacr);
 
-  wv_splx(x);
-} /* wv_ints_off */
+       restore_flags(flags);
+}                              /* wv_ints_off */
 
 /*------------------------------------------------------------------*/
 /*
  * Enable interrupts on the WaveLAN hardware.
  */
-static inline void
-wv_ints_on(device *    dev)
+static inline void wv_ints_on(device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  u_long       x;
-
-  x = wv_splhi();
-
-  lp->hacr |= HACR_INTRON;
-  hacr_write(ioaddr, lp->hacr);
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       unsigned long flags;
 
-  wv_splx(x);
-} /* wv_ints_on */
+       save_flags(flags);
+       cli();
+       lp->hacr |= HACR_INTRON;
+       hacr_write(ioaddr, lp->hacr);
+       restore_flags(flags);
+}                              /* wv_ints_on */
 
 /******************* MODEM MANAGEMENT SUBROUTINES *******************/
 /*
@@ -238,57 +218,48 @@ wv_ints_on(device *       dev)
 /*
  * Read bytes from the PSA.
  */
-static void
-psa_read(u_long                ioaddr,
-        u_short        hacr,
-        int            o,      /* offset in PSA */
-        u_char *       b,      /* buffer to fill */
-        int            n)      /* size to read */
-{
-  wv_16_off(ioaddr, hacr);
-
-  while(n-- > 0)
-    {
-      outw(o, PIOR2(ioaddr));
-      o++;
-      *b++ = inb(PIOP2(ioaddr));
-    }
+static void psa_read(unsigned long ioaddr, u16 hacr, int o,    /* offset in PSA */
+                    u8 * b,    /* buffer to fill */
+                    int n)
+{                              /* size to read */
+       wv_16_off(ioaddr, hacr);
+
+       while (n-- > 0) {
+               outw(o, PIOR2(ioaddr));
+               o++;
+               *b++ = inb(PIOP2(ioaddr));
+       }
 
-  wv_16_on(ioaddr, hacr);
-} /* psa_read */
+       wv_16_on(ioaddr, hacr);
+}                              /* psa_read */
 
 /*------------------------------------------------------------------*/
 /*
  * Write the Parameter Storage Area to the WaveLAN card's memory.
  */
-static void
-psa_write(u_long       ioaddr,
-         u_short       hacr,
-         int           o,      /* Offset in PSA */
-         u_char *      b,      /* Buffer in memory */
-         int           n)      /* Length of buffer */
-{
-  int  count = 0;
+static void psa_write(unsigned long ioaddr, u16 hacr, int o,   /* Offset in PSA */
+                     u8 * b,   /* Buffer in memory */
+                     int n)
+{                              /* Length of buffer */
+       int count = 0;
 
-  wv_16_off(ioaddr, hacr);
+       wv_16_off(ioaddr, hacr);
 
-  while(n-- > 0)
-    {
-      outw(o, PIOR2(ioaddr));
-      o++;
+       while (n-- > 0) {
+               outw(o, PIOR2(ioaddr));
+               o++;
 
-      outb(*b, PIOP2(ioaddr));
-      b++;
+               outb(*b, PIOP2(ioaddr));
+               b++;
 
-      /* Wait for the memory to finish its write cycle */
-      count = 0;
-      while((count++ < 100) &&
-           (hasr_read(ioaddr) & HASR_PSA_BUSY))
-       mdelay(1);
-    }
+               /* Wait for the memory to finish its write cycle */
+               count = 0;
+               while ((count++ < 100) &&
+                      (hasr_read(ioaddr) & HASR_PSA_BUSY)) mdelay(1);
+       }
 
-  wv_16_on(ioaddr, hacr);
-} /* psa_write */
+       wv_16_on(ioaddr, hacr);
+}                              /* psa_write */
 
 #ifdef SET_PSA_CRC
 /*------------------------------------------------------------------*/
@@ -301,88 +272,80 @@ psa_write(u_long  ioaddr,
  * The Windows drivers don't use the CRC, but the AP and the PtP tool
  * depend on it.
  */
-static inline u_short
-psa_crc(u_char *       psa,    /* The PSA */
-       int             size)   /* Number of short for CRC */
-{
-  int          byte_cnt;       /* Loop on the PSA */
-  u_short      crc_bytes = 0;  /* Data in the PSA */
-  int          bit_cnt;        /* Loop on the bits of the short */
-
-  for(byte_cnt = 0; byte_cnt < size; byte_cnt++ )
-    {
-      crc_bytes ^= psa[byte_cnt];      /* Its an xor */
-
-      for(bit_cnt = 1; bit_cnt < 9; bit_cnt++ )
-       {
-         if(crc_bytes & 0x0001)
-           crc_bytes = (crc_bytes >> 1) ^ 0xA001;
-         else
-           crc_bytes >>= 1 ;
-        }
-    }
+static inline u16 psa_crc(u8 * psa,    /* The PSA */
+                             int size)
+{                              /* Number of short for CRC */
+       int byte_cnt;           /* Loop on the PSA */
+       u16 crc_bytes = 0;      /* Data in the PSA */
+       int bit_cnt;            /* Loop on the bits of the short */
+
+       for (byte_cnt = 0; byte_cnt < size; byte_cnt++) {
+               crc_bytes ^= psa[byte_cnt];     /* Its an xor */
+
+               for (bit_cnt = 1; bit_cnt < 9; bit_cnt++) {
+                       if (crc_bytes & 0x0001)
+                               crc_bytes = (crc_bytes >> 1) ^ 0xA001;
+                       else
+                               crc_bytes >>= 1;
+               }
+       }
 
-  return crc_bytes;
-} /* psa_crc */
-#endif /* SET_PSA_CRC */
+       return crc_bytes;
+}                              /* psa_crc */
+#endif                         /* SET_PSA_CRC */
 
 /*------------------------------------------------------------------*/
 /*
  * update the checksum field in the Wavelan's PSA
  */
-static void
-update_psa_checksum(device *   dev,
-                   u_long      ioaddr,
-                   u_short     hacr)
+static void update_psa_checksum(device * dev, unsigned long ioaddr, u16 hacr)
 {
 #ifdef SET_PSA_CRC
-  psa_t                psa;
-  u_short      crc;
+       psa_t psa;
+       u16 crc;
 
-  /* read the parameter storage area */
-  psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa));
+       /* read the parameter storage area */
+       psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa));
 
-  /* update the checksum */
-  crc = psa_crc((unsigned char *) &psa,
-               sizeof(psa) - sizeof(psa.psa_crc[0]) - sizeof(psa.psa_crc[1])
-               - sizeof(psa.psa_crc_status));
+       /* update the checksum */
+       crc = psa_crc((unsigned char *) &psa,
+                     sizeof(psa) - sizeof(psa.psa_crc[0]) -
+                     sizeof(psa.psa_crc[1])
+                     - sizeof(psa.psa_crc_status));
 
-  psa.psa_crc[0] = crc & 0xFF;
-  psa.psa_crc[1] = (crc & 0xFF00) >> 8;
+       psa.psa_crc[0] = crc & 0xFF;
+       psa.psa_crc[1] = (crc & 0xFF00) >> 8;
 
-  /* Write it ! */
-  psa_write(ioaddr, hacr, (char *)&psa.psa_crc - (char *)&psa,
-           (unsigned char *)&psa.psa_crc, 2);
+       /* Write it ! */
+       psa_write(ioaddr, hacr, (char *) &psa.psa_crc - (char *) &psa,
+                 (unsigned char *) &psa.psa_crc, 2);
 
 #ifdef DEBUG_IOCTL_INFO
-  printk (KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n",
-          dev->name, psa.psa_crc[0], psa.psa_crc[1]);
+       printk(KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n",
+              dev->name, psa.psa_crc[0], psa.psa_crc[1]);
 
-  /* Check again (luxury !) */
-  crc = psa_crc ((unsigned char *) &psa,
-                sizeof(psa) - sizeof(psa.psa_crc_status));
+       /* Check again (luxury !) */
+       crc = psa_crc((unsigned char *) &psa,
+                     sizeof(psa) - sizeof(psa.psa_crc_status));
 
-  if(crc != 0)
-    printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name);
-#endif /* DEBUG_IOCTL_INFO */
-#endif /* SET_PSA_CRC */
-} /* update_psa_checksum */
+       if (crc != 0)
+               printk(KERN_WARNING
+                      "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n",
+                      dev->name);
+#endif                         /* DEBUG_IOCTL_INFO */
+#endif                         /* SET_PSA_CRC */
+}                              /* update_psa_checksum */
 
 /*------------------------------------------------------------------*/
 /*
  * Write 1 byte to the MMC.
  */
-static inline void
-mmc_out(u_long         ioaddr,
-       u_short         o,
-       u_char          d)
+static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d)
 {
-  /* Wait for MMC to go idle */
-  while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
-    ;
+       /* Wait for MMC to go idle */
+       while (inw(HASR(ioaddr)) & HASR_MMC_BUSY);
 
-  outw((u_short) (((u_short) d << 8) | (o << 1) | 1),
-       MMCR(ioaddr));
+       outw((u16) (((u16) d << 8) | (o << 1) | 1), MMCR(ioaddr));
 }
 
 /*------------------------------------------------------------------*/
@@ -390,35 +353,27 @@ mmc_out(u_long            ioaddr,
  * Routine to write bytes to the Modem Management Controller.
  * We start at the end because it is the way it should be!
  */
-static inline void
-mmc_write(u_long       ioaddr,
-         u_char        o,
-         u_char *      b,
-         int           n)
+static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
 {
-  o += n;
-  b += n;
+       o += n;
+       b += n;
 
-  while(n-- > 0 )
-    mmc_out(ioaddr, --o, *(--b));
-} /* mmc_write */
+       while (n-- > 0)
+               mmc_out(ioaddr, --o, *(--b));
+}                              /* mmc_write */
 
 /*------------------------------------------------------------------*/
 /*
  * Read a byte from the MMC.
  * Optimised version for 1 byte, avoid using memory.
  */
-static inline u_char
-mmc_in(u_long  ioaddr,
-       u_short o)
+static inline u8 mmc_in(unsigned long ioaddr, u16 o)
 {
-  while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
-    ;
-  outw(o << 1, MMCR(ioaddr));
+       while (inw(HASR(ioaddr)) & HASR_MMC_BUSY);
+       outw(o << 1, MMCR(ioaddr));
 
-  while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
-    ;
-  return (u_char) (inw(MMCR(ioaddr)) >> 8);
+       while (inw(HASR(ioaddr)) & HASR_MMC_BUSY);
+       return (u8) (inw(MMCR(ioaddr)) >> 8);
 }
 
 /*------------------------------------------------------------------*/
@@ -429,33 +384,28 @@ mmc_in(u_long     ioaddr,
  * (code has just been moved in the above function)
  * We start at the end because it is the way it should be!
  */
-static inline void
-mmc_read(u_long                ioaddr,
-        u_char         o,
-        u_char *       b,
-        int            n)
+static inline void mmc_read(unsigned long ioaddr, u8 o, u8 * b, int n)
 {
-  o += n;
-  b += n;
+       o += n;
+       b += n;
 
-  while(n-- > 0)
-    *(--b) = mmc_in(ioaddr, --o);
-} /* mmc_read */
+       while (n-- > 0)
+               *(--b) = mmc_in(ioaddr, --o);
+}                              /* mmc_read */
 
 /*------------------------------------------------------------------*/
 /*
  * Get the type of encryption available.
  */
-static inline int
-mmc_encr(u_long                ioaddr) /* I/O port of the card */
-{
-  int  temp;
-
-  temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
-  if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
-    return 0;
-  else
-    return temp;
+static inline int mmc_encr(unsigned long ioaddr)
+{                              /* I/O port of the card */
+       int temp;
+
+       temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
+       if ((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
+               return 0;
+       else
+               return temp;
 }
 
 /*------------------------------------------------------------------*/
@@ -463,49 +413,47 @@ mmc_encr(u_long           ioaddr) /* I/O port of the card */
  * Wait for the frequency EEPROM to complete a command.
  * I hope this one will be optimally inlined.
  */
-static inline void
-fee_wait(u_long                ioaddr, /* I/O port of the card */
-        int            delay,  /* Base delay to wait for */
-        int            number) /* Number of time to wait */
-{
-  int          count = 0;      /* Wait only a limited time */
-
-  while((count++ < number) &&
-       (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & MMR_FEE_STATUS_BUSY))
-    udelay(delay);
+static inline void fee_wait(unsigned long ioaddr,      /* I/O port of the card */
+                           int delay,  /* Base delay to wait for */
+                           int number)
+{                              /* Number of time to wait */
+       int count = 0;          /* Wait only a limited time */
+
+       while ((count++ < number) &&
+              (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+               MMR_FEE_STATUS_BUSY)) udelay(delay);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Read bytes from the Frequency EEPROM (frequency select cards).
  */
-static void
-fee_read(u_long                ioaddr, /* I/O port of the card */
-        u_short        o,      /* destination offset */
-        u_short *      b,      /* data buffer */
-        int            n)      /* number of registers */
-{
-  b += n;              /* Position at the end of the area */
-
-  /* Write the address */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
-
-  /* Loop on all buffer */
-  while(n-- > 0)
-    {
-      /* Write the read command */
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ);
-
-      /* Wait until EEPROM is ready (should be quick). */
-      fee_wait(ioaddr, 10, 100);
-
-      /* Read the value. */
-      *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) |
-             mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
-    }
+static void fee_read(unsigned long ioaddr,     /* I/O port of the card */
+                    u16 o,     /* destination offset */
+                    u16 * b,   /* data buffer */
+                    int n)
+{                              /* number of registers */
+       b += n;                 /* Position at the end of the area */
+
+       /* Write the address */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
+
+       /* Loop on all buffer */
+       while (n-- > 0) {
+               /* Write the read command */
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+                       MMW_FEE_CTRL_READ);
+
+               /* Wait until EEPROM is ready (should be quick). */
+               fee_wait(ioaddr, 10, 100);
+
+               /* Read the value. */
+               *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) |
+                       mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
+       }
 }
 
-#ifdef WIRELESS_EXT    /* if the wireless extension exists in the kernel */
+#ifdef WIRELESS_EXT            /* if the wireless extension exists in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -514,83 +462,82 @@ fee_read(u_long           ioaddr, /* I/O port of the card */
  * be unprotected and the write enabled.
  * Jean II
  */
-static void
-fee_write(u_long       ioaddr, /* I/O port of the card */
-         u_short       o,      /* destination offset */
-         u_short *     b,      /* data buffer */
-         int           n)      /* number of registers */
-{
-  b += n;              /* Position at the end of the area. */
+static void fee_write(unsigned long ioaddr,    /* I/O port of the card */
+                     u16 o,    /* destination offset */
+                     u16 * b,  /* data buffer */
+                     int n)
+{                              /* number of registers */
+       b += n;                 /* Position at the end of the area. */
 
 #ifdef EEPROM_IS_PROTECTED     /* disabled */
 #ifdef DOESNT_SEEM_TO_WORK     /* disabled */
-  /* Ask to read the protected register */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);
+       /* Ask to read the protected register */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);
 
-  fee_wait(ioaddr, 10, 100);
+       fee_wait(ioaddr, 10, 100);
 
-  /* Read the protected register. */
-  printk("Protected 2:  %02X-%02X\n",
-        mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)),
-        mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
-#endif /* DOESNT_SEEM_TO_WORK */
+       /* Read the protected register. */
+       printk("Protected 2:  %02X-%02X\n",
+              mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)),
+              mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
+#endif                         /* DOESNT_SEEM_TO_WORK */
 
-  /* Enable protected register. */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN);
+       /* Enable protected register. */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN);
 
-  fee_wait(ioaddr, 10, 100);
+       fee_wait(ioaddr, 10, 100);
 
-  /* Unprotect area. */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n);
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
+       /* Unprotect area. */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n);
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
 #ifdef DOESNT_SEEM_TO_WORK     /* disabled */
-  /* or use: */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR);
-#endif /* DOESNT_SEEM_TO_WORK */
+       /* or use: */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR);
+#endif                         /* DOESNT_SEEM_TO_WORK */
 
-  fee_wait(ioaddr, 10, 100);
-#endif /* EEPROM_IS_PROTECTED */
+       fee_wait(ioaddr, 10, 100);
+#endif                         /* EEPROM_IS_PROTECTED */
 
-  /* Write enable. */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN);
+       /* Write enable. */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN);
 
-  fee_wait(ioaddr, 10, 100);
+       fee_wait(ioaddr, 10, 100);
 
-  /* Write the EEPROM address. */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
+       /* Write the EEPROM address. */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
 
-  /* Loop on all buffer */
-  while(n-- > 0)
-    {
-      /* Write the value. */
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8);
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF);
+       /* Loop on all buffer */
+       while (n-- > 0) {
+               /* Write the value. */
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8);
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF);
 
-      /* Write the write command. */
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE);
+               /* Write the write command. */
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+                       MMW_FEE_CTRL_WRITE);
 
-      /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */
-      mdelay(10);
-      fee_wait(ioaddr, 10, 100);
-    }
+               /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */
+               mdelay(10);
+               fee_wait(ioaddr, 10, 100);
+       }
 
-  /* Write disable. */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS);
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS);
+       /* Write disable. */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS);
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS);
 
-  fee_wait(ioaddr, 10, 100);
+       fee_wait(ioaddr, 10, 100);
 
 #ifdef EEPROM_IS_PROTECTED     /* disabled */
-  /* Reprotect EEPROM. */
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00);
-  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
+       /* Reprotect EEPROM. */
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00);
+       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
 
-  fee_wait(ioaddr, 10, 100);
-#endif /* EEPROM_IS_PROTECTED */
+       fee_wait(ioaddr, 10, 100);
+#endif                         /* EEPROM_IS_PROTECTED */
 }
-#endif /* WIRELESS_EXT */
+#endif                         /* WIRELESS_EXT */
 
 /************************ I82586 SUBROUTINES *************************/
 /*
@@ -602,68 +549,61 @@ fee_write(u_long  ioaddr, /* I/O port of the card */
  * Read bytes from the on-board RAM.
  * Why does inlining this function make it fail?
  */
-static /*inline*/ void
-obram_read(u_long      ioaddr,
-          u_short      o,
-          u_char *     b,
-          int          n)
+static /*inline */ void obram_read(unsigned long ioaddr,
+                                  u16 o, u8 * b, int n)
 {
-  outw(o, PIOR1(ioaddr));
-  insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
+       outw(o, PIOR1(ioaddr));
+       insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Write bytes to the on-board RAM.
  */
-static inline void
-obram_write(u_long     ioaddr,
-           u_short     o,
-           u_char *    b,
-           int         n)
+static inline void obram_write(unsigned long ioaddr, u16 o, u8 * b, int n)
 {
-  outw(o, PIOR1(ioaddr));
-  outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
+       outw(o, PIOR1(ioaddr));
+       outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Acknowledge the reading of the status issued by the i82586.
  */
-static void
-wv_ack(device *                dev)
+static void wv_ack(device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  u_short      scb_cs;
-  int          i;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       u16 scb_cs;
+       int i;
 
-  obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
-            (unsigned char *) &scb_cs, sizeof(scb_cs));
-  scb_cs &= SCB_ST_INT;
+       obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
+                  (unsigned char *) &scb_cs, sizeof(scb_cs));
+       scb_cs &= SCB_ST_INT;
 
-  if(scb_cs == 0)
-    return;
+       if (scb_cs == 0)
+               return;
 
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
-             (unsigned char *) &scb_cs, sizeof(scb_cs));
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+                   (unsigned char *) &scb_cs, sizeof(scb_cs));
 
-  set_chan_attn(ioaddr, lp->hacr);
+       set_chan_attn(ioaddr, lp->hacr);
 
-  for(i = 1000; i > 0; i--)
-    {
-      obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs));
-      if(scb_cs == 0)
-       break;
+       for (i = 1000; i > 0; i--) {
+               obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
+                          (unsigned char *) &scb_cs, sizeof(scb_cs));
+               if (scb_cs == 0)
+                       break;
 
-      udelay(10);
-    }
-  udelay(100);
+               udelay(10);
+       }
+       udelay(100);
 
 #ifdef DEBUG_CONFIG_ERROR
-  if(i <= 0)
-    printk(KERN_INFO "%s: wv_ack(): board not accepting command.\n",
-          dev->name);
+       if (i <= 0)
+               printk(KERN_INFO
+                      "%s: wv_ack(): board not accepting command.\n",
+                      dev->name);
 #endif
 }
 
@@ -672,48 +612,45 @@ wv_ack(device *           dev)
  * Set channel attention bit and busy wait until command has
  * completed, then acknowledge completion of the command.
  */
-static inline int
-wv_synchronous_cmd(device *    dev,
-                  const char * str)
+static inline int wv_synchronous_cmd(device * dev, const char *str)
 {
-  net_local *  lp = (net_local *)dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  u_short      scb_cmd;
-  ach_t                cb;
-  int          i;
-
-  scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO;
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
-             (unsigned char *) &scb_cmd, sizeof(scb_cmd));
-
-  set_chan_attn(ioaddr, lp->hacr);
-
-  for (i = 1000; i > 0; i--)
-    {
-      obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
-      if (cb.ac_status & AC_SFLD_C)
-       break;
-
-      udelay(10);
-    }
-  udelay(100);
-
-  if(i <= 0 || !(cb.ac_status & AC_SFLD_OK))
-    {
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       u16 scb_cmd;
+       ach_t cb;
+       int i;
+
+       scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO;
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+                   (unsigned char *) &scb_cmd, sizeof(scb_cmd));
+
+       set_chan_attn(ioaddr, lp->hacr);
+
+       for (i = 1000; i > 0; i--) {
+               obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb,
+                          sizeof(cb));
+               if (cb.ac_status & AC_SFLD_C)
+                       break;
+
+               udelay(10);
+       }
+       udelay(100);
+
+       if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: %s failed; status = 0x%x\n",
-            dev->name, str, cb.ac_status);
+               printk(KERN_INFO "%s: %s failed; status = 0x%x\n",
+                      dev->name, str, cb.ac_status);
 #endif
 #ifdef DEBUG_I82586_SHOW
-      wv_scb_show(ioaddr);
+               wv_scb_show(ioaddr);
 #endif
-      return -1;
-    }
+               return -1;
+       }
 
-  /* Ack the status */
-  wv_ack(dev);
+       /* Ack the status */
+       wv_ack(dev);
 
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -722,60 +659,64 @@ wv_synchronous_cmd(device *       dev,
  * Check if done, and if OK.
  */
 static inline int
-wv_config_complete(device *    dev,
-                  u_long       ioaddr,
-                  net_local *  lp)
+wv_config_complete(device * dev, unsigned long ioaddr, net_local * lp)
 {
-  unsigned short       mcs_addr;
-  unsigned short       status;
-  int                  ret;
+       unsigned short mcs_addr;
+       unsigned short status;
+       int ret;
 
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name);
 #endif
 
-  mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t)
-    + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t);
+       mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t)
+           + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t);
 
-  /* Read the status of the last command (set mc list). */
-  obram_read(ioaddr, acoff(mcs_addr, ac_status), (unsigned char *)&status, sizeof(status));
+       /* Read the status of the last command (set mc list). */
+       obram_read(ioaddr, acoff(mcs_addr, ac_status),
+                  (unsigned char *) &status, sizeof(status));
 
-  /* If not completed -> exit */
-  if((status & AC_SFLD_C) == 0)
-    ret = 0;           /* Not ready to be scrapped */
-  else
-    {
+       /* If not completed -> exit */
+       if ((status & AC_SFLD_C) == 0)
+               ret = 0;        /* Not ready to be scrapped */
+       else {
 #ifdef DEBUG_CONFIG_ERROR
-      unsigned short   cfg_addr;
-      unsigned short   ias_addr;
-
-      /* Check mc_config command */
-      if((status & AC_SFLD_OK) != AC_SFLD_OK)
-       printk(KERN_INFO "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
-              dev->name, status);
-
-      /* check ia-config command */
-      ias_addr = mcs_addr - sizeof(ac_ias_t);
-      obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status));
-      if((status & AC_SFLD_OK) != AC_SFLD_OK)
-       printk(KERN_INFO "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n",
-              dev->name, status);
-
-      /* Check config command. */
-      cfg_addr = ias_addr - sizeof(ac_cfg_t);
-      obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status));
-      if((status & AC_SFLD_OK) != AC_SFLD_OK)
-       printk(KERN_INFO "%s: wv_config_complete(): configure failed; status = 0x%x\n",
-              dev->name, status);
-#endif /* DEBUG_CONFIG_ERROR */
-
-      ret = 1;         /* Ready to be scrapped */
-    }
+               unsigned short cfg_addr;
+               unsigned short ias_addr;
+
+               /* Check mc_config command */
+               if ((status & AC_SFLD_OK) != AC_SFLD_OK)
+                       printk(KERN_INFO
+                              "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
+                              dev->name, status);
+
+               /* check ia-config command */
+               ias_addr = mcs_addr - sizeof(ac_ias_t);
+               obram_read(ioaddr, acoff(ias_addr, ac_status),
+                          (unsigned char *) &status, sizeof(status));
+               if ((status & AC_SFLD_OK) != AC_SFLD_OK)
+                       printk(KERN_INFO
+                              "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n",
+                              dev->name, status);
+
+               /* Check config command. */
+               cfg_addr = ias_addr - sizeof(ac_cfg_t);
+               obram_read(ioaddr, acoff(cfg_addr, ac_status),
+                          (unsigned char *) &status, sizeof(status));
+               if ((status & AC_SFLD_OK) != AC_SFLD_OK)
+                       printk(KERN_INFO
+                              "%s: wv_config_complete(): configure failed; status = 0x%x\n",
+                              dev->name, status);
+#endif                         /* DEBUG_CONFIG_ERROR */
+
+               ret = 1;        /* Ready to be scrapped */
+       }
 
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name, ret);
+       printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name,
+              ret);
 #endif
-  return ret;
+       return ret;
 }
 
 /*------------------------------------------------------------------*/
@@ -783,141 +724,137 @@ wv_config_complete(device *     dev,
  * Command completion interrupt.
  * Reclaim as many freed tx buffers as we can.
  */
-static int
-wv_complete(device *   dev,
-           u_long      ioaddr,
-           net_local * lp)
+static int wv_complete(device * dev, unsigned long ioaddr, net_local * lp)
 {
-  int  nreaped = 0;
+       int nreaped = 0;
 
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name);
 #endif
 
-  /* Loop on all the transmit buffers */
-  while(lp->tx_first_in_use != I82586NULL)
-    {
-      unsigned short   tx_status;
+       /* Loop on all the transmit buffers */
+       while (lp->tx_first_in_use != I82586NULL) {
+               unsigned short tx_status;
 
-      /* Read the first transmit buffer */
-      obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status));
+               /* Read the first transmit buffer */
+               obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status),
+                          (unsigned char *) &tx_status,
+                          sizeof(tx_status));
 
-      /* If not completed -> exit */
-      if((tx_status & AC_SFLD_C) == 0)
-       break;
+               /* If not completed -> exit */
+               if ((tx_status & AC_SFLD_C) == 0)
+                       break;
 
-      /* Hack for reconfiguration */
-      if(tx_status == 0xFFFF)
-       if(!wv_config_complete(dev, ioaddr, lp))
-         break;        /* Not completed */
+               /* Hack for reconfiguration */
+               if (tx_status == 0xFFFF)
+                       if (!wv_config_complete(dev, ioaddr, lp))
+                               break;  /* Not completed */
 
-      /* We now remove this buffer */
-      nreaped++;
-      --lp->tx_n_in_use;
+               /* We now remove this buffer */
+               nreaped++;
+               --lp->tx_n_in_use;
 
 /*
 if (lp->tx_n_in_use > 0)
        printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]);
 */
 
-      /* Was it the last one? */
-      if(lp->tx_n_in_use <= 0)
-       lp->tx_first_in_use = I82586NULL;
-      else
-       {
-         /* Next one in the chain */
-         lp->tx_first_in_use += TXBLOCKZ;
-         if(lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
-           lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ;
-       }
-
-      /* Hack for reconfiguration */
-      if(tx_status == 0xFFFF)
-       continue;
-
-      /* Now, check status of the finished command */
-      if(tx_status & AC_SFLD_OK)
-       {
-         int   ncollisions;
-
-         lp->stats.tx_packets++;
-         ncollisions = tx_status & AC_SFLD_MAXCOL;
-         lp->stats.collisions += ncollisions;
+               /* Was it the last one? */
+               if (lp->tx_n_in_use <= 0)
+                       lp->tx_first_in_use = I82586NULL;
+               else {
+                       /* Next one in the chain */
+                       lp->tx_first_in_use += TXBLOCKZ;
+                       if (lp->tx_first_in_use >=
+                           OFFSET_CU +
+                           NTXBLOCKS * TXBLOCKZ) lp->tx_first_in_use -=
+                                   NTXBLOCKS * TXBLOCKZ;
+               }
+
+               /* Hack for reconfiguration */
+               if (tx_status == 0xFFFF)
+                       continue;
+
+               /* Now, check status of the finished command */
+               if (tx_status & AC_SFLD_OK) {
+                       int ncollisions;
+
+                       lp->stats.tx_packets++;
+                       ncollisions = tx_status & AC_SFLD_MAXCOL;
+                       lp->stats.collisions += ncollisions;
 #ifdef DEBUG_TX_INFO
-         if(ncollisions > 0)
-           printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n",
-                  dev->name, ncollisions);
+                       if (ncollisions > 0)
+                               printk(KERN_DEBUG
+                                      "%s: wv_complete(): tx completed after %d collisions.\n",
+                                      dev->name, ncollisions);
 #endif
-       }
-      else
-       {
-         lp->stats.tx_errors++;
-         if(tx_status & AC_SFLD_S10)
-           {
-             lp->stats.tx_carrier_errors++;
+               } else {
+                       lp->stats.tx_errors++;
+                       if (tx_status & AC_SFLD_S10) {
+                               lp->stats.tx_carrier_errors++;
 #ifdef DEBUG_TX_FAIL
-             printk(KERN_DEBUG "%s: wv_complete(): tx error: no CS.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_complete(): tx error: no CS.\n",
+                                      dev->name);
 #endif
-           }
-         if(tx_status & AC_SFLD_S9)
-           {
-             lp->stats.tx_carrier_errors++;
+                       }
+                       if (tx_status & AC_SFLD_S9) {
+                               lp->stats.tx_carrier_errors++;
 #ifdef DEBUG_TX_FAIL
-             printk(KERN_DEBUG "%s: wv_complete(): tx error: lost CTS.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_complete(): tx error: lost CTS.\n",
+                                      dev->name);
 #endif
-           }
-         if(tx_status & AC_SFLD_S8)
-           {
-             lp->stats.tx_fifo_errors++;
+                       }
+                       if (tx_status & AC_SFLD_S8) {
+                               lp->stats.tx_fifo_errors++;
 #ifdef DEBUG_TX_FAIL
-             printk(KERN_DEBUG "%s: wv_complete(): tx error: slow DMA.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_complete(): tx error: slow DMA.\n",
+                                      dev->name);
 #endif
-           }
-         if(tx_status & AC_SFLD_S6)
-           {
-             lp->stats.tx_heartbeat_errors++;
+                       }
+                       if (tx_status & AC_SFLD_S6) {
+                               lp->stats.tx_heartbeat_errors++;
 #ifdef DEBUG_TX_FAIL
-             printk(KERN_DEBUG "%s: wv_complete(): tx error: heart beat.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_complete(): tx error: heart beat.\n",
+                                      dev->name);
 #endif
-           }
-         if(tx_status & AC_SFLD_S5)
-           {
-             lp->stats.tx_aborted_errors++;
+                       }
+                       if (tx_status & AC_SFLD_S5) {
+                               lp->stats.tx_aborted_errors++;
 #ifdef DEBUG_TX_FAIL
-             printk(KERN_DEBUG "%s: wv_complete(): tx error: too many collisions.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_complete(): tx error: too many collisions.\n",
+                                      dev->name);
 #endif
-           }
-       }
+                       }
+               }
 
 #ifdef DEBUG_TX_INFO
-      printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n",
-            dev->name, tx_status);
+               printk(KERN_DEBUG
+                      "%s: wv_complete(): tx completed, tx_status 0x%04x\n",
+                      dev->name, tx_status);
 #endif
-    }
+       }
 
 #ifdef DEBUG_INTERRUPT_INFO
-  if(nreaped > 1)
-    printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n", dev->name, nreaped);
+       if (nreaped > 1)
+               printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n",
+                      dev->name, nreaped);
 #endif
 
-  /*
-   * Inform upper layers.
-   */
-  if(lp->tx_n_in_use < NTXBLOCKS - 1)
-    {
-      dev->tbusy = 0;
-      mark_bh(NET_BH);
-    }
-
+       /*
+        * Inform upper layers.
+        */
+       if (lp->tx_n_in_use < NTXBLOCKS - 1) {
+               netif_wake_queue(dev);
+       }
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name);
 #endif
-  return nreaped;
+       return nreaped;
 }
 
 /*------------------------------------------------------------------*/
@@ -929,22 +866,21 @@ if (lp->tx_n_in_use > 0)
  * wavelan_interrupt is not an option), so you may experience
  * delays sometimes.
  */
-static inline void
-wv_82586_reconfig(device *     dev)
+static inline void wv_82586_reconfig(device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
+       net_local *lp = (net_local *) dev->priv;
 
-  /* Check if we can do it now ! */
-  if(!(dev->start) || (test_and_set_bit(0, (void *)&dev->tbusy) != 0))
-    {
-      lp->reconfig_82586 = 1;
+       /* Check if we can do it now ! */
+       if (!test_bit(LINK_STATE_START, &dev->state) &&
+           test_bit(LINK_STATE_XOFF, &dev->state)) {
+               lp->reconfig_82586 = 1;
 #ifdef DEBUG_CONFIG_INFO
-      printk(KERN_DEBUG "%s: wv_82586_reconfig(): delayed (busy = %ld, start = %d)\n",
-            dev->name, dev->tbusy, dev->start);
+               printk(KERN_DEBUG
+                      "%s: wv_82586_reconfig(): delayed (state = %lX)\n",
+                              dev->name, dev->state);
 #endif
-    }
-  else
-    wv_82586_config(dev);
+       } else
+               wv_82586_config(dev);
 }
 
 /********************* DEBUG & INFO SUBROUTINES *********************/
@@ -958,89 +894,73 @@ wv_82586_reconfig(device *        dev)
 /*
  * Print the formatted contents of the Parameter Storage Area.
  */
-static void
-wv_psa_show(psa_t *    p)
+static void wv_psa_show(psa_t * p)
 {
-  printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n");
-  printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
-        p->psa_io_base_addr_1,
-        p->psa_io_base_addr_2,
-        p->psa_io_base_addr_3,
-        p->psa_io_base_addr_4);
-  printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n",
-        p->psa_rem_boot_addr_1,
-        p->psa_rem_boot_addr_2,
-        p->psa_rem_boot_addr_3);
-  printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
-  printk("psa_int_req_no: %d\n", p->psa_int_req_no);
+       printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n");
+       printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
+              p->psa_io_base_addr_1,
+              p->psa_io_base_addr_2,
+              p->psa_io_base_addr_3, p->psa_io_base_addr_4);
+       printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n",
+              p->psa_rem_boot_addr_1,
+              p->psa_rem_boot_addr_2, p->psa_rem_boot_addr_3);
+       printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
+       printk("psa_int_req_no: %d\n", p->psa_int_req_no);
 #ifdef DEBUG_SHOW_UNUSED
-  printk(KERN_DEBUG "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-        p->psa_unused0[0],
-        p->psa_unused0[1],
-        p->psa_unused0[2],
-        p->psa_unused0[3],
-        p->psa_unused0[4],
-        p->psa_unused0[5],
-        p->psa_unused0[6]);
-#endif /* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
-        p->psa_univ_mac_addr[0],
-        p->psa_univ_mac_addr[1],
-        p->psa_univ_mac_addr[2],
-        p->psa_univ_mac_addr[3],
-        p->psa_univ_mac_addr[4],
-        p->psa_univ_mac_addr[5]);
-  printk(KERN_DEBUG "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
-        p->psa_local_mac_addr[0],
-        p->psa_local_mac_addr[1],
-        p->psa_local_mac_addr[2],
-        p->psa_local_mac_addr[3],
-        p->psa_local_mac_addr[4],
-        p->psa_local_mac_addr[5]);
-  printk(KERN_DEBUG "psa_univ_local_sel: %d, ", p->psa_univ_local_sel);
-  printk("psa_comp_number: %d, ", p->psa_comp_number);
-  printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set);
-  printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ",
-        p->psa_feature_select);
-  printk("psa_subband/decay_update_prm: %d\n", p->psa_subband);
-  printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr);
-  printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay);
-  printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0], p->psa_nwid[1]);
-  printk("psa_nwid_select: %d\n", p->psa_nwid_select);
-  printk(KERN_DEBUG "psa_encryption_select: %d, ", p->psa_encryption_select);
-  printk("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
-        p->psa_encryption_key[0],
-        p->psa_encryption_key[1],
-        p->psa_encryption_key[2],
-        p->psa_encryption_key[3],
-        p->psa_encryption_key[4],
-        p->psa_encryption_key[5],
-        p->psa_encryption_key[6],
-        p->psa_encryption_key[7]);
-  printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width);
-  printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ",
-        p->psa_call_code[0]);
-  printk("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-        p->psa_call_code[0],
-        p->psa_call_code[1],
-        p->psa_call_code[2],
-        p->psa_call_code[3],
-        p->psa_call_code[4],
-        p->psa_call_code[5],
-        p->psa_call_code[6],
-        p->psa_call_code[7]);
+       printk(KERN_DEBUG
+              "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+              p->psa_unused0[0], p->psa_unused0[1], p->psa_unused0[2],
+              p->psa_unused0[3], p->psa_unused0[4], p->psa_unused0[5],
+              p->psa_unused0[6]);
+#endif                         /* DEBUG_SHOW_UNUSED */
+       printk(KERN_DEBUG
+              "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
+              p->psa_univ_mac_addr[0], p->psa_univ_mac_addr[1],
+              p->psa_univ_mac_addr[2], p->psa_univ_mac_addr[3],
+              p->psa_univ_mac_addr[4], p->psa_univ_mac_addr[5]);
+       printk(KERN_DEBUG
+              "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
+              p->psa_local_mac_addr[0], p->psa_local_mac_addr[1],
+              p->psa_local_mac_addr[2], p->psa_local_mac_addr[3],
+              p->psa_local_mac_addr[4], p->psa_local_mac_addr[5]);
+       printk(KERN_DEBUG "psa_univ_local_sel: %d, ",
+              p->psa_univ_local_sel);
+       printk("psa_comp_number: %d, ", p->psa_comp_number);
+       printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set);
+       printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ",
+              p->psa_feature_select);
+       printk("psa_subband/decay_update_prm: %d\n", p->psa_subband);
+       printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr);
+       printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay);
+       printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0],
+              p->psa_nwid[1]);
+       printk("psa_nwid_select: %d\n", p->psa_nwid_select);
+       printk(KERN_DEBUG "psa_encryption_select: %d, ",
+              p->psa_encryption_select);
+       printk
+           ("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+            p->psa_encryption_key[0], p->psa_encryption_key[1],
+            p->psa_encryption_key[2], p->psa_encryption_key[3],
+            p->psa_encryption_key[4], p->psa_encryption_key[5],
+            p->psa_encryption_key[6], p->psa_encryption_key[7]);
+       printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width);
+       printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ",
+              p->psa_call_code[0]);
+       printk
+           ("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+            p->psa_call_code[0], p->psa_call_code[1], p->psa_call_code[2],
+            p->psa_call_code[3], p->psa_call_code[4], p->psa_call_code[5],
+            p->psa_call_code[6], p->psa_call_code[7]);
 #ifdef DEBUG_SHOW_UNUSED
-  printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n",
-        p->psa_reserved[0],
-        p->psa_reserved[1],
-        p->psa_reserved[2],
-        p->psa_reserved[3]);
-#endif /* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status);
-  printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]);
-  printk("psa_crc_status: 0x%02x\n", p->psa_crc_status);
-} /* wv_psa_show */
-#endif /* DEBUG_PSA_SHOW */
+       printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n",
+              p->psa_reserved[0],
+              p->psa_reserved[1], p->psa_reserved[2], p->psa_reserved[3]);
+#endif                         /* DEBUG_SHOW_UNUSED */
+       printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status);
+       printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]);
+       printk("psa_crc_status: 0x%02x\n", p->psa_crc_status);
+}                              /* wv_psa_show */
+#endif                         /* DEBUG_PSA_SHOW */
 
 #ifdef DEBUG_MMC_SHOW
 /*------------------------------------------------------------------*/
@@ -1048,411 +968,432 @@ wv_psa_show(psa_t *    p)
  * Print the formatted status of the Modem Management Controller.
  * This function needs to be completed.
  */
-static void
-wv_mmc_show(device *   dev)
+static void wv_mmc_show(device * dev)
 {
-  u_long       ioaddr = dev->base_addr;
-  net_local *  lp = (net_local *)dev->priv;
-  mmr_t                m;
-
-  /* Basic check */
-  if(hasr_read(ioaddr) & HASR_NO_CLK)
-    {
-      printk(KERN_WARNING "%s: wv_mmc_show: modem not connected\n",
-            dev->name);
-      return;
-    }
-
-  /* Read the mmc */
-  mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
-  mmc_read(ioaddr, 0, (u_char *)&m, sizeof(m));
-  mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
-
-#ifdef WIRELESS_EXT    /* if wireless extension exists in the kernel */
-  /* Don't forget to update statistics */
-  lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif /* WIRELESS_EXT */
-
-  printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
+       unsigned long ioaddr = dev->base_addr;
+       net_local *lp = (net_local *) dev->priv;
+       mmr_t m;
+
+       /* Basic check */
+       if (hasr_read(ioaddr) & HASR_NO_CLK) {
+               printk(KERN_WARNING
+                      "%s: wv_mmc_show: modem not connected\n",
+                      dev->name);
+               return;
+       }
+
+       /* Read the mmc */
+       mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
+       mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m));
+       mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
+
+#ifdef WIRELESS_EXT            /* if wireless extension exists in the kernel */
+       /* Don't forget to update statistics */
+       lp->wstats.discard.nwid +=
+           (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
+#endif                         /* WIRELESS_EXT */
+
+       printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
 #ifdef DEBUG_SHOW_UNUSED
-  printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-        m.mmr_unused0[0],
-        m.mmr_unused0[1],
-        m.mmr_unused0[2],
-        m.mmr_unused0[3],
-        m.mmr_unused0[4],
-        m.mmr_unused0[5],
-        m.mmr_unused0[6],
-        m.mmr_unused0[7]);
-#endif /* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n",
-        m.mmr_des_avail, m.mmr_des_status);
+       printk(KERN_DEBUG
+              "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+              m.mmr_unused0[0], m.mmr_unused0[1], m.mmr_unused0[2],
+              m.mmr_unused0[3], m.mmr_unused0[4], m.mmr_unused0[5],
+              m.mmr_unused0[6], m.mmr_unused0[7]);
+#endif                         /* DEBUG_SHOW_UNUSED */
+       printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n",
+              m.mmr_des_avail, m.mmr_des_status);
 #ifdef DEBUG_SHOW_UNUSED
-  printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n",
-        m.mmr_unused1[0],
-        m.mmr_unused1[1],
-        m.mmr_unused1[2],
-        m.mmr_unused1[3],
-        m.mmr_unused1[4]);
-#endif /* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n",
-        m.mmr_dce_status,
-        (m.mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ? "energy detected,":"",
-        (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ?
-        "loop test indicated," : "",
-        (m.mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ? "transmitter on," : "",
-        (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ?
-        "jabber timer expired," : "");
-  printk(KERN_DEBUG "Dsp ID: %02X\n",
-        m.mmr_dsp_id);
+       printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n",
+              m.mmr_unused1[0],
+              m.mmr_unused1[1],
+              m.mmr_unused1[2], m.mmr_unused1[3], m.mmr_unused1[4]);
+#endif                         /* DEBUG_SHOW_UNUSED */
+       printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n",
+              m.mmr_dce_status,
+              (m.
+               mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ?
+              "energy detected," : "",
+              (m.
+               mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ?
+              "loop test indicated," : "",
+              (m.
+               mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ?
+              "transmitter on," : "",
+              (m.
+               mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ?
+              "jabber timer expired," : "");
+       printk(KERN_DEBUG "Dsp ID: %02X\n", m.mmr_dsp_id);
 #ifdef DEBUG_SHOW_UNUSED
-  printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n",
-        m.mmr_unused2[0],
-        m.mmr_unused2[1]);
-#endif /* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n",
-        (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l,
-        (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l);
-  printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n",
-        m.mmr_thr_pre_set & MMR_THR_PRE_SET,
-        (m.mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" : "below");
-  printk(KERN_DEBUG "signal_lvl: %d [%s], ",
-        m.mmr_signal_lvl & MMR_SIGNAL_LVL,
-        (m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" : "no new msg");
-  printk("silence_lvl: %d [%s], ", m.mmr_silence_lvl & MMR_SILENCE_LVL,
-        (m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" : "no new update");
-  printk("sgnl_qual: 0x%x [%s]\n",
-        m.mmr_sgnl_qual & MMR_SGNL_QUAL,
-        (m.mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" : "Antenna 0");
+       printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n",
+              m.mmr_unused2[0], m.mmr_unused2[1]);
+#endif                         /* DEBUG_SHOW_UNUSED */
+       printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n",
+              (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l,
+              (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l);
+       printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n",
+              m.mmr_thr_pre_set & MMR_THR_PRE_SET,
+              (m.
+               mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" :
+              "below");
+       printk(KERN_DEBUG "signal_lvl: %d [%s], ",
+              m.mmr_signal_lvl & MMR_SIGNAL_LVL,
+              (m.
+               mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" :
+              "no new msg");
+       printk("silence_lvl: %d [%s], ",
+              m.mmr_silence_lvl & MMR_SILENCE_LVL,
+              (m.
+               mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" :
+              "no new update");
+       printk("sgnl_qual: 0x%x [%s]\n", m.mmr_sgnl_qual & MMR_SGNL_QUAL,
+              (m.
+               mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" :
+              "Antenna 0");
 #ifdef DEBUG_SHOW_UNUSED
-  printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l);
-#endif /* DEBUG_SHOW_UNUSED */
-} /* wv_mmc_show */
-#endif /* DEBUG_MMC_SHOW */
+       printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l);
+#endif                         /* DEBUG_SHOW_UNUSED */
+}                              /* wv_mmc_show */
+#endif                         /* DEBUG_MMC_SHOW */
 
 #ifdef DEBUG_I82586_SHOW
 /*------------------------------------------------------------------*/
 /*
  * Print the last block of the i82586 memory.
  */
-static void
-wv_scb_show(u_long     ioaddr)
+static void wv_scb_show(unsigned long ioaddr)
 {
-  scb_t                scb;
-
-  obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb));   
-
-  printk(KERN_DEBUG "##### WaveLAN system control block: #####\n");
-
-  printk(KERN_DEBUG "status: ");
-  printk("stat 0x%x[%s%s%s%s] ",
-        (scb.scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | SCB_ST_RNR)) >> 12,
-        (scb.scb_status & SCB_ST_CX) ? "command completion interrupt," : "",
-        (scb.scb_status & SCB_ST_FR) ? "frame received," : "",
-        (scb.scb_status & SCB_ST_CNA) ? "command unit not active," : "",
-        (scb.scb_status & SCB_ST_RNR) ? "receiving unit not ready," : "");
-  printk("cus 0x%x[%s%s%s] ",
-        (scb.scb_status & SCB_ST_CUS) >> 8,
-        ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_IDLE) ? "idle" : "",
-        ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_SUSP) ? "suspended" : "",
-        ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_ACTV) ? "active" : "");
-  printk("rus 0x%x[%s%s%s%s]\n",
-        (scb.scb_status & SCB_ST_RUS) >> 4,
-        ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_IDLE) ? "idle" : "",
-        ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_SUSP) ? "suspended" : "",
-        ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_NRES) ? "no resources" : "",
-        ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_RDY) ? "ready" : "");
-
-  printk(KERN_DEBUG "command: ");
-  printk("ack 0x%x[%s%s%s%s] ",
-        (scb.scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12,
-        (scb.scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "",
-        (scb.scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "",
-        (scb.scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "",
-        (scb.scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "");
-  printk("cuc 0x%x[%s%s%s%s%s] ",
-        (scb.scb_command & SCB_CMD_CUC) >> 8,
-        ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_NOP) ? "nop" : "",
-        ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_GO) ? "start cbl_offset" : "",
-        ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_RES) ? "resume execution" : "",
-        ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_SUS) ? "suspend execution" : "",
-        ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_ABT) ? "abort execution" : "");
-  printk("ruc 0x%x[%s%s%s%s%s]\n",
-        (scb.scb_command & SCB_CMD_RUC) >> 4,
-        ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_NOP) ? "nop" : "",
-        ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_GO) ? "start rfa_offset" : "",
-        ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_RES) ? "resume reception" : "",
-        ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_SUS) ? "suspend reception" : "",
-        ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_ABT) ? "abort reception" : "");
-
-  printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset);
-  printk("rfa_offset 0x%x\n", scb.scb_rfa_offset);
-
-  printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs);
-  printk("alnerrs %d ", scb.scb_alnerrs);
-  printk("rscerrs %d ", scb.scb_rscerrs);
-  printk("ovrnerrs %d\n", scb.scb_ovrnerrs);
+       scb_t scb;
+
+       obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb,
+                  sizeof(scb));
+
+       printk(KERN_DEBUG "##### WaveLAN system control block: #####\n");
+
+       printk(KERN_DEBUG "status: ");
+       printk("stat 0x%x[%s%s%s%s] ",
+              (scb.
+               scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA |
+                             SCB_ST_RNR)) >> 12,
+              (scb.
+               scb_status & SCB_ST_CX) ? "command completion interrupt," :
+              "", (scb.scb_status & SCB_ST_FR) ? "frame received," : "",
+              (scb.
+               scb_status & SCB_ST_CNA) ? "command unit not active," : "",
+              (scb.
+               scb_status & SCB_ST_RNR) ? "receiving unit not ready," :
+              "");
+       printk("cus 0x%x[%s%s%s] ", (scb.scb_status & SCB_ST_CUS) >> 8,
+              ((scb.scb_status & SCB_ST_CUS) ==
+               SCB_ST_CUS_IDLE) ? "idle" : "",
+              ((scb.scb_status & SCB_ST_CUS) ==
+               SCB_ST_CUS_SUSP) ? "suspended" : "",
+              ((scb.scb_status & SCB_ST_CUS) ==
+               SCB_ST_CUS_ACTV) ? "active" : "");
+       printk("rus 0x%x[%s%s%s%s]\n", (scb.scb_status & SCB_ST_RUS) >> 4,
+              ((scb.scb_status & SCB_ST_RUS) ==
+               SCB_ST_RUS_IDLE) ? "idle" : "",
+              ((scb.scb_status & SCB_ST_RUS) ==
+               SCB_ST_RUS_SUSP) ? "suspended" : "",
+              ((scb.scb_status & SCB_ST_RUS) ==
+               SCB_ST_RUS_NRES) ? "no resources" : "",
+              ((scb.scb_status & SCB_ST_RUS) ==
+               SCB_ST_RUS_RDY) ? "ready" : "");
+
+       printk(KERN_DEBUG "command: ");
+       printk("ack 0x%x[%s%s%s%s] ",
+              (scb.
+               scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR |
+                              SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12,
+              (scb.
+               scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "",
+              (scb.
+               scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "",
+              (scb.
+               scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "",
+              (scb.
+               scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "");
+       printk("cuc 0x%x[%s%s%s%s%s] ",
+              (scb.scb_command & SCB_CMD_CUC) >> 8,
+              ((scb.scb_command & SCB_CMD_CUC) ==
+               SCB_CMD_CUC_NOP) ? "nop" : "",
+              ((scb.scb_command & SCB_CMD_CUC) ==
+               SCB_CMD_CUC_GO) ? "start cbl_offset" : "",
+              ((scb.scb_command & SCB_CMD_CUC) ==
+               SCB_CMD_CUC_RES) ? "resume execution" : "",
+              ((scb.scb_command & SCB_CMD_CUC) ==
+               SCB_CMD_CUC_SUS) ? "suspend execution" : "",
+              ((scb.scb_command & SCB_CMD_CUC) ==
+               SCB_CMD_CUC_ABT) ? "abort execution" : "");
+       printk("ruc 0x%x[%s%s%s%s%s]\n",
+              (scb.scb_command & SCB_CMD_RUC) >> 4,
+              ((scb.scb_command & SCB_CMD_RUC) ==
+               SCB_CMD_RUC_NOP) ? "nop" : "",
+              ((scb.scb_command & SCB_CMD_RUC) ==
+               SCB_CMD_RUC_GO) ? "start rfa_offset" : "",
+              ((scb.scb_command & SCB_CMD_RUC) ==
+               SCB_CMD_RUC_RES) ? "resume reception" : "",
+              ((scb.scb_command & SCB_CMD_RUC) ==
+               SCB_CMD_RUC_SUS) ? "suspend reception" : "",
+              ((scb.scb_command & SCB_CMD_RUC) ==
+               SCB_CMD_RUC_ABT) ? "abort reception" : "");
+
+       printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset);
+       printk("rfa_offset 0x%x\n", scb.scb_rfa_offset);
+
+       printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs);
+       printk("alnerrs %d ", scb.scb_alnerrs);
+       printk("rscerrs %d ", scb.scb_rscerrs);
+       printk("ovrnerrs %d\n", scb.scb_ovrnerrs);
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Print the formatted status of the i82586's receive unit.
  */
-static void
-wv_ru_show(device *    dev)
+static void wv_ru_show(device * dev)
 {
-  /* net_local *lp = (net_local *) dev->priv; */
+       /* net_local *lp = (net_local *) dev->priv; */
 
-  printk(KERN_DEBUG "##### WaveLAN i82586 receiver unit status: #####\n");
-  printk(KERN_DEBUG "ru:");
-  /*
-   * Not implemented yet
-   */
-  printk("\n");
-} /* wv_ru_show */
+       printk(KERN_DEBUG
+              "##### WaveLAN i82586 receiver unit status: #####\n");
+       printk(KERN_DEBUG "ru:");
+       /*
+        * Not implemented yet
+        */
+       printk("\n");
+}                              /* wv_ru_show */
 
 /*------------------------------------------------------------------*/
 /*
  * Display info about one control block of the i82586 memory.
  */
-static void
-wv_cu_show_one(device *                dev,
-              net_local *      lp,
-              int              i,
-              u_short          p)
+static void wv_cu_show_one(device * dev, net_local * lp, int i, u16 p)
 {
-  u_long               ioaddr;
-  ac_tx_t              actx;
+       unsigned long ioaddr;
+       ac_tx_t actx;
 
-  ioaddr = dev->base_addr;
+       ioaddr = dev->base_addr;
 
-  printk("%d: 0x%x:", i, p);
+       printk("%d: 0x%x:", i, p);
 
-  obram_read(ioaddr, p, (unsigned char *)&actx, sizeof(actx));
-  printk(" status=0x%x,", actx.tx_h.ac_status);
-  printk(" command=0x%x,", actx.tx_h.ac_command);
+       obram_read(ioaddr, p, (unsigned char *) &actx, sizeof(actx));
+       printk(" status=0x%x,", actx.tx_h.ac_status);
+       printk(" command=0x%x,", actx.tx_h.ac_command);
 
-  /*
-  {
-    tbd_t      tbd;
+       /*
+          {
+          tbd_t      tbd;
 
-    obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd));
-    printk(" tbd_status=0x%x,", tbd.tbd_status);
-  }
-  */
+          obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd));
+          printk(" tbd_status=0x%x,", tbd.tbd_status);
+          }
+        */
 
-  printk("|");
+       printk("|");
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Print status of the command unit of the i82586.
  */
-static void
-wv_cu_show(device *    dev)
+static void wv_cu_show(device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
-  unsigned int i;
-  u_short      p;
-
-  printk(KERN_DEBUG "##### WaveLAN i82586 command unit status: #####\n");
-
-  printk(KERN_DEBUG);
-  for(i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++)
-    {
-      wv_cu_show_one(dev, lp, i, p);
-
-      p += TXBLOCKZ;
-      if(p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
-       p -= NTXBLOCKS * TXBLOCKZ;
-    }
-  printk("\n");
+       net_local *lp = (net_local *) dev->priv;
+       unsigned int i;
+       u16 p;
+
+       printk(KERN_DEBUG
+              "##### WaveLAN i82586 command unit status: #####\n");
+
+       printk(KERN_DEBUG);
+       for (i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) {
+               wv_cu_show_one(dev, lp, i, p);
+
+               p += TXBLOCKZ;
+               if (p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
+                       p -= NTXBLOCKS * TXBLOCKZ;
+       }
+       printk("\n");
 }
-#endif /* DEBUG_I82586_SHOW */
+#endif                         /* DEBUG_I82586_SHOW */
 
 #ifdef DEBUG_DEVICE_SHOW
 /*------------------------------------------------------------------*/
 /*
  * Print the formatted status of the WaveLAN PCMCIA device driver.
  */
-static void
-wv_dev_show(device *   dev)
+static void wv_dev_show(device * dev)
 {
-  printk(KERN_DEBUG "dev:");
-  printk(" start=%d,", dev->start);
-  printk(" tbusy=%ld,", dev->tbusy);
-  printk(" interrupt=%d,", dev->interrupt);
-  printk(" trans_start=%ld,", dev->trans_start);
-  printk(" flags=0x%x,", dev->flags);
-  printk("\n");
-} /* wv_dev_show */
+       printk(KERN_DEBUG "dev:");
+       printk(" state=%lX,", dev->state);
+       printk(" trans_start=%ld,", dev->trans_start);
+       printk(" flags=0x%x,", dev->flags);
+       printk("\n");
+}                              /* wv_dev_show */
 
 /*------------------------------------------------------------------*/
 /*
  * Print the formatted status of the WaveLAN PCMCIA device driver's
  * private information.
  */
-static void
-wv_local_show(device * dev)
+static void wv_local_show(device * dev)
 {
-  net_local *lp;
+       net_local *lp;
 
-  lp = (net_local *)dev->priv;
+       lp = (net_local *) dev->priv;
 
-  printk(KERN_DEBUG "local:");
-  printk(" tx_n_in_use=%d,", lp->tx_n_in_use);
-  printk(" hacr=0x%x,", lp->hacr);
-  printk(" rx_head=0x%x,", lp->rx_head);
-  printk(" rx_last=0x%x,", lp->rx_last);
-  printk(" tx_first_free=0x%x,", lp->tx_first_free);
-  printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use);
-  printk("\n");
-} /* wv_local_show */
-#endif /* DEBUG_DEVICE_SHOW */
+       printk(KERN_DEBUG "local:");
+       printk(" tx_n_in_use=%d,", lp->tx_n_in_use);
+       printk(" hacr=0x%x,", lp->hacr);
+       printk(" rx_head=0x%x,", lp->rx_head);
+       printk(" rx_last=0x%x,", lp->rx_last);
+       printk(" tx_first_free=0x%x,", lp->tx_first_free);
+       printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use);
+       printk("\n");
+}                              /* wv_local_show */
+#endif                         /* DEBUG_DEVICE_SHOW */
 
 #if defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO)
 /*------------------------------------------------------------------*/
 /*
  * Dump packet header (and content if necessary) on the screen
  */
-static inline void
-wv_packet_info(u_char *                p,              /* Packet to dump */
-              int              length,         /* Length of the packet */
-              char *           msg1,           /* Name of the device */
-              char *           msg2)           /* Name of the function */
-{
-  int          i;
-  int          maxi;
-
-  printk(KERN_DEBUG "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n",
-        msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length);
-  printk(KERN_DEBUG "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n",
-        msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13]);
+static inline void wv_packet_info(u8 * p,      /* Packet to dump */
+                                 int length,   /* Length of the packet */
+                                 char *msg1,   /* Name of the device */
+                                 char *msg2)
+{                              /* Name of the function */
+       int i;
+       int maxi;
+
+       printk(KERN_DEBUG
+              "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n",
+              msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length);
+       printk(KERN_DEBUG
+              "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n",
+              msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12],
+              p[13]);
 
 #ifdef DEBUG_PACKET_DUMP
 
-  printk(KERN_DEBUG "data=\"");
-
-  if((maxi = length) > DEBUG_PACKET_DUMP)
-    maxi = DEBUG_PACKET_DUMP;
-  for(i = 14; i < maxi; i++)
-    if(p[i] >= ' ' && p[i] <= '~')
-      printk(" %c", p[i]);
-    else
-      printk("%02X", p[i]);
-  if(maxi < length)
-    printk("..");
-  printk("\"\n");
-  printk(KERN_DEBUG "\n");
-#endif /* DEBUG_PACKET_DUMP */
+       printk(KERN_DEBUG "data=\"");
+
+       if ((maxi = length) > DEBUG_PACKET_DUMP)
+               maxi = DEBUG_PACKET_DUMP;
+       for (i = 14; i < maxi; i++)
+               if (p[i] >= ' ' && p[i] <= '~')
+                       printk(" %c", p[i]);
+               else
+                       printk("%02X", p[i]);
+       if (maxi < length)
+               printk("..");
+       printk("\"\n");
+       printk(KERN_DEBUG "\n");
+#endif                         /* DEBUG_PACKET_DUMP */
 }
-#endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */
+#endif                         /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */
 
 /*------------------------------------------------------------------*/
 /*
  * This is the information which is displayed by the driver at startup.
  * There are lots of flags for configuring it to your liking.
  */
-static inline void
-wv_init_info(device *  dev)
+static inline void wv_init_info(device * dev)
 {
-  short                ioaddr = dev->base_addr;
-  net_local *  lp = (net_local *)dev->priv;
-  psa_t                psa;
-  int          i;
+       short ioaddr = dev->base_addr;
+       net_local *lp = (net_local *) dev->priv;
+       psa_t psa;
+       int i;
 
-  /* Read the parameter storage area */
-  psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
+       /* Read the parameter storage area */
+       psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
 
 #ifdef DEBUG_PSA_SHOW
-  wv_psa_show(&psa);
+       wv_psa_show(&psa);
 #endif
 #ifdef DEBUG_MMC_SHOW
-  wv_mmc_show(dev);
+       wv_mmc_show(dev);
 #endif
 #ifdef DEBUG_I82586_SHOW
-  wv_cu_show(dev);
+       wv_cu_show(dev);
 #endif
 
 #ifdef DEBUG_BASIC_SHOW
-  /* Now, let's go for the basic stuff. */
-  printk(KERN_NOTICE "%s: WaveLAN at %#x,", dev->name, ioaddr);
-  for(i = 0; i < WAVELAN_ADDR_SIZE; i++)
-    printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]);
-  printk(", IRQ %d", dev->irq);
-
-  /* Print current network ID. */
-  if(psa.psa_nwid_select)
-    printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], psa.psa_nwid[1]);
-  else
-    printk(", nwid off");
-
-  /* If 2.00 card */
-  if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-       (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-    {
-      unsigned short   freq;
-
-      /* Ask the EEPROM to read the frequency from the first area. */
-      fee_read(ioaddr, 0x00, &freq, 1);
-
-      /* Print frequency */
-      printk(", 2.00, %ld", (freq >> 6) + 2400L);
-
-      /* Hack! */
-      if(freq & 0x20)
-       printk(".5");
-    }
-  else
-    {
-      printk(", PC");
-      switch(psa.psa_comp_number)
-       {
-       case PSA_COMP_PC_AT_915:
-       case PSA_COMP_PC_AT_2400:
-         printk("-AT");
-         break;
-       case PSA_COMP_PC_MC_915:
-       case PSA_COMP_PC_MC_2400:
-         printk("-MC");
-         break;
-       case PSA_COMP_PCMCIA_915:
-         printk("MCIA");
-         break;
-       default:
-         printk("?");
+       /* Now, let's go for the basic stuff. */
+       printk(KERN_NOTICE "%s: WaveLAN at %#x,", dev->name, ioaddr);
+       for (i = 0; i < WAVELAN_ADDR_SIZE; i++)
+               printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]);
+       printk(", IRQ %d", dev->irq);
+
+       /* Print current network ID. */
+       if (psa.psa_nwid_select)
+               printk(", nwid 0x%02X-%02X", psa.psa_nwid[0],
+                      psa.psa_nwid[1]);
+       else
+               printk(", nwid off");
+
+       /* If 2.00 card */
+       if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+             (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+               unsigned short freq;
+
+               /* Ask the EEPROM to read the frequency from the first area. */
+               fee_read(ioaddr, 0x00, &freq, 1);
+
+               /* Print frequency */
+               printk(", 2.00, %ld", (freq >> 6) + 2400L);
+
+               /* Hack! */
+               if (freq & 0x20)
+                       printk(".5");
+       } else {
+               printk(", PC");
+               switch (psa.psa_comp_number) {
+               case PSA_COMP_PC_AT_915:
+               case PSA_COMP_PC_AT_2400:
+                       printk("-AT");
+                       break;
+               case PSA_COMP_PC_MC_915:
+               case PSA_COMP_PC_MC_2400:
+                       printk("-MC");
+                       break;
+               case PSA_COMP_PCMCIA_915:
+                       printk("MCIA");
+                       break;
+               default:
+                       printk("?");
+               }
+               printk(", ");
+               switch (psa.psa_subband) {
+               case PSA_SUBBAND_915:
+                       printk("915");
+                       break;
+               case PSA_SUBBAND_2425:
+                       printk("2425");
+                       break;
+               case PSA_SUBBAND_2460:
+                       printk("2460");
+                       break;
+               case PSA_SUBBAND_2484:
+                       printk("2484");
+                       break;
+               case PSA_SUBBAND_2430_5:
+                       printk("2430.5");
+                       break;
+               default:
+                       printk("?");
+               }
        }
-      printk(", ");
-      switch (psa.psa_subband)
-       {
-       case PSA_SUBBAND_915:
-         printk("915");
-         break;
-       case PSA_SUBBAND_2425:
-         printk("2425");
-         break;
-       case PSA_SUBBAND_2460:
-         printk("2460");
-         break;
-       case PSA_SUBBAND_2484:
-         printk("2484");
-         break;
-       case PSA_SUBBAND_2430_5:
-         printk("2430.5");
-         break;
-       default:
-         printk("?");
-       }
-    }
 
-  printk(" MHz\n");
-#endif /* DEBUG_BASIC_SHOW */
+       printk(" MHz\n");
+#endif                         /* DEBUG_BASIC_SHOW */
 
 #ifdef DEBUG_VERSION_SHOW
-  /* Print version information */
-  printk(KERN_NOTICE "%s", version);
+       /* Print version information */
+       printk(KERN_NOTICE "%s", version);
 #endif
-} /* wv_init_info */
+}                              /* wv_init_info */
 
 /********************* IOCTL, STATS & RECONFIG *********************/
 /*
@@ -1468,14 +1409,13 @@ wv_init_info(device *   dev)
  * card open or closed.
  * Used when the user read /proc/net/dev
  */
-static en_stats        *
-wavelan_get_stats(device *     dev)
+static en_stats *wavelan_get_stats(device * dev)
 {
 #ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);
+       printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);
 #endif
 
-  return(&((net_local *) dev->priv)->stats);
+       return (&((net_local *) dev->priv)->stats);
 }
 
 /*------------------------------------------------------------------*/
@@ -1486,76 +1426,70 @@ wavelan_get_stats(device *      dev)
  * num_addrs > 0       Multicast mode, receive normal and MC packets,
  *                     and do best-effort filtering.
  */
-static void
-wavelan_set_multicast_list(device *    dev)
+static void wavelan_set_multicast_list(device * dev)
 {
-  net_local *  lp = (net_local *) dev->priv;
+       net_local *lp = (net_local *) dev->priv;
 
 #ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n",
+              dev->name);
 #endif
 
 #ifdef DEBUG_IOCTL_INFO
-  printk(KERN_DEBUG "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n",
-        dev->name, dev->flags, dev->mc_count);
+       printk(KERN_DEBUG
+              "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n",
+              dev->name, dev->flags, dev->mc_count);
 #endif
 
-  /* Are we asking for promiscuous mode,
-   * or all multicast addresses (we don't have that!)
-   * or too many multicast addresses for the hardware filter? */
-  if((dev->flags & IFF_PROMISC) ||
-     (dev->flags & IFF_ALLMULTI) ||
-     (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES))
-    {
-      /*
-       * Enable promiscuous mode: receive all packets.
-       */
-      if(!lp->promiscuous)
-       {
-         lp->promiscuous = 1;
-         lp->mc_count = 0;
-
-         wv_82586_reconfig(dev);
-
-         /* Tell the kernel that we are doing a really bad job. */
-         dev->flags |= IFF_PROMISC;
-       }
-    }
-  else
-    /* Are there multicast addresses to send? */
-    if(dev->mc_list != (struct dev_mc_list *) NULL)
-      {
-       /*
-        * Disable promiscuous mode, but receive all packets
-        * in multicast list
-        */
+       /* Are we asking for promiscuous mode,
+        * or all multicast addresses (we don't have that!)
+        * or too many multicast addresses for the hardware filter? */
+       if ((dev->flags & IFF_PROMISC) ||
+           (dev->flags & IFF_ALLMULTI) ||
+           (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) {
+               /*
+                * Enable promiscuous mode: receive all packets.
+                */
+               if (!lp->promiscuous) {
+                       lp->promiscuous = 1;
+                       lp->mc_count = 0;
+
+                       wv_82586_reconfig(dev);
+
+                       /* Tell the kernel that we are doing a really bad job. */
+                       dev->flags |= IFF_PROMISC;
+               }
+       } else
+               /* Are there multicast addresses to send? */
+       if (dev->mc_list != (struct dev_mc_list *) NULL) {
+               /*
+                * Disable promiscuous mode, but receive all packets
+                * in multicast list
+                */
 #ifdef MULTICAST_AVOID
-       if(lp->promiscuous ||
-          (dev->mc_count != lp->mc_count))
+               if (lp->promiscuous || (dev->mc_count != lp->mc_count))
 #endif
-         {
-           lp->promiscuous = 0;
-           lp->mc_count = dev->mc_count;
-
-           wv_82586_reconfig(dev);
-         }
-      }
-    else
-      {
-       /*
-        * Switch to normal mode: disable promiscuous mode and 
-        * clear the multicast list.
-        */
-       if(lp->promiscuous || lp->mc_count == 0)
-         {
-           lp->promiscuous = 0;
-           lp->mc_count = 0;
-
-           wv_82586_reconfig(dev);
-         }
-      }
+               {
+                       lp->promiscuous = 0;
+                       lp->mc_count = dev->mc_count;
+
+                       wv_82586_reconfig(dev);
+               }
+       } else {
+               /*
+                * Switch to normal mode: disable promiscuous mode and 
+                * clear the multicast list.
+                */
+               if (lp->promiscuous || lp->mc_count == 0) {
+                       lp->promiscuous = 0;
+                       lp->mc_count = 0;
+
+                       wv_82586_reconfig(dev);
+               }
+       }
 #ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n",
+              dev->name);
 #endif
 }
 
@@ -1565,23 +1499,21 @@ wavelan_set_multicast_list(device *     dev)
  * (Note : it was a nice way to test the reconfigure stuff...)
  */
 #ifdef SET_MAC_ADDRESS
-static int
-wavelan_set_mac_address(device *       dev,
-                       void *          addr)
+static int wavelan_set_mac_address(device * dev, void *addr)
 {
-  struct sockaddr *    mac = addr;
+       struct sockaddr *mac = addr;
 
-  /* Copy the address. */
-  memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE);
+       /* Copy the address. */
+       memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE);
 
-  /* Reconfigure the beast. */
-  wv_82586_reconfig(dev);
+       /* Reconfigure the beast. */
+       wv_82586_reconfig(dev);
 
-  return 0;
+       return 0;
 }
-#endif /* SET_MAC_ADDRESS */
+#endif                         /* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT    /* if wireless extensions exist in the kernel */
+#ifdef WIRELESS_EXT            /* if wireless extensions exist in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -1589,232 +1521,215 @@ wavelan_set_mac_address(device *      dev,
  * It's a bit complicated and you don't really want to look into it.
  * (called in wavelan_ioctl)
  */
-static inline int
-wv_set_frequency(u_long                ioaddr, /* I/O port of the card */
-                iw_freq *      frequency)
+static inline int wv_set_frequency(unsigned long ioaddr,       /* I/O port of the card */
+                                  iw_freq * frequency)
 {
-  const int    BAND_NUM = 10;  /* Number of bands */
-  long         freq = 0L;      /* offset to 2.4 GHz in .5 MHz */
+       const int BAND_NUM = 10;        /* Number of bands */
+       long freq = 0L;         /* offset to 2.4 GHz in .5 MHz */
 #ifdef DEBUG_IOCTL_INFO
-  int          i;
+       int i;
 #endif
 
-  /* Setting by frequency */
-  /* Theoretically, you may set any frequency between
-   * the two limits with a 0.5 MHz precision. In practice,
-   * I don't want you to have trouble with local regulations.
-   */
-  if((frequency->e == 1) &&
-     (frequency->m >= (int) 2.412e8) && (frequency->m <= (int) 2.487e8))
-    {
-      freq = ((frequency->m / 10000) - 24000L) / 5;
-    }
-
-  /* Setting by channel (same as wfreqsel) */
-  /* Warning: each channel is 22 MHz wide, so some of the channels
-   * will interfere. */
-  if((frequency->e == 0) &&
-     (frequency->m >= 0) && (frequency->m < BAND_NUM))
-    {
-      /* Get frequency offset. */
-      freq = channel_bands[frequency->m] >> 1;
-    }
-
-  /* Verify that the frequency is allowed. */
-  if(freq != 0L)
-    {
-      u_short  table[10];      /* Authorized frequency table */
-
-      /* Read the frequency table. */
-      fee_read(ioaddr, 0x71, table, 10);
+       /* Setting by frequency */
+       /* Theoretically, you may set any frequency between
+        * the two limits with a 0.5 MHz precision. In practice,
+        * I don't want you to have trouble with local regulations.
+        */
+       if ((frequency->e == 1) &&
+           (frequency->m >= (int) 2.412e8)
+           && (frequency->m <= (int) 2.487e8)) {
+               freq = ((frequency->m / 10000) - 24000L) / 5;
+       }
 
-#ifdef DEBUG_IOCTL_INFO
-      printk(KERN_DEBUG "Frequency table: ");
-      for(i = 0; i < 10; i++)
-       {
-         printk(" %04X",
-                table[i]);
+       /* Setting by channel (same as wfreqsel) */
+       /* Warning: each channel is 22 MHz wide, so some of the channels
+        * will interfere. */
+       if ((frequency->e == 0) &&
+           (frequency->m >= 0) && (frequency->m < BAND_NUM)) {
+               /* Get frequency offset. */
+               freq = channel_bands[frequency->m] >> 1;
        }
-      printk("\n");
-#endif
 
-      /* Look in the table to see whether the frequency is allowed. */
-      if(!(table[9 - ((freq - 24) / 16)] &
-          (1 << ((freq - 24) % 16))))
-       return -EINVAL;         /* not allowed */
-    }
-  else
-    return -EINVAL;
-
-  /* if we get a usable frequency */
-  if(freq != 0L)
-    {
-      unsigned short   area[16];
-      unsigned short   dac[2];
-      unsigned short   area_verify[16];
-      unsigned short   dac_verify[2];
-      /* Corresponding gain (in the power adjust value table)
-       * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8
-       * and WCIN062D.DOC, page 6.2.9. */
-      unsigned short   power_limit[] = { 40, 80, 120, 160, 0 };
-      int              power_band = 0;         /* Selected band */
-      unsigned short   power_adjust;           /* Correct value */
-
-      /* Search for the gain. */
-      power_band = 0;
-      while((freq > power_limit[power_band]) &&
-           (power_limit[++power_band] != 0))
-       ;
-
-      /* Read the first area. */
-      fee_read(ioaddr, 0x00, area, 16);
-
-      /* Read the DAC. */
-      fee_read(ioaddr, 0x60, dac, 2);
-
-      /* Read the new power adjust value. */
-      fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust, 1);
-      if(power_band & 0x1)
-       power_adjust >>= 8;
-      else
-       power_adjust &= 0xFF;
+       /* Verify that the frequency is allowed. */
+       if (freq != 0L) {
+               u16 table[10];  /* Authorized frequency table */
+
+               /* Read the frequency table. */
+               fee_read(ioaddr, 0x71, table, 10);
 
 #ifdef DEBUG_IOCTL_INFO
-      printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
-      for(i = 0; i < 16; i++)
-       {
-         printk(" %04X",
-                area[i]);
-       }
-      printk("\n");
+               printk(KERN_DEBUG "Frequency table: ");
+               for (i = 0; i < 10; i++) {
+                       printk(" %04X", table[i]);
+               }
+               printk("\n");
+#endif
 
-      printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
-            dac[0], dac[1]);
+               /* Look in the table to see whether the frequency is allowed. */
+               if (!(table[9 - ((freq - 24) / 16)] &
+                     (1 << ((freq - 24) % 16)))) return -EINVAL;       /* not allowed */
+       } else
+               return -EINVAL;
+
+       /* if we get a usable frequency */
+       if (freq != 0L) {
+               unsigned short area[16];
+               unsigned short dac[2];
+               unsigned short area_verify[16];
+               unsigned short dac_verify[2];
+               /* Corresponding gain (in the power adjust value table)
+                * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8
+                * and WCIN062D.DOC, page 6.2.9. */
+               unsigned short power_limit[] = { 40, 80, 120, 160, 0 };
+               int power_band = 0;     /* Selected band */
+               unsigned short power_adjust;    /* Correct value */
+
+               /* Search for the gain. */
+               power_band = 0;
+               while ((freq > power_limit[power_band]) &&
+                      (power_limit[++power_band] != 0));
+
+               /* Read the first area. */
+               fee_read(ioaddr, 0x00, area, 16);
+
+               /* Read the DAC. */
+               fee_read(ioaddr, 0x60, dac, 2);
+
+               /* Read the new power adjust value. */
+               fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust,
+                        1);
+               if (power_band & 0x1)
+                       power_adjust >>= 8;
+               else
+                       power_adjust &= 0xFF;
+
+#ifdef DEBUG_IOCTL_INFO
+               printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
+               for (i = 0; i < 16; i++) {
+                       printk(" %04X", area[i]);
+               }
+               printk("\n");
+
+               printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
+                      dac[0], dac[1]);
 #endif
 
-      /* Frequency offset (for info only) */
-      area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F);
+               /* Frequency offset (for info only) */
+               area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F);
 
-      /* Receiver Principle main divider coefficient */
-      area[3] = (freq >> 1) + 2400L - 352L;
-      area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
+               /* Receiver Principle main divider coefficient */
+               area[3] = (freq >> 1) + 2400L - 352L;
+               area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
 
-      /* Transmitter Main divider coefficient */
-      area[13] = (freq >> 1) + 2400L;
-      area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
+               /* Transmitter Main divider coefficient */
+               area[13] = (freq >> 1) + 2400L;
+               area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
 
-      /* Other parts of the area are flags, bit streams or unused. */
+               /* Other parts of the area are flags, bit streams or unused. */
 
-      /* Set the value in the DAC. */
-      dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80);
-      dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF);
+               /* Set the value in the DAC. */
+               dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80);
+               dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF);
 
-      /* Write the first area. */
-      fee_write(ioaddr, 0x00,
-               area, 16);
+               /* Write the first area. */
+               fee_write(ioaddr, 0x00, area, 16);
 
-      /* Write the DAC. */
-      fee_write(ioaddr, 0x60,
-               dac, 2);
+               /* Write the DAC. */
+               fee_write(ioaddr, 0x60, dac, 2);
 
-      /* We now should verify here that the writing of the EEPROM went OK. */
+               /* We now should verify here that the writing of the EEPROM went OK. */
 
-      /* Reread the first area. */
-      fee_read(ioaddr, 0x00, area_verify, 16);
+               /* Reread the first area. */
+               fee_read(ioaddr, 0x00, area_verify, 16);
 
-      /* Reread the DAC. */
-      fee_read(ioaddr, 0x60, dac_verify, 2);
+               /* Reread the DAC. */
+               fee_read(ioaddr, 0x60, dac_verify, 2);
 
-      /* Compare. */
-      if(memcmp(area, area_verify, 16 * 2) ||
-        memcmp(dac, dac_verify, 2 * 2))
-       {
+               /* Compare. */
+               if (memcmp(area, area_verify, 16 * 2) ||
+                   memcmp(dac, dac_verify, 2 * 2)) {
 #ifdef DEBUG_IOCTL_ERROR
-         printk(KERN_INFO "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n");
+                       printk(KERN_INFO
+                              "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n");
 #endif
-         return -EOPNOTSUPP;
-       }
+                       return -EOPNOTSUPP;
+               }
 
-      /* We must download the frequency parameters to the
-       * synthesizers (from the EEPROM - area 1)
-       * Note: as the EEPROM is automatically decremented, we set the end
-       * if the area... */
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F);
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
-             MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
+               /* We must download the frequency parameters to the
+                * synthesizers (from the EEPROM - area 1)
+                * Note: as the EEPROM is automatically decremented, we set the end
+                * if the area... */
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F);
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+                       MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
 
-      /* Wait until the download is finished. */
-      fee_wait(ioaddr, 100, 100);
+               /* Wait until the download is finished. */
+               fee_wait(ioaddr, 100, 100);
 
-      /* We must now download the power adjust value (gain) to
-       * the synthesizers (from the EEPROM - area 7 - DAC). */
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61);
-      mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
-             MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
+               /* We must now download the power adjust value (gain) to
+                * the synthesizers (from the EEPROM - area 7 - DAC). */
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61);
+               mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+                       MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
 
-      /* Wait for the download to finish. */
-      fee_wait(ioaddr, 100, 100);
+               /* Wait for the download to finish. */
+               fee_wait(ioaddr, 100, 100);
 
 #ifdef DEBUG_IOCTL_INFO
-      /* Verification of what we have done */
+               /* Verification of what we have done */
 
-      printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
-      for(i = 0; i < 16; i++)
-       {
-         printk(" %04X",
-                area_verify[i]);
-       }
-      printk("\n");
+               printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
+               for (i = 0; i < 16; i++) {
+                       printk(" %04X", area_verify[i]);
+               }
+               printk("\n");
 
-      printk(KERN_DEBUG "WaveLAN EEPROM DAC:  %04X %04X\n",
-            dac_verify[0], dac_verify[1]);
+               printk(KERN_DEBUG "WaveLAN EEPROM DAC:  %04X %04X\n",
+                      dac_verify[0], dac_verify[1]);
 #endif
 
-      return 0;
-    }
-  else
-    return -EINVAL;            /* Bah, never get there... */
+               return 0;
+       } else
+               return -EINVAL; /* Bah, never get there... */
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Give the list of available frequencies.
  */
-static inline int
-wv_frequency_list(u_long       ioaddr, /* I/O port of the card */
-                 iw_freq *     list,   /* List of frequencies to fill */
-                 int           max)    /* Maximum number of frequencies */
-{
-  u_short      table[10];      /* Authorized frequency table */
-  long         freq = 0L;      /* offset to 2.4 GHz in .5 MHz + 12 MHz */
-  int          i;              /* index in the table */
-  int          c = 0;          /* Channel number */
-
-  /* Read the frequency table. */
-  fee_read(ioaddr, 0x71 /* frequency table */, table, 10);
-
-  /* Check all frequencies. */
-  i = 0;
-  for(freq = 0; freq < 150; freq++)
-    /* Look in the table if the frequency is allowed */
-    if(table[9 - (freq / 16)] & (1 << (freq % 16)))
-      {
-       /* Compute approximate channel number */
-       while((((channel_bands[c] >> 1) - 24) < freq) &&
-             (c < NELS(channel_bands)))
-         c++;
-       list[i].i = c;  /* Set the list index */
-
-       /* put in the list */
-       list[i].m = (((freq + 24) * 5) + 24000L) * 10000;
-       list[i++].e = 1;
-
-       /* Check number. */
-       if(i >= max)
-         return(i);
-      }
-
-  return(i);
+static inline int wv_frequency_list(unsigned long ioaddr,      /* I/O port of the card */
+                                   iw_freq * list,     /* List of frequencies to fill */
+                                   int max)
+{                              /* Maximum number of frequencies */
+       u16 table[10];  /* Authorized frequency table */
+       long freq = 0L;         /* offset to 2.4 GHz in .5 MHz + 12 MHz */
+       int i;                  /* index in the table */
+       int c = 0;              /* Channel number */
+
+       /* Read the frequency table. */
+       fee_read(ioaddr, 0x71 /* frequency table */ , table, 10);
+
+       /* Check all frequencies. */
+       i = 0;
+       for (freq = 0; freq < 150; freq++)
+               /* Look in the table if the frequency is allowed */
+               if (table[9 - (freq / 16)] & (1 << (freq % 16))) {
+                       /* Compute approximate channel number */
+                       while ((((channel_bands[c] >> 1) - 24) < freq) &&
+                              (c < NELS(channel_bands)))
+                               c++;
+                       list[i].i = c;  /* Set the list index */
+
+                       /* put in the list */
+                       list[i].m = (((freq + 24) * 5) + 24000L) * 10000;
+                       list[i++].e = 1;
+
+                       /* Check number. */
+                       if (i >= max)
+                               return (i);
+               }
+
+       return (i);
 }
 
 #ifdef WIRELESS_SPY
@@ -1824,27 +1739,24 @@ wv_frequency_list(u_long        ioaddr, /* I/O port of the card */
  * address with our list, and if they match, get the statistics.
  * Sorry, but this function really needs the wireless extensions.
  */
-static inline void
-wl_spy_gather(device * dev,
-             u_char *  mac,            /* MAC address */
-             u_char *  stats)          /* Statistics to gather */
-{
-  net_local *  lp = (net_local *) dev->priv;
-  int          i;
-
-  /* Check all addresses. */
-  for(i = 0; i < lp->spy_number; i++)
-    /* If match */
-    if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE))
-      {
-       /* Update statistics */
-       lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL;
-       lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL;
-       lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL;
-       lp->spy_stat[i].updated = 0x7;
-      }
+static inline void wl_spy_gather(device * dev, u8 * mac,       /* MAC address */
+                                u8 * stats)
+{                              /* Statistics to gather */
+       net_local *lp = (net_local *) dev->priv;
+       int i;
+
+       /* Check all addresses. */
+       for (i = 0; i < lp->spy_number; i++)
+               /* If match */
+               if (!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) {
+                       /* Update statistics */
+                       lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL;
+                       lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL;
+                       lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL;
+                       lp->spy_stat[i].updated = 0x7;
+               }
 }
-#endif /* WIRELESS_SPY */
+#endif                         /* WIRELESS_SPY */
 
 #ifdef HISTOGRAM
 /*------------------------------------------------------------------*/
@@ -1856,494 +1768,516 @@ wl_spy_gather(device *        dev,
  * With this histogram you may detect if one WaveLAN is really weak,
  * or you may also calculate the mean and standard deviation of the level.
  */
-static inline void
-wl_his_gather(device * dev,
-             u_char *  stats)          /* Statistics to gather */
-{
-  net_local *  lp = (net_local *) dev->priv;
-  u_char       level = stats[0] & MMR_SIGNAL_LVL;
-  int          i;
-
-  /* Find the correct interval. */
-  i = 0;
-  while((i < (lp->his_number - 1)) && (level >= lp->his_range[i++]))
-    ;
-
-  /* Increment interval counter. */
-  (lp->his_sum[i])++;
+static inline void wl_his_gather(device * dev, u8 * stats)
+{                              /* Statistics to gather */
+       net_local *lp = (net_local *) dev->priv;
+       u8 level = stats[0] & MMR_SIGNAL_LVL;
+       int i;
+
+       /* Find the correct interval. */
+       i = 0;
+       while ((i < (lp->his_number - 1))
+              && (level >= lp->his_range[i++]));
+
+       /* Increment interval counter. */
+       (lp->his_sum[i])++;
 }
-#endif /* HISTOGRAM */
+#endif                         /* HISTOGRAM */
 
 /*------------------------------------------------------------------*/
 /*
  * Perform ioctl for configuration and information.
  * It is here that the wireless extensions are treated (iwconfig).
  */
-static int
-wavelan_ioctl(struct net_device *      dev,    /* device on which the ioctl is applied */
-             struct ifreq *    rq,     /* data passed */
-             int               cmd)    /* ioctl number */
-{
-  u_long               ioaddr = dev->base_addr;
-  net_local *          lp = (net_local *)dev->priv;    /* lp is not unused */
-  struct iwreq *       wrq = (struct iwreq *) rq;
-  psa_t                        psa;
-  mm_t                 m;
-  unsigned long                x;
-  int                  ret = 0;
+static int wavelan_ioctl(struct net_device *dev,       /* device on which the ioctl is applied */
+                        struct ifreq *rq,      /* data passed */
+                        int cmd)
+{                              /* ioctl number */
+       unsigned long ioaddr = dev->base_addr;
+       net_local *lp = (net_local *) dev->priv;        /* lp is not unused */
+       struct iwreq *wrq = (struct iwreq *) rq;
+       psa_t psa;
+       mm_t m;
+       unsigned long flags;
+       int ret = 0;
 
 #ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
+       printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name,
+              cmd);
 #endif
 
-  /* Disable interrupts and save flags. */
-  x = wv_splhi();
-
-  /* Look what is the request */
-  switch(cmd)
-    {
-      /* --------------- WIRELESS EXTENSIONS --------------- */
-
-    case SIOCGIWNAME:
-      strcpy(wrq->u.name, "WaveLAN");
-      break;
-
-    case SIOCSIWNWID:
-      /* Set NWID in WaveLAN. */
-      if(!wrq->u.nwid.disabled)
-       {
-         /* Set NWID in psa */
-         psa.psa_nwid[0] = (wrq->u.nwid.value & 0xFF00) >> 8;
-         psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
-         psa.psa_nwid_select = 0x01;
-         psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
-                   (unsigned char *)psa.psa_nwid, 3);
-
-         /* Set NWID in mmc. */
-         m.w.mmw_netw_id_l = psa.psa_nwid[1];
-         m.w.mmw_netw_id_h = psa.psa_nwid[0];
-         mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m,
-                   (unsigned char *)&m.w.mmw_netw_id_l, 2);
-         mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
-       }
-      else
-       {
-         /* Disable NWID in the psa. */
-         psa.psa_nwid_select = 0x00;
-         psa_write(ioaddr, lp->hacr,
-                   (char *)&psa.psa_nwid_select - (char *)&psa,
-                   (unsigned char *)&psa.psa_nwid_select, 1);
-
-         /* Disable NWID in the mmc (no filtering). */
-         mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
-       }
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev, ioaddr, lp->hacr);
-      break;
-
-    case SIOCGIWNWID:
-      /* Read the NWID. */
-      psa_read(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
-              (unsigned char *)psa.psa_nwid, 3);
-      wrq->u.nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
-      wrq->u.nwid.disabled = !(psa.psa_nwid_select);
-      wrq->u.nwid.fixed = 1;   /* Superfluous */
-      break;
-
-    case SIOCSIWFREQ:
-      /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
-      if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-          (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-       ret = wv_set_frequency(ioaddr, &(wrq->u.freq));
-      else
-       ret = -EOPNOTSUPP;
-      break;
-
-    case SIOCGIWFREQ:
-      /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
-       * Does it work for everybody, especially old cards? */
-      if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-          (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-       {
-         unsigned short        freq;
-
-         /* Ask the EEPROM to read the frequency from the first area. */
-         fee_read(ioaddr, 0x00, &freq, 1);
-         wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
-         wrq->u.freq.e = 1;
-       }
-      else
-       {
-         psa_read(ioaddr, lp->hacr, (char *)&psa.psa_subband - (char *)&psa,
-                  (unsigned char *)&psa.psa_subband, 1);
-
-         if(psa.psa_subband <= 4)
-           {
-             wrq->u.freq.m = fixed_bands[psa.psa_subband];
-             wrq->u.freq.e = (psa.psa_subband != 0);
-           }
-         else
-           ret = -EOPNOTSUPP;
-       }
-      break;
-
-    case SIOCSIWSENS:
-      /* Set the level threshold. */
-      /* We should complain loudly if wrq->u.sens.fixed = 0, because we
-       * can't set auto mode... */
-      psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
-      psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
-              (unsigned char *) &psa.psa_thr_pre_set, 1);
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev, ioaddr, lp->hacr);
-      mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
-      break;
-
-    case SIOCGIWSENS:
-      /* Read the level threshold. */
-      psa_read(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
-              (unsigned char *) &psa.psa_thr_pre_set, 1);
-      wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
-      wrq->u.sens.fixed = 1;
-      break;
-
-    case SIOCSIWENCODE:
-      /* Set encryption key */
-      if(!mmc_encr(ioaddr))
-       {
-         ret = -EOPNOTSUPP;
-         break;
-       }
-
-      /* Basic checking... */
-      if(wrq->u.encoding.pointer != (caddr_t) 0)
-       {
-         /* Check the size of the key */
-         if(wrq->u.encoding.length != 8)
-           {
-             ret = -EINVAL;
-             break;
-           }
-
-         /* Copy the key in the driver */
-         if(copy_from_user(psa.psa_encryption_key, wrq->u.encoding.pointer,
-                           wrq->u.encoding.length))
-           {
-             ret = -EFAULT;
-             break;
-           }
-
-         psa.psa_encryption_select = 1;
-         psa_write(ioaddr, lp->hacr,
-                   (char *) &psa.psa_encryption_select - (char *) &psa,
-                   (unsigned char *) &psa.psa_encryption_select, 8+1);
-
-         mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
-                 MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
-         mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
-                   (unsigned char *) &psa.psa_encryption_key, 8);
-       }
-
-      if(wrq->u.encoding.flags & IW_ENCODE_DISABLED)
-       {       /* disable encryption */
-         psa.psa_encryption_select = 0;
-         psa_write(ioaddr, lp->hacr,
-                   (char *) &psa.psa_encryption_select - (char *) &psa,
-                   (unsigned char *) &psa.psa_encryption_select, 1);
-
-         mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
-       }
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev, ioaddr, lp->hacr);
-      break;
-
-    case SIOCGIWENCODE:
-      /* Read the encryption key */
-      if(!mmc_encr(ioaddr))
-       {
-         ret = -EOPNOTSUPP;
-         break;
-       }
-
-      /* only super-user can see encryption key */
-      if(!suser())
-       {
-         ret = -EPERM;
-         break;
-       }
-
-      /* Basic checking... */
-      if(wrq->u.encoding.pointer != (caddr_t) 0)
-       {
-         /* Verify the user buffer */
-         ret = verify_area(VERIFY_WRITE, wrq->u.encoding.pointer, 8);
-         if(ret)
-           break;
-
-         psa_read(ioaddr, lp->hacr,
-                  (char *) &psa.psa_encryption_select - (char *) &psa,
-                  (unsigned char *) &psa.psa_encryption_select, 1+8);
-
-         /* encryption is enabled ? */
-         if(psa.psa_encryption_select)
-           wrq->u.encoding.flags = IW_ENCODE_ENABLED;
-         else
-           wrq->u.encoding.flags = IW_ENCODE_DISABLED;
-         wrq->u.encoding.flags |= mmc_encr(ioaddr);
-
-         /* Copy the key to the user buffer */
-         wrq->u.encoding.length = 8;
-         if(copy_to_user(wrq->u.encoding.pointer, psa.psa_encryption_key, 8))
-           ret = -EFAULT;
-       }
-      break;
-
-    case SIOCGIWRANGE:
-      /* basic checking */
-      if(wrq->u.data.pointer != (caddr_t) 0)
-       {
-         struct iw_range       range;
-
-         /* Set the length (useless:  it's constant). */
-         wrq->u.data.length = sizeof(struct iw_range);
-
-         /* Set information in the range struct.  */
-         range.throughput = 1.6 * 1000 * 1000; /* don't argue on this ! */
-         range.min_nwid = 0x0000;
-         range.max_nwid = 0xFFFF;
-
-         /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
-         if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-              (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-           {
-             range.num_channels = 10;
-             range.num_frequency = wv_frequency_list(ioaddr, range.freq,
+       /* Disable interrupts and save flags. */
+       save_flags(flags);
+       cli();
+       /* FIXME: can't copy*user when cli this is broken! */
+       
+       /* Look what is the request */
+       switch (cmd) {
+               /* --------------- WIRELESS EXTENSIONS --------------- */
+
+       case SIOCGIWNAME:
+               strcpy(wrq->u.name, "WaveLAN");
+               break;
+
+       case SIOCSIWNWID:
+               /* Set NWID in WaveLAN. */
+               if (!wrq->u.nwid.disabled) {
+                       /* Set NWID in psa */
+                       psa.psa_nwid[0] =
+                           (wrq->u.nwid.value & 0xFF00) >> 8;
+                       psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
+                       psa.psa_nwid_select = 0x01;
+                       psa_write(ioaddr, lp->hacr,
+                                 (char *) psa.psa_nwid - (char *) &psa,
+                                 (unsigned char *) psa.psa_nwid, 3);
+
+                       /* Set NWID in mmc. */
+                       m.w.mmw_netw_id_l = psa.psa_nwid[1];
+                       m.w.mmw_netw_id_h = psa.psa_nwid[0];
+                       mmc_write(ioaddr,
+                                 (char *) &m.w.mmw_netw_id_l -
+                                 (char *) &m,
+                                 (unsigned char *) &m.w.mmw_netw_id_l, 2);
+                       mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
+               } else {
+                       /* Disable NWID in the psa. */
+                       psa.psa_nwid_select = 0x00;
+                       psa_write(ioaddr, lp->hacr,
+                                 (char *) &psa.psa_nwid_select -
+                                 (char *) &psa,
+                                 (unsigned char *) &psa.psa_nwid_select,
+                                 1);
+
+                       /* Disable NWID in the mmc (no filtering). */
+                       mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel),
+                               MMW_LOOPT_SEL_DIS_NWID);
+               }
+               /* update the Wavelan checksum */
+               update_psa_checksum(dev, ioaddr, lp->hacr);
+               break;
+
+       case SIOCGIWNWID:
+               /* Read the NWID. */
+               psa_read(ioaddr, lp->hacr,
+                        (char *) psa.psa_nwid - (char *) &psa,
+                        (unsigned char *) psa.psa_nwid, 3);
+               wrq->u.nwid.value =
+                   (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+               wrq->u.nwid.disabled = !(psa.psa_nwid_select);
+               wrq->u.nwid.fixed = 1;  /* Superfluous */
+               break;
+
+       case SIOCSIWFREQ:
+               /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+               if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+                     (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
+                       ret = wv_set_frequency(ioaddr, &(wrq->u.freq));
+               else
+                       ret = -EOPNOTSUPP;
+               break;
+
+       case SIOCGIWFREQ:
+               /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
+                * Does it work for everybody, especially old cards? */
+               if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+                     (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+                       unsigned short freq;
+
+                       /* Ask the EEPROM to read the frequency from the first area. */
+                       fee_read(ioaddr, 0x00, &freq, 1);
+                       wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
+                       wrq->u.freq.e = 1;
+               } else {
+                       psa_read(ioaddr, lp->hacr,
+                                (char *) &psa.psa_subband - (char *) &psa,
+                                (unsigned char *) &psa.psa_subband, 1);
+
+                       if (psa.psa_subband <= 4) {
+                               wrq->u.freq.m =
+                                   fixed_bands[psa.psa_subband];
+                               wrq->u.freq.e = (psa.psa_subband != 0);
+                       } else
+                               ret = -EOPNOTSUPP;
+               }
+               break;
+
+       case SIOCSIWSENS:
+               /* Set the level threshold. */
+               /* We should complain loudly if wrq->u.sens.fixed = 0, because we
+                * can't set auto mode... */
+               psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
+               psa_write(ioaddr, lp->hacr,
+                         (char *) &psa.psa_thr_pre_set - (char *) &psa,
+                         (unsigned char *) &psa.psa_thr_pre_set, 1);
+               /* update the Wavelan checksum */
+               update_psa_checksum(dev, ioaddr, lp->hacr);
+               mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set),
+                       psa.psa_thr_pre_set);
+               break;
+
+       case SIOCGIWSENS:
+               /* Read the level threshold. */
+               psa_read(ioaddr, lp->hacr,
+                        (char *) &psa.psa_thr_pre_set - (char *) &psa,
+                        (unsigned char *) &psa.psa_thr_pre_set, 1);
+               wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
+               wrq->u.sens.fixed = 1;
+               break;
+
+       case SIOCSIWENCODE:
+               /* Set encryption key */
+               if (!mmc_encr(ioaddr)) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+
+               /* Basic checking... */
+               if (wrq->u.encoding.pointer != (caddr_t) 0) {
+                       /* Check the size of the key */
+                       if (wrq->u.encoding.length != 8) {
+                               ret = -EINVAL;
+                               break;
+                       }
+
+                       /* Copy the key in the driver */
+                       if (copy_from_user
+                           (psa.psa_encryption_key,
+                            wrq->u.encoding.pointer,
+                            wrq->u.encoding.length)) {
+                               ret = -EFAULT;
+                               break;
+                       }
+
+                       psa.psa_encryption_select = 1;
+                       psa_write(ioaddr, lp->hacr,
+                                 (char *) &psa.psa_encryption_select -
+                                 (char *) &psa,
+                                 (unsigned char *) &psa.
+                                 psa_encryption_select, 8 + 1);
+
+                       mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
+                               MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
+                       mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
+                                 (unsigned char *) &psa.
+                                 psa_encryption_key, 8);
+               }
+
+               if (wrq->u.encoding.flags & IW_ENCODE_DISABLED) {       /* disable encryption */
+                       psa.psa_encryption_select = 0;
+                       psa_write(ioaddr, lp->hacr,
+                                 (char *) &psa.psa_encryption_select -
+                                 (char *) &psa,
+                                 (unsigned char *) &psa.
+                                 psa_encryption_select, 1);
+
+                       mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
+               }
+               /* update the Wavelan checksum */
+               update_psa_checksum(dev, ioaddr, lp->hacr);
+               break;
+
+       case SIOCGIWENCODE:
+               /* Read the encryption key */
+               if (!mmc_encr(ioaddr)) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+
+               /* only super-user can see encryption key */
+               if (!suser()) {
+                       ret = -EPERM;
+                       break;
+               }
+
+               /* Basic checking... */
+               if (wrq->u.encoding.pointer != (caddr_t) 0) {
+                       /* Verify the user buffer */
+                       ret =
+                           verify_area(VERIFY_WRITE,
+                                       wrq->u.encoding.pointer, 8);
+                       if (ret)
+                               break;
+
+                       psa_read(ioaddr, lp->hacr,
+                                (char *) &psa.psa_encryption_select -
+                                (char *) &psa,
+                                (unsigned char *) &psa.
+                                psa_encryption_select, 1 + 8);
+
+                       /* encryption is enabled ? */
+                       if (psa.psa_encryption_select)
+                               wrq->u.encoding.flags = IW_ENCODE_ENABLED;
+                       else
+                               wrq->u.encoding.flags = IW_ENCODE_DISABLED;
+                       wrq->u.encoding.flags |= mmc_encr(ioaddr);
+
+                       /* Copy the key to the user buffer */
+                       wrq->u.encoding.length = 8;
+                       if (copy_to_user
+                           (wrq->u.encoding.pointer,
+                            psa.psa_encryption_key, 8)) ret = -EFAULT;
+               }
+               break;
+
+       case SIOCGIWRANGE:
+               /* basic checking */
+               if (wrq->u.data.pointer != (caddr_t) 0) {
+                       struct iw_range range;
+
+                       /* Set the length (useless:  it's constant). */
+                       wrq->u.data.length = sizeof(struct iw_range);
+
+                       /* Set information in the range struct.  */
+                       range.throughput = 1.6 * 1000 * 1000;   /* don't argue on this ! */
+                       range.min_nwid = 0x0000;
+                       range.max_nwid = 0xFFFF;
+
+                       /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+                       if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+                             (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+                               range.num_channels = 10;
+                               range.num_frequency =
+                                   wv_frequency_list(ioaddr, range.freq,
                                                      IW_MAX_FREQUENCIES);
-           }
-         else
-           range.num_channels = range.num_frequency = 0;
-
-         range.sensitivity = 0x3F;
-         range.max_qual.qual = MMR_SGNL_QUAL;
-         range.max_qual.level = MMR_SIGNAL_LVL;
-         range.max_qual.noise = MMR_SILENCE_LVL;
-
-         range.num_bitrates = 1;
-         range.bitrate[0] = 2000000;   /* 2 Mb/s */
-
-         /* Encryption supported ? */
-         if(mmc_encr(ioaddr))
-           {
-             range.encoding_size[0] = 8;       /* DES = 64 bits key */
-             range.num_encoding_sizes = 1;
-             range.max_encoding_tokens = 1;    /* Only one key possible */
-           }
-         else
-           {
-             range.num_encoding_sizes = 0;
-             range.max_encoding_tokens = 0;
-           }
-
-         /* Copy structure to the user buffer. */
-         if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
-               ret = -EFAULT;
-       }
-      break;
-
-    case SIOCGIWPRIV:
-      /* Basic checking */
-      if(wrq->u.data.pointer != (caddr_t) 0)
-       {
-         struct iw_priv_args   priv[] =
-         {     /* cmd,         set_args,       get_args,       name */
-           { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
-           { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
-
-           { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,     0, "sethisto" },
-           { SIOCGIPHISTO, 0,      IW_PRIV_TYPE_INT | 16, "gethisto" },
-         };
-
-         /* Set the number of available ioctls. */
-         wrq->u.data.length = 4;
-
-         /* Copy structure to the user buffer. */
-         if (copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv)))
-               ret = -EFAULT;
-       }
-      break;
+                       } else
+                               range.num_channels = range.num_frequency =
+                                   0;
+
+                       range.sensitivity = 0x3F;
+                       range.max_qual.qual = MMR_SGNL_QUAL;
+                       range.max_qual.level = MMR_SIGNAL_LVL;
+                       range.max_qual.noise = MMR_SILENCE_LVL;
+
+                       range.num_bitrates = 1;
+                       range.bitrate[0] = 2000000;     /* 2 Mb/s */
+
+                       /* Encryption supported ? */
+                       if (mmc_encr(ioaddr)) {
+                               range.encoding_size[0] = 8;     /* DES = 64 bits key */
+                               range.num_encoding_sizes = 1;
+                               range.max_encoding_tokens = 1;  /* Only one key possible */
+                       } else {
+                               range.num_encoding_sizes = 0;
+                               range.max_encoding_tokens = 0;
+                       }
+
+                       /* Copy structure to the user buffer. */
+                       if (copy_to_user
+                           (wrq->u.data.pointer, &range,
+                            sizeof(struct iw_range))) ret = -EFAULT;
+               }
+               break;
+
+       case SIOCGIWPRIV:
+               /* Basic checking */
+               if (wrq->u.data.pointer != (caddr_t) 0) {
+                       struct iw_priv_args priv[] = {  /* cmd,         set_args,       get_args,       name */
+                               
+                                   {SIOCSIPQTHR,
+                                IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED |
+                                    1, 0, "setqualthr"},
+                               {SIOCGIPQTHR, 0,
+                                IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED |
+                                1, "getqualthr"},
+
+                               
+                                   {SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,
+                                0, "sethisto"},
+                               {SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16,
+                                "gethisto"},
+                       };
+
+                       /* Set the number of available ioctls. */
+                       wrq->u.data.length = 4;
+
+                       /* Copy structure to the user buffer. */
+                       if (copy_to_user
+                           (wrq->u.data.pointer, (u8 *) priv,
+                            sizeof(priv))) ret = -EFAULT;
+               }
+               break;
 
 #ifdef WIRELESS_SPY
-    case SIOCSIWSPY:
-      /* Set the spy list */
-
-      /* Check the number of addresses. */
-      if(wrq->u.data.length > IW_MAX_SPY)
-       {
-         ret = -E2BIG;
-         break;
-       }
-      lp->spy_number = wrq->u.data.length;
-
-      /* Are there are addresses to copy? */
-      if(lp->spy_number > 0)
-       {
-         struct sockaddr       address[IW_MAX_SPY];
-         int                   i;
-
-         /* Copy addresses to the driver. */
-         if (copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number)) {
-               ret = -EFAULT;
-               break;
-         }
-
-         /* Copy addresses to the lp structure. */
-         for(i = 0; i < lp->spy_number; i++)
-           {
-             memcpy(lp->spy_address[i], address[i].sa_data,
-                    WAVELAN_ADDR_SIZE);
-           }
-
-         /* Reset structure. */
-         memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+       case SIOCSIWSPY:
+               /* Set the spy list */
+
+               /* Check the number of addresses. */
+               if (wrq->u.data.length > IW_MAX_SPY) {
+                       ret = -E2BIG;
+                       break;
+               }
+               lp->spy_number = wrq->u.data.length;
+
+               /* Are there are addresses to copy? */
+               if (lp->spy_number > 0) {
+                       struct sockaddr address[IW_MAX_SPY];
+                       int i;
+
+                       /* Copy addresses to the driver. */
+                       if (copy_from_user
+                           (address, wrq->u.data.pointer,
+                            sizeof(struct sockaddr) * lp->spy_number)) {
+                               ret = -EFAULT;
+                               break;
+                       }
+
+                       /* Copy addresses to the lp structure. */
+                       for (i = 0; i < lp->spy_number; i++) {
+                               memcpy(lp->spy_address[i],
+                                      address[i].sa_data,
+                                      WAVELAN_ADDR_SIZE);
+                       }
+
+                       /* Reset structure. */
+                       memset(lp->spy_stat, 0x00,
+                              sizeof(iw_qual) * IW_MAX_SPY);
 
 #ifdef DEBUG_IOCTL_INFO
-         printk(KERN_DEBUG "SetSpy:  set of new addresses is: \n");
-         for(i = 0; i < wrq->u.data.length; i++)
-           printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X \n",
-                  lp->spy_address[i][0],
-                  lp->spy_address[i][1],
-                  lp->spy_address[i][2],
-                  lp->spy_address[i][3],
-                  lp->spy_address[i][4],
-                  lp->spy_address[i][5]);
-#endif /* DEBUG_IOCTL_INFO */
-       }
-
-      break;
-
-    case SIOCGIWSPY:
-      /* Get the spy list and spy stats. */
-
-      /* Set the number of addresses */
-      wrq->u.data.length = lp->spy_number;
-
-      /* Does the user want to have the addresses back? */
-      if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
-       {
-         struct sockaddr       address[IW_MAX_SPY];
-         int                   i;
-
-         /* Copy addresses from the lp structure. */
-         for(i = 0; i < lp->spy_number; i++)
-           {
-             memcpy(address[i].sa_data, lp->spy_address[i],
-                    WAVELAN_ADDR_SIZE);
-             address[i].sa_family = AF_UNIX;
-           }
-
-         /* Copy addresses to the user buffer. */
-         if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number)) {
-               ret = -EFAULT;
-               break;
-         }
-               
-         /* Copy stats to the user buffer (just after). */
-         if (copy_to_user(wrq->u.data.pointer +
-                      (sizeof(struct sockaddr) * lp->spy_number),
-                      lp->spy_stat, sizeof(iw_qual) * lp->spy_number)) {
-                               ret = -EFAULT;
-                               break;
-         }
-
-         /* Reset updated flags. */
-         for(i = 0; i < lp->spy_number; i++)
-           lp->spy_stat[i].updated = 0x0;
-       }       /* if(pointer != NULL) */
-
-      break;
-#endif /* WIRELESS_SPY */
-
-      /* ------------------ PRIVATE IOCTL ------------------ */
-
-    case SIOCSIPQTHR:
-      if(!suser())
-        {
-         ret = -EPERM;
-         break;
-       }
-      psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
-      psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
-              (unsigned char *)&psa.psa_quality_thr, 1);
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev, ioaddr, lp->hacr);
-      mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
-      break;
-
-    case SIOCGIPQTHR:
-      psa_read(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
-              (unsigned char *)&psa.psa_quality_thr, 1);
-      *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
-      break;
+                       printk(KERN_DEBUG
+                              "SetSpy:  set of new addresses is: \n");
+                       for (i = 0; i < wrq->u.data.length; i++)
+                               printk(KERN_DEBUG
+                                      "%02X:%02X:%02X:%02X:%02X:%02X \n",
+                                      lp->spy_address[i][0],
+                                      lp->spy_address[i][1],
+                                      lp->spy_address[i][2],
+                                      lp->spy_address[i][3],
+                                      lp->spy_address[i][4],
+                                      lp->spy_address[i][5]);
+#endif                         /* DEBUG_IOCTL_INFO */
+               }
+
+               break;
+
+       case SIOCGIWSPY:
+               /* Get the spy list and spy stats. */
+
+               /* Set the number of addresses */
+               wrq->u.data.length = lp->spy_number;
+
+               /* Does the user want to have the addresses back? */
+               if ((lp->spy_number > 0)
+                   && (wrq->u.data.pointer != (caddr_t) 0)) {
+                       struct sockaddr address[IW_MAX_SPY];
+                       int i;
+
+                       /* Copy addresses from the lp structure. */
+                       for (i = 0; i < lp->spy_number; i++) {
+                               memcpy(address[i].sa_data,
+                                      lp->spy_address[i],
+                                      WAVELAN_ADDR_SIZE);
+                               address[i].sa_family = AF_UNIX;
+                       }
+
+                       /* Copy addresses to the user buffer. */
+                       if (copy_to_user
+                           (wrq->u.data.pointer, address,
+                            sizeof(struct sockaddr) * lp->spy_number)) {
+                               ret = -EFAULT;
+                               break;
+                       }
+
+                       /* Copy stats to the user buffer (just after). */
+                       if (copy_to_user(wrq->u.data.pointer +
+                                        (sizeof(struct sockaddr) *
+                                         lp->spy_number), lp->spy_stat,
+                                        sizeof(iw_qual) * lp->spy_number)) {
+                               ret = -EFAULT;
+                               break;
+                       }
+
+                       /* Reset updated flags. */
+                       for (i = 0; i < lp->spy_number; i++)
+                               lp->spy_stat[i].updated = 0x0;
+               }
+               /* if(pointer != NULL) */
+               break;
+#endif                         /* WIRELESS_SPY */
+
+               /* ------------------ PRIVATE IOCTL ------------------ */
+
+       case SIOCSIPQTHR:
+               if (!suser()) {
+                       ret = -EPERM;
+                       break;
+               }
+               psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
+               psa_write(ioaddr, lp->hacr,
+                         (char *) &psa.psa_quality_thr - (char *) &psa,
+                         (unsigned char *) &psa.psa_quality_thr, 1);
+               /* update the Wavelan checksum */
+               update_psa_checksum(dev, ioaddr, lp->hacr);
+               mmc_out(ioaddr, mmwoff(0, mmw_quality_thr),
+                       psa.psa_quality_thr);
+               break;
+
+       case SIOCGIPQTHR:
+               psa_read(ioaddr, lp->hacr,
+                        (char *) &psa.psa_quality_thr - (char *) &psa,
+                        (unsigned char *) &psa.psa_quality_thr, 1);
+               *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
+               break;
 
 #ifdef HISTOGRAM
-    case SIOCSIPHISTO:
-      /* Verify that the user is root. */
-      if(!suser())
-        {
-         ret = -EPERM;
-         break;
-       }
-
-      /* Check the number of intervals. */
-      if(wrq->u.data.length > 16)
-       {
-         ret = -E2BIG;
-         break;
-       }
-      lp->his_number = wrq->u.data.length;
+       case SIOCSIPHISTO:
+               /* Verify that the user is root. */
+               if (!suser()) {
+                       ret = -EPERM;
+                       break;
+               }
+
+               /* Check the number of intervals. */
+               if (wrq->u.data.length > 16) {
+                       ret = -E2BIG;
+                       break;
+               }
+               lp->his_number = wrq->u.data.length;
+
+               /* Are there addresses to copy? */
+               if (lp->his_number > 0) {
+                       /* Copy interval ranges to the driver */
+                       if (copy_from_user
+                           (lp->his_range, wrq->u.data.pointer,
+                            sizeof(char) * lp->his_number)) {
+                               ret = -EFAULT;
+                               break;
+                       }
+
+                       /* Reset structure. */
+                       memset(lp->his_sum, 0x00, sizeof(long) * 16);
+               }
+               break;
+
+       case SIOCGIPHISTO:
+               /* Set the number of intervals. */
+               wrq->u.data.length = lp->his_number;
+
+               /* Give back the distribution statistics */
+               if ((lp->his_number > 0)
+                   && (wrq->u.data.pointer != (caddr_t) 0)) {
+                       /* Copy data to the user buffer. */
+                       if (copy_to_user
+                           (wrq->u.data.pointer, lp->his_sum,
+                            sizeof(long) * lp->his_number))
+                               ret = -EFAULT;
+
+               }               /* if(pointer != NULL) */
+               break;
+#endif                         /* HISTOGRAM */
+
+               /* ------------------- OTHER IOCTL ------------------- */
 
-      /* Are there addresses to copy? */
-      if(lp->his_number > 0)
-       {
-         /* Copy interval ranges to the driver */
-         if (copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number)) {
-               ret = -EFAULT;
-               break;
-         }
-
-         /* Reset structure. */
-         memset(lp->his_sum, 0x00, sizeof(long) * 16);
+       default:
+               ret = -EOPNOTSUPP;
        }
-      break;
-
-    case SIOCGIPHISTO:
-      /* Set the number of intervals. */
-      wrq->u.data.length = lp->his_number;
-
-      /* Give back the distribution statistics */
-      if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
-       {
-         /* Copy data to the user buffer. */
-         if (copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number)) 
-                       ret = -EFAULT;
-                       
-       }       /* if(pointer != NULL) */
-      break;
-#endif /* HISTOGRAM */
 
-      /* ------------------- OTHER IOCTL ------------------- */
-
-    default:
-      ret = -EOPNOTSUPP;
-    }
-
-  /* Enable interrupts and restore flags. */
-  wv_splx(x);
+       /* Enable interrupts and restore flags. */
+       restore_flags(flags);
 
 #ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
 #endif
-  return ret;
+       return ret;
 }
 
 /*------------------------------------------------------------------*/
@@ -2351,56 +2285,64 @@ wavelan_ioctl(struct net_device *       dev,    /* device on which the ioctl is applied *
  * Get wireless statistics.
  * Called by /proc/net/wireless
  */
-static iw_stats *
-wavelan_get_wireless_stats(device *    dev)
+static iw_stats *wavelan_get_wireless_stats(device * dev)
 {
-  u_long               ioaddr = dev->base_addr;
-  net_local *          lp = (net_local *) dev->priv;
-  mmr_t                        m;
-  iw_stats *           wstats;
-  unsigned long                x;
+       unsigned long ioaddr = dev->base_addr;
+       net_local *lp = (net_local *) dev->priv;
+       mmr_t m;
+       iw_stats *wstats;
+       unsigned long flags;
 
 #ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n",
+              dev->name);
 #endif
 
-  /* Disable interrupts and save flags. */
-  x = wv_splhi();
-
-  if(lp == (net_local *) NULL)
-    return (iw_stats *) NULL;
-  wstats = &lp->wstats;
-
-  /* Get data from the mmc. */
-  mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
-
-  mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1);
-  mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, 2);
-  mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, 4);
-
-  mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
-
-  /* Copy data to wireless stuff. */
-  wstats->status = m.mmr_dce_status & MMR_DCE_STATUS;
-  wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL;
-  wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL;
-  wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL;
-  wstats->qual.updated = (((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) |
-                         ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) |
-                         ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5));
-  wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-  wstats->discard.code = 0L;
-  wstats->discard.misc = 0L;
-
-  /* Enable interrupts and restore flags. */
-  wv_splx(x);
+       /* Disable interrupts and save flags. */
+       save_flags(flags);
+       cli();
+       
+       if (lp == (net_local *) NULL)
+       {
+               restore_flags(flags);
+               return (iw_stats *) NULL;
+       }
+       
+       wstats = &lp->wstats;
+
+       /* Get data from the mmc. */
+       mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
+
+       mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1);
+       mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l,
+                2);
+       mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set,
+                4);
+
+       mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
+
+       /* Copy data to wireless stuff. */
+       wstats->status = m.mmr_dce_status & MMR_DCE_STATUS;
+       wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL;
+       wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL;
+       wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL;
+       wstats->qual.updated = (((m. mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) 
+                       | ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) 
+                       | ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5));
+       wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
+       wstats->discard.code = 0L;
+       wstats->discard.misc = 0L;
+
+       /* Enable interrupts and restore flags. */
+       restore_flags(flags);
 
 #ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n",
+              dev->name);
 #endif
-  return &lp->wstats;
+       return &lp->wstats;
 }
-#endif /* WIRELESS_EXT */
+#endif                         /* WIRELESS_EXT */
 
 /************************* PACKET RECEPTION *************************/
 /*
@@ -2423,90 +2365,90 @@ wavelan_get_wireless_stats(device *     dev)
  * (called by wv_packet_rcv())
  */
 static inline void
-wv_packet_read(device *                dev,
-              u_short          buf_off,
-              int              sksize)
+wv_packet_read(device * dev, u16 buf_off, int sksize)
 {
-  net_local *          lp = (net_local *) dev->priv;
-  u_long               ioaddr = dev->base_addr;
-  struct sk_buff *     skb;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       struct sk_buff *skb;
 
 #ifdef DEBUG_RX_TRACE
-  printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n",
-        dev->name, buf_off, sksize);
+       printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n",
+              dev->name, buf_off, sksize);
 #endif
 
-  /* Allocate buffer for the data */
-  if((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL)
-    {
+       /* Allocate buffer for the data */
+       if ((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL) {
 #ifdef DEBUG_RX_ERROR
-      printk(KERN_INFO "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n",
-            dev->name, sksize);
+               printk(KERN_INFO
+                      "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n",
+                      dev->name, sksize);
 #endif
-      lp->stats.rx_dropped++;
-      return;
-    }
+               lp->stats.rx_dropped++;
+               return;
+       }
 
-  skb->dev = dev;
+       skb->dev = dev;
 
-  /* Copy the packet to the buffer. */
-  obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize);
-  skb->protocol=eth_type_trans(skb, dev);
+       /* Copy the packet to the buffer. */
+       obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize);
+       skb->protocol = eth_type_trans(skb, dev);
 
 #ifdef DEBUG_RX_INFO
-  wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read");
-#endif /* DEBUG_RX_INFO */
+       wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read");
+#endif                         /* DEBUG_RX_INFO */
 
-  /* Statistics-gathering and associated stuff.
-   * It seem a bit messy with all the define, but it's really simple... */
+       /* Statistics-gathering and associated stuff.
+        * It seem a bit messy with all the define, but it's really simple... */
 #if defined(WIRELESS_SPY) || defined(HISTOGRAM)
-  if(
+       if (
 #ifdef WIRELESS_SPY
-     (lp->spy_number > 0) ||
-#endif /* WIRELESS_SPY */
+                  (lp->spy_number > 0) ||
+#endif                         /* WIRELESS_SPY */
 #ifdef HISTOGRAM
-     (lp->his_number > 0) ||
-#endif /* HISTOGRAM */
-     0)
-    {
-      u_char   stats[3];       /* signal level, noise level, signal quality */
-
-      /* Read signal level, silence level and signal quality bytes. */
-      /* Note: in the PCMCIA hardware, these are part of the frame.  It seems
-       * that for the ISA hardware, it's nowhere to be found in the frame,
-       * so I'm obliged to do this (it has a side effect on /proc/net/wireless).
-       * Any ideas?
-       */
-      mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
-      mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3);
-      mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
+                  (lp->his_number > 0) ||
+#endif                         /* HISTOGRAM */
+                  0) {
+               u8 stats[3];    /* signal level, noise level, signal quality */
+
+               /* Read signal level, silence level and signal quality bytes. */
+               /* Note: in the PCMCIA hardware, these are part of the frame.  It seems
+                * that for the ISA hardware, it's nowhere to be found in the frame,
+                * so I'm obliged to do this (it has a side effect on /proc/net/wireless).
+                * Any ideas?
+                */
+               mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
+               mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3);
+               mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
 
 #ifdef DEBUG_RX_INFO
-      printk(KERN_DEBUG "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n",
-            dev->name, stats[0] & 0x3F, stats[1] & 0x3F, stats[2] & 0x0F);
+               printk(KERN_DEBUG
+                      "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n",
+                      dev->name, stats[0] & 0x3F, stats[1] & 0x3F,
+                      stats[2] & 0x0F);
 #endif
 
-      /* Spying stuff */
+               /* Spying stuff */
 #ifdef WIRELESS_SPY
-      wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats);
-#endif /* WIRELESS_SPY */
+               wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE,
+                             stats);
+#endif                         /* WIRELESS_SPY */
 #ifdef HISTOGRAM
-      wl_his_gather(dev, stats);
-#endif /* HISTOGRAM */
-    }
-#endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */
+               wl_his_gather(dev, stats);
+#endif                         /* HISTOGRAM */
+       }
+#endif                         /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */
 
-  /*
-   * Hand the packet to the network module.
-   */
-  netif_rx(skb);
+       /*
+        * Hand the packet to the network module.
+        */
+       netif_rx(skb);
 
-  /* Keep statistics up to date */
-  lp->stats.rx_packets++;
-  lp->stats.rx_bytes += skb->len;
+       /* Keep statistics up to date */
+       lp->stats.rx_packets++;
+       lp->stats.rx_bytes += skb->len;
 
 #ifdef DEBUG_RX_TRACE
-  printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
 #endif
 }
 
@@ -2516,150 +2458,160 @@ wv_packet_read(device *               dev,
  * from the device RAM.
  * Called by the interrupt handler.
  */
-static inline void
-wv_receive(device *    dev)
+static inline void wv_receive(device * dev)
 {
-  u_long       ioaddr = dev->base_addr;
-  net_local *  lp = (net_local *)dev->priv;
-  fd_t         fd;
-  rbd_t                rbd;
-  int          nreaped = 0;
+       unsigned long ioaddr = dev->base_addr;
+       net_local *lp = (net_local *) dev->priv;
+       fd_t fd;
+       rbd_t rbd;
+       int nreaped = 0;
 
 #ifdef DEBUG_RX_TRACE
-  printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name);
 #endif
 
-  /* Loop on each received packet. */
-  for(;;)
-    {
-      obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd));
-
-      /* Note about the status :
-       * It start up to be 0 (the value we set). Then, when the RU
-       * grab the buffer to prepare for reception, it sets the
-       * FD_STATUS_B flag. When the RU has finished receiving the
-       * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate
-       * completion and set the other flags to indicate the eventual
-       * errors. FD_STATUS_OK indicates that the reception was OK.
-       */
-
-      /* If the current frame is not complete, we have reached the end. */
-      if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C)
-       break;          /* This is how we exit the loop. */
-
-      nreaped++;
-
-      /* Check whether frame was correctly received. */
-      if((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK)
-       {
-         /* Does the frame contain a pointer to the data?  Let's check. */
-         if(fd.fd_rbd_offset != I82586NULL)
-           {
-             /* Read the receive buffer descriptor */
-             obram_read(ioaddr, fd.fd_rbd_offset,
-                        (unsigned char *) &rbd, sizeof(rbd));
+       /* Loop on each received packet. */
+       for (;;) {
+               obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd,
+                          sizeof(fd));
+
+               /* Note about the status :
+                * It start up to be 0 (the value we set). Then, when the RU
+                * grab the buffer to prepare for reception, it sets the
+                * FD_STATUS_B flag. When the RU has finished receiving the
+                * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate
+                * completion and set the other flags to indicate the eventual
+                * errors. FD_STATUS_OK indicates that the reception was OK.
+                */
+
+               /* If the current frame is not complete, we have reached the end. */
+               if ((fd.fd_status & FD_STATUS_C) != FD_STATUS_C)
+                       break;  /* This is how we exit the loop. */
+
+               nreaped++;
+
+               /* Check whether frame was correctly received. */
+               if ((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK) {
+                       /* Does the frame contain a pointer to the data?  Let's check. */
+                       if (fd.fd_rbd_offset != I82586NULL) {
+                               /* Read the receive buffer descriptor */
+                               obram_read(ioaddr, fd.fd_rbd_offset,
+                                          (unsigned char *) &rbd,
+                                          sizeof(rbd));
 
 #ifdef DEBUG_RX_ERROR
-             if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF)
-               printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n",
-                      dev->name);
-
-             if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F)
-               printk(KERN_INFO "%s: wv_receive(): missing F flag.\n",
-                      dev->name);
-#endif /* DEBUG_RX_ERROR */
-
-             /* Read the packet and transmit to Linux */
-             wv_packet_read(dev, rbd.rbd_bufl,
-                            rbd.rbd_status & RBD_STATUS_ACNT);
-           }
+                               if ((rbd.rbd_status & RBD_STATUS_EOF) !=
+                                   RBD_STATUS_EOF) printk(KERN_INFO
+                                                          "%s: wv_receive(): missing EOF flag.\n",
+                                                          dev->name);
+
+                               if ((rbd.rbd_status & RBD_STATUS_F) !=
+                                   RBD_STATUS_F) printk(KERN_INFO
+                                                        "%s: wv_receive(): missing F flag.\n",
+                                                        dev->name);
+#endif                         /* DEBUG_RX_ERROR */
+
+                               /* Read the packet and transmit to Linux */
+                               wv_packet_read(dev, rbd.rbd_bufl,
+                                              rbd.
+                                              rbd_status &
+                                              RBD_STATUS_ACNT);
+                       }
 #ifdef DEBUG_RX_ERROR
-         else  /* if frame has no data */
-           printk(KERN_INFO "%s: wv_receive(): frame has no data.\n",
-                  dev->name);
+                       else    /* if frame has no data */
+                               printk(KERN_INFO
+                                      "%s: wv_receive(): frame has no data.\n",
+                                      dev->name);
 #endif
-       }
-      else     /* If reception was no successful */
-       {
-         lp->stats.rx_errors++;
+               } else {        /* If reception was no successful */
+
+                       lp->stats.rx_errors++;
 
 #ifdef DEBUG_RX_INFO
-         printk(KERN_DEBUG "%s: wv_receive(): frame not received successfully (%X).\n",
-                dev->name, fd.fd_status);
+                       printk(KERN_DEBUG
+                              "%s: wv_receive(): frame not received successfully (%X).\n",
+                              dev->name, fd.fd_status);
 #endif
 
 #ifdef DEBUG_RX_ERROR
-         if((fd.fd_status & FD_STATUS_S6) != 0)
-           printk(KERN_INFO "%s: wv_receive(): no EOF flag.\n", dev->name);
+                       if ((fd.fd_status & FD_STATUS_S6) != 0)
+                               printk(KERN_INFO
+                                      "%s: wv_receive(): no EOF flag.\n",
+                                      dev->name);
 #endif
 
-         if((fd.fd_status & FD_STATUS_S7) != 0)
-           {
-             lp->stats.rx_length_errors++;
+                       if ((fd.fd_status & FD_STATUS_S7) != 0) {
+                               lp->stats.rx_length_errors++;
 #ifdef DEBUG_RX_FAIL
-             printk(KERN_DEBUG "%s: wv_receive(): frame too short.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_receive(): frame too short.\n",
+                                      dev->name);
 #endif
-           }
+                       }
 
-         if((fd.fd_status & FD_STATUS_S8) != 0)
-           {
-             lp->stats.rx_over_errors++;
+                       if ((fd.fd_status & FD_STATUS_S8) != 0) {
+                               lp->stats.rx_over_errors++;
 #ifdef DEBUG_RX_FAIL
-             printk(KERN_DEBUG "%s: wv_receive(): rx DMA overrun.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_receive(): rx DMA overrun.\n",
+                                      dev->name);
 #endif
-           }
+                       }
 
-         if((fd.fd_status & FD_STATUS_S9) != 0)
-           {
-             lp->stats.rx_fifo_errors++;
+                       if ((fd.fd_status & FD_STATUS_S9) != 0) {
+                               lp->stats.rx_fifo_errors++;
 #ifdef DEBUG_RX_FAIL
-             printk(KERN_DEBUG "%s: wv_receive(): ran out of resources.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_receive(): ran out of resources.\n",
+                                      dev->name);
 #endif
-           }
+                       }
 
-         if((fd.fd_status & FD_STATUS_S10) != 0)
-           {
-             lp->stats.rx_frame_errors++;
+                       if ((fd.fd_status & FD_STATUS_S10) != 0) {
+                               lp->stats.rx_frame_errors++;
 #ifdef DEBUG_RX_FAIL
-             printk(KERN_DEBUG "%s: wv_receive(): alignment error.\n",
-                    dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_receive(): alignment error.\n",
+                                      dev->name);
 #endif
-           }
+                       }
 
-         if((fd.fd_status & FD_STATUS_S11) != 0)
-           {
-             lp->stats.rx_crc_errors++;
+                       if ((fd.fd_status & FD_STATUS_S11) != 0) {
+                               lp->stats.rx_crc_errors++;
 #ifdef DEBUG_RX_FAIL
-             printk(KERN_DEBUG "%s: wv_receive(): CRC error.\n", dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: wv_receive(): CRC error.\n",
+                                      dev->name);
 #endif
-           }
-       }
+                       }
+               }
 
-      fd.fd_status = 0;
-      obram_write(ioaddr, fdoff(lp->rx_head, fd_status),
-                 (unsigned char *) &fd.fd_status, sizeof(fd.fd_status));
+               fd.fd_status = 0;
+               obram_write(ioaddr, fdoff(lp->rx_head, fd_status),
+                           (unsigned char *) &fd.fd_status,
+                           sizeof(fd.fd_status));
 
-      fd.fd_command = FD_COMMAND_EL;
-      obram_write(ioaddr, fdoff(lp->rx_head, fd_command),
-                 (unsigned char *) &fd.fd_command, sizeof(fd.fd_command));
+               fd.fd_command = FD_COMMAND_EL;
+               obram_write(ioaddr, fdoff(lp->rx_head, fd_command),
+                           (unsigned char *) &fd.fd_command,
+                           sizeof(fd.fd_command));
 
-      fd.fd_command = 0;
-      obram_write(ioaddr, fdoff(lp->rx_last, fd_command),
-                 (unsigned char *) &fd.fd_command, sizeof(fd.fd_command));
+               fd.fd_command = 0;
+               obram_write(ioaddr, fdoff(lp->rx_last, fd_command),
+                           (unsigned char *) &fd.fd_command,
+                           sizeof(fd.fd_command));
 
-      lp->rx_last = lp->rx_head;
-      lp->rx_head = fd.fd_link_offset;
-    }  /* for(;;) -> loop on all frames */
+               lp->rx_last = lp->rx_head;
+               lp->rx_head = fd.fd_link_offset;
+       }                       /* for(;;) -> loop on all frames */
 
 #ifdef DEBUG_RX_INFO
-  if(nreaped > 1)
-    printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n", dev->name, nreaped);
+       if (nreaped > 1)
+               printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n",
+                      dev->name, nreaped);
 #endif
 #ifdef DEBUG_RX_TRACE
-  printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name);
 #endif
 }
 
@@ -2689,130 +2641,124 @@ wv_receive(device *   dev)
  *
  * (called in wavelan_packet_xmit())
  */
-static inline void
-wv_packet_write(device *       dev,
-               void *  buf,
-               short   length)
+static inline void wv_packet_write(device * dev, void *buf, short length)
 {
-  net_local *          lp = (net_local *) dev->priv;
-  u_long               ioaddr = dev->base_addr;
-  unsigned short       txblock;
-  unsigned short       txpred;
-  unsigned short       tx_addr;
-  unsigned short       nop_addr;
-  unsigned short       tbd_addr;
-  unsigned short       buf_addr;
-  ac_tx_t              tx;
-  ac_nop_t             nop;
-  tbd_t                        tbd;
-  int                  clen = length;
-  unsigned long                x;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       unsigned short txblock;
+       unsigned short txpred;
+       unsigned short tx_addr;
+       unsigned short nop_addr;
+       unsigned short tbd_addr;
+       unsigned short buf_addr;
+       ac_tx_t tx;
+       ac_nop_t nop;
+       tbd_t tbd;
+       int clen = length;
+       unsigned long flags;
 
 #ifdef DEBUG_TX_TRACE
-  printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length);
+       printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name,
+              length);
 #endif
 
-  /* Do we need some padding? */
-  if(clen < ETH_ZLEN)
-    clen = ETH_ZLEN;
+       /* Do we need some padding? */
+       if (clen < ETH_ZLEN)
+               clen = ETH_ZLEN;
+
+       save_flags(flags);
+       cli();
+       
+       /* Calculate addresses of next block and previous block. */
+       txblock = lp->tx_first_free;
+       txpred = txblock - TXBLOCKZ;
+       if (txpred < OFFSET_CU)
+               txpred += NTXBLOCKS * TXBLOCKZ;
+       lp->tx_first_free += TXBLOCKZ;
+       if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
+               lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
+
+       lp->tx_n_in_use++;
+
+       /* Calculate addresses of the different parts of the block. */
+       tx_addr = txblock;
+       nop_addr = tx_addr + sizeof(tx);
+       tbd_addr = nop_addr + sizeof(nop);
+       buf_addr = tbd_addr + sizeof(tbd);
 
-  x = wv_splhi();
+       /*
+        * Transmit command
+        */
+       tx.tx_h.ac_status = 0;
+       obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
+                   (unsigned char *) &tx.tx_h.ac_status,
+                   sizeof(tx.tx_h.ac_status));
 
-  /* Calculate addresses of next block and previous block. */
-  txblock = lp->tx_first_free;
-  txpred = txblock - TXBLOCKZ;
-  if(txpred < OFFSET_CU)
-    txpred += NTXBLOCKS * TXBLOCKZ;
-  lp->tx_first_free += TXBLOCKZ;
-  if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
-    lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
+       /*
+        * NOP command
+        */
+       nop.nop_h.ac_status = 0;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+                   (unsigned char *) &nop.nop_h.ac_status,
+                   sizeof(nop.nop_h.ac_status));
+       nop.nop_h.ac_link = nop_addr;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+                   (unsigned char *) &nop.nop_h.ac_link,
+                   sizeof(nop.nop_h.ac_link));
 
-/*
-if (lp->tx_n_in_use > 0)
-       printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]);
-*/
+       /*
+        * Transmit buffer descriptor
+        */
+       tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen);
+       tbd.tbd_next_bd_offset = I82586NULL;
+       tbd.tbd_bufl = buf_addr;
+       tbd.tbd_bufh = 0;
+       obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd));
+
+       /*
+        * Data
+        */
+       obram_write(ioaddr, buf_addr, buf, length);
+
+       /*
+        * Overwrite the predecessor NOP link
+        * so that it points to this txblock.
+        */
+       nop_addr = txpred + sizeof(tx);
+       nop.nop_h.ac_status = 0;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+                   (unsigned char *) &nop.nop_h.ac_status,
+                   sizeof(nop.nop_h.ac_status));
+       nop.nop_h.ac_link = txblock;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+                   (unsigned char *) &nop.nop_h.ac_link,
+                   sizeof(nop.nop_h.ac_link));
+
+       /* Keep stats up to date. */
+       lp->stats.tx_bytes += length;
+
+       /* If watchdog not already active, activate it... */
+       if (lp->watchdog.prev == (timer_list *) NULL) {
+               /* Set timer to expire in WATCHDOG_JIFFIES. */
+               lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+               add_timer(&lp->watchdog);
+       }
 
-  lp->tx_n_in_use++;
-
-  /* Calculate addresses of the different parts of the block. */
-  tx_addr = txblock;
-  nop_addr = tx_addr + sizeof(tx);
-  tbd_addr = nop_addr + sizeof(nop);
-  buf_addr = tbd_addr + sizeof(tbd);
-
-  /*
-   * Transmit command
-   */
-  tx.tx_h.ac_status = 0;
-  obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
-             (unsigned char *) &tx.tx_h.ac_status,
-             sizeof(tx.tx_h.ac_status));
-
-  /*
-   * NOP command
-   */
-  nop.nop_h.ac_status = 0;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
-             (unsigned char *) &nop.nop_h.ac_status,
-             sizeof(nop.nop_h.ac_status));
-  nop.nop_h.ac_link = nop_addr;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
-             (unsigned char *) &nop.nop_h.ac_link,
-             sizeof(nop.nop_h.ac_link));
-
-  /*
-   * Transmit buffer descriptor
-   */
-  tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen);
-  tbd.tbd_next_bd_offset = I82586NULL;
-  tbd.tbd_bufl = buf_addr;
-  tbd.tbd_bufh = 0;
-  obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd));
-
-  /*
-   * Data
-   */
-  obram_write(ioaddr, buf_addr, buf, length);
-
-  /*
-   * Overwrite the predecessor NOP link
-   * so that it points to this txblock.
-   */
-  nop_addr = txpred + sizeof(tx);
-  nop.nop_h.ac_status = 0;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
-             (unsigned char *)&nop.nop_h.ac_status,
-             sizeof(nop.nop_h.ac_status));
-  nop.nop_h.ac_link = txblock;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
-             (unsigned char *) &nop.nop_h.ac_link,
-             sizeof(nop.nop_h.ac_link));
-
-  /* Keep stats up to date. */
-  lp->stats.tx_bytes += length;
-
-  /* If watchdog not already active, activate it... */
-  if(lp->watchdog.prev == (timer_list *) NULL)
-    {
-      /* Set timer to expire in WATCHDOG_JIFFIES. */
-      lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
-      add_timer(&lp->watchdog);
-    }
-
-  if(lp->tx_first_in_use == I82586NULL)
-    lp->tx_first_in_use = txblock;
-
-  if(lp->tx_n_in_use < NTXBLOCKS - 1)
-    dev->tbusy = 0;
-
-  wv_splx(x);
+       if (lp->tx_first_in_use == I82586NULL)
+               lp->tx_first_in_use = txblock;
 
+       if (lp->tx_n_in_use < NTXBLOCKS - 1)
+               netif_wake_queue(dev);
+
+       restore_flags(flags);
+       
 #ifdef DEBUG_TX_INFO
-  wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write");
-#endif /* DEBUG_TX_INFO */
+       wv_packet_info((u8 *) buf, length, dev->name,
+                      "wv_packet_write");
+#endif                         /* DEBUG_TX_INFO */
 
 #ifdef DEBUG_TX_TRACE
-  printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
 #endif
 }
 
@@ -2823,59 +2769,41 @@ if (lp->tx_n_in_use > 0)
  * the packet.  We also prevent reentrance.  Then we call the function
  * to send the packet.
  */
-static int
-wavelan_packet_xmit(struct sk_buff *   skb,
-                   device *            dev)
+static int wavelan_packet_xmit(struct sk_buff *skb, device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
+       net_local *lp = (net_local *) dev->priv;
 
 #ifdef DEBUG_TX_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
-        (unsigned) skb);
+       printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
+              (unsigned) skb);
 #endif
 
-  /* This flag indicate that the hardware can't perform a transmission.
-   * Theoretically, NET3 checks it before sending a packet to the driver,
-   * but in fact it never does that and pools continuously.
-   * As the watchdog will abort overly long transmissions, we are quite safe.
-   */
-  if(dev->tbusy)
-    return 1;
-
-  /*
-   * Block a timer-based transmit from overlapping.
-   * In other words, prevent reentering this routine.
-   */
-  if(test_and_set_bit(0, (void *)&dev->tbusy) != 0)
-#ifdef DEBUG_TX_ERROR
-    printk(KERN_INFO "%s: Transmitter access conflict.\n", dev->name);
-#endif
-  else
-    {
-      /* If somebody has asked to reconfigure the controller, 
-       * we can do it now.
-       */
-      if(lp->reconfig_82586)
-       {
-         wv_82586_config(dev);
-         if(dev->tbusy)
-           return 1;
-       }
+       /*
+        * Block a timer-based transmit from overlapping.
+        * In other words, prevent reentering this routine.
+        */
 
+       netif_stop_queue(dev);
+
+       /* If somebody has asked to reconfigure the controller, 
+        * we can do it now.
+        */
+       if (lp->reconfig_82586) {
+               wv_82586_config(dev);
+       }
 #ifdef DEBUG_TX_ERROR
-      if(skb->next)
-       printk(KERN_INFO "skb has next\n");
+       if (skb->next)
+               printk(KERN_INFO "skb has next\n");
 #endif
 
-      wv_packet_write(dev, skb->data, skb->len);
-    }
+       wv_packet_write(dev, skb->data, skb->len);
 
-  dev_kfree_skb(skb);
+       dev_kfree_skb(skb);
 
 #ifdef DEBUG_TX_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*********************** HARDWARE CONFIGURATION ***********************/
@@ -2888,166 +2816,170 @@ wavelan_packet_xmit(struct sk_buff *  skb,
  * Routine to initialize the Modem Management Controller.
  * (called by wv_hw_reset())
  */
-static inline int
-wv_mmc_init(device *   dev)
+static inline int wv_mmc_init(device * dev)
 {
-  u_long       ioaddr = dev->base_addr;
-  net_local *  lp = (net_local *)dev->priv;
-  psa_t                psa;
-  mmw_t                m;
-  int          configured;
+       unsigned long ioaddr = dev->base_addr;
+       net_local *lp = (net_local *) dev->priv;
+       psa_t psa;
+       mmw_t m;
+       int configured;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name);
 #endif
 
-  /* Read the parameter storage area. */
-  psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
+       /* Read the parameter storage area. */
+       psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
 
 #ifdef USE_PSA_CONFIG
-  configured = psa.psa_conf_status & 1;
+       configured = psa.psa_conf_status & 1;
 #else
-  configured = 0;
+       configured = 0;
 #endif
 
-  /* Is the PSA is not configured */
-  if(!configured)
-    {
-      /* User will be able to configure NWID later (with iwconfig). */
-      psa.psa_nwid[0] = 0;
-      psa.psa_nwid[1] = 0;
-
-      /* no NWID checking since NWID is not set */
-      psa.psa_nwid_select = 0;
-
-      /* Disable encryption */
-      psa.psa_encryption_select = 0;
-
-      /* Set to standard values:
-       * 0x04 for AT,
-       * 0x01 for MCA,
-       * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document)
-       */
-      if (psa.psa_comp_number & 1)
-       psa.psa_thr_pre_set = 0x01;
-      else
-       psa.psa_thr_pre_set = 0x04;
-      psa.psa_quality_thr = 0x03;
-
-      /* It is configured */
-      psa.psa_conf_status |= 1;
+       /* Is the PSA is not configured */
+       if (!configured) {
+               /* User will be able to configure NWID later (with iwconfig). */
+               psa.psa_nwid[0] = 0;
+               psa.psa_nwid[1] = 0;
+
+               /* no NWID checking since NWID is not set */
+               psa.psa_nwid_select = 0;
+
+               /* Disable encryption */
+               psa.psa_encryption_select = 0;
+
+               /* Set to standard values:
+                * 0x04 for AT,
+                * 0x01 for MCA,
+                * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document)
+                */
+               if (psa.psa_comp_number & 1)
+                       psa.psa_thr_pre_set = 0x01;
+               else
+                       psa.psa_thr_pre_set = 0x04;
+               psa.psa_quality_thr = 0x03;
+
+               /* It is configured */
+               psa.psa_conf_status |= 1;
 
 #ifdef USE_PSA_CONFIG
-      /* Write the psa. */
-      psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
-               (unsigned char *)psa.psa_nwid, 4);
-      psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
-               (unsigned char *)&psa.psa_thr_pre_set, 1);
-      psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
-               (unsigned char *)&psa.psa_quality_thr, 1);
-      psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa,
-               (unsigned char *)&psa.psa_conf_status, 1);
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev, ioaddr, lp->hacr);
+               /* Write the psa. */
+               psa_write(ioaddr, lp->hacr,
+                         (char *) psa.psa_nwid - (char *) &psa,
+                         (unsigned char *) psa.psa_nwid, 4);
+               psa_write(ioaddr, lp->hacr,
+                         (char *) &psa.psa_thr_pre_set - (char *) &psa,
+                         (unsigned char *) &psa.psa_thr_pre_set, 1);
+               psa_write(ioaddr, lp->hacr,
+                         (char *) &psa.psa_quality_thr - (char *) &psa,
+                         (unsigned char *) &psa.psa_quality_thr, 1);
+               psa_write(ioaddr, lp->hacr,
+                         (char *) &psa.psa_conf_status - (char *) &psa,
+                         (unsigned char *) &psa.psa_conf_status, 1);
+               /* update the Wavelan checksum */
+               update_psa_checksum(dev, ioaddr, lp->hacr);
 #endif
-    }
-
-  /* Zero the mmc structure. */
-  memset(&m, 0x00, sizeof(m));
-
-  /* Copy PSA info to the mmc. */
-  m.mmw_netw_id_l = psa.psa_nwid[1];
-  m.mmw_netw_id_h = psa.psa_nwid[0];
-  
-  if(psa.psa_nwid_select & 1)
-    m.mmw_loopt_sel = 0x00;
-  else
-    m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
-
-  memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, 
-        sizeof(m.mmw_encr_key));
-
-  if(psa.psa_encryption_select)
-    m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
-  else
-    m.mmw_encr_enable = 0;
-
-  m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
-  m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
-
-  /*
-   * Set default modem control parameters.
-   * See NCR document 407-0024326 Rev. A.
-   */
-  m.mmw_jabber_enable = 0x01;
-  m.mmw_freeze = 0;
-  m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN;
-  m.mmw_ifs = 0x20;
-  m.mmw_mod_delay = 0x04;
-  m.mmw_jam_time = 0x38;
-
-  m.mmw_des_io_invert = 0;
-  m.mmw_decay_prm = 0;
-  m.mmw_decay_updat_prm = 0;
-
-  /* Write all info to MMC. */
-  mmc_write(ioaddr, 0, (u_char *)&m, sizeof(m));
-
-  /* The following code starts the modem of the 2.00 frequency
-   * selectable cards at power on.  It's not strictly needed for the
-   * following boots.
-   * The original patch was by Joe Finney for the PCMCIA driver, but
-   * I've cleaned it up a bit and added documentation.
-   * Thanks to Loeke Brederveld from Lucent for the info.
-   */
-
-  /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
-   * Does it work for everybody, especially old cards? */
-  /* Note: WFREQSEL verifies that it is able to read a sensible
-   * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID
-   * is 0xA (Xilinx version) or 0xB (Ariadne version).
-   * My test is more crude but does work. */
-  if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-       (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-    {
-      /* We must download the frequency parameters to the
-       * synthesizers (from the EEPROM - area 1)
-       * Note: as the EEPROM is automatically decremented, we set the end
-       * if the area... */
-      m.mmw_fee_addr = 0x0F;
-      m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
-      mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m,
-               (unsigned char *)&m.mmw_fee_ctrl, 2);
-
-      /* Wait until the download is finished. */
-      fee_wait(ioaddr, 100, 100);
+       }
+
+       /* Zero the mmc structure. */
+       memset(&m, 0x00, sizeof(m));
+
+       /* Copy PSA info to the mmc. */
+       m.mmw_netw_id_l = psa.psa_nwid[1];
+       m.mmw_netw_id_h = psa.psa_nwid[0];
+
+       if (psa.psa_nwid_select & 1)
+               m.mmw_loopt_sel = 0x00;
+       else
+               m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
+
+       memcpy(&m.mmw_encr_key, &psa.psa_encryption_key,
+              sizeof(m.mmw_encr_key));
+
+       if (psa.psa_encryption_select)
+               m.mmw_encr_enable =
+                   MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
+       else
+               m.mmw_encr_enable = 0;
+
+       m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
+       m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
+
+       /*
+        * Set default modem control parameters.
+        * See NCR document 407-0024326 Rev. A.
+        */
+       m.mmw_jabber_enable = 0x01;
+       m.mmw_freeze = 0;
+       m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN;
+       m.mmw_ifs = 0x20;
+       m.mmw_mod_delay = 0x04;
+       m.mmw_jam_time = 0x38;
+
+       m.mmw_des_io_invert = 0;
+       m.mmw_decay_prm = 0;
+       m.mmw_decay_updat_prm = 0;
+
+       /* Write all info to MMC. */
+       mmc_write(ioaddr, 0, (u8 *) & m, sizeof(m));
+
+       /* The following code starts the modem of the 2.00 frequency
+        * selectable cards at power on.  It's not strictly needed for the
+        * following boots.
+        * The original patch was by Joe Finney for the PCMCIA driver, but
+        * I've cleaned it up a bit and added documentation.
+        * Thanks to Loeke Brederveld from Lucent for the info.
+        */
+
+       /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
+        * Does it work for everybody, especially old cards? */
+       /* Note: WFREQSEL verifies that it is able to read a sensible
+        * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID
+        * is 0xA (Xilinx version) or 0xB (Ariadne version).
+        * My test is more crude but does work. */
+       if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+             (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+               /* We must download the frequency parameters to the
+                * synthesizers (from the EEPROM - area 1)
+                * Note: as the EEPROM is automatically decremented, we set the end
+                * if the area... */
+               m.mmw_fee_addr = 0x0F;
+               m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
+               mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m,
+                         (unsigned char *) &m.mmw_fee_ctrl, 2);
+
+               /* Wait until the download is finished. */
+               fee_wait(ioaddr, 100, 100);
 
 #ifdef DEBUG_CONFIG_INFO
-      /* The frequency was in the last word downloaded. */
-      mmc_read(ioaddr, (char *)&m.mmw_fee_data_l - (char *)&m,
-              (unsigned char *)&m.mmw_fee_data_l, 2);
-
-      /* Print some info for the user. */
-      printk(KERN_DEBUG "%s: WaveLAN 2.00 recognised (frequency select).  Current frequency = %ld\n",
-            dev->name,
-            ((m.mmw_fee_data_h << 4) |
-             (m.mmw_fee_data_l >> 4)) * 5 / 2 + 24000L);
+               /* The frequency was in the last word downloaded. */
+               mmc_read(ioaddr, (char *) &m.mmw_fee_data_l - (char *) &m,
+                        (unsigned char *) &m.mmw_fee_data_l, 2);
+
+               /* Print some info for the user. */
+               printk(KERN_DEBUG
+                      "%s: WaveLAN 2.00 recognised (frequency select).  Current frequency = %ld\n",
+                      dev->name,
+                      ((m.
+                        mmw_fee_data_h << 4) | (m.mmw_fee_data_l >> 4)) *
+                      5 / 2 + 24000L);
 #endif
 
-      /* We must now download the power adjust value (gain) to
-       * the synthesizers (from the EEPROM - area 7 - DAC). */
-      m.mmw_fee_addr = 0x61;
-      m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
-      mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m,
-               (unsigned char *)&m.mmw_fee_ctrl, 2);
-
-      /* Wait until the download is finished. */
-    }  /* if 2.00 card */
+               /* We must now download the power adjust value (gain) to
+                * the synthesizers (from the EEPROM - area 7 - DAC). */
+               m.mmw_fee_addr = 0x61;
+               m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
+               mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m,
+                         (unsigned char *) &m.mmw_fee_ctrl, 2);
 
+               /* Wait until the download is finished. */
+       }
+       /* if 2.00 card */
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -3056,81 +2988,79 @@ wv_mmc_init(device *    dev)
  * Start the receive unit.
  * (called by wv_hw_reset())
  */
-static inline int
-wv_ru_start(device *   dev)
+static inline int wv_ru_start(device * dev)
 {
-  net_local *  lp = (net_local *) dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  u_short      scb_cs;
-  fd_t         fd;
-  rbd_t                rbd;
-  u_short      rx;
-  u_short      rx_next;
-  int          i;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       u16 scb_cs;
+       fd_t fd;
+       rbd_t rbd;
+       u16 rx;
+       u16 rx_next;
+       int i;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name);
 #endif
 
-  obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs));
-  if((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY)
-    return 0;
+       obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
+                  (unsigned char *) &scb_cs, sizeof(scb_cs));
+       if ((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY)
+               return 0;
 
-  lp->rx_head = OFFSET_RU;
+       lp->rx_head = OFFSET_RU;
 
-  for(i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next)
-    {
-      rx_next = (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ;
+       for (i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) {
+               rx_next =
+                   (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ;
 
-      fd.fd_status = 0;
-      fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0;
-      fd.fd_link_offset = rx_next;
-      fd.fd_rbd_offset = rx + sizeof(fd);
-      obram_write(ioaddr, rx, (unsigned char *)&fd, sizeof(fd));
+               fd.fd_status = 0;
+               fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0;
+               fd.fd_link_offset = rx_next;
+               fd.fd_rbd_offset = rx + sizeof(fd);
+               obram_write(ioaddr, rx, (unsigned char *) &fd, sizeof(fd));
 
-      rbd.rbd_status = 0;
-      rbd.rbd_next_rbd_offset = I82586NULL;
-      rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd);
-      rbd.rbd_bufh = 0;
-      rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ);
-      obram_write(ioaddr, rx + sizeof(fd),
-                 (unsigned char *) &rbd, sizeof(rbd));
+               rbd.rbd_status = 0;
+               rbd.rbd_next_rbd_offset = I82586NULL;
+               rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd);
+               rbd.rbd_bufh = 0;
+               rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ);
+               obram_write(ioaddr, rx + sizeof(fd),
+                           (unsigned char *) &rbd, sizeof(rbd));
 
-      lp->rx_last = rx;
-    }
+               lp->rx_last = rx;
+       }
 
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset),
-             (unsigned char *) &lp->rx_head, sizeof(lp->rx_head));
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset),
+                   (unsigned char *) &lp->rx_head, sizeof(lp->rx_head));
 
-  scb_cs = SCB_CMD_RUC_GO;
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
-             (unsigned char *) &scb_cs, sizeof(scb_cs));
+       scb_cs = SCB_CMD_RUC_GO;
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+                   (unsigned char *) &scb_cs, sizeof(scb_cs));
 
-  set_chan_attn(ioaddr, lp->hacr);
+       set_chan_attn(ioaddr, lp->hacr);
 
-  for(i = 1000; i > 0; i--)
-    {
-      obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
-                (unsigned char *) &scb_cs, sizeof(scb_cs));
-      if (scb_cs == 0)
-       break;
+       for (i = 1000; i > 0; i--) {
+               obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
+                          (unsigned char *) &scb_cs, sizeof(scb_cs));
+               if (scb_cs == 0)
+                       break;
 
-      udelay(10);
-    }
+               udelay(10);
+       }
 
-  if(i <= 0)
-    {
+       if (i <= 0) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: wavelan_ru_start(): board not accepting command.\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wavelan_ru_start(): board not accepting command.\n",
+                      dev->name);
 #endif
-      return -1;
-    }
-
+               return -1;
+       }
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -3150,94 +3080,93 @@ wv_ru_start(device *    dev)
  *
  * (called by wv_hw_reset())
  */
-static inline int
-wv_cu_start(device *   dev)
+static inline int wv_cu_start(device * dev)
 {
-  net_local *  lp = (net_local *) dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  int          i;
-  u_short      txblock;
-  u_short      first_nop;
-  u_short      scb_cs;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       int i;
+       u16 txblock;
+       u16 first_nop;
+       u16 scb_cs;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name);
 #endif
 
-  lp->tx_first_free = OFFSET_CU;
-  lp->tx_first_in_use = I82586NULL;
-
-  for(i = 0, txblock = OFFSET_CU;
-      i < NTXBLOCKS;
-      i++, txblock += TXBLOCKZ)
-    {
-      ac_tx_t          tx;
-      ac_nop_t         nop;
-      tbd_t            tbd;
-      unsigned short   tx_addr;
-      unsigned short   nop_addr;
-      unsigned short   tbd_addr;
-      unsigned short   buf_addr;
-
-      tx_addr = txblock;
-      nop_addr = tx_addr + sizeof(tx);
-      tbd_addr = nop_addr + sizeof(nop);
-      buf_addr = tbd_addr + sizeof(tbd);
-
-      tx.tx_h.ac_status = 0;
-      tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I;
-      tx.tx_h.ac_link = nop_addr;
-      tx.tx_tbd_offset = tbd_addr;
-      obram_write(ioaddr, tx_addr, (unsigned char *) &tx, sizeof(tx));
-
-      nop.nop_h.ac_status = 0;
-      nop.nop_h.ac_command = acmd_nop;
-      nop.nop_h.ac_link = nop_addr;
-      obram_write(ioaddr, nop_addr, (unsigned char *) &nop, sizeof(nop));
-
-      tbd.tbd_status = TBD_STATUS_EOF;
-      tbd.tbd_next_bd_offset = I82586NULL;
-      tbd.tbd_bufl = buf_addr;
-      tbd.tbd_bufh = 0;
-      obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd));
-    }
-
-  first_nop = OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t);
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset),
-             (unsigned char *) &first_nop, sizeof(first_nop));
-
-  scb_cs = SCB_CMD_CUC_GO;
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
-             (unsigned char *) &scb_cs, sizeof(scb_cs));
-
-  set_chan_attn(ioaddr, lp->hacr);
-
-  for(i = 1000; i > 0; i--)
-    {
-      obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
-                (unsigned char *) &scb_cs, sizeof(scb_cs));
-      if (scb_cs == 0)
-       break;
-
-      udelay(10);
-    }
-
-  if(i <= 0)
-    {
+       lp->tx_first_free = OFFSET_CU;
+       lp->tx_first_in_use = I82586NULL;
+
+       for (i = 0, txblock = OFFSET_CU;
+            i < NTXBLOCKS; i++, txblock += TXBLOCKZ) {
+               ac_tx_t tx;
+               ac_nop_t nop;
+               tbd_t tbd;
+               unsigned short tx_addr;
+               unsigned short nop_addr;
+               unsigned short tbd_addr;
+               unsigned short buf_addr;
+
+               tx_addr = txblock;
+               nop_addr = tx_addr + sizeof(tx);
+               tbd_addr = nop_addr + sizeof(nop);
+               buf_addr = tbd_addr + sizeof(tbd);
+
+               tx.tx_h.ac_status = 0;
+               tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I;
+               tx.tx_h.ac_link = nop_addr;
+               tx.tx_tbd_offset = tbd_addr;
+               obram_write(ioaddr, tx_addr, (unsigned char *) &tx,
+                           sizeof(tx));
+
+               nop.nop_h.ac_status = 0;
+               nop.nop_h.ac_command = acmd_nop;
+               nop.nop_h.ac_link = nop_addr;
+               obram_write(ioaddr, nop_addr, (unsigned char *) &nop,
+                           sizeof(nop));
+
+               tbd.tbd_status = TBD_STATUS_EOF;
+               tbd.tbd_next_bd_offset = I82586NULL;
+               tbd.tbd_bufl = buf_addr;
+               tbd.tbd_bufh = 0;
+               obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd,
+                           sizeof(tbd));
+       }
+
+       first_nop =
+           OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t);
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset),
+                   (unsigned char *) &first_nop, sizeof(first_nop));
+
+       scb_cs = SCB_CMD_CUC_GO;
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+                   (unsigned char *) &scb_cs, sizeof(scb_cs));
+
+       set_chan_attn(ioaddr, lp->hacr);
+
+       for (i = 1000; i > 0; i--) {
+               obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
+                          (unsigned char *) &scb_cs, sizeof(scb_cs));
+               if (scb_cs == 0)
+                       break;
+
+               udelay(10);
+       }
+
+       if (i <= 0) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: wavelan_cu_start(): board not accepting command.\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wavelan_cu_start(): board not accepting command.\n",
+                      dev->name);
 #endif
-      return -1;
-    }
-
-  lp->tx_n_in_use = 0;
-  dev->tbusy = 0;
+               return -1;
+       }
 
+       lp->tx_n_in_use = 0;
+       netif_wake_queue(dev);
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -3252,121 +3181,122 @@ wv_cu_start(device *  dev)
  *
  * (called by wv_hw_reset())
  */
-static inline int
-wv_82586_start(device *        dev)
+static inline int wv_82586_start(device * dev)
 {
-  net_local *  lp = (net_local *) dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  scp_t                scp;            /* system configuration pointer */
-  iscp_t       iscp;           /* intermediate scp */
-  scb_t                scb;            /* system control block */
-  ach_t                cb;             /* Action command header */
-  u_char       zeroes[512];
-  int          i;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       scp_t scp;              /* system configuration pointer */
+       iscp_t iscp;            /* intermediate scp */
+       scb_t scb;              /* system control block */
+       ach_t cb;               /* Action command header */
+       u8 zeroes[512];
+       int i;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name);
 #endif
 
-  /*
-   * Clear the onboard RAM.
-   */
-  memset(&zeroes[0], 0x00, sizeof(zeroes));
-  for(i = 0; i < I82586_MEMZ; i += sizeof(zeroes))
-    obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes));
-
-  /*
-   * Construct the command unit structures:
-   * scp, iscp, scb, cb.
-   */
-  memset(&scp, 0x00, sizeof(scp));
-  scp.scp_sysbus = SCP_SY_16BBUS;
-  scp.scp_iscpl = OFFSET_ISCP;
-  obram_write(ioaddr, OFFSET_SCP, (unsigned char *)&scp, sizeof(scp));
-
-  memset(&iscp, 0x00, sizeof(iscp));
-  iscp.iscp_busy = 1;
-  iscp.iscp_offset = OFFSET_SCB;
-  obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp));
-
-  /* Our first command is to reset the i82586. */
-  memset(&scb, 0x00, sizeof(scb));
-  scb.scb_command = SCB_CMD_RESET;
-  scb.scb_cbl_offset = OFFSET_CU;
-  scb.scb_rfa_offset = OFFSET_RU;
-  obram_write(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb));
-
-  set_chan_attn(ioaddr, lp->hacr);
-
-  /* Wait for command to finish. */
-  for(i = 1000; i > 0; i--)
-    {
-      obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, sizeof(iscp));
-
-      if(iscp.iscp_busy == (unsigned short) 0)
-       break;
-
-      udelay(10);
-    }
-
-  if(i <= 0)
-    {
+       /*
+        * Clear the onboard RAM.
+        */
+       memset(&zeroes[0], 0x00, sizeof(zeroes));
+       for (i = 0; i < I82586_MEMZ; i += sizeof(zeroes))
+               obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes));
+
+       /*
+        * Construct the command unit structures:
+        * scp, iscp, scb, cb.
+        */
+       memset(&scp, 0x00, sizeof(scp));
+       scp.scp_sysbus = SCP_SY_16BBUS;
+       scp.scp_iscpl = OFFSET_ISCP;
+       obram_write(ioaddr, OFFSET_SCP, (unsigned char *) &scp,
+                   sizeof(scp));
+
+       memset(&iscp, 0x00, sizeof(iscp));
+       iscp.iscp_busy = 1;
+       iscp.iscp_offset = OFFSET_SCB;
+       obram_write(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp,
+                   sizeof(iscp));
+
+       /* Our first command is to reset the i82586. */
+       memset(&scb, 0x00, sizeof(scb));
+       scb.scb_command = SCB_CMD_RESET;
+       scb.scb_cbl_offset = OFFSET_CU;
+       scb.scb_rfa_offset = OFFSET_RU;
+       obram_write(ioaddr, OFFSET_SCB, (unsigned char *) &scb,
+                   sizeof(scb));
+
+       set_chan_attn(ioaddr, lp->hacr);
+
+       /* Wait for command to finish. */
+       for (i = 1000; i > 0; i--) {
+               obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp,
+                          sizeof(iscp));
+
+               if (iscp.iscp_busy == (unsigned short) 0)
+                       break;
+
+               udelay(10);
+       }
+
+       if (i <= 0) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: wv_82586_start(): iscp_busy timeout.\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wv_82586_start(): iscp_busy timeout.\n",
+                      dev->name);
 #endif
-      return -1;
-    }
+               return -1;
+       }
 
-  /* Check command completion. */
-  for(i = 15; i > 0; i--)
-    {
-      obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, sizeof(scb));
+       /* Check command completion. */
+       for (i = 15; i > 0; i--) {
+               obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb,
+                          sizeof(scb));
 
-      if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA))
-       break;
+               if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA))
+                       break;
 
-      udelay(10);
-    }
+               udelay(10);
+       }
 
-  if (i <= 0)
-    {
+       if (i <= 0) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n",
-            dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
+               printk(KERN_INFO
+                      "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n",
+                      dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
 #endif
-      return -1;
-    }
+               return -1;
+       }
 
-  wv_ack(dev);
+       wv_ack(dev);
 
-  /* Set the action command header. */
-  memset(&cb, 0x00, sizeof(cb));
-  cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose);
-  cb.ac_link = OFFSET_CU;
-  obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
+       /* Set the action command header. */
+       memset(&cb, 0x00, sizeof(cb));
+       cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose);
+       cb.ac_link = OFFSET_CU;
+       obram_write(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb));
 
-  if(wv_synchronous_cmd(dev, "diag()") == -1)
-    return -1;
+       if (wv_synchronous_cmd(dev, "diag()") == -1)
+               return -1;
 
-  obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
-  if(cb.ac_status & AC_SFLD_FAIL)
-    {
+       obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb));
+       if (cb.ac_status & AC_SFLD_FAIL) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: wv_82586_start(): i82586 Self Test failed.\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wv_82586_start(): i82586 Self Test failed.\n",
+                      dev->name);
 #endif
-      return -1;
-    }
-
+               return -1;
+       }
 #ifdef DEBUG_I82586_SHOW
-  wv_scb_show(ioaddr);
+       wv_scb_show(ioaddr);
 #endif
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -3383,184 +3313,179 @@ wv_82586_start(device *       dev)
  *
  * (called by wv_hw_reset(), wv_82586_reconfig())
  */
-static void
-wv_82586_config(device *       dev)
+static void wv_82586_config(device * dev)
 {
-  net_local *          lp = (net_local *) dev->priv;
-  u_long               ioaddr = dev->base_addr;
-  unsigned short       txblock;
-  unsigned short       txpred;
-  unsigned short       tx_addr;
-  unsigned short       nop_addr;
-  unsigned short       tbd_addr;
-  unsigned short       cfg_addr;
-  unsigned short       ias_addr;
-  unsigned short       mcs_addr;
-  ac_tx_t              tx;
-  ac_nop_t             nop;
-  ac_cfg_t             cfg;            /* Configure action */
-  ac_ias_t             ias;            /* IA-setup action */
-  ac_mcs_t             mcs;            /* Multicast setup */
-  struct dev_mc_list * dmi;
-  unsigned long                x;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       unsigned short txblock;
+       unsigned short txpred;
+       unsigned short tx_addr;
+       unsigned short nop_addr;
+       unsigned short tbd_addr;
+       unsigned short cfg_addr;
+       unsigned short ias_addr;
+       unsigned short mcs_addr;
+       ac_tx_t tx;
+       ac_nop_t nop;
+       ac_cfg_t cfg;           /* Configure action */
+       ac_ias_t ias;           /* IA-setup action */
+       ac_mcs_t mcs;           /* Multicast setup */
+       struct dev_mc_list *dmi;
+       unsigned long flags;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name);
 #endif
 
-  x = wv_splhi();
-
-  /* Calculate addresses of next block and previous block. */
-  txblock = lp->tx_first_free;
-  txpred = txblock - TXBLOCKZ;
-  if(txpred < OFFSET_CU)
-    txpred += NTXBLOCKS * TXBLOCKZ;
-  lp->tx_first_free += TXBLOCKZ;
-  if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
-    lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
-
-  lp->tx_n_in_use++;
-
-  /* Calculate addresses of the different parts of the block. */
-  tx_addr = txblock;
-  nop_addr = tx_addr + sizeof(tx);
-  tbd_addr = nop_addr + sizeof(nop);
-  cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */
-  ias_addr = cfg_addr + sizeof(cfg);
-  mcs_addr = ias_addr + sizeof(ias);
-
-  /*
-   * Transmit command
-   */
-  tx.tx_h.ac_status = 0xFFFF;  /* Fake completion value */
-  obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
-             (unsigned char *) &tx.tx_h.ac_status,
-             sizeof(tx.tx_h.ac_status));
-
-  /*
-   * NOP command
-   */
-  nop.nop_h.ac_status = 0;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
-             (unsigned char *) &nop.nop_h.ac_status,
-             sizeof(nop.nop_h.ac_status));
-  nop.nop_h.ac_link = nop_addr;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
-             (unsigned char *) &nop.nop_h.ac_link,
-             sizeof(nop.nop_h.ac_link));
-
-  /* Create a configure action. */
-  memset(&cfg, 0x00, sizeof(cfg));
-
-  /*
-   * For Linux we invert AC_CFG_ALOC() so as to conform
-   * to the way that net packets reach us from above.
-   * (See also ac_tx_t.)
-   *
-   * Updated from Wavelan Manual WCIN085B
-   */
-  cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t));
-  cfg.cfg_fifolim = AC_CFG_FIFOLIM(4);
-  cfg.cfg_byte8 = AC_CFG_SAV_BF(1) |
-                 AC_CFG_SRDY(0);
-  cfg.cfg_byte9 = AC_CFG_ELPBCK(0) |
-                 AC_CFG_ILPBCK(0) |
-                 AC_CFG_PRELEN(AC_CFG_PLEN_2) |
-                 AC_CFG_ALOC(1) |
-                 AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE);
-  cfg.cfg_byte10 = AC_CFG_BOFMET(1) |
-                  AC_CFG_ACR(6) |
-                  AC_CFG_LINPRIO(0);
-  cfg.cfg_ifs = 0x20;
-  cfg.cfg_slotl = 0x0C;
-  cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) |
-                  AC_CFG_SLTTMHI(0);
-  cfg.cfg_byte14 = AC_CFG_FLGPAD(0) |
-                  AC_CFG_BTSTF(0) |
-                  AC_CFG_CRC16(0) |
-                  AC_CFG_NCRC(0) |
-                  AC_CFG_TNCRS(1) |
-                  AC_CFG_MANCH(0) |
-                  AC_CFG_BCDIS(0) |
-                  AC_CFG_PRM(lp->promiscuous);
-  cfg.cfg_byte15 = AC_CFG_ICDS(0) |
-                  AC_CFG_CDTF(0) |
-                  AC_CFG_ICSS(0) |
-                  AC_CFG_CSTF(0);
+       save_flags(flags);
+       cli();
+       
+       /* Calculate addresses of next block and previous block. */
+       txblock = lp->tx_first_free;
+       txpred = txblock - TXBLOCKZ;
+       if (txpred < OFFSET_CU)
+               txpred += NTXBLOCKS * TXBLOCKZ;
+       lp->tx_first_free += TXBLOCKZ;
+       if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
+               lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
+
+       lp->tx_n_in_use++;
+
+       /* Calculate addresses of the different parts of the block. */
+       tx_addr = txblock;
+       nop_addr = tx_addr + sizeof(tx);
+       tbd_addr = nop_addr + sizeof(nop);
+       cfg_addr = tbd_addr + sizeof(tbd_t);    /* beginning of the buffer */
+       ias_addr = cfg_addr + sizeof(cfg);
+       mcs_addr = ias_addr + sizeof(ias);
+
+       /*
+        * Transmit command
+        */
+       tx.tx_h.ac_status = 0xFFFF;     /* Fake completion value */
+       obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
+                   (unsigned char *) &tx.tx_h.ac_status,
+                   sizeof(tx.tx_h.ac_status));
+
+       /*
+        * NOP command
+        */
+       nop.nop_h.ac_status = 0;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+                   (unsigned char *) &nop.nop_h.ac_status,
+                   sizeof(nop.nop_h.ac_status));
+       nop.nop_h.ac_link = nop_addr;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+                   (unsigned char *) &nop.nop_h.ac_link,
+                   sizeof(nop.nop_h.ac_link));
+
+       /* Create a configure action. */
+       memset(&cfg, 0x00, sizeof(cfg));
+
+       /*
+        * For Linux we invert AC_CFG_ALOC() so as to conform
+        * to the way that net packets reach us from above.
+        * (See also ac_tx_t.)
+        *
+        * Updated from Wavelan Manual WCIN085B
+        */
+       cfg.cfg_byte_cnt =
+           AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t));
+       cfg.cfg_fifolim = AC_CFG_FIFOLIM(4);
+       cfg.cfg_byte8 = AC_CFG_SAV_BF(1) | AC_CFG_SRDY(0);
+       cfg.cfg_byte9 = AC_CFG_ELPBCK(0) |
+           AC_CFG_ILPBCK(0) |
+           AC_CFG_PRELEN(AC_CFG_PLEN_2) |
+           AC_CFG_ALOC(1) | AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE);
+       cfg.cfg_byte10 = AC_CFG_BOFMET(1) |
+           AC_CFG_ACR(6) | AC_CFG_LINPRIO(0);
+       cfg.cfg_ifs = 0x20;
+       cfg.cfg_slotl = 0x0C;
+       cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | AC_CFG_SLTTMHI(0);
+       cfg.cfg_byte14 = AC_CFG_FLGPAD(0) |
+           AC_CFG_BTSTF(0) |
+           AC_CFG_CRC16(0) |
+           AC_CFG_NCRC(0) |
+           AC_CFG_TNCRS(1) |
+           AC_CFG_MANCH(0) |
+           AC_CFG_BCDIS(0) | AC_CFG_PRM(lp->promiscuous);
+       cfg.cfg_byte15 = AC_CFG_ICDS(0) |
+           AC_CFG_CDTF(0) | AC_CFG_ICSS(0) | AC_CFG_CSTF(0);
 /*
   cfg.cfg_min_frm_len = AC_CFG_MNFRM(64);
 */
-  cfg.cfg_min_frm_len = AC_CFG_MNFRM(8);
-
-  cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure);
-  cfg.cfg_h.ac_link = ias_addr;
-  obram_write(ioaddr, cfg_addr, (unsigned char *)&cfg, sizeof(cfg));
-
-  /* Set up the MAC address */
-  memset(&ias, 0x00, sizeof(ias));
-  ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup);
-  ias.ias_h.ac_link = mcs_addr;
-  memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr));
-  obram_write(ioaddr, ias_addr, (unsigned char *)&ias, sizeof(ias));
-
-  /* Initialize adapter's Ethernet multicast addresses */
-  memset(&mcs, 0x00, sizeof(mcs));
-  mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup);
-  mcs.mcs_h.ac_link = nop_addr;
-  mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count;
-  obram_write(ioaddr, mcs_addr, (unsigned char *)&mcs, sizeof(mcs));
-
-  /* Any address to set? */
-  if(lp->mc_count)
-    {
-      for(dmi=dev->mc_list; dmi; dmi=dmi->next)
-       outsw(PIOP1(ioaddr), (u_short *) dmi->dmi_addr,
-             WAVELAN_ADDR_SIZE >> 1);
+       cfg.cfg_min_frm_len = AC_CFG_MNFRM(8);
+
+       cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure);
+       cfg.cfg_h.ac_link = ias_addr;
+       obram_write(ioaddr, cfg_addr, (unsigned char *) &cfg, sizeof(cfg));
+
+       /* Set up the MAC address */
+       memset(&ias, 0x00, sizeof(ias));
+       ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup);
+       ias.ias_h.ac_link = mcs_addr;
+       memcpy(&ias.ias_addr[0], (unsigned char *) &dev->dev_addr[0],
+              sizeof(ias.ias_addr));
+       obram_write(ioaddr, ias_addr, (unsigned char *) &ias, sizeof(ias));
+
+       /* Initialize adapter's Ethernet multicast addresses */
+       memset(&mcs, 0x00, sizeof(mcs));
+       mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup);
+       mcs.mcs_h.ac_link = nop_addr;
+       mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count;
+       obram_write(ioaddr, mcs_addr, (unsigned char *) &mcs, sizeof(mcs));
+
+       /* Any address to set? */
+       if (lp->mc_count) {
+               for (dmi = dev->mc_list; dmi; dmi = dmi->next)
+                       outsw(PIOP1(ioaddr), (u16 *) dmi->dmi_addr,
+                             WAVELAN_ADDR_SIZE >> 1);
 
 #ifdef DEBUG_CONFIG_INFO
-      printk(KERN_DEBUG "%s: wv_82586_config(): set %d multicast addresses:\n",
-            dev->name, lp->mc_count);
-      for(dmi=dev->mc_list; dmi; dmi=dmi->next)
-       printk(KERN_DEBUG " %02x:%02x:%02x:%02x:%02x:%02x\n",
-              dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
-              dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5] );
+               printk(KERN_DEBUG
+                      "%s: wv_82586_config(): set %d multicast addresses:\n",
+                      dev->name, lp->mc_count);
+               for (dmi = dev->mc_list; dmi; dmi = dmi->next)
+                       printk(KERN_DEBUG
+                              " %02x:%02x:%02x:%02x:%02x:%02x\n",
+                              dmi->dmi_addr[0], dmi->dmi_addr[1],
+                              dmi->dmi_addr[2], dmi->dmi_addr[3],
+                              dmi->dmi_addr[4], dmi->dmi_addr[5]);
 #endif
-    }
-
-  /*
-   * Overwrite the predecessor NOP link
-   * so that it points to the configure action.
-   */
-  nop_addr = txpred + sizeof(tx);
-  nop.nop_h.ac_status = 0;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
-             (unsigned char *)&nop.nop_h.ac_status,
-             sizeof(nop.nop_h.ac_status));
-  nop.nop_h.ac_link = cfg_addr;
-  obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
-             (unsigned char *) &nop.nop_h.ac_link,
-             sizeof(nop.nop_h.ac_link));
-
-  /* If watchdog not already active, activate it... */
-  if(lp->watchdog.prev == (timer_list *) NULL)
-    {
-      /* set timer to expire in WATCHDOG_JIFFIES */
-      lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
-      add_timer(&lp->watchdog);
-    }
-
-  lp->reconfig_82586 = 0;
-
-  if(lp->tx_first_in_use == I82586NULL)
-    lp->tx_first_in_use = txblock;
-
-  if(lp->tx_n_in_use < NTXBLOCKS - 1)
-    dev->tbusy = 0;
-
-  wv_splx(x);
+       }
+
+       /*
+        * Overwrite the predecessor NOP link
+        * so that it points to the configure action.
+        */
+       nop_addr = txpred + sizeof(tx);
+       nop.nop_h.ac_status = 0;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+                   (unsigned char *) &nop.nop_h.ac_status,
+                   sizeof(nop.nop_h.ac_status));
+       nop.nop_h.ac_link = cfg_addr;
+       obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+                   (unsigned char *) &nop.nop_h.ac_link,
+                   sizeof(nop.nop_h.ac_link));
+
+       /* If watchdog not already active, activate it... */
+       if (lp->watchdog.prev == (timer_list *) NULL) {
+               /* set timer to expire in WATCHDOG_JIFFIES */
+               lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+               add_timer(&lp->watchdog);
+       }
+
+       lp->reconfig_82586 = 0;
 
+       if (lp->tx_first_in_use == I82586NULL)
+               lp->tx_first_in_use = txblock;
+
+       if (lp->tx_n_in_use < NTXBLOCKS - 1)
+               netif_wake_queue(dev);
+
+       restore_flags(flags);
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name);
 #endif
 }
 
@@ -3569,28 +3494,29 @@ wv_82586_config(device *        dev)
  * This routine, called by wavelan_close(), gracefully stops the 
  * WaveLAN controller (i82586).
  */
-static inline void
-wv_82586_stop(device * dev)
+static inline void wv_82586_stop(device * dev)
 {
-  net_local *  lp = (net_local *) dev->priv;
-  u_long       ioaddr = dev->base_addr;
-  u_short      scb_cmd;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
+       u16 scb_cmd;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name);
 #endif
 
-  /* Suspend both command unit and receive unit. */
-  scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS);
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
-             (unsigned char *)&scb_cmd, sizeof(scb_cmd));
-  set_chan_attn(ioaddr, lp->hacr);
+       /* Suspend both command unit and receive unit. */
+       scb_cmd =
+           (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC &
+                                              SCB_CMD_RUC_SUS);
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+                   (unsigned char *) &scb_cmd, sizeof(scb_cmd));
+       set_chan_attn(ioaddr, lp->hacr);
 
-  /* No more interrupts */
-  wv_ints_off(dev);
+       /* No more interrupts */
+       wv_ints_off(dev);
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name);
 #endif
 }
 
@@ -3604,49 +3530,47 @@ wv_82586_stop(device *  dev)
  *     4. Start the LAN controller's command unit
  *     5. Start the LAN controller's receive unit
  */
-static int
-wv_hw_reset(device *   dev)
+static int wv_hw_reset(device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
-  u_long       ioaddr = dev->base_addr;
+       net_local *lp = (net_local *) dev->priv;
+       unsigned long ioaddr = dev->base_addr;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
-        (unsigned int)dev);
+       printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
+              (unsigned int) dev);
 #endif
 
-  /* If watchdog was activated, kill it! */
-  if(lp->watchdog.prev != (timer_list *) NULL)
-    del_timer(&lp->watchdog);
+       /* If watchdog was activated, kill it! */
+       if (lp->watchdog.prev != (timer_list *) NULL)
+               del_timer(&lp->watchdog);
 
-  /* Increase the number of resets done. */
-  lp->nresets++;
+       /* Increase the number of resets done. */
+       lp->nresets++;
 
-  wv_hacr_reset(ioaddr);
-  lp->hacr = HACR_DEFAULT;
+       wv_hacr_reset(ioaddr);
+       lp->hacr = HACR_DEFAULT;
 
-  if((wv_mmc_init(dev) < 0) ||
-     (wv_82586_start(dev) < 0))
-    return -1;
+       if ((wv_mmc_init(dev) < 0) || (wv_82586_start(dev) < 0))
+               return -1;
 
-  /* Enable the card to send interrupts. */
-  wv_ints_on(dev);
+       /* Enable the card to send interrupts. */
+       wv_ints_on(dev);
 
-  /* Start card functions */
-  if(wv_cu_start(dev) < 0)
-    return -1;
+       /* Start card functions */
+       if (wv_cu_start(dev) < 0)
+               return -1;
 
-  /* Setup the controller and parameters */
-  wv_82586_config(dev);
+       /* Setup the controller and parameters */
+       wv_82586_config(dev);
 
-  /* Finish configuration with the receive unit */
-  if(wv_ru_start(dev) < 0)
-    return -1;
+       /* Finish configuration with the receive unit */
+       if (wv_ru_start(dev) < 0)
+               return -1;
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -3655,40 +3579,39 @@ wv_hw_reset(device *    dev)
  * As a side effect, this reads the MAC address.
  * (called in wavelan_probe() and init_module())
  */
-static int
-wv_check_ioaddr(u_long         ioaddr,
-               u_char *        mac)
+static int wv_check_ioaddr(unsigned long ioaddr, u8 * mac)
 {
-  int          i;              /* Loop counter */
-
-  /* Check if the base address if available. */
-  if(check_region(ioaddr, sizeof(ha_t)))
-    return  EADDRINUSE;                /* ioaddr already used */
-
-  /* Reset host interface */
-  wv_hacr_reset(ioaddr);
-
-  /* Read the MAC address from the parameter storage area. */
-  psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr),
-          mac, 6);
-
-  /*
-   * Check the first three octets of the address for the manufacturer's code.
-   * Note: if this can't find your WaveLAN card, you've got a
-   * non-NCR/AT&T/Lucent ISA card.  See wavelan.p.h for detail on
-   * how to configure your card.
-   */
-  for(i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++)
-    if((mac[0] == MAC_ADDRESSES[i][0]) &&
-       (mac[1] == MAC_ADDRESSES[i][1]) &&
-       (mac[2] == MAC_ADDRESSES[i][2]))
-      return 0;
+       int i;                  /* Loop counter */
+
+       /* Check if the base address if available. */
+       if (check_region(ioaddr, sizeof(ha_t)))
+               return EADDRINUSE;      /* ioaddr already used */
+
+       /* Reset host interface */
+       wv_hacr_reset(ioaddr);
+
+       /* Read the MAC address from the parameter storage area. */
+       psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr),
+                mac, 6);
+
+       /*
+        * Check the first three octets of the address for the manufacturer's code.
+        * Note: if this can't find your WaveLAN card, you've got a
+        * non-NCR/AT&T/Lucent ISA card.  See wavelan.p.h for detail on
+        * how to configure your card.
+        */
+       for (i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++)
+               if ((mac[0] == MAC_ADDRESSES[i][0]) &&
+                   (mac[1] == MAC_ADDRESSES[i][1]) &&
+                   (mac[2] == MAC_ADDRESSES[i][2]))
+                       return 0;
 
 #ifdef DEBUG_CONFIG_INFO
-  printk(KERN_WARNING "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n",
-        ioaddr, mac[0], mac[1], mac[2]);
+       printk(KERN_WARNING
+              "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n",
+              ioaddr, mac[0], mac[1], mac[2]);
 #endif
-    return ENODEV;
+       return ENODEV;
 }
 
 /************************ INTERRUPT HANDLING ************************/
@@ -3697,133 +3620,121 @@ wv_check_ioaddr(u_long                ioaddr,
  * This function is the interrupt handler for the WaveLAN card. This
  * routine will be called whenever: 
  */
-static void
-wavelan_interrupt(int                  irq,
-                 void *                dev_id,
-                 struct pt_regs *      regs)
+static void wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-  device *     dev;
-  u_long       ioaddr;
-  net_local *  lp;
-  u_short      hasr;
-  u_short      status;
-  u_short      ack_cmd;
+       device *dev;
+       unsigned long ioaddr;
+       net_local *lp;
+       u16 hasr;
+       u16 status;
+       u16 ack_cmd;
 
-  dev = dev_id;
+       dev = dev_id;
 
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
 #endif
 
-  lp = (net_local *) dev->priv;
-  ioaddr = dev->base_addr;
+       lp = (net_local *) dev->priv;
+       ioaddr = dev->base_addr;
 
-  /* Prevent reentrance. What should we do here? */
-#ifdef DEBUG_INTERRUPT_ERROR
-  if(dev->interrupt)
-    printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n",
-          dev->name);
-#endif
-  dev->interrupt = 1;
+       /* Prevent reentrance. What should we do here? */
 
-  if((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR)
-    {
-      u_char   dce_status;
+       if ((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR) {
+               u8 dce_status;
 
-      /*
-       * Interrupt from the modem management controller.
-       * This will clear it -- ignored for now.
-       */
-      mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status));
+               /*
+                * Interrupt from the modem management controller.
+                * This will clear it -- ignored for now.
+                */
+               mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status,
+                        sizeof(dce_status));
 #ifdef DEBUG_INTERRUPT_ERROR
-      printk(KERN_INFO "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
-            dev->name, dce_status);
+               printk(KERN_INFO
+                      "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
+                      dev->name, dce_status);
 #endif
-    }
+       }
 
-  if((hasr & HASR_82586_INTR) == 0)
-    {
-      dev->interrupt = 0;
+       if ((hasr & HASR_82586_INTR) == 0) {
 #ifdef DEBUG_INTERRUPT_ERROR
-      printk(KERN_INFO "%s: wavelan_interrupt(): interrupt not coming from i82586\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wavelan_interrupt(): interrupt not coming from i82586\n",
+                      dev->name);
 #endif
-      return;
-    }
+               return;
+       }
 
-  /* Read interrupt data. */
-  obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
-            (unsigned char *) &status, sizeof(status));
+       /* Read interrupt data. */
+       obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
+                  (unsigned char *) &status, sizeof(status));
 
-  /*
-   * Acknowledge the interrupt(s).
-   */
-  ack_cmd = status & SCB_ST_INT;
-  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
-             (unsigned char *) &ack_cmd, sizeof(ack_cmd));
-  set_chan_attn(ioaddr, lp->hacr);
+       /*
+        * Acknowledge the interrupt(s).
+        */
+       ack_cmd = status & SCB_ST_INT;
+       obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+                   (unsigned char *) &ack_cmd, sizeof(ack_cmd));
+       set_chan_attn(ioaddr, lp->hacr);
 
 #ifdef DEBUG_INTERRUPT_INFO
-  printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n",
-        dev->name, status);
+       printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n",
+              dev->name, status);
 #endif
 
-  /* Command completed. */
-  if((status & SCB_ST_CX) == SCB_ST_CX)
-    {
+       /* Command completed. */
+       if ((status & SCB_ST_CX) == SCB_ST_CX) {
 #ifdef DEBUG_INTERRUPT_INFO
-      printk(KERN_DEBUG "%s: wavelan_interrupt(): command completed.\n",
-            dev->name);
+               printk(KERN_DEBUG
+                      "%s: wavelan_interrupt(): command completed.\n",
+                      dev->name);
 #endif
-      wv_complete(dev, ioaddr, lp);
-
-      /* If watchdog was activated, kill it ! */
-      if(lp->watchdog.prev != (timer_list *) NULL)
-       del_timer(&lp->watchdog);
-      if(lp->tx_n_in_use > 0)
-       {
-         /* set timer to expire in WATCHDOG_JIFFIES */
-         lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
-         add_timer(&lp->watchdog);
+               wv_complete(dev, ioaddr, lp);
+
+               /* If watchdog was activated, kill it ! */
+               if (lp->watchdog.prev != (timer_list *) NULL)
+                       del_timer(&lp->watchdog);
+               if (lp->tx_n_in_use > 0) {
+                       /* set timer to expire in WATCHDOG_JIFFIES */
+                       lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+                       add_timer(&lp->watchdog);
+               }
        }
-    }
 
-  /* Frame received. */
-  if((status & SCB_ST_FR) == SCB_ST_FR)
-    {
+       /* Frame received. */
+       if ((status & SCB_ST_FR) == SCB_ST_FR) {
 #ifdef DEBUG_INTERRUPT_INFO
-      printk(KERN_DEBUG "%s: wavelan_interrupt(): received packet.\n",
-            dev->name);
+               printk(KERN_DEBUG
+                      "%s: wavelan_interrupt(): received packet.\n",
+                      dev->name);
 #endif
-      wv_receive(dev);
-    }
+               wv_receive(dev);
+       }
 
-  /* Check the state of the command unit. */
-  if(((status & SCB_ST_CNA) == SCB_ST_CNA) ||
-     (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start))
-    {
+       /* Check the state of the command unit. */
+       if (((status & SCB_ST_CNA) == SCB_ST_CNA) ||
+           (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && test_bit(LINK_STATE_START, &dev->state))) {
 #ifdef DEBUG_INTERRUPT_ERROR
-      printk(KERN_INFO "%s: wavelan_interrupt(): CU inactive -- restarting\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wavelan_interrupt(): CU inactive -- restarting\n",
+                      dev->name);
 #endif
-      wv_hw_reset(dev);
-    }
+               wv_hw_reset(dev);
+       }
 
-  /* Check the state of the command unit. */
-  if(((status & SCB_ST_RNR) == SCB_ST_RNR) ||
-     (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start))
-    {
+       /* Check the state of the command unit. */
+       if (((status & SCB_ST_RNR) == SCB_ST_RNR) ||
+           (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && test_bit(LINK_STATE_START, &dev->state))) {
 #ifdef DEBUG_INTERRUPT_ERROR
-      printk(KERN_INFO "%s: wavelan_interrupt(): RU not ready -- restarting\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wavelan_interrupt(): RU not ready -- restarting\n",
+                      dev->name);
 #endif
-      wv_hw_reset(dev);
-    }
-
-  dev->interrupt = 0;
+               wv_hw_reset(dev);
+       }
 
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
 #endif
 }
 
@@ -3838,83 +3749,81 @@ wavelan_interrupt(int                   irq,
  * way because the overhead of add_timer() and del_timer() is nothing
  * and because it avoids calling the watchdog, saving some CPU.
  */
-static void
-wavelan_watchdog(u_long                a)
+static void wavelan_watchdog(unsigned long a)
 {
-  device *             dev;
-  net_local *          lp;
-  u_long               ioaddr;
-  unsigned long                x;
-  unsigned int         nreaped;
+       device *dev;
+       net_local *lp;
+       unsigned long ioaddr;
+       unsigned long flags;
+       unsigned int nreaped;
 
-  dev = (device *) a;
-  ioaddr = dev->base_addr;
-  lp = (net_local *) dev->priv;
+       dev = (device *) a;
+       ioaddr = dev->base_addr;
+       lp = (net_local *) dev->priv;
 
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name);
+       printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name);
 #endif
 
 #ifdef DEBUG_INTERRUPT_ERROR
-  printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n",
-        dev->name);
+       printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n",
+              dev->name);
 #endif
 
-  x = wv_splhi();
-
-  dev = (device *) a;
-  ioaddr = dev->base_addr;
-  lp = (net_local *) dev->priv;
+       save_flags(flags);
+       cli();
+       
+       dev = (device *) a;
+       ioaddr = dev->base_addr;
+       lp = (net_local *) dev->priv;
 
-  if(lp->tx_n_in_use <= 0)
-    {
-      wv_splx(x);
-      return;
-    }
+       if (lp->tx_n_in_use <= 0) {
+               restore_flags(flags);
+               return;
+       }
 
-  nreaped = wv_complete(dev, ioaddr, lp);
+       nreaped = wv_complete(dev, ioaddr, lp);
 
 #ifdef DEBUG_INTERRUPT_INFO
-  printk(KERN_DEBUG "%s: wavelan_watchdog(): %d reaped, %d remain.\n",
-        dev->name, nreaped, lp->tx_n_in_use);
+       printk(KERN_DEBUG
+              "%s: wavelan_watchdog(): %d reaped, %d remain.\n",
+              dev->name, nreaped, lp->tx_n_in_use);
 #endif
 
 #ifdef DEBUG_PSA_SHOW
-  {
-    psa_t              psa;
-    psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa));
-    wv_psa_show(&psa);
-  }
+       {
+               psa_t psa;
+               psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa));
+               wv_psa_show(&psa);
+       }
 #endif
 #ifdef DEBUG_MMC_SHOW
-  wv_mmc_show(dev);
+       wv_mmc_show(dev);
 #endif
 #ifdef DEBUG_I82586_SHOW
-  wv_cu_show(dev);
+       wv_cu_show(dev);
 #endif
 
-  /* If no buffer has been freed */
-  if(nreaped == 0)
-    {
+       /* If no buffer has been freed */
+       if (nreaped == 0) {
 #ifdef DEBUG_INTERRUPT_ERROR
-      printk(KERN_INFO "%s: wavelan_watchdog(): cleanup failed, trying reset\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wavelan_watchdog(): cleanup failed, trying reset\n",
+                      dev->name);
 #endif
-      wv_hw_reset(dev);
-    }
-  else
-    /* Reset watchdog for next transmission. */
-    if(lp->tx_n_in_use > 0)
-      {
-       /* set timer to expire in WATCHDOG_JIFFIES */
-       lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
-       add_timer(&lp->watchdog);
-      }
-
-  wv_splx(x);
+               wv_hw_reset(dev);
+       } else
+               /* Reset watchdog for next transmission. */
+       if (lp->tx_n_in_use > 0) {
+               /* set timer to expire in WATCHDOG_JIFFIES */
+               lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+               add_timer(&lp->watchdog);
+       }
 
+       restore_flags(flags);
+       
 #ifdef DEBUG_INTERRUPT_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
 #endif
 }
 
@@ -3930,56 +3839,55 @@ wavelan_watchdog(u_long         a)
  * Configure and start up the WaveLAN PCMCIA adaptor.
  * Called by NET3 when it "opens" the device.
  */
-static int
-wavelan_open(device *  dev)
+static int wavelan_open(device * dev)
 {
-  u_long       x;
+       unsigned long flags;
 
 #ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name,
-        (unsigned int) dev);
+       printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name,
+              (unsigned int) dev);
 #endif
 
-  /* Check irq */
-  if(dev->irq == 0)
-    {
+       /* Check irq */
+       if (dev->irq == 0) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name);
+               printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n",
+                      dev->name);
 #endif
-      return -ENXIO;
-    }
+               return -ENXIO;
+       }
 
-  if(request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0)
-    {
+       if (request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0) 
+       {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name);
+               printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n",
+                      dev->name);
 #endif
-      return -EAGAIN;
-    }
-
-  x = wv_splhi();
-  if(wv_hw_reset(dev) != -1)
-    {
-      dev->interrupt = 0;
-      dev->start = 1;
-    }
-  else
-    {
-      free_irq(dev->irq, dev);
+               return -EAGAIN;
+       }
+
+       save_flags(flags);
+       cli();
+       
+       if (wv_hw_reset(dev) != -1) {
+               netif_start_queue(dev);
+       } else {
+               free_irq(dev->irq, dev);
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n",
-            dev->name);
+               printk(KERN_INFO
+                      "%s: wavelan_open(): impossible to start the card\n",
+                      dev->name);
 #endif
-      return -EAGAIN;
-    }
-  wv_splx(x);
-
-  MOD_INC_USE_COUNT;
+               return -EAGAIN;
+       }
+       restore_flags(flags);
+       
+       MOD_INC_USE_COUNT;
 
 #ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -3987,40 +3895,34 @@ wavelan_open(device *   dev)
  * Shut down the WaveLAN ISA card.
  * Called by NET3 when it "closes" the device.
  */
-static int
-wavelan_close(device * dev)
+static int wavelan_close(device * dev)
 {
-  net_local *  lp = (net_local *)dev->priv;
+       net_local *lp = (net_local *) dev->priv;
 
 #ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name,
-        (unsigned int) dev);
+       printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name,
+              (unsigned int) dev);
 #endif
 
-  /* Don't do the job twice. */
-  if(dev->start == 0)
-    return 0;
-
-  dev->tbusy = 1;
-  dev->start = 0;
+       netif_stop_queue(dev);
 
-  /* If watchdog was activated, kill it! */
-  if(lp->watchdog.prev != (timer_list *) NULL)
-    del_timer(&lp->watchdog);
+       /* If watchdog was activated, kill it! */
+       if (lp->watchdog.prev != (timer_list *) NULL)
+               del_timer(&lp->watchdog);
 
-  /*
-   * Flush the Tx and disable Rx.
-   */
-  wv_82586_stop(dev);
+       /*
+        * Flush the Tx and disable Rx.
+        */
+       wv_82586_stop(dev);
 
-  free_irq(dev->irq, dev);
+       free_irq(dev->irq, dev);
 
-  MOD_DEC_USE_COUNT;
+       MOD_DEC_USE_COUNT;
 
 #ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -4029,113 +3931,111 @@ wavelan_close(device *        dev)
  * device structure
  * (called by wavelan_probe() and via init_module()).
  */
-static int __init 
-wavelan_config(device *        dev)
+static int __init wavelan_config(device * dev)
 {
-  u_long       ioaddr = dev->base_addr;
-  u_char       irq_mask;
-  int          irq;
-  net_local *  lp;
+       unsigned long ioaddr = dev->base_addr;
+       u8 irq_mask;
+       int irq;
+       net_local *lp;
 
 #ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%x)\n", dev->name,
-        (unsigned int)dev, ioaddr);
+       printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%x)\n",
+              dev->name, (unsigned int) dev, ioaddr);
 #endif
 
-  /* Check IRQ argument on command line. */
-  if(dev->irq != 0)
-    {
-      irq_mask = wv_irq_to_psa(dev->irq);
+       /* Check IRQ argument on command line. */
+       if (dev->irq != 0) {
+               irq_mask = wv_irq_to_psa(dev->irq);
 
-      if(irq_mask == 0)
-       {
+               if (irq_mask == 0) {
 #ifdef DEBUG_CONFIG_ERROR
-         printk(KERN_WARNING "%s: wavelan_config(): invalid IRQ %d ignored.\n",
-                dev->name, dev->irq);
+                       printk(KERN_WARNING
+                              "%s: wavelan_config(): invalid IRQ %d ignored.\n",
+                              dev->name, dev->irq);
 #endif
-         dev->irq = 0;
-       }
-      else
-       {
+                       dev->irq = 0;
+               } else {
 #ifdef DEBUG_CONFIG_INFO
-         printk(KERN_DEBUG "%s: wavelan_config(): changing IRQ to %d\n",
-                dev->name, dev->irq);
+                       printk(KERN_DEBUG
+                              "%s: wavelan_config(): changing IRQ to %d\n",
+                              dev->name, dev->irq);
 #endif
-         psa_write(ioaddr, HACR_DEFAULT,
-                   psaoff(0, psa_int_req_no), &irq_mask, 1);
-         /* update the Wavelan checksum */
-         update_psa_checksum(dev, ioaddr, HACR_DEFAULT);
-         wv_hacr_reset(ioaddr);
+                       psa_write(ioaddr, HACR_DEFAULT,
+                                 psaoff(0, psa_int_req_no), &irq_mask, 1);
+                       /* update the Wavelan checksum */
+                       update_psa_checksum(dev, ioaddr, HACR_DEFAULT);
+                       wv_hacr_reset(ioaddr);
+               }
        }
-    }
 
-  psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no), &irq_mask, 1);
-  if((irq = wv_psa_to_irq(irq_mask)) == -1)
-    {
+       psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no),
+                &irq_mask, 1);
+       if ((irq = wv_psa_to_irq(irq_mask)) == -1) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_INFO "%s: wavelan_config(): could not wavelan_map_irq(%d).\n",
-            dev->name, irq_mask);
+               printk(KERN_INFO
+                      "%s: wavelan_config(): could not wavelan_map_irq(%d).\n",
+                      dev->name, irq_mask);
 #endif
-      return EAGAIN;
-    }
-
-  dev->irq = irq;
-
-  request_region(ioaddr, sizeof(ha_t), "wavelan");
-
-  dev->mem_start = 0x0000;
-  dev->mem_end = 0x0000;
-  dev->if_port = 0;
-
-  /* Initialize device structures */
-  dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
-  if(dev->priv == NULL)
-    return -ENOMEM;
-  memset(dev->priv, 0x00, sizeof(net_local));
-  lp = (net_local *)dev->priv;
-
-  /* Back link to the device structure. */
-  lp->dev = dev;
-  /* Add the device at the beginning of the linked list. */
-  lp->next = wavelan_list;
-  wavelan_list = lp;
-
-  lp->hacr = HACR_DEFAULT;
-
-  lp->watchdog.function = wavelan_watchdog;
-  lp->watchdog.data = (unsigned long) dev;
-  lp->promiscuous = 0;
-  lp->mc_count = 0;
-
-  /*
-   * Fill in the fields of the device structure
-   * with generic Ethernet values.
-   */
-  ether_setup(dev);
-
-  dev->open = wavelan_open;
-  dev->stop = wavelan_close;
-  dev->hard_start_xmit = wavelan_packet_xmit;
-  dev->get_stats = wavelan_get_stats;
-  dev->set_multicast_list = &wavelan_set_multicast_list;
+               return EAGAIN;
+       }
+
+       dev->irq = irq;
+
+       request_region(ioaddr, sizeof(ha_t), "wavelan");
+
+       dev->mem_start = 0x0000;
+       dev->mem_end = 0x0000;
+       dev->if_port = 0;
+
+       /* Initialize device structures */
+       dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
+       if (dev->priv == NULL)
+               return -ENOMEM;
+       memset(dev->priv, 0x00, sizeof(net_local));
+       lp = (net_local *) dev->priv;
+
+       /* Back link to the device structure. */
+       lp->dev = dev;
+       /* Add the device at the beginning of the linked list. */
+       lp->next = wavelan_list;
+       wavelan_list = lp;
+
+       lp->hacr = HACR_DEFAULT;
+
+       lp->watchdog.function = wavelan_watchdog;
+       lp->watchdog.data = (unsigned long) dev;
+       lp->promiscuous = 0;
+       lp->mc_count = 0;
+
+       /*
+        * Fill in the fields of the device structure
+        * with generic Ethernet values.
+        */
+       ether_setup(dev);
+
+       dev->open = wavelan_open;
+       dev->stop = wavelan_close;
+       dev->hard_start_xmit = wavelan_packet_xmit;
+       dev->get_stats = wavelan_get_stats;
+       dev->set_multicast_list = &wavelan_set_multicast_list;
 #ifdef SET_MAC_ADDRESS
-  dev->set_mac_address = &wavelan_set_mac_address;
-#endif /* SET_MAC_ADDRESS */
+       dev->set_mac_address = &wavelan_set_mac_address;
+#endif                         /* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT    /* if wireless extension exists in the kernel */
-  dev->do_ioctl = wavelan_ioctl;
-  dev->get_wireless_stats = wavelan_get_wireless_stats;
+#ifdef WIRELESS_EXT            /* if wireless extension exists in the kernel */
+       dev->do_ioctl = wavelan_ioctl;
+       dev->get_wireless_stats = wavelan_get_wireless_stats;
 #endif
 
-  dev->mtu = WAVELAN_MTU;
+       dev->mtu = WAVELAN_MTU;
 
-  /* Display nice information. */
-  wv_init_info(dev);
+       /* Display nice information. */
+       wv_init_info(dev);
 
 #ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name);
+       printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name);
 #endif
-  return 0;
+       return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -4146,90 +4046,88 @@ wavelan_config(device * dev)
  * We follow the example in drivers/net/ne.c.
  * (called in "Space.c")
  */
-int __init 
-wavelan_probe(device * dev)
+int __init wavelan_probe(device * dev)
 {
-  short                base_addr;
-  mac_addr     mac;            /* MAC address (check existence of WaveLAN) */
-  int          i;
-  int          r;
+       short base_addr;
+       mac_addr mac;           /* MAC address (check existence of WaveLAN) */
+       int i;
+       int r;
 
 #ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n",
-        dev->name, (unsigned int)dev, (unsigned int)dev->base_addr);
+       printk(KERN_DEBUG
+              "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n",
+              dev->name, (unsigned int) dev,
+              (unsigned int) dev->base_addr);
 #endif
 
 #ifdef STRUCT_CHECK
-  if (wv_struct_check() != (char *) NULL)
-    {
-      printk(KERN_WARNING "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n",
-            dev->name, wv_struct_check());
-      return ENODEV;
-    }
-#endif /* STRUCT_CHECK */
-
-  /* Check the value of the command line parameter for base address. */
-  base_addr = dev->base_addr;
-
-  /* Don't probe at all. */
-  if(base_addr < 0)
-    {
+       if (wv_struct_check() != (char *) NULL) {
+               printk(KERN_WARNING
+                      "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n",
+                      dev->name, wv_struct_check());
+               return ENODEV;
+       }
+#endif                         /* STRUCT_CHECK */
+
+       /* Check the value of the command line parameter for base address. */
+       base_addr = dev->base_addr;
+
+       /* Don't probe at all. */
+       if (base_addr < 0) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_WARNING "%s: wavelan_probe(): invalid base address\n",
-            dev->name);
+               printk(KERN_WARNING
+                      "%s: wavelan_probe(): invalid base address\n",
+                      dev->name);
 #endif
-      return ENXIO;
-    }
-
-  /* Check a single specified location. */
-  if(base_addr > 0x100)
-    {
-      /* Check if there is something at this base address */
-      if((r = wv_check_ioaddr(base_addr, mac)) == 0)
-       {
-         memcpy(dev->dev_addr, mac, 6);        /* Copy MAC address. */
-         r = wavelan_config(dev);
+               return ENXIO;
        }
 
+       /* Check a single specified location. */
+       if (base_addr > 0x100) {
+               /* Check if there is something at this base address */
+               if ((r = wv_check_ioaddr(base_addr, mac)) == 0) {
+                       memcpy(dev->dev_addr, mac, 6);  /* Copy MAC address. */
+                       r = wavelan_config(dev);
+               }
 #ifdef DEBUG_CONFIG_INFO
-      if(r != 0)
-       printk(KERN_DEBUG "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n",
-              dev->name, base_addr);
+               if (r != 0)
+                       printk(KERN_DEBUG
+                              "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n",
+                              dev->name, base_addr);
 #endif
 
 #ifdef DEBUG_CALLBACK_TRACE
-      printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
+               printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
 #endif
-      return r;
-    }
-
-  /* Scan all possible addresses of the WaveLAN hardware. */
-  for(i = 0; i < NELS(iobase); i++)
-    {
-      /* Check whether there is something at this base address. */
-      if(wv_check_ioaddr(iobase[i], mac) == 0)
-       {
-         dev->base_addr = iobase[i];           /* Copy base address. */
-         memcpy(dev->dev_addr, mac, 6);        /* Copy MAC address. */
-         if(wavelan_config(dev) == 0)
-           {
+               return r;
+       }
+
+       /* Scan all possible addresses of the WaveLAN hardware. */
+       for (i = 0; i < NELS(iobase); i++) {
+               /* Check whether there is something at this base address. */
+               if (wv_check_ioaddr(iobase[i], mac) == 0) {
+                       dev->base_addr = iobase[i];     /* Copy base address. */
+                       memcpy(dev->dev_addr, mac, 6);  /* Copy MAC address. */
+                       if (wavelan_config(dev) == 0) {
 #ifdef DEBUG_CALLBACK_TRACE
-             printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
+                               printk(KERN_DEBUG
+                                      "%s: <-wavelan_probe()\n",
+                                      dev->name);
 #endif
-             return 0;
-           }
+                               return 0;
+                       }
+               }
        }
-    }
 
-  /* We may have touched base_addr.  Another driver may not like it. */
-  dev->base_addr = base_addr;
+       /* We may have touched base_addr.  Another driver may not like it. */
+       dev->base_addr = base_addr;
 
 #ifdef DEBUG_CONFIG_INFO
-  printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n",
-        dev->name);
+       printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n",
+              dev->name);
 #endif
 
-  return ENODEV;
+       return ENODEV;
 }
 
 /****************************** MODULE ******************************/
@@ -4243,120 +4141,115 @@ wavelan_probe(device *        dev)
  * Insertion of the module
  * I'm now quite proud of the multi-device support.
  */
-int
-init_module(void)
+int init_module(void)
 {
-  mac_addr     mac;            /* MAC address (check WaveLAN existence) */
-  int          ret = -EIO;     /* Return error if no cards found */
-  int          i;
+       mac_addr mac;           /* MAC address (check WaveLAN existence) */
+       int ret = -EIO;         /* Return error if no cards found */
+       int i;
 
 #ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> init_module()\n");
+       printk(KERN_DEBUG "-> init_module()\n");
 #endif
 
-  /* If probing is asked */
-  if(io[0] == 0)
-    {
+       /* If probing is asked */
+       if (io[0] == 0) {
 #ifdef DEBUG_CONFIG_ERROR
-      printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n");
-      printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n");
+               printk(KERN_WARNING
+                      "WaveLAN init_module(): doing device probing (bad !)\n");
+               printk(KERN_WARNING
+                      "Specify base addresses while loading module to correct the problem\n");
 #endif
 
-      /* Copy the basic set of address to be probed. */
-      for(i = 0; i < NELS(iobase); i++)
-       io[i] = iobase[i];
-    }
+               /* Copy the basic set of address to be probed. */
+               for (i = 0; i < NELS(iobase); i++)
+                       io[i] = iobase[i];
+       }
 
 
-  /* Loop on all possible base addresses. */
-  i = -1;
-  while((io[++i] != 0) && (i < NELS(io)))
-    {
-      /* Check if there is something at this base address. */
-      if(wv_check_ioaddr(io[i], mac) == 0)
-       {
-         device *      dev;
-
-         /* Create device and set basic arguments. */
-         dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-         if(dev==NULL)
-         {
-               ret = -ENOMEM;
-               break;
-         }
-         memset(dev, 0x00, sizeof(struct net_device));
-         dev->name = name[i];
-         dev->base_addr = io[i];
-         dev->irq = irq[i];
-         dev->init = &wavelan_config;
-         memcpy(dev->dev_addr, mac, 6);        /* Copy MAC address. */
-
-         /* Try to create the device. */
-         if(register_netdev(dev) != 0)
-           {
-             /* Deallocate everything. */
-             /* Note: if dev->priv is mallocated, there is no way to fail. */
-             kfree_s(dev, sizeof(struct net_device));
-           }
-         else
-           {
-              /* If at least one device OK, we do not fail */
-              ret = 0;
-           }
-       }       /* if there is something at the address */
-    }          /* Loop on all addresses. */
+       /* Loop on all possible base addresses. */
+       i = -1;
+       while ((io[++i] != 0) && (i < NELS(io))) {
+               /* Check if there is something at this base address. */
+               if (wv_check_ioaddr(io[i], mac) == 0) {
+                       device *dev;
+
+                       /* Create device and set basic arguments. */
+                       dev =
+                           kmalloc(sizeof(struct net_device), GFP_KERNEL);
+                       if (dev == NULL) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       memset(dev, 0x00, sizeof(struct net_device));
+                       dev->name = name[i];
+                       dev->base_addr = io[i];
+                       dev->irq = irq[i];
+                       dev->init = &wavelan_config;
+                       memcpy(dev->dev_addr, mac, 6);  /* Copy MAC address. */
+
+                       /* Try to create the device. */
+                       if (register_netdev(dev) != 0) {
+                               /* Deallocate everything. */
+                               /* Note: if dev->priv is mallocated, there is no way to fail. */
+                               kfree_s(dev, sizeof(struct net_device));
+                       } else {
+                               /* If at least one device OK, we do not fail */
+                               ret = 0;
+                       }
+               }               /* if there is something at the address */
+       }                       /* Loop on all addresses. */
 
 #ifdef DEBUG_CONFIG_ERROR
-  if(wavelan_list == (net_local *) NULL)
-    printk(KERN_WARNING "WaveLAN init_module(): no device found\n");
+       if (wavelan_list == (net_local *) NULL)
+               printk(KERN_WARNING
+                      "WaveLAN init_module(): no device found\n");
 #endif
 
 #ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- init_module()\n");
+       printk(KERN_DEBUG "<- init_module()\n");
 #endif
-  return ret;
+       return ret;
 }
 
 /*------------------------------------------------------------------*/
 /*
  * Removal of the module
  */
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
 #ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> cleanup_module()\n");
+       printk(KERN_DEBUG "-> cleanup_module()\n");
 #endif
 
-  /* Loop on all devices and release them. */
-  while(wavelan_list != (net_local *) NULL)
-    {
-      device * dev = wavelan_list->dev;
+       /* Loop on all devices and release them. */
+       while (wavelan_list != (net_local *) NULL) {
+               device *dev = wavelan_list->dev;
 
 #ifdef DEBUG_CONFIG_INFO
-      printk(KERN_DEBUG "%s: cleanup_module(): removing device at 0x%x\n",
-            dev->name, (unsigned int) dev);
+               printk(KERN_DEBUG
+                      "%s: cleanup_module(): removing device at 0x%x\n",
+                      dev->name, (unsigned int) dev);
 #endif
 
-      /* Release the ioport region. */
-      release_region(dev->base_addr, sizeof(ha_t));
+               /* Release the ioport region. */
+               release_region(dev->base_addr, sizeof(ha_t));
 
-      /* Definitely remove the device. */
-      unregister_netdev(dev);
+               /* Definitely remove the device. */
+               unregister_netdev(dev);
 
-      /* Unlink the device. */
-      wavelan_list = wavelan_list->next;
+               /* Unlink the device. */
+               wavelan_list = wavelan_list->next;
 
-      /* Free pieces. */
-      kfree_s(dev->priv, sizeof(struct net_local));
-      kfree_s(dev, sizeof(struct net_device));
-    }
+               /* Free pieces. */
+               kfree_s(dev->priv, sizeof(struct net_local));
+               kfree_s(dev, sizeof(struct net_device));
+       }
 
 #ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- cleanup_module()\n");
+       printk(KERN_DEBUG "<- cleanup_module()\n");
 #endif
 }
-#endif /* MODULE */
+#endif                         /* MODULE */
 
 /*
  * This software may only be used and distributed
@@ -4379,7 +4272,7 @@ cleanup_module(void)
  *
  * Thanks go also to:
  *     James Ashton (jaa101@syseng.anu.edu.au),
- *     Alan Cox (iialan@iiit.swan.ac.uk),
+ *     Alan Cox (alan@redhat.com),
  *     Allan Creighton (allanc@cs.usyd.edu.au),
  *     Matthew Geier (matthew@cs.usyd.edu.au),
  *     Remo di Giovanni (remo@cs.usyd.edu.au),
index f48e41e7ed683dd8479112e5d3cb4dde8e2dfe65..7ca88c26a6a7cf22ea4a9336d41c981ef4d3734f 100644 (file)
@@ -119,10 +119,13 @@ static unsigned int znet_debug = ZNET_DEBUG;
 #define CMD0_STAT2 (2 << 5)
 #define CMD0_STAT3 (3 << 5)
 
+#define TX_TIMEOUT     10
+
 #define net_local znet_private
 struct znet_private {
        int rx_dma, tx_dma;
        struct net_device_stats stats;
+       spinlock_t lock;
        /* The starting, current, and end pointers for the packet buffers. */
        ushort *rx_start, *rx_cur, *rx_end;
        ushort *tx_start, *tx_cur, *tx_end;
@@ -190,6 +193,7 @@ static struct net_device_stats *net_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void hardware_init(struct net_device *dev);
 static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset);
+static void znet_tx_timeout (struct net_device *dev);
 
 #ifdef notdef
 static struct sigaction znet_sigaction = { &znet_interrupt, 0, 0, NULL, };
@@ -245,6 +249,7 @@ int __init znet_probe(struct net_device *dev)
        dev->priv = (void *) &zn;
        zn.rx_dma = netinfo->dma1;
        zn.tx_dma = netinfo->dma2;
+       zn.lock = SPIN_LOCK_UNLOCKED;
 
        /* These should never fail.  You can't add devices to a sealed box! */
        if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet", dev)
@@ -275,6 +280,8 @@ int __init znet_probe(struct net_device *dev)
        dev->stop = &znet_close;
        dev->get_stats  = net_get_stats;
        dev->set_multicast_list = &set_multicast_list;
+       dev->tx_timeout = znet_tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
 
        /* Fill in the 'dev' with ethernet-generic values. */
        ether_setup(dev);
@@ -306,41 +313,47 @@ static int znet_open(struct net_device *dev)
                printk(KERN_WARNING "%s: Problem turning on the transceiver power.\n",
                           dev->name);
 
-       dev->tbusy = 0;
-       dev->interrupt = 0;
        hardware_init(dev);
-       dev->start = 1;
+       netif_start_queue (dev);
 
        return 0;
 }
 
+
+static void znet_tx_timeout (struct net_device *dev)
+{
+       int ioaddr = dev->base_addr;
+       ushort event, tx_status, rx_offset, state;
+
+       outb (CMD0_STAT0, ioaddr);
+       event = inb (ioaddr);
+       outb (CMD0_STAT1, ioaddr);
+       tx_status = inw (ioaddr);
+       outb (CMD0_STAT2, ioaddr);
+       rx_offset = inw (ioaddr);
+       outb (CMD0_STAT3, ioaddr);
+       state = inb (ioaddr);
+       printk (KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x,"
+        " resetting.\n", dev->name, event, tx_status, rx_offset, state);
+       if (tx_status == 0x0400)
+               printk (KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n",
+                       dev->name);
+       outb (CMD0_RESET, ioaddr);
+       hardware_init (dev);
+       netif_start_queue (dev);
+}
+
 static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
        int ioaddr = dev->base_addr;
        struct net_local *lp = (struct net_local *)dev->priv;
+       unsigned long flags;
 
        if (znet_debug > 4)
-               printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy);
-
-       /* Transmitter timeout, likely just recovery after suspending the machine. */
-       if (dev->tbusy) {
-               ushort event, tx_status, rx_offset, state;
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 10)
-                       return 1;
-               outb(CMD0_STAT0, ioaddr); event = inb(ioaddr);
-               outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr);
-               outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr);
-               outb(CMD0_STAT3, ioaddr); state = inb(ioaddr);
-               printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x,"
-                          " resetting.\n", dev->name, event, tx_status, rx_offset, state);
-               if (tx_status == 0x0400)
-                 printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n",
-                                dev->name);
-               outb(CMD0_RESET, ioaddr);
-               hardware_init(dev);
-       }
+               printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name);
 
+       netif_stop_queue (dev);
+       
        /* Check that the part hasn't reset itself, probably from suspend. */
        outb(CMD0_STAT0, ioaddr);
        if (inw(ioaddr) == 0x0010
@@ -348,11 +361,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
                && inw(ioaddr) == 0x0010)
          hardware_init(dev);
 
-       /* Block a timer-based transmit from overlapping.  This could better be
-          done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-               printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
-       else {
+       if (1) {
                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
                unsigned char *buf = (void *)skb->data;
                ushort *tx_link = zn.tx_cur - 1;
@@ -385,13 +394,18 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
                        zn.tx_cur += rnd_len;
                }
                *zn.tx_cur++ = 0;
-               cli(); {
+
+               spin_lock_irqsave(&lp->lock, flags);
+               {
                        *tx_link = CMD0_TRANSMIT + CMD0_CHNL_1;
                        /* Is this always safe to do? */
                        outb(CMD0_TRANSMIT + CMD0_CHNL_1,ioaddr);
-               } sti();
+               }
+               spin_unlock_irqrestore (&lp->lock, flags);
 
                dev->trans_start = jiffies;
+               netif_start_queue (dev);
+
                if (znet_debug > 4)
                  printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length);
        }
@@ -403,6 +417,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
 static void    znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        struct net_device *dev = dev_id;
+       struct net_local *lp = (struct net_local *)dev->priv;
        int ioaddr;
        int boguscnt = 20;
 
@@ -411,7 +426,8 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                return;
        }
 
-       dev->interrupt = 1;
+       spin_lock (&lp->lock);
+       
        ioaddr = dev->base_addr;
 
        outb(CMD0_STAT0, ioaddr);
@@ -432,7 +448,6 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                        break;
 
                if ((status & 0x0F) == 4) {     /* Transmit done. */
-                       struct net_local *lp = (struct net_local *)dev->priv;
                        int tx_status;
                        outb(CMD0_STAT1, ioaddr);
                        tx_status = inw(ioaddr);
@@ -449,8 +464,7 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                                if ((tx_status | 0x0760) != 0x0760)
                                  lp->stats.tx_errors++;
                        }
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);        /* Inform upper layers. */
+                       netif_wake_queue (dev);
                }
 
                if ((status & 0x40)
@@ -461,7 +475,8 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                outb(CMD0_ACK,ioaddr);
        } while (boguscnt--);
 
-       dev->interrupt = 0;
+       spin_unlock (&lp->lock);
+       
        return;
 }
 
@@ -594,8 +609,7 @@ static int znet_close(struct net_device *dev)
        unsigned long flags;
        int ioaddr = dev->base_addr;
 
-       dev->tbusy = 1;
-       dev->start = 0;
+       netif_stop_queue (dev);
 
        outb(CMD0_RESET, ioaddr);                       /* CMD0_RESET */
 
@@ -728,7 +742,7 @@ static void hardware_init(struct net_device *dev)
        update_stop_hit(ioaddr, 8192);
        if (znet_debug > 1)  printk("enabling Rx.\n");
        outb(CMD0_Rx_ENABLE+CMD0_CHNL_0, ioaddr);
-       dev->tbusy = 0;
+       netif_start_queue (dev);
 }
 
 static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset)
index 543a98419ef1018af0ee986ca37276c3bb95116d..e216ef03a0eb5a842b75f15ecae986faae15eef7 100644 (file)
@@ -182,6 +182,7 @@ END OF TERMS AND CONDITIONS
     -   Initial Beta Release.  
 *****************************************************************************/
 
+
 #ifdef MODULE
 #include <linux/module.h>
 #endif
@@ -2789,7 +2790,7 @@ qla1280_setup_chip(scsi_qla_host_t *ha)
 
         DEBUG(sprintf(debug_buff,"qla1280_setup_chip:  loading risc @ =(0x%p),%d,%d(0x%x).\n\r",risc_code_address,cnt,num,risc_address);)
         DEBUG(qla1280_print(debug_buff));
-        printk("qla1280_setup_chip:  loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address);
+        DEBUG(printk("qla1280_setup_chip:  loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address));
         BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, (cnt <<1));
         mb[0] = MBC_LOAD_RAM; 
         /* mb[0] = MBC_LOAD_RAM_A64; */
@@ -2799,7 +2800,7 @@ qla1280_setup_chip(scsi_qla_host_t *ha)
         mb[2] = (uint16_t) (ha->request_dma >> 16) & 0xffff;
         mb[7] = (uint16_t) (MS_64BITS(ha->request_dma) & 0xffff);
         mb[6] = (uint16_t) (MS_64BITS(ha->request_dma) >> 16) & 0xffff;
-        printk("qla1280_setup_chip: op=%d  0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3]);
+        DEBUG(printk("qla1280_setup_chip: op=%d  0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3]));
         if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
             &mb[0]))  )
         {
index f0630dadaffdae240f33dd226f725c600a5e4427..1456858ee379bd96a693db50ce6b329d82e2f38c 100644 (file)
@@ -811,6 +811,7 @@ int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
                ds = cmd->dataseg;
 
                sg_count = pci_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg);
+               Cmnd->use_sg = sg_count;
 
                cmd->segment_cnt = cpu_to_le16(sg_count);
 
index ae627ed3b761d44fb9af9bbf1faaa4d5da3e3061..06be153261de11889b7e3f39fbec3434cf566238 100644 (file)
@@ -116,6 +116,7 @@ History:
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
+#include <asm/feature.h>
 #include "awacs_defs.h"
 #include <linux/nvram.h>
 #include <linux/vt_kern.h>
@@ -178,6 +179,7 @@ static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma;
 static int awacs_rate_index;
 static int awacs_subframe;
 static int awacs_spkr_vol;
+static struct device_node* awacs_node;
 
 static int awacs_revision;
 #define AWACS_BURGUNDY 100             /* fake revision # for burgundy */
@@ -898,7 +900,7 @@ static inline int ioctl_return(int *addr, int value)
 
 
 void dmasound_init(void);
-void dmasound_setup(char *str, int *ints);
+static int dmasound_setup(char *str);
 
 
 /*** Translations ************************************************************/
@@ -3208,9 +3210,15 @@ static void PMacIrqCleanup(void)
        out_le32(&awacs_txdma->control, RUN<<16);
        /* disable interrupts from awacs interface */
        out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff);
-       free_irq(awacs_irq, pmac_awacs_intr);
-       free_irq(awacs_tx_irq, pmac_awacs_tx_intr);
-       free_irq(awacs_rx_irq, pmac_awacs_rx_intr);
+#ifdef CONFIG_PMAC_PBOOK
+       if (is_pbook_G3) {
+               feature_clear(awacs_node, FEATURE_Sound_power);
+               feature_clear(awacs_node, FEATURE_Sound_CLK_enable);
+       }
+#endif
+       free_irq(awacs_irq, 0);
+       free_irq(awacs_tx_irq, 0);
+       free_irq(awacs_rx_irq, 0);
        kfree(awacs_tx_cmd_space);
        if (awacs_rx_cmd_space)
                kfree(awacs_rx_cmd_space);
@@ -3281,12 +3289,10 @@ static void PMacInit(void)
        /* We really want to execute a DMA stop command, after the AWACS
         * is initialized.
         * For reasons I don't understand, it stops the hissing noise
-        * common to many PowerBook G3 systems (like mine :-).  Maybe it
-        * is just the AWACS control register change......
+        * common to many PowerBook G3 systems (like mine :-).
         */
        out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
        st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
-       out_le32(&awacs->control, (in_le32(&awacs->control) & ~0x1f00));
        out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
        out_le32(&awacs_txdma->control, RUN | (RUN << 16));
 
@@ -3544,6 +3550,11 @@ static void awacs_nosound(unsigned long xx)
        save_flags(flags); cli();
        if (beep_playing) {
                st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
+               out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
+               out_le32(&awacs->control,
+                        (in_le32(&awacs->control) & ~0x1f00)
+                        | (awacs_rate_index << 8));
+               out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
                beep_playing = 0;
        }
        restore_flags(flags);
@@ -3645,8 +3656,23 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
                PMacSilence();
                disable_irq(awacs_irq);
                disable_irq(awacs_tx_irq);
+               if (is_pbook_G3) {
+                       feature_clear(awacs_node, FEATURE_Sound_CLK_enable);
+                       feature_clear(awacs_node, FEATURE_Sound_power);
+               }
                break;
        case PBOOK_WAKE:
+               /* There is still a problem on wake. Sound seems to work fine
+                  if I launch mpg123 and resumes fine if mpg123 was playing,
+                  but the console beep is dead until I do something with the
+                  mixer. Probably yet another timing issue */
+               if (!feature_test(awacs_node, FEATURE_Sound_CLK_enable)
+                   || !feature_test(awacs_node, FEATURE_Sound_power)) {
+                       /* these aren't present on the 3400 AFAIK -- paulus */
+                       feature_set(awacs_node, FEATURE_Sound_CLK_enable);
+                       feature_set(awacs_node, FEATURE_Sound_power);
+                       mdelay(1000);
+               }
                out_le32(&awacs->control, MASK_IEPC
                         | (awacs_rate_index << 8) | 0x11
                         | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0));
@@ -3663,6 +3689,16 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
                        mdelay(2);
                        awacs_write(awacs_reg[1] | MASK_ADDR1);
                }
+               /* enable CD sound input */
+               if (macio_base && is_pbook_G3) {
+                       out_8(macio_base + 0x37, 3);
+               } else if (is_pbook_3400) {
+                       feature_set(awacs_node, FEATURE_IOBUS_enable);
+                       udelay(10);
+                       in_8((unsigned char *)0xf301a190);
+               }
+               /* Resume pending sounds. */
+               PMacPlay();
        }
        return PBOOK_SLEEP_OK;
 }
@@ -5139,6 +5175,7 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
        u_long fmt;
        int data;
        int size, nbufs;
+       audio_buf_info info;
 
        switch (cmd) {
        case SNDCTL_DSP_RESET:
@@ -5214,6 +5251,14 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
                sq_setup(numBufs, size, sound_buffers);
                sq.max_active = nbufs;
                return 0;
+       case SNDCTL_DSP_GETOSPACE:
+               info.fragments = sq.max_active - sq.count;
+               info.fragstotal = sq.max_active;
+               info.fragsize = sq.block_size;
+               info.bytes = info.fragments * info.fragsize;
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
 
        default:
                return mixer_ioctl(inode, file, cmd, arg);
@@ -5308,7 +5353,7 @@ static int state_open(struct inode *inode, struct file *file)
 {
        char *buffer = state.buf, *mach = "";
 #ifdef CONFIG_PPC
-       char awacs_buf[50];
+       char awacs_buf[64];
 #endif
        int len = 0;
 
@@ -5576,6 +5621,16 @@ void __init dmasound_init(void)
                        printk(KERN_ERR "DMA sound driver: Not enough buffer memory, driver disabled!\n");
                        return;
                }
+               awacs_node = np;
+#ifdef CONFIG_PMAC_PBOOK
+               if (machine_is_compatible("PowerBook1,1")
+                   || machine_is_compatible("AAPL,PowerBook1998")) {
+                       feature_set(np, FEATURE_Sound_CLK_enable);
+                       feature_set(np, FEATURE_Sound_power);
+                       /* Shorter delay will not work */
+                       mdelay(1000);
+               }
+#endif
                awacs_tx_cmds = (volatile struct dbdma_cmd *)
                        DBDMA_ALIGN(awacs_tx_cmd_space);
 
@@ -5607,7 +5662,10 @@ void __init dmasound_init(void)
                        awacs_revision =
                                (in_le32(&awacs->codec_stat) >> 12) & 0xf;
                        if (awacs_revision == 3) {
+                               mdelay(100);
                                awacs_write(0x6000);
+                               mdelay(2);
+                               awacs_write(awacs_reg[1] + MASK_ADDR1);
                                awacs_enable_amp(100 * 0x101);
                        }
                }
@@ -5629,26 +5687,34 @@ void __init dmasound_init(void)
                /* Powerbooks have odd ways of enabling inputs such as
                   an expansion-bay CD or sound from an internal modem
                   or a PC-card modem. */
-               if (machine_is_compatible("AAPL,3400/2400")) {
+               if (machine_is_compatible("AAPL,3400/2400")
+                       || machine_is_compatible("AAPL,3500")) {
                        is_pbook_3400 = 1;
                        /*
                         * Enable CD and PC-card sound inputs.
                         * This is done by reading from address
                         * f301a000, + 0x10 to enable the expansion-bay
                         * CD sound input, + 0x80 to enable the PC-card
-                        * sound input.  The 0x100 seems to enable the
-                        * MESH and/or its SCSI bus drivers.
+                        * sound input.  The 0x100 enables the SCSI bus
+                        * terminator power.
                         */
                        in_8((unsigned char *)0xf301a190);
-               } else if (machine_is_compatible("PowerBook1,1")) {
-                       np = find_devices("mac-io");
-                       if (np && np->n_addrs > 0) {
-                               is_pbook_G3 = 1;
-                               macio_base = (unsigned char *)
-                                       ioremap(np->addrs[0].address, 0x40);
-                               /* enable CD sound input */
-                               out_8(macio_base + 0x37, 3);
+               } else if (machine_is_compatible("PowerBook1,1")
+                          || machine_is_compatible("AAPL,PowerBook1998")) {
+                       struct device_node* mio;
+                       macio_base = 0;
+                       is_pbook_G3 = 1;
+                       for (mio = np->parent; mio; mio = mio->parent) {
+                               if (strcmp(mio->name, "mac-io") == 0
+                                   && mio->n_addrs > 0) {
+                                       macio_base = (unsigned char *) ioremap
+                                               (mio->addrs[0].address, 0x40);
+                                       break;
+                               }
                        }
+                       /* enable CD sound input */
+                       if (macio_base)
+                               out_8(macio_base + 0x37, 3);
                }
        }
 #endif /* CONFIG_PPC */
index c157e62f7aba039721132acc89ec5091cce6d3b6..b2fd41ca49c3ac7a5912b307f48e86dbc61878c5 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
 
 static unsigned char keybdev_x86_e0s[] = 
        { 0x1c, 0x1d, 0x35, 0x2a, 0x38, 0x39, 0x47, 0x48,
@@ -77,7 +77,7 @@ void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int
 {
        if (type != EV_KEY || code > 255) return;
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
 
        if (code >= 189) {
                printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code);
index cfd83644f18fcfad37724657b980a0ecf71bd2e2..cc806fbce3a98f5f6ab907b246383d11a02aaa90 100644 (file)
@@ -1675,9 +1675,9 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
 #endif /* CONFIG_PPC */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)
-    if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
-                      &defaultmode, 8))
-        var = default_var;
+       if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
+                         &defaultmode, 8))
+           var = default_var;
 #endif
 
 #ifdef CONFIG_PPC
@@ -1685,6 +1685,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
         if (mac_vmode_to_var(default_vmode, default_cmode, &var))
             var = default_var;
 #endif /* CONFIG_PPC */
+    }
 #endif /* MODULE */
 
     if (noaccel)
index a132dada1b073e648d3a64b4f9b58f451982d558..57ae6e15ebcfd1264da0c6049034c8f85c38d410 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.138 2000/02/10 02:52:12 davem Exp $
+/*  $Id: atyfb.c,v 1.139 2000/02/12 22:47:04 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *     Copyright (C) 1997-1998  Geert Uytterhoeven
index eb3a6df36f48d98b2d417298006f933239a0eb15..d462fb621ac85b6d8bddcdcf4c2904bcd0f1035d 100644 (file)
@@ -713,8 +713,8 @@ int __init igafb_init(void)
        info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
        if (!info->mmap_map) {
                printk("igafb_init: can't alloc mmap_map\n");
-               iounmap(info->io_base);
-               iounmap((void *)info->frame_buffer);
+               iounmap((void *)info->io_base);
+               iounmap(info->frame_buffer);
                 kfree(info);
                return -ENOMEM;
        }
@@ -768,8 +768,8 @@ int __init igafb_init(void)
 #endif
 
        if (!iga_init(info)) {
-               iounmap(info->io_base);
-               iounmap((void *)info->frame_buffer);
+               iounmap((void *)info->io_base);
+               iounmap(info->frame_buffer);
                if (info->mmap_map)
                        kfree(info->mmap_map);
                kfree(info);
index 934a7a70aaec605004424f1524d377a5c2802ba7..07b80515cdcc8171ebf9ec24b63f4e572e80b750 100644 (file)
@@ -60,7 +60,9 @@ tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
 dep_bool '  SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE $CONFIG_SYSV_FS $CONFIG_EXPERIMENTAL
 
 tristate 'UDF filesystem support (read only)' CONFIG_UDF_FS
-dep_bool '  UDF write support (DANGEROUS)' CONFIG_UDF_RW $CONFIG_UDF_FS $CONFIG_EXPERIMENTAL
+if [ "$CONFIG_UDF_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  dep_bool '  UDF write support (DANGEROUS)' CONFIG_UDF_RW
+fi
 
 tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
 dep_bool '  UFS filesystem write support (DANGEROUS)' CONFIG_UFS_FS_WRITE $CONFIG_UFS_FS $CONFIG_EXPERIMENTAL
index a2f105b06d85ebfe16086e8f6c4133dea0c61b7a..0d5f4346e2b6ab6533660e1fb604aa62fd0bf483 100644 (file)
@@ -44,4 +44,8 @@ static struct file_operations adfs_file_operations = {
 
 struct inode_operations adfs_file_inode_operations = {
        &adfs_file_operations,  /* default file operations */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+       readpage:       generic_readpage,
+       bmap:           adfs_bmap,
+#endif
 };
index 30398d62f9c830640738c12edacac710ed68cb9a..96b3370ff4e0981a1246853256e2046db11965f6 100644 (file)
@@ -48,30 +48,36 @@ abort_negative:
 abort_toobig:
        return 0;
 }
+
 static int adfs_writepage(struct dentry *dentry, struct page *page)
 {
-       return block_write_full_page(page,adfs_get_block);
+       return block_write_full_page(page, adfs_get_block);
 }
+
 static int adfs_readpage(struct dentry *dentry, struct page *page)
 {
-       return block_read_full_page(page,adfs_get_block);
+       return block_read_full_page(page, adfs_get_block);
 }
-static int adfs_prepare_write(struct page *page, unsigned from, unsigned to)
+
+static int adfs_prepare_write(struct page *page, unsigned int from, unsigned int to)
 {
-       return cont_prepare_write(page,from,to,adfs_get_block,
-               &((struct inode*)page->mapping->host)->u.adfs_i.mmu_private);
+       return cont_prepare_write(page, from, to, adfs_get_block,
+               &((struct inode *)page->mapping->host)->u.adfs_i.mmu_private);
 }
+
 static int _adfs_bmap(struct address_space *mapping, long block)
 {
-       return generic_block_bmap(mapping,block,adfs_get_block);
+       return generic_block_bmap(mapping, block, adfs_get_block);
 }
-struct address_space_operations adfs_aops = {
-       readpage: adfs_readpage,
-       writepage: adfs_writepage,
-       prepare_write: adfs_prepare_write,
-       commit_write: generic_commit_write,
-       bmap: _adfs_bmap
+
+static struct address_space_operations adfs_aops = {
+       readpage:       adfs_readpage,
+       writepage:      adfs_writepage,
+       prepare_write:  adfs_prepare_write,
+       commit_write:   generic_commit_write,
+       bmap:           _adfs_bmap
 };
+
 #else
 int adfs_bmap(struct inode *inode, int block)
 {
@@ -280,7 +286,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
        if (S_ISDIR(inode->i_mode))
                inode->i_op     = &adfs_dir_inode_operations;
        else if (S_ISREG(inode->i_mode)) {
-               inode->i_op      = &adfs_file_inode_operations;
+               inode->i_op     = &adfs_file_inode_operations;
                inode->i_mapping->a_ops = &adfs_aops;
                inode->u.adfs_i.mmu_private = inode->i_size;
        }
index 0fde11f5da950c61d8ae3788a36b37317c758e42..0c6507411ab9ad408bf3794132a1f960685aef9f 100644 (file)
@@ -44,7 +44,6 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen,
                /*
                 * get fragment id
                 */
-               //asm("@ get fragment id start");
                {
                        unsigned long v2;
                        unsigned int tmp;
@@ -60,14 +59,12 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen,
 
                        frag &= idmask;
                }
-               //asm("@ get fragment id end");
 
                mapptr = start + idlen;
 
                /*
                 * find end of fragment
                 */
-               //asm("@ find end of fragment start");
                {
                        unsigned long v2;
 
@@ -79,7 +76,6 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen,
 
                        mapptr += 1 + ffz(~v2);
                }
-               //asm("@ find end of fragment end");
 
                if (frag == frag_id)
                        goto found;
@@ -122,7 +118,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
        /*
         * get fragment id
         */
-       //asm("@ get fragment id start");
        {
                unsigned long v2;
                unsigned int tmp;
@@ -138,7 +133,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
 
                frag &= idmask;
        }
-       //asm("@ get fragment id end");
 
        /*
         * If the freelink is null, then no free fragments
@@ -153,7 +147,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
                /*
                 * get fragment id
                 */
-               //asm("@ get fragment id start");
                {
                        unsigned long v2;
                        unsigned int tmp;
@@ -169,14 +162,12 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
 
                        frag &= idmask;
                }
-               //asm("@ get fragment id end");
 
                mapptr = start + idlen;
 
                /*
                 * find end of fragment
                 */
-               //asm("@ find end of fragment start");
                {
                        unsigned long v2;
 
@@ -188,7 +179,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
 
                        mapptr += 1 + ffz(~v2);
                }
-               //asm("@ find end of fragment end");
 
                total += mapptr - start;
        } while (frag >= idlen + 1);
index 21adfd00ebbb38beadb40135506c348f75f82bb2..d49af37d1951192cc9d884ede5b8fb8cd8684ff2 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -99,5 +99,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
                if (!error)
                        inode_setattr(inode, attr);
        }
+       if (!error && (attr->ia_valid & ATTR_SIZE))
+               vmtruncate(inode, attr->ia_size);
        return error;
 }
index 3ca25fedf081d0d0f8fcfae60fc4f5e8b9034fa9..6638170858120981e86b1d440afbbb84d0b0e735 100644 (file)
@@ -329,21 +329,18 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry)
                d_delete(dentry);
        } else {        /* no space for deleting, try to truncate file */
                struct iattr newattrs;
+               int err;
                hpfs_unlock_2inodes(dir, inode);
                if (rep || dentry->d_count > 1 || permission(inode, MAY_WRITE) || get_write_access(inode)) goto ret;
                /*printk("HPFS: truncating file before delete.\n");*/
-               down(&inode->i_sem);    /* do_truncate should be called here, but it's */
-               newattrs.ia_size = 0;   /* not exported */
+               down(&inode->i_sem);
+               newattrs.ia_size = 0;
                newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-               if (notify_change(dentry, &newattrs)) {
-                       up(&inode->i_sem);
-                       put_write_access(inode);
-                       goto ret;
-               }
-               vmtruncate(inode, 0);
-               if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode);
+               err = notify_change(dentry, &newattrs);
                up(&inode->i_sem);
                put_write_access(inode);
+               if (err)
+                       goto ret;
                rep = 1;
                goto again;
        }
index 3b9927c7a7458b442bbd4c7eccfaf64d5511f937..2532104cc991e9f37d4023b72892581d25638a22 100644 (file)
@@ -301,7 +301,7 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
        struct dentry *dentry, *result = NULL;
        struct dentry *tmp;
        int  found =0;
-       u32 err;
+       long err;
        /* This semaphore is needed to make sure that only one unconnected (free)
         * dcache path ever exists, as otherwise two partial paths might get
         * joined together, which would be very confusing.
index b1af9399ea4789b0e5128cd2aa37c460b0ed6e75..1cfa0515ba2e2357654bda03813c4924caf614ae 100644 (file)
@@ -310,11 +310,6 @@ printk("nfsd_setattr: size change??\n");
        if (iap->ia_valid & ATTR_SIZE) {
                fh_lock(fhp);
                err = notify_change(dentry, iap);
-               if (!err) {
-                       vmtruncate(inode,iap->ia_size);         
-                       if (inode->i_op && inode->i_op->truncate)
-                               inode->i_op->truncate(inode);
-               }
                fh_unlock(fhp);
                put_write_access(inode);
        }
@@ -1082,11 +1077,6 @@ nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size)
                cap_clear(current->cap_effective);
        }
        err = notify_change(dentry, &newattrs);
-       if (!err) {
-               vmtruncate(inode, size);
-               if (inode->i_op && inode->i_op->truncate)
-                       inode->i_op->truncate(inode);
-       }
        if (current->fsuid != 0)
                current->cap_effective = saved_cap;
        put_write_access(inode);
index 159b08bf7ddb264c7b189dc331f642cacee47ba9..808ddcaf8c303905e70af7301a7cb8ba43505b7d 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -69,12 +69,6 @@ int do_truncate(struct dentry *dentry, loff_t length)
        newattrs.ia_size = length;
        newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
        error = notify_change(dentry, &newattrs);
-       if (!error) {
-               /* truncate virtual mappings of this file */
-               vmtruncate(inode, length);
-               if (inode->i_op && inode->i_op->truncate)
-                       inode->i_op->truncate(inode);
-       }
        up(&inode->i_sem);
        return error;
 }
index 7ef200cce1595380335daa85c5b3e6ca6d132e9f..ff8c6e9d1d79003d169f1343a728f532eacebca9 100644 (file)
@@ -249,8 +249,9 @@ extern inline pte_t pte_mkyoung(pte_t pte)  { pte_val(pte) |= __ACCESS_BITS; retu
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 /* to find an entry in a page-table-directory. */
-#define __pgd_offset(address)  ((address >> PGDIR_SHIFT) & PTRS_PER_PGD)
-#define pgd_offset(mm, address)        ((mm)->pgd+__pgd_offset(address))
+#define pgd_index(address)     ((address >> PGDIR_SHIFT) & PTRS_PER_PGD)
+#define __pgd_offset(address)  pgd_index(address)
+#define pgd_offset(mm, address)        ((mm)->pgd+pgd_index(address))
 
 /* Find an entry in the second-level page table.. */
 extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
index 79aec2cf6040befc6756db7fefe440c5b5d90566..399ba566db89168649557f43ccec590e4960d1b4 100644 (file)
@@ -9,7 +9,10 @@ extern unsigned int local_irq_count[NR_CPUS];
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
  */
-#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0)
+#define in_interrupt() ({ const int __cpu = smp_processor_id(); \
+       (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
+
+#define in_irq() (local_irq_count[smp_processor_id()] != 0)
 
 #ifndef __SMP__
 
index 7e2192902fcaaf1cd29b6adf3692a05ce2fbe2ad..871e50a6517f124f32db7c3760557d7e9331cc4b 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef __ASM_ARM_IO_H
 #define __ASM_ARM_IO_H
 
+#include <linux/types.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/io.h>
 #include <asm/proc/io.h>
@@ -66,21 +67,31 @@ extern __inline__ void *phys_to_virt(unsigned long x)
 /*
  * ioremap and friends
  */
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags);
 extern void __iounmap(void *addr);
 
 #define ioremap(off,sz)                        __arch_ioremap((off),(sz),0)
 #define ioremap_nocache(off,sz)                __arch_ioremap((off),(sz),1)
 #define iounmap(_addr)                 __iounmap(_addr)
 
+/*
+ * DMA-consistent mapping functions.  These allocate/free a region of
+ * uncached, unwrite-buffered mapped memory space for use with DMA
+ * devices.  This is the "generic" version.  The PCI specific version
+ * is in pci.h
+ */
+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
+extern void consistent_free(void *vaddr);
+extern void consistent_sync(void *vaddr, size_t size, int rw);
+
 extern void __readwrite_bug(const char *fn);
 
 /*
  * String version of IO memory access ops:
  */
-extern void _memcpy_fromio(void *, unsigned long, unsigned long);
-extern void _memcpy_toio(unsigned long, const void *, unsigned long);
-extern void _memset_io(unsigned long, int, unsigned long);
+extern void _memcpy_fromio(void *, unsigned long, size_t);
+extern void _memcpy_toio(unsigned long, const void *, size_t);
+extern void _memset_io(unsigned long, int, size_t);
 
 #define __raw_writeb(val,addr)         __arch_putb(val,addr)
 #define __raw_writew(val,addr)         __arch_putw(val,addr)
diff --git a/include/asm-arm/md.h b/include/asm-arm/md.h
deleted file mode 100644 (file)
index 0a2c5dd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: md.h,v 1.1 1997/12/15 15:11:57 jj Exp $
- * md.h: High speed xor_block operation for RAID4/5 
- *
- */
-#ifndef __ASM_MD_H
-#define __ASM_MD_H
-
-/* #define HAVE_ARCH_XORBLOCK */
-
-#define MD_XORBLOCK_ALIGNMENT  sizeof(long)
-
-#endif /* __ASM_MD_H */
index 5505909d45773c2aab7a0288f19bb0c9f7d00446..86ade5703166b44ba612617cfaa30c001aed3c42 100644 (file)
@@ -3,5 +3,153 @@
 
 #define pcibios_assign_all_busses()    0
 
-#endif
+#define PCIBIOS_MIN_IO         0x8000
+#define PCIBIOS_MIN_MEM                0x40000000
+
+#ifdef __KERNEL__
+
+#include <asm/scatterlist.h>
+#include <asm/io.h>
+
+struct pci_dev;
+
+/* Allocate and map kernel buffer using consistent mode DMA for a device.
+ * hwdev should be valid struct pci_dev pointer for PCI devices,
+ * NULL for PCI-like buses (ISA, EISA).
+ * Returns non-NULL cpu-view pointer to the buffer if successful and
+ * sets *dma_addrp to the pci side dma address as well, else *dma_addrp
+ * is undefined.
+ */
+#define pci_alloc_consistent(hwdev,size,handle)                \
+       ({                                              \
+               void *__ret;                            \
+               int __gfp = GFP_KERNEL;                 \
+                                                       \
+               if ((hwdev) == NULL ||                  \
+                   (hwdev)->dma_mask != 0xffffffff)    \
+                       __gfp |= GFP_DMA;               \
+                                                       \
+               __ret = consistent_alloc(__gfp, (size), \
+                                        (handle));     \
+               __ret;                                  \
+       })
+
+/* Free and unmap a consistent DMA buffer.
+ * cpu_addr is what was returned from pci_alloc_consistent,
+ * size must be the same as what as passed into pci_alloc_consistent,
+ * and likewise dma_addr must be the same as what *dma_addrp was set to.
+ *
+ * References to the memory and mappings associated with cpu_addr/dma_addr
+ * past this call are illegal.
+ */
+extern inline void
+pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr,
+                   dma_addr_t dma_handle)
+{
+       consistent_free(vaddr);
+}
+
+/* Map a single buffer of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory
+ * until either pci_unmap_single or pci_dma_sync_single is performed.
+ */
+extern inline dma_addr_t
+pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size)
+{
+       consistent_sync(ptr, size, 3);
+       return virt_to_bus(ptr);
+}
+
+/* Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guarenteed to see
+ * whatever the device wrote there.
+ */
+extern inline void
+pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size)
+{
+       /* nothing to do */
+}
+
+/* Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+extern inline int
+pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+{
+       int i;
 
+       for (i = 0; i < nents; i++, sg++)
+               consistent_sync(sg->address, sg->length, 3);
+
+       return nents;
+}
+
+/* Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+extern inline void
+pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+{
+       /* nothing to do */
+}
+
+/* Make physical memory consistent for a single
+ * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, the
+ * device again owns the buffer.
+ */
+extern inline void
+pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size)
+{
+       consistent_sync(bus_to_virt(dma_handle), size, 3);
+}
+
+/* Make physical memory consistent for a set of streaming
+ * mode DMA translations after a transfer.
+ *
+ * The same as pci_dma_sync_single but for a scatter-gather list,
+ * same rules and usage.
+ */
+extern inline void
+pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nelems)
+{
+       int i;
+
+       for (i = 0; i < nelems; i++, sg++)
+               consistent_sync(sg->address, sg->length, 3);
+}
+
+/* These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg)      (virt_to_bus((sg)->address))
+#define sg_dma_len(sg)          ((sg)->length)
+
+#endif /* __KERNEL__ */
+#endif
index 033541764a6b4e65a0b695b137b315cc7fac547b..418ed812abcd59c5b3858c6ed785c3158f025abd 100644 (file)
@@ -122,9 +122,10 @@ extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 #define page_pte(page)         mk_pte(page, __pgprot(0))
 
 /* to find an entry in a page-table-directory */
-#define __pgd_offset(addr)     ((addr) >> PGDIR_SHIFT)
+#define pgd_index(addr)                ((addr) >> PGDIR_SHIFT)
+#define __pgd_offset(addr)     pgd_index(addr)
 
-#define pgd_offset(mm, addr)   ((mm)->pgd+__pgd_offset(addr))
+#define pgd_offset(mm, addr)   ((mm)->pgd+pgd_index(addr))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(addr)     pgd_offset(&init_mm, addr)
index 19fa29bf9ea96e5b2f8decc161cd75272b6dbd1e..6926fad126af550f40c679543956f4d1c7691fe3 100644 (file)
 /*
- * linux/include/asm-arm/proc-armo/semaphore.h
+ * linux/include/asm-arm/proc-armo/locks.h
+ *
+ * Copyright (C) 2000 Russell King
+ *
+ * Interrupt safe locking assembler.
  */
-#ifndef __ASM_PROC_SEMAPHORE_H
-#define __ASM_PROC_SEMAPHORE_H
+#ifndef __ASM_PROC_LOCKS_H
+#define __ASM_PROC_LOCKS_H
 
-/*
- * This is ugly, but we want the default case to fall through.
- * "__down" is the actual routine that waits...
- */
-extern inline void down(struct semaphore * sem)
-{
-       __asm__ __volatile__ ("
-       @ atomic down operation
-       mov     r0, pc
-       orr     lr, r0, #0x08000000
-       teqp    lr, #0
-       ldr     lr, [%0]
-       and     r0, r0, #0x0c000003
-       subs    lr, lr, #1
-       str     lr, [%0]
-       orrmi   r0, r0, #0x80000000     @ set N
-       teqp    r0, #0
-       movmi   r0, %0
-       blmi    " SYMBOL_NAME_STR(__down_failed)
-               :
-               : "r" (sem)
-               : "r0", "lr", "cc");
-}
+#define __down_op(ptr,fail)                    \
+       ({                                      \
+       __asm__ __volatile__ (                  \
+       "@ atomic down operation\n"             \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+"      ldr     lr, [%0]\n"                     \
+"      and     r0, r0, #0x0c000003\n"          \
+"      subs    lr, lr, #1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      orrmi   r0, r0, #0x80000000     @ set N\n" \
+"      teqp    r0, #0\n"                       \
+"      movmi   r0, %0\n"                       \
+       blmi    " SYMBOL_NAME_STR(fail)         \
+       :                                       \
+       : "r" (ptr)                             \
+       : "r0", "lr", "cc");                    \
+       })
 
-/*
- * This is ugly, but we want the default case to fall through.
- * "__down_interruptible" is the actual routine that waits...
- */
-extern inline int down_interruptible (struct semaphore * sem)
-{
-       int result;
-       __asm__ __volatile__ ("
-       @ atomic down operation
-       mov     r0, pc
-       orr     lr, r0, #0x08000000
-       teqp    lr, #0
-       ldr     lr, [%1]
-       and     r0, r0, #0x0c000003
-       subs    lr, lr, #1
-       str     lr, [%1]
-       orrmi   r0, r0, #0x80000000     @ set N
-       teqp    r0, #0
-       movmi   r0, %1
-       movpl   r0, #0
-       blmi    " SYMBOL_NAME_STR(__down_interruptible_failed) "
-       mov     %0, r0"
-               : "=r" (result)
-               : "r" (sem)
-               : "r0", "lr", "cc");
-       return result;
-}
+#define __down_op_ret(ptr,fail)                        \
+       ({                                      \
+               unsigned int result;            \
+       __asm__ __volatile__ (                  \
+"      @ down_op_ret\n"                        \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+"      ldr     lr, [%1]\m"                     \
+"      and     r0, r0, #0x0c000003\n"          \
+"      subs    lr, lr, #1\n"                   \
+"      str     lr, [%1]\n"                     \
+"      orrmi   r0, r0, #0x80000000     @ set N\n" \
+"      teqp    r0, #0\n"                       \
+"      movmi   r0, %1\n"                       \
+"      movpl   r0, #0\n"                       \
+"      blmi    " SYMBOL_NAME_STR(fail) "\n"    \
+"      mov     %0, r0"                         \
+       : "=&r" (result)                        \
+       : "r" (ptr)                             \
+       : "r0", "lr", "cc");                    \
+       result;                                 \
+       })
 
-extern inline int down_trylock(struct semaphore * sem)
-{
-       int result;
-       __asm__ __volatile__ ("
-       @ atomic down operation
-       mov     r0, pc
-       orr     lr, r0, #0x08000000
-       teqp    lr, #0
-       ldr     lr, [%1]
-       and     r0, r0, #0x0c000003
-       subs    lr, lr, #1
-       str     lr, [%1]
-       orrmi   r0, r0, #0x80000000     @ set N
-       teqp    r0, #0
-       movmi   r0, %1
-       movpl   r0, #0
-       blmi    " SYMBOL_NAME_STR(__down_trylock_failed) "
-       mov     %0, r0"
-               : "=r" (result)
-               : "r" (sem)
-               : "r0", "lr", "cc");
-       return result;
-}
-
-/*
- * Note! This is subtle. We jump to wake people up only if
- * the semaphore was negative (== somebody was waiting on it).
- * The default case (no contention) will result in NO
- * jumps for both down() and up().
- */
-extern inline void up(struct semaphore * sem)
-{
-       __asm__ __volatile__ ("
-       @ atomic up operation
-       mov     r0, pc
-       orr     lr, r0, #0x08000000
-       teqp    lr, #0
-       ldr     lr, [%0]
-       and     r0, r0, #0x0c000003
-       adds    lr, lr, #1
-       str     lr, [%0]
-       orrle   r0, r0, #0x80000000     @ set N
-       teqp    r0, #0
-       movmi   r0, %0
-       blmi    " SYMBOL_NAME_STR(__up_wakeup)
-               :
-               : "r" (sem)
-               : "r0", "lr", "cc");
-}
+#define __up_op(ptr,wake)                      \
+       ({                                      \
+       __asm__ __volatile__ (                  \
+       "@ up_op\n"                             \
+       mov     r0, pc\n"                       \
+       orr     lr, r0, #0x08000000\n"          \
+       teqp    lr, #0\n"                       \
+       ldr     lr, [%0]\n"                     \
+       and     r0, r0, #0x0c000003\n"          \
+       adds    lr, lr, #1\n"                   \
+       str     lr, [%0]\n"                     \
+       orrle   r0, r0, #0x80000000     @ set N\n" \
+       teqp    r0, #0\n"                       \
+       movmi   r0, %0\n"                       \
+       blmi    " SYMBOL_NAME_STR(wake)         \
+       :                                       \
+       : "r" (ptr)                             \
+       : "r0", "lr", "cc");                    \
+       })
 
 #endif
diff --git a/include/asm-arm/proc-armv/locks.h b/include/asm-arm/proc-armv/locks.h
new file mode 100644 (file)
index 0000000..c1cfded
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * linux/include/asm-arm/proc-armv/locks.h
+ *
+ * Copyright (C) 2000 Russell King
+ *
+ * Interrupt safe locking assembler. 
+ */
+#ifndef __ASM_PROC_LOCKS_H
+#define __ASM_PROC_LOCKS_H
+
+#define __down_op(ptr,fail)                    \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ down_op\n"                           \
+"      mrs     r0, cpsr\n"                     \
+"      orr     lr, r0, #128\n"                 \
+"      msr     cpsr_c, lr\n"                   \
+"      ldr     lr, [%0]\n"                     \
+"      subs    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      msr     cpsr_c, r0\n"                   \
+"      movmi   r0, %0\n"                       \
+"      blmi    " SYMBOL_NAME_STR(fail)         \
+       :                                       \
+       : "r" (ptr), "I" (1)                    \
+       : "r0", "lr", "cc");                    \
+       })
+
+#define __down_op_ret(ptr,fail)                        \
+       ({                                      \
+               unsigned int ret;               \
+       __asm__ __volatile__(                   \
+       "@ down_op_ret\n"                       \
+"      mrs     r0, cpsr\n"                     \
+"      orr     lr, r0, #128\n"                 \
+"      msr     cpsr_c, lr\n"                   \
+"      ldr     lr, [%1]\n"                     \
+"      subs    lr, lr, %2\n"                   \
+"      str     lr, [%1]\n"                     \
+"      msr     cpsr_c, r0\n"                   \
+"      movmi   r0, %1\n"                       \
+"      movpl   r0, #0\n"                       \
+"      blmi    " SYMBOL_NAME_STR(fail) "\n"    \
+"      mov     %0, r0"                         \
+       : "=&r" (ret)                           \
+       : "r" (ptr), "I" (1)                    \
+       : "r0", "lr", "cc");                    \
+       ret;                                    \
+       })
+
+#define __up_op(ptr,wake)                      \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ up_op\n"                             \
+"      mrs     r0, cpsr\n"                     \
+"      orr     lr, r0, #128\n"                 \
+"      msr     cpsr_c, lr\n"                   \
+"      ldr     lr, [%0]\n"                     \
+"      adds    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      msr     cpsr_c, r0\n"                   \
+"      movle   r0, %0\n"                       \
+"      blle    " SYMBOL_NAME_STR(wake)         \
+       :                                       \
+       : "r" (ptr), "I" (1)                    \
+       : "r0", "lr", "cc");                    \
+       })
+
+/*
+ * The value 0x01000000 supports up to 128 processors and
+ * lots of processes.  BIAS must be chosen such that sub'ing
+ * BIAS once per CPU will result in the long remaining
+ * negative.
+ */
+#define RW_LOCK_BIAS   0x01000000
+
+#define __down_op_write(ptr,fail)              \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ down_op_write\n"                     \
+"      mrs     r0, cpsr\n"                     \
+"      orr     lr, r0, #128\n"                 \
+"      msr     cpsr_c, lr\n"                   \
+"      ldr     lr, [%0]\n"                     \
+"      subs    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      msr     cpsr_c, r0\n"                   \
+"      movne   r0, %0\n"                       \
+"      blne    " SYMBOL_NAME_STR(fail)         \
+       :                                       \
+       : "r" (ptr), "I" (RW_LOCK_BIAS)         \
+       : "r0", "lr", "cc");                    \
+       })
+
+#define __up_op_write(ptr,wake)                        \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ up_op_read\n"                        \
+"      mrs     r0, cpsr\n"                     \
+"      orr     lr, r0, #128\n"                 \
+"      msr     cpsr_c, lr\n"                   \
+"      ldr     lr, [%0]\n"                     \
+"      adds    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      msr     cpsr_c, r0\n"                   \
+"      movcs   r0, %0\n"                       \
+"      blcs    " SYMBOL_NAME_STR(wake)         \
+       :                                       \
+       : "r" (ptr), "I" (RW_LOCK_BIAS)         \
+       : "r0", "lr", "cc");                    \
+       })
+
+#define __down_op_read(ptr,fail)               \
+       __down_op(ptr, fail)
+
+#define __up_op_read(ptr,wake)                 \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ up_op_read\n"                        \
+"      mrs     r0, cpsr\n"                     \
+"      orr     lr, r0, #128\n"                 \
+"      msr     cpsr_c, lr\n"                   \
+"      ldr     lr, [%0]\n"                     \
+"      adds    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      msr     cpsr_c, r0\n"                   \
+"      moveq   r0, %0\n"                       \
+"      bleq    " SYMBOL_NAME_STR(wake)         \
+       :                                       \
+       : "r" (ptr), "I" (1)                    \
+       : "r0", "lr", "cc");                    \
+       })
+
+#endif
diff --git a/include/asm-arm/proc-armv/semaphore.h b/include/asm-arm/proc-armv/semaphore.h
deleted file mode 100644 (file)
index 45ceaa3..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * linux/include/asm-arm/semaphore.h
- */
-#ifndef __ASM_PROC_SEMAPHORE_H
-#define __ASM_PROC_SEMAPHORE_H
-
-/*
- * This is ugly, but we want the default case to fall through.
- * "__down" is the actual routine that waits...
- */
-extern inline void down(struct semaphore * sem)
-{
-       unsigned int cpsr, temp;
-
-       __asm__ __volatile__ ("
-       @ atomic down operation
-       mrs     %0, cpsr
-       orr     %1, %0, #128            @ disable IRQs
-       msr     cpsr, %1
-       ldr     %1, [%2]
-       bic     %0, %0, #0x80000000     @ clear N
-       subs    %1, %1, #1
-       str     %1, [%2]
-       orrmi   %0, %0, #0x80000000     @ set N
-       msr     cpsr, %0
-       movmi   r0, %2
-       blmi    " SYMBOL_NAME_STR(__down_failed)
-               : "=&r" (cpsr), "=&r" (temp)
-               : "r" (sem)
-               : "r0", "lr", "cc");
-}
-
-/*
- * This is ugly, but we want the default case to fall through.
- * "__down_interruptible" is the actual routine that waits...
- */
-extern inline int down_interruptible (struct semaphore * sem)
-{
-       unsigned int cpsr, temp;
-
-       __asm__ __volatile__ ("
-       @ atomic down interruptible operation
-       mrs     %0, cpsr
-       orr     %1, %0, #128            @ disable IRQs
-       msr     cpsr, %1
-       ldr     %1, [%2]
-       bic     %0, %0, #0x80000000     @ clear N
-       subs    %1, %1, #1
-       str     %1, [%2]
-       orrmi   %0, %0, #0x80000000     @ set N
-       msr     cpsr, %0
-       movmi   r0, %2
-       movpl   r0, #0
-       blmi    " SYMBOL_NAME_STR(__down_interruptible_failed) "
-       mov     %1, r0"
-               : "=&r" (cpsr), "=&r" (temp)
-               : "r" (sem)
-               : "r0", "lr", "cc");
-
-       return temp;
-}
-
-extern inline int down_trylock(struct semaphore *sem)
-{
-       unsigned int cpsr, temp;
-
-       __asm__ __volatile__ ("
-       @ atomic down try lock operation
-       mrs     %0, cpsr
-       orr     %1, %0, #128            @ disable IRQs
-       msr     cpsr, %1
-       ldr     %1, [%2]
-       bic     %0, %0, #0x80000000     @ clear N
-       subs    %1, %1, #1
-       str     %1, [%2]
-       orrmi   %0, %0, #0x80000000     @ set N
-       msr     cpsr, %0
-       movmi   r0, %2
-       movpl   r0, #0
-       blmi    " SYMBOL_NAME_STR(__down_trylock_failed) "
-       mov     %1, r0"
-               : "=&r" (cpsr), "=&r" (temp)
-               : "r" (sem)
-               : "r0", "lr", "cc");
-
-       return temp;
-}
-
-/*
- * Note! This is subtle. We jump to wake people up only if
- * the semaphore was negative (== somebody was waiting on it).
- * The default case (no contention) will result in NO
- * jumps for both down() and up().
- */
-extern inline void up(struct semaphore * sem)
-{
-       unsigned int cpsr, temp;
-
-       __asm__ __volatile__ ("
-       @ atomic up operation
-       mrs     %0, cpsr
-       orr     %1, %0, #128            @ disable IRQs
-       msr     cpsr, %1
-       ldr     %1, [%2]
-       bic     %0, %0, #0x80000000     @ clear N
-       adds    %1, %1, #1
-       str     %1, [%2]
-       orrle   %0, %0, #0x80000000     @ set N
-       msr     cpsr, %0
-       movmi   r0, %2
-       blmi    " SYMBOL_NAME_STR(__up_wakeup)
-               : "=&r" (cpsr), "=&r" (temp)
-               : "r" (sem)
-               : "r0", "lr", "cc");
-}
-
-#endif
index 5ba171be8a28274df94e91e01987b39e3c57600f..0ce171a3f263424861a40c3b45ecd993c0cfc1e4 100644 (file)
@@ -9,16 +9,28 @@
 #include <linux/wait.h>
 
 #include <asm/atomic.h>
+#include <asm/proc/locks.h>
 
 struct semaphore {
        atomic_t count;
        int sleepers;
        wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+       long __magic;
+#endif
 };
 
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+               , (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
 #define __SEMAPHORE_INIT(name,count)                   \
        { ATOMIC_INIT(count), 0,                        \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
+         __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+         __SEM_DEBUG_INIT(name) }
 
 #define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INIT(name,1)
@@ -29,12 +41,15 @@ struct semaphore {
 #define DECLARE_MUTEX(name)            __DECLARE_SEMAPHORE_GENERIC(name,1)
 #define DECLARE_MUTEX_LOCKED(name)     __DECLARE_SEMAPHORE_GENERIC(name,0)
 
-#define sema_init(sem, val)                    \
-do {                                           \
-       atomic_set(&((sem)->count), (val));     \
-       (sem)->sleepers = 0;                    \
-       init_waitqueue_head(&(sem)->wait);      \
-} while (0)
+extern inline void sema_init(struct semaphore *sem, int val)
+{
+       atomic_set(&sem->count, val);
+       sem->sleepers = 0;
+       init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+       sem->__magic = (long)&sem->__magic;
+#endif
+}
 
 static inline void init_MUTEX(struct semaphore *sem)
 {
@@ -46,18 +61,196 @@ static inline void init_MUTEX_LOCKED(struct semaphore *sem)
        sema_init(sem, 0);
 }
 
-asmlinkage void __down_failed (void /* special register calling convention */);
-asmlinkage int  __down_interruptible_failed (void /* special register calling convention */);
-asmlinkage int  __down_trylock_failed(void  /* params in registers */);
-asmlinkage void __up_wakeup (void /* special register calling convention */);
+/*
+ * special register calling convention
+ */
+asmlinkage void __down_failed(void);
+asmlinkage int  __down_interruptible_failed(void);
+asmlinkage int  __down_trylock_failed(void);
+asmlinkage void __up_wakeup(void);
 
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
 extern int  __down_trylock(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
-extern spinlock_t semaphore_wake_lock;
+/*
+ * This is ugly, but we want the default case to fall through.
+ * "__down" is the actual routine that waits...
+ */
+extern inline void down(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
+       __down_op(sem, __down_failed);
+}
+
+/*
+ * This is ugly, but we want the default case to fall through.
+ * "__down_interruptible" is the actual routine that waits...
+ */
+extern inline int down_interruptible (struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
+       return __down_op_ret(sem, __down_interruptible_failed);
+}
+
+extern inline int down_trylock(struct semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
+       return __down_op_ret(sem, __down_trylock_failed);
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ * The default case (no contention) will result in NO
+ * jumps for both down() and up().
+ */
+extern inline void up(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
+       __up_op(sem, __up_wakeup);
+}
+
+/* rw mutexes (should that be mutices? =) -- throw rw
+ * spinlocks and semaphores together, and this is what we
+ * end up with...
+ *
+ * The lock is initialized to BIAS.  This way, a writer
+ * subtracts BIAS ands gets 0 for the case of an uncontended
+ * lock.  Readers decrement by 1 and see a positive value
+ * when uncontended, negative if there are writers waiting
+ * (in which case it goes to sleep).
+ *
+ * In terms of fairness, this should result in the lock
+ * flopping back and forth between readers and writers
+ * under heavy use.
+ *
+ *              -ben
+ */
+struct rw_semaphore {
+       atomic_t                count;
+       volatile unsigned char  write_bias_granted;
+       volatile unsigned char  read_bias_granted;
+       volatile unsigned char  pad1;
+       volatile unsigned char  pad2;
+       wait_queue_head_t       wait;
+       wait_queue_head_t       write_bias_wait;
+#if WAITQUEUE_DEBUG
+       long                    __magic;
+       atomic_t                readers;
+       atomic_t                writers;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
+#else
+#define __RWSEM_DEBUG_INIT     /* */
+#endif
+
+#define __RWSEM_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
+       __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
+       __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
+
+#define __DECLARE_RWSEM_GENERIC(name,count) \
+       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
+
+#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
+#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
+#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
+
+extern inline void init_rwsem(struct rw_semaphore *sem)
+{
+       atomic_set(&sem->count, RW_LOCK_BIAS);
+       sem->read_bias_granted = 0;
+       sem->write_bias_granted = 0;
+       init_waitqueue_head(&sem->wait);
+       init_waitqueue_head(&sem->write_bias_wait);
+#if WAITQUEUE_DEBUG
+       sem->__magic = (long)&sem->__magic;
+       atomic_set(&sem->readers, 0);
+       atomic_set(&sem->writers, 0);
+#endif
+}
+
+extern struct rw_semaphore *__down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *__down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *__rwsem_wake(struct rw_semaphore *sem);
+
+extern inline void down_read(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+       __down_op_read(sem, __down_read_failed);
+#if WAITQUEUE_DEBUG
+       if (sem->write_bias_granted)
+               BUG();
+       if (atomic_read(&sem->writers))
+               BUG();
+       atomic_inc(&sem->readers);
+#endif
+}
+
+extern inline void down_write(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+       __down_op_write(sem, __down_write_failed);
+#if WAITQUEUE_DEBUG
+       if (atomic_read(&sem->writers))
+               BUG();
+       if (atomic_read(&sem->readers))
+               BUG();
+       if (sem->read_bias_granted)
+               BUG();
+       if (sem->write_bias_granted)
+               BUG();
+       atomic_inc(&sem->writers);
+#endif
+}
+
+extern inline void up_read(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+       if (sem->write_bias_granted)
+               BUG();
+       if (atomic_read(&sem->writers))
+               BUG();
+       atomic_dec(&sem->readers);
+#endif
+       __up_op_read(sem, __rwsem_wake);
+}
 
-#include <asm/proc/semaphore.h>
+extern inline void up_write(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+       if (sem->read_bias_granted)
+               BUG();
+       if (sem->write_bias_granted)
+               BUG();
+       if (atomic_read(&sem->readers))
+               BUG();
+       if (atomic_read(&sem->writers) != 1)
+               BUG();
+       atomic_dec(&sem->writers);
+#endif
+       __up_op_write(sem, __rwsem_wake);
+}
 
 #endif
index 28ac2eb2a36746690ad9408cd290808562c02d9c..f987548131379663997e7addcf2f2a7fab38a4e1 100644 (file)
@@ -9,72 +9,9 @@ extern unsigned int local_bh_count[NR_CPUS];
 #define cpu_bh_disable(cpu)    do { local_bh_count[(cpu)]++; barrier(); } while (0)
 #define cpu_bh_enable(cpu)     do { barrier(); local_bh_count[(cpu)]--; } while (0)
 
-#define cpu_bh_trylock(cpu)    (local_bh_count[(cpu)] ? 0 : (local_bh_count[(cpu)] = 1))
-#define cpu_bh_endlock(cpu)    (local_bh_count[(cpu)] = 0)
-
 #define local_bh_disable()     cpu_bh_disable(smp_processor_id())
 #define local_bh_enable()      cpu_bh_enable(smp_processor_id())
 
-#define get_active_bhs()       (bh_mask & bh_active)
-#define clear_active_bhs(x)    atomic_clear_mask((x),&bh_active)
-
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-       bh_base[nr] = routine;
-       atomic_set(&bh_mask_count[nr], 0);
-       bh_mask |= 1 << nr;
-}
-
-extern inline void remove_bh(int nr)
-{
-       bh_mask &= ~(1 << nr);
-       mb();
-       bh_base[nr] = NULL;
-}
-
-extern inline void mark_bh(int nr)
-{
-       set_bit(nr, &bh_active);
-}
-
-#ifdef __SMP__
-#error SMP not supported
-#else
-
-extern inline void start_bh_atomic(void)
-{
-       local_bh_disable();
-       barrier();
-}
-
-extern inline void end_bh_atomic(void)
-{
-       barrier();
-       local_bh_enable();
-}
-
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)   (cpu_bh_trylock(cpu))
-#define softirq_endlock(cpu)   (cpu_bh_endlock(cpu))
-#define synchronize_bh()       barrier()
-
-#endif /* SMP */
-
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-       bh_mask &= ~(1 << nr);
-       atomic_inc(&bh_mask_count[nr]);
-       synchronize_bh();
-}
-
-extern inline void enable_bh(int nr)
-{
-       if (atomic_dec_and_test(&bh_mask_count[nr]))
-               bh_mask |= 1 << nr;
-}
+#define in_softirq()           (local_bh_count[smp_processor_id()] != 0)
 
 #endif /* __ASM_SOFTIRQ_H */
index 0a37bbfb919628ffb27482f600771037c5f897a4..7716dc422e4ee2efd4b394ce48b0dd433eba24c4 100644 (file)
@@ -292,10 +292,11 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
 
 /* to find an entry in a page-table-directory. */
-#define __pgd_offset(address) \
-               ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
-#define pgd_offset(mm, address) ((mm)->pgd+__pgd_offset(address))
+#define __pgd_offset(address) pgd_index(address)
+
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
index 3e6185064e7a62f598a6181d81965e03a051f570..4e9b30a918c87dabfa28c76f2b070b8a15e35e65 100644 (file)
@@ -6,11 +6,11 @@
  * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <asm/io.h>            /* need byte IO */
 #include <linux/config.h>
 #include <linux/spinlock.h>    /* And spinlocks */
 #include <linux/delay.h>
 
+#include <asm/io.h>            /* need byte IO */
 
 #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
 #define dma_outb       outb_p
index a6facbd8cab315912435482e9ec639d18010424b..bbf8afcfdd44783559e94ba34fad1ab82aed4f2e 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright (C) 1999 Goutham Rao <goutham.rao@intel.com>
  */
 
-#if 0
+#if 1
 #define FPSWA_BUG
 #endif
 
index 95523854eb7cc03d6e1d5cd1ca5da59157fcd330..56724365024372809bde5d8a020b16b713988a00 100644 (file)
@@ -17,12 +17,16 @@ extern unsigned long hardirq_no[NR_CPUS];
  * or hardware interrupt processing?
  */
 
+#define in_irq() (local_irq_count[smp_processor_id()] != 0)
+
 #define in_interrupt()                                         \
 ({                                                             \
        int __cpu = smp_processor_id();                         \
        (local_irq_count[__cpu] + local_bh_count[__cpu]) != 0;  \
 })
 
+
+
 #ifndef CONFIG_SMP
 # define hardirq_trylock(cpu)          (local_irq_count[cpu] == 0)
 # define hardirq_endlock(cpu)          ((void) 0)
index b775d0a9a23643509b7c7bfcf02af8ae9c7e88b4..22c2b22973311bc262e8e6089200985d43059089 100644 (file)
@@ -60,6 +60,11 @@ extern unsigned long ia64_next_context;
 
 extern void get_new_mmu_context (struct mm_struct *mm);
 
+static inline void
+enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
+
 extern inline unsigned long
 ia64_rid (unsigned long context, unsigned long region_addr)
 {
index 9639a9e408782d6ffa1fe6be4d2535b17422d959..d989cb911aa6f9f138e1664c9fa2edaf921bca00 100644 (file)
@@ -10,7 +10,7 @@
 
 #define PF_PTRACED_BIT                 4
 
-#define IA64_TASK_SIZE                 2752    /* 0xac0 */
+#define IA64_TASK_SIZE                 3280    /* 0xcd0 */
 #define IA64_PT_REGS_SIZE              400     /* 0x190 */
 #define IA64_SWITCH_STACK_SIZE         560     /* 0x230 */
 #define IA64_SIGINFO_SIZE              136     /* 0x88 */
@@ -18,8 +18,9 @@
 #define IA64_TASK_FLAGS_OFFSET         8       /* 0x8 */
 #define IA64_TASK_SIGPENDING_OFFSET    16      /* 0x10 */
 #define IA64_TASK_NEED_RESCHED_OFFSET  40      /* 0x28 */
-#define IA64_TASK_THREAD_OFFSET                912     /* 0x390 */
-#define IA64_TASK_THREAD_KSP_OFFSET    912     /* 0x390 */
+#define IA64_TASK_PROCESSOR_OFFSET     108     /* 0x6c */
+#define IA64_TASK_THREAD_OFFSET                1424    /* 0x590 */
+#define IA64_TASK_THREAD_KSP_OFFSET    1424    /* 0x590 */
 #define IA64_TASK_PID_OFFSET           188     /* 0xbc */
 #define IA64_TASK_MM_OFFSET            88      /* 0x58 */
 #define IA64_PT_REGS_CR_IPSR_OFFSET    0       /* 0x0 */
index 2defe7cdfb9c5586e150a35f2ad66a5c4c41a5cc..203005b5c7de6ea960fe797dadd6e086a6d65673 100644 (file)
 #define flush_cache_page(vma, vmaddr)          do { } while (0)
 #define flush_page_to_ram(page)                        do { } while (0)
 #define flush_icache_range(start, end)         do { } while (0)
+
 extern void ia64_flush_icache_page (unsigned long addr);
 
-#define flush_icache_page(pg)  ia64_flush_icache_page(page_address(pg))
+#define flush_icache_page(vma,pg)                              \
+do {                                                           \
+       if ((vma)->vm_flags & PROT_EXEC)                        \
+               ia64_flush_icache_page(page_address(pg));       \
+} while (0)
 
 /*
  * Now come the defines and routines to manage and access the three-level
@@ -289,15 +294,21 @@ extern pmd_t *ia64_bad_pagetable (void);
  */
 #define pgprot_noncached(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC)
 
+extern __inline__ unsigned long
+pgd_index (unsigned long address)
+{
+       unsigned long region = address >> 61;
+       unsigned long l1index = (address >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1);
+
+       return (region << (PAGE_SHIFT - 6)) | l1index;
+}
+
 /* The offset in the 1-level directory is given by the 3 region bits
    (61..63) and the seven level-1 bits (33-39).  */
 extern __inline__ pgd_t*
 pgd_offset (struct mm_struct *mm, unsigned long address)
 {
-       unsigned long region = address >> 61;
-       unsigned long l1index = (address >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1);
-
-       return mm->pgd + ((region << (PAGE_SHIFT - 6)) | l1index);
+       return mm->pgd + pgd_index(address);
 }
 
 /* In the kernel's mapped region we have a full 43 bit space available and completely
index b2d0cc906410e19647f2c8e271417c87ef79e9bf..d50ce82e799534b70b0a4a27e4ee37729b4bfea1 100644 (file)
@@ -145,10 +145,10 @@ struct pt_regs {
         * Floating point registers that the kernel considers
         * scratch:
         */
-       struct ia64_fpreg f6;           /* scratch*/
-       struct ia64_fpreg f7;           /* scratch*/
-       struct ia64_fpreg f8;           /* scratch*/
-       struct ia64_fpreg f9;           /* scratch*/
+       struct ia64_fpreg f6;           /* scratch */
+       struct ia64_fpreg f7;           /* scratch */
+       struct ia64_fpreg f8;           /* scratch */
+       struct ia64_fpreg f9;           /* scratch */
 };
 
 /*
index 2c75056c58bc154f0d605cc8b33feb6be4f99edf..a50ee01e39f64df30b0438adacd4b543606d98eb 100644 (file)
@@ -137,13 +137,6 @@ up (struct semaphore * sem)
  * In terms of fairness, when there is heavy use of the lock, we want
  * to see the lock being passed back and forth between readers and
  * writers (like in a producer/consumer style of communication).
- * 
-
-  For
- * liveness, it would be necessary to process the blocked readers and
- * writers in FIFO order.  However, we don't do this (yet).  I suppose
- * if you have a lock that is _that_ heavily contested, you're in big
- * trouble anyhow.
  *
  *           -ben (with clarifications & IA-64 comments by davidm)
  */
index 1ad1a8149664609e1faa525a12ccacb8db1d9f2d..a6ea5c17d293ec1527c9c37fe1f9cfc56436734f 100644 (file)
@@ -8,6 +8,7 @@
 #define _ASM_IA64_SMP_H
 
 #include <linux/config.h>
+
 #include <linux/init.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
@@ -25,9 +26,10 @@ extern unsigned long cpu_present_map;
 extern unsigned long cpu_online_map;
 extern unsigned long ipi_base_addr;
 extern int bootstrap_processor;
-extern volatile int cpu_number_map[NR_CPUS];
+extern volatile int __cpu_number_map[NR_CPUS];
 extern volatile int __cpu_logical_map[NR_CPUS];
 
+#define cpu_number_map(i)      __cpu_number_map[i]
 #define cpu_logical_map(i)     __cpu_logical_map[i]
 
 #if defined(CONFIG_KDB)
index 8b92f4442a4eadb30b6e0c0be07d94768007178a..fb40999e244ef08649c4ea49a6fb44a36ce90ee5 100644 (file)
@@ -2,13 +2,9 @@
 #define _ASM_IA64_SOFTIRQ_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  */
-#include <linux/config.h>
-#include <linux/stddef.h>
-
-#include <asm/system.h>
 #include <asm/hardirq.h>
 
 extern unsigned int local_bh_count[NR_CPUS];
@@ -16,137 +12,9 @@ extern unsigned int local_bh_count[NR_CPUS];
 #define cpu_bh_disable(cpu)    do { local_bh_count[(cpu)]++; barrier(); } while (0)
 #define cpu_bh_enable(cpu)     do { barrier(); local_bh_count[(cpu)]--; } while (0)
 
-#define cpu_bh_trylock(cpu)    (local_bh_count[(cpu)] ? 0 : (local_bh_count[(cpu)] = 1))
-#define cpu_bh_endlock(cpu)    (local_bh_count[(cpu)] = 0)
-
 #define local_bh_disable()     cpu_bh_disable(smp_processor_id())
 #define local_bh_enable()      cpu_bh_enable(smp_processor_id())
 
-#define get_active_bhs()       (bh_mask & bh_active)
-
-static inline void
-clear_active_bhs (unsigned long x)
-{
-       unsigned long old, new;
-       volatile unsigned long *bh_activep = (void *) &bh_active;
-       CMPXCHG_BUGCHECK_DECL
-
-       do {
-               CMPXCHG_BUGCHECK(bh_activep);
-               old = *bh_activep;
-               new = old & ~x;
-       } while (ia64_cmpxchg(bh_activep, old, new, 8) != old);
-}
-
-extern inline void
-init_bh (int nr, void (*routine)(void))
-{
-       bh_base[nr] = routine;
-       atomic_set(&bh_mask_count[nr], 0);
-       bh_mask |= 1 << nr;
-}
-
-extern inline void
-remove_bh (int nr)
-{
-       bh_mask &= ~(1 << nr);
-       mb();
-       bh_base[nr] = NULL;
-}
-
-extern inline void
-mark_bh (int nr)
-{
-       set_bit(nr, &bh_active);
-}
-
-#ifdef CONFIG_SMP
-
-/*
- * The locking mechanism for base handlers, to prevent re-entrancy,
- * is entirely private to an implementation, it should not be
- * referenced at all outside of this file.
- */
-extern atomic_t global_bh_lock;
-extern atomic_t global_bh_count;
-
-extern void synchronize_bh(void);
-
-static inline void
-start_bh_atomic (void)
-{
-       atomic_inc(&global_bh_lock);
-       synchronize_bh();
-}
-
-static inline void
-end_bh_atomic (void)
-{
-       atomic_dec(&global_bh_lock);
-}
-
-/* These are for the irq's testing the lock */
-static inline int
-softirq_trylock (int cpu)
-{
-       if (cpu_bh_trylock(cpu)) {
-               if (!test_and_set_bit(0, &global_bh_count)) {
-                       if (atomic_read(&global_bh_lock) == 0)
-                               return 1;
-                       clear_bit(0,&global_bh_count);
-               }
-               cpu_bh_endlock(cpu);
-       }
-       return 0;
-}
-
-static inline void
-softirq_endlock (int cpu)
-{
-       cpu_bh_enable(cpu);
-       clear_bit(0,&global_bh_count);
-}
-
-#else /* !CONFIG_SMP */
-
-extern inline void
-start_bh_atomic (void)
-{
-       local_bh_disable();
-       barrier();
-}
-
-extern inline void
-end_bh_atomic (void)
-{
-       barrier();
-       local_bh_enable();
-}
-
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)   (cpu_bh_trylock(cpu))
-#define softirq_endlock(cpu)   (cpu_bh_endlock(cpu))
-#define synchronize_bh()       barrier()
-
-#endif /* !CONFIG_SMP */
-
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void
-disable_bh (int nr)
-{
-       bh_mask &= ~(1 << nr);
-       atomic_inc(&bh_mask_count[nr]);
-       synchronize_bh();
-}
-
-extern inline void
-enable_bh (int nr)
-{
-       if (atomic_dec_and_test(&bh_mask_count[nr]))
-               bh_mask |= 1 << nr;
-}
+#define in_softirq()           (local_bh_count[smp_processor_id()] != 0)
 
 #endif /* _ASM_IA64_SOFTIRQ_H */
index a86d0a7f34246f9de99f2afb3918ddf9181b19ef..d4b1732e2d2b7114e2b697f212442fa11aea1641 100644 (file)
@@ -8,8 +8,8 @@
  * not a major issue.  However, for interoperability, libraries still
  * need to be careful to avoid a name clashes.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #ifdef __ASSEMBLY__
@@ -38,52 +38,28 @@ typedef unsigned short __u16;
 typedef __signed__ int __s32;
 typedef unsigned int __u32;
 
-/*
- * There are 32-bit compilers for the ia-64 out there..
- */
-# if ((~0UL) == 0xffffffff)
-#  if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
-#  endif
-# else
 typedef __signed__ long __s64;
 typedef unsigned long __u64;
-# endif
 
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
 # ifdef __KERNEL__
 
-typedef signed char s8;
-typedef unsigned char u8;
+typedef __s8 s8;
+typedef __u8 u8;
 
-typedef signed short s16;
-typedef unsigned short u16;
+typedef __s16 s16;
+typedef __u16 u16;
 
-typedef signed int s32;
-typedef unsigned int u32;
+typedef __s32 s32;
+typedef __u32 u32;
 
-/*
- * There are 32-bit compilers for the ia-64 out there...  (don't rely
- * on cpp because that may cause su problem in a 32->64 bit
- * cross-compilation environment).
- */
-#  ifdef __LP64__
+typedef __s64 s64;
+typedef __u64 u64;
 
-typedef signed long s64;
-typedef unsigned long u64;
 #define BITS_PER_LONG 64
 
-#  else
-
-typedef signed long long s64;
-typedef unsigned long long u64;
-#define BITS_PER_LONG 32
-
-#  endif
-
 /* DMA addresses are 64-bits wide, in general.  */
 
 typedef u64 dma_addr_t;
index 9df773f9fc8afb38b2ab4b913431f889dd21a9aa..a92c28b12d5c2485ccaf3d87b93ec8f1e1ba6300 100644 (file)
@@ -285,10 +285,12 @@ extern inline pte_t pte_mkcache(pte_t pte)        { pte_val(pte) = (pte_val(pte) & _CAC
 
 #define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
 
+#define pgd_index(address)     ((address) >> PGDIR_SHIFT)
+
 /* to find an entry in a page-table-directory */
 extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
 {
-       return mm->pgd + (address >> PGDIR_SHIFT);
+       return mm->pgd + pgd_index(address);
 }
 
 #define swapper_pg_dir kernel_pg_dir
index 9b23b03c5ae5386b26f8e27b52019c27e9cacabf..8cb15ede743f10684b81c84d8604c7df1c365b63 100644 (file)
@@ -371,10 +371,12 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
+#define pgd_index(address)     ((address) >> PGDIR_SHIFT)
+
 /* to find an entry in a page-table-directory */
 extern inline pgd_t *pgd_offset(struct mm_struct *mm, unsigned long address)
 {
-       return mm->pgd + (address >> PGDIR_SHIFT);
+       return mm->pgd + pgd_index(address);
 }
 
 /* Find an entry in the second-level page table.. */
index 002736abf1ce57af068daf3a25feffb7f457ab2d..3ae89d9cc9ec1a28b3752d0f2eaba9ca0bd6970d 100644 (file)
@@ -8,6 +8,7 @@
 
 #define ELF_NGREG      48      /* includes nip, msr, lr, etc. */
 #define ELF_NFPREG     33      /* includes fpscr */
+#define ELF_NVRREG     33      /* includes vscr */
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
@@ -37,6 +38,10 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 typedef double elf_fpreg_t;
 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
+/* Altivec registers */
+typedef vector128 elf_vrreg_t;
+typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG];
+
 #define ELF_CORE_COPY_REGS(gregs, regs) \
        memcpy(gregs, regs, \
               sizeof(struct pt_regs) < sizeof(elf_gregset_t)? \
index ac5ac69fc18d0f8b8e187e821f7bac70642af74f..80c3e1de67487811279aa6e71754f7dfd417f0c1 100644 (file)
@@ -3,22 +3,24 @@
 
 #include <asm/smp.h>
 
-extern unsigned int ppc_local_irq_count[NR_CPUS];
+extern unsigned int local_irq_count[NR_CPUS];
 
 /*
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
  */
 #define in_interrupt() ({ int __cpu = smp_processor_id(); \
-       (ppc_local_irq_count[__cpu] + ppc_local_bh_count[__cpu] != 0); })
+       (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
+
+#define in_irq() (local_irq_count[smp_processor_id()] != 0)
 
 #ifndef __SMP__
 
-#define hardirq_trylock(cpu)   (ppc_local_irq_count[cpu] == 0)
+#define hardirq_trylock(cpu)   (local_irq_count[cpu] == 0)
 #define hardirq_endlock(cpu)   do { } while (0)
 
-#define hardirq_enter(cpu)     (ppc_local_irq_count[cpu]++)
-#define hardirq_exit(cpu)      (ppc_local_irq_count[cpu]--)
+#define hardirq_enter(cpu)     (local_irq_count[cpu]++)
+#define hardirq_exit(cpu)      (local_irq_count[cpu]--)
 
 #define synchronize_irq()      do { } while (0)
 
@@ -41,14 +43,31 @@ static inline void release_irqlock(int cpu)
 
 static inline void hardirq_enter(int cpu)
 {
-       ++ppc_local_irq_count[cpu];
+       unsigned int loops = 10000000;
+       
+       ++local_irq_count[cpu];
        atomic_inc(&global_irq_count);
+       while (test_bit(0,&global_irq_lock)) {
+               if (smp_processor_id() == global_irq_holder) {
+                       printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+                       xmon(0);
+#endif
+                       break;
+               }
+               if (loops-- == 0) {
+                       printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+                       xmon(0);
+#endif
+               }
+       }
 }
 
 static inline void hardirq_exit(int cpu)
 {
        atomic_dec(&global_irq_count);
-       --ppc_local_irq_count[cpu];
+       --local_irq_count[cpu];
 }
 
 static inline int hardirq_trylock(int cpu)
index 55168a8b2b3ed91f44038dd4f20766cf93d8fd42..8c8b8895480e84df60a219fbfd9ff7e4173b4c18 100644 (file)
@@ -77,7 +77,7 @@ typedef unsigned long pgprot_t;
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
 extern void clear_page(void *page);
-#define copy_page(to,from)     memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+extern void copy_page(void *to, void *from);
 
 /* map phys->virtual and virtual->phys for RAM pages */
 static inline unsigned long ___pa(unsigned long v)
index f1f0f578a6bc3ad51f4e3c6710b890c66086e782..6ab7eb70d2a6668798782489cb20ef7b35f7b42e 100644 (file)
@@ -413,7 +413,8 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 /* to find an entry in a page-table-directory */
-#define pgd_offset(mm, address)         ((mm)->pgd + ((address) >> PGDIR_SHIFT))
+#define pgd_index(address)      ((address) >> PGDIR_SHIFT)
+#define pgd_offset(mm, address)         ((mm)->pgd + pgd_index(address))
 
 /* Find an entry in the second-level page table.. */
 extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
index f6d0d70ea79f85911f1633e64d70e1ba0186f7e6..04c59a5b3db18c114f70153bc9efae3f2327577f 100644 (file)
@@ -24,8 +24,8 @@ typedef long          __kernel_clock_t;
 typedef int            __kernel_daddr_t;
 typedef char *         __kernel_caddr_t;
 typedef short             __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid16_t;
-typedef unsigned int   __kernel_gid16_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
 typedef unsigned int   __kernel_uid32_t;
 typedef unsigned int   __kernel_gid32_t;
 
index 20e337f34ec8d86f7108d730798baf6b2b75dd8a..704bd68ab524308676b93efc9c13e8b1f35be47f 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/residual.h>
+#include <asm/types.h>
 
 /* Machine State Register (MSR) Fields */
 
@@ -625,9 +626,11 @@ struct thread_struct {
        double          fpr[32];        /* Complete floating point set */
        unsigned long   fpscr_pad;      /* fpr ... fpscr must be contiguous */
        unsigned long   fpscr;          /* Floating point status */
-       unsigned long   vrf[128];
-       unsigned long   vscr;
+#ifdef CONFIG_ALTIVEC
+       vector128       vr[32];         /* Complete AltiVec set */
+       vector128       vscr;           /* AltiVec status */
        unsigned long   vrsave;
+#endif /* CONFIG_ALTIVEC */
 };
 
 #define INIT_SP                (sizeof(init_stack) + (unsigned long) &init_stack)
index ac1442861337fd9b7ab2d046d0dd6bbaab2721aa..156d8db72e4c7be8114f32a81f2d56ba0aba7d38 100644 (file)
@@ -33,7 +33,7 @@ void smp_send_tlb_invalidate(int);
 
 /* 1 to 1 mapping on PPC -- Cort */
 #define cpu_logical_map(cpu) (cpu)
-extern int cpu_number_map[NR_CPUS];
+#define cpu_number_map(x) (x)
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
 
 #define hard_smp_processor_id() (0)
index 1188809e9b5112d58c7d10ffeab555a1378d4daa..550b46192481bf0c2d4a269414053640fc21d265 100644 (file)
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
 
-#define get_active_bhs()       (bh_mask & bh_active)
-#define clear_active_bhs(x)    atomic_clear_mask((x),&bh_active)
+extern unsigned int local_bh_count[NR_CPUS];
 
-extern unsigned int ppc_local_bh_count[NR_CPUS];
+#define local_bh_disable()     do { local_bh_count[smp_processor_id()]++; barrier(); } while (0)
+#define local_bh_enable()      do { barrier(); local_bh_count[smp_processor_id()]--; } while (0)
 
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-       bh_base[nr] = routine;
-       atomic_set(&bh_mask_count[nr], 0);
-       bh_mask |= 1 << nr;
-}
-
-extern inline void remove_bh(int nr)
-{
-       bh_mask &= ~(1 << nr);
-       wmb();
-       bh_base[nr] = 0;
-}
-
-extern inline void mark_bh(int nr)
-{
-       set_bit(nr, &bh_active);
-}
-
-#ifdef __SMP__
-
-/*
- * The locking mechanism for base handlers, to prevent re-entrancy,
- * is entirely private to an implementation, it should not be
- * referenced at all outside of this file.
- */
-extern atomic_t global_bh_lock;
-extern atomic_t global_bh_count;
-
-extern void synchronize_bh(void);
-
-static inline void start_bh_atomic(void)
-{
-       atomic_inc(&global_bh_lock);
-       synchronize_bh();
-}
-
-static inline void end_bh_atomic(void)
-{
-       atomic_dec(&global_bh_lock);
-}
-
-/* These are for the IRQs testing the lock */
-static inline int softirq_trylock(int cpu)
-{
-       if (ppc_local_bh_count[cpu] == 0) {
-               ppc_local_bh_count[cpu] = 1;
-               if (!test_and_set_bit(0,&global_bh_count)) {
-                       mb();
-                       if (atomic_read(&global_bh_lock) == 0)
-                               return 1;
-                       clear_bit(0,&global_bh_count);
-               }
-               ppc_local_bh_count[cpu] = 0;
-               mb();
-       }
-       return 0;
-}
-
-static inline void softirq_endlock(int cpu)
-{
-       mb();
-       ppc_local_bh_count[cpu]--;
-       clear_bit(0,&global_bh_count);
-}
-
-#else
-
-extern inline void start_bh_atomic(void)
-{
-       ppc_local_bh_count[smp_processor_id()]++;
-       barrier();
-}
-
-extern inline void end_bh_atomic(void)
-{
-       barrier();
-       ppc_local_bh_count[smp_processor_id()]--;
-}
-
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)   (ppc_local_bh_count[cpu] ? 0 : (ppc_local_bh_count[cpu]=1))
-#define softirq_endlock(cpu)   (ppc_local_bh_count[cpu] = 0)
-#define synchronize_bh()       barrier()
-
-#endif /* SMP */
-
-#define local_bh_disable()     (ppc_local_bh_count[smp_processor_id()]++)
-#define local_bh_enable()      (ppc_local_bh_count[smp_processor_id()]--)
-
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-       bh_mask &= ~(1 << nr);
-       atomic_inc(&bh_mask_count[nr]);
-       synchronize_bh();
-}
-
-extern inline void enable_bh(int nr)
-{
-       if (atomic_dec_and_test(&bh_mask_count[nr]))
-               bh_mask |= 1 << nr;
-}
+#define in_softirq() (local_bh_count[smp_processor_id()] != 0)
 
 #endif /* __ASM_SOFTIRQ_H */
index ad1fdda173b2ca8742e76353a19219bad08fe9dd..5e7e2a19eba45d36915c1fc038928a2303937f79 100644 (file)
@@ -14,6 +14,7 @@ typedef struct {
 #define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0, 0, 0 }
 #define spin_lock_init(lp)     do { (lp)->lock = 0; } while(0)
 #define spin_unlock_wait(lp)   do { barrier(); } while((lp)->lock)
+#define spin_is_locked(x)      ((x)->lock != 0)
 
 extern void _spin_lock(spinlock_t *lock);
 extern void _spin_unlock(spinlock_t *lock);
index 4c5e9766e6ef9864dd4e25849940b3e4f92c0ecc..d39f91cf9c624cb52569f5646e7a961274d100f5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _PPC_TYPES_H
 #define _PPC_TYPES_H
 
+#ifndef __ASSEMBLY__
 /*
  * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
  * header files exported to user space
@@ -41,10 +42,15 @@ typedef unsigned long long u64;
 
 #define BITS_PER_LONG 32
 
+typedef struct {
+       u32 u[4];
+} __attribute((aligned(16))) vector128;
+
 /* DMA addresses are 32-bits wide */
 
 typedef u32 dma_addr_t;
 
 #endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
 
 #endif
index cd6dc704afa2f45ba77d86855a4f10147e23c447..9dbd7005c79fa0d4ffa3d2dd6b88999a61ad7ed1 100644 (file)
@@ -250,10 +250,9 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
 
 /* to find an entry in a page-table-directory. */
-#define __pgd_offset(address) \
-               ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-
-#define pgd_offset(mm, address) ((mm)->pgd+__pgd_offset(address))
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+#define __pgd_offset(address) pgd_index(address)
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
index fb65d46dc1cf373751e59a2327a182fffb60b97a..4d178602db5898e1b6f007b7f9325a25a475291f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.25 2000/01/28 13:43:14 jj Exp $
+/* $Id: floppy.h,v 1.26 2000/02/12 23:32:35 davem Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -727,8 +727,8 @@ static unsigned long __init sun_floppy_init(void)
         * which the generic floppy driver tries to do once again.
         */
        sun_fdc = (struct sun_flpy_controller *)
-               (PAGE_OFFSET + fd_regs[0].phys_addr + 
-                (((unsigned long)fd_regs[0].which_io) << 32));
+               ((unsigned long)fd_regs[0].phys_addr + 
+                (((unsigned long)fd_regs[0].which_io) << 32UL));
 
        /* Last minute sanity check... */
        if(sbus_readb(&sun_fdc->status1_82077) == 0xff) {
index 3b93b20c14a376305036a7d131f57ef90a6a0191..878b99142c6f19dbf1ed73b1855b16f80b3900c4 100644 (file)
@@ -235,7 +235,8 @@ static __inline__ pte_t pte_mkdirty(pte_t _pte)
 }
 
 /* to find an entry in a page-table-directory. */
-#define pgd_offset(mm, address) ((mm)->pgd + ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD)))
+#define pgd_index(address)     (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD))
+#define pgd_offset(mm, address)        ((mm)->pgd + pgd_index(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
index 94d5607bfa54d4bc52bd366422c8fb4e980dc32d..7da1ceda02d6a033e9fea337583dd50acba2e149 100644 (file)
@@ -11,7 +11,7 @@
  * adfs file system inode data in memory
  */
 struct adfs_inode_info {
-       unsigned long mmu_private;
+       unsigned long   mmu_private;
        unsigned long   parent_id;      /* object id of parent          */
        __u32           loadaddr;       /* RISC OS load address         */
        __u32           execaddr;       /* RISC OS exec address         */
index 55e103dd583dcc1d4615b5f85e3bf0c8df541aac..22a5ed28ada44a80b8bedc716f05153d6b8bc1bd 100644 (file)
@@ -68,6 +68,7 @@
 #define I2C_DRIVERID_SAA7110   22      /*                              */
 #define I2C_DRIVERID_MGATVO    23      /* Matrox TVOut                 */
 #define I2C_DRIVERID_SAA5249   24      /* SAA5249 and compatibles      */
+#define I2C_DRIVERID_PCF8583   25      /* real time clock              */
 
 #define I2C_DRIVERID_EXP0      0xF0    /* experimental use id's        */
 #define I2C_DRIVERID_EXP1      0xF1
 #define I2C_HW_B_G400  0x09    /* Matrox G400                          */
 #define I2C_HW_B_I810  0x0a    /* Intel I810                           */
 #define I2C_HW_B_RIVA  0x10    /* Riva based graphics cards            */
+#define I2C_HW_B_IOC   0x11    /* IOC bit-wiggling                     */
 
 /* --- PCF 8584 based algorithms                                       */
 #define I2C_HW_P_LP    0x00    /* Parallel port interface              */
index 4256df6d9519f364510677d6010071454fd346cb..83abfcf92fb4927d93a4ad5006455142d3a974f5 100644 (file)
@@ -3,6 +3,7 @@
 */
 
 #include <linux/config.h>
+#include <linux/errno.h>
 
 #ifdef CONFIG_KMOD
 extern int request_module(const char * name);
index f0a220f725453846068abf5ddd0be7915bce6882..61efca7db2f5d787558066bfc3f231829650d968 100644 (file)
@@ -427,7 +427,7 @@ struct softnet_data
 
 extern struct softnet_data softnet_data[NR_CPUS];
 
-#define HAS_NETIF_QUEUE
+#define HAVE_NETIF_QUEUE
 
 extern __inline__ void __netif_schedule(struct net_device *dev)
 {
index 2838a23ac5736bf722e457892d63042826b972d0..614fd3a58ba2e29e5f87ba3fa326c5bf65ac022c 100644 (file)
@@ -126,6 +126,7 @@ EXPORT_SYMBOL(highmem_start_page);
 #endif
 
 /* filesystem internal functions */
+EXPORT_SYMBOL(def_blk_fops);
 EXPORT_SYMBOL(in_group_p);
 EXPORT_SYMBOL(update_atime);
 EXPORT_SYMBOL(get_super);
index 2980059b24920b1b093cfd4e6af4060e0ebd8836..c3f75124f47af005ae09a011b735de19a5ff6f8e 100644 (file)
@@ -53,6 +53,7 @@ repeat:
                maddr = kmap(page);
                memcpy((char *)maddr + (addr & ~PAGE_MASK), buf, len);
                flush_page_to_ram(page);
+               flush_icache_page(vma, page);
                kunmap(page);
        } else {
                maddr = kmap(page);
index 9e7525245d7cd938906c3de585c8562bd1b37209..6abcf9bb0d1cca573f5ff3b24a39903a2c37d2c4 100644 (file)
@@ -904,6 +904,8 @@ void vmtruncate(struct inode * inode, loff_t offset)
        } while ((mpnt = mpnt->vm_next_share) != NULL);
 out_unlock:
        spin_unlock(&inode->i_shared_lock);
+       if (inode->i_op && inode->i_op->truncate)
+               inode->i_op->truncate(inode);
 }
 
 
@@ -957,6 +959,7 @@ static int do_swap_page(struct task_struct * tsk,
                        return -1;
 
                flush_page_to_ram(page);
+               flush_icache_page(vma, page);
        }
 
        vma->vm_mm->rss++;
@@ -1057,6 +1060,7 @@ static int do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
         * handle that later.
         */
        flush_page_to_ram(new_page);
+       flush_icache_page(vma, new_page);
        entry = mk_pte(new_page, vma->vm_page_prot);
        if (write_access) {
                entry = pte_mkwrite(pte_mkdirty(entry));
index d6d89e5f53fb91d68b8fcb5e14fa5549120c3672..aca4d99d8bb40142dba9245f50bbe211021ac187 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -580,6 +580,7 @@ static void free_pgtables(struct mm_struct * mm, struct vm_area_struct *prev,
 {
        unsigned long first = start & PGDIR_MASK;
        unsigned long last = (end + PGDIR_SIZE - 1) & PGDIR_MASK;
+       unsigned long start_index, end_index;
 
        if (!prev) {
                prev = mm->mmap;
@@ -607,12 +608,14 @@ static void free_pgtables(struct mm_struct * mm, struct vm_area_struct *prev,
                break;
        }
 no_mmaps:
-       first = first >> PGDIR_SHIFT;
-       last = last >> PGDIR_SHIFT;
-       if (last > first) {
-               clear_page_tables(mm, first, last-first);
-               flush_tlb_pgtables(mm, first << PGDIR_SHIFT, last << PGDIR_SHIFT);
-       }
+       /*
+        * If the PGD bits are not consecutive in the virtual address, the
+        * old method of shifting the VA >> by PGDIR_SHIFT doesn't work.
+        */
+       start_index = pgd_index(first);
+       end_index = pgd_index(last);
+       if (end_index > start_index)
+               clear_page_tables(mm, start_index, end_index - start_index);
 }
 
 /* Munmap is split into 2 main parts -- this part which finds
index 00d5caa2a37b7a3fb589b1f6cab490ddb1803638..32c8143fba118704470e53921a4b3de06f49b734 100644 (file)
@@ -911,15 +911,14 @@ static __inline__ void skb_bond(struct sk_buff *skb)
 static void net_tx_action(struct softirq_action *h)
 {
        int cpu = smp_processor_id();
-       unsigned long flags;
 
        if (softnet_data[cpu].completion_queue) {
                struct sk_buff *clist;
 
-               local_irq_save(flags);
+               local_irq_disable();
                clist = softnet_data[cpu].completion_queue;
                softnet_data[cpu].completion_queue = NULL;
-               local_irq_restore(flags);
+               local_irq_enable();
 
                while (clist != NULL) {
                        struct sk_buff *skb = clist;
@@ -933,10 +932,10 @@ static void net_tx_action(struct softirq_action *h)
        if (softnet_data[cpu].output_queue) {
                struct net_device *head;
 
-               local_irq_save(flags);
+               local_irq_disable();
                head = softnet_data[cpu].output_queue;
                softnet_data[cpu].output_queue = NULL;
-               local_irq_restore(flags);
+               local_irq_enable();
 
                while (head != NULL) {
                        struct net_device *dev = head;
index 06d6209521823bffee1ca7adad24433df5252ab7..09b9c1a11752af66390178677b4586f5fb13c548 100644 (file)
@@ -7,7 +7,7 @@
  *
  *     Adapted from linux/net/ipv4/af_inet.c
  *
- *     $Id: af_inet6.c,v 1.53 2000/02/04 21:04:08 davem Exp $
+ *     $Id: af_inet6.c,v 1.54 2000/02/12 23:34:45 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -451,7 +451,7 @@ struct proto_ops inet6_dgram_ops = {
        inet6_bind,
        inet_dgram_connect,             /* ok           */
        sock_no_socketpair,             /* a do nothing */
-       inet_accept,                    /* ok           */
+       sock_no_accept,                 /* a do nothing */
        inet6_getname, 
        datagram_poll,                  /* ok           */
        inet6_ioctl,                    /* must change  */
index 0d575abdfb5fad9f5e7861ddc462eb7647e6262b..60e66fdf884a94612e2d3e8fca78c88bde6670e0 100644 (file)
@@ -71,8 +71,6 @@ int StartListening(const int Port)
 
        /* Grrr... setsockopt() does this. */
        sock->sk->reuse   = 1;
-       /* Wow!!! */
-       sock->sk->linger  = 1;
 
        /* Now, start listening on the socket */
        
index b6f367df23ce9f2518c42505a3cfbb541e109683..1a1e7513eebd36b9e8ec965378bfa6858546fcc8 100644 (file)
@@ -540,6 +540,7 @@ EXPORT_SYMBOL(unregister_hipdev);
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_wmem_max);
 EXPORT_SYMBOL(sysctl_rmem_max);
+EXPORT_SYMBOL(sysctl_ip_default_ttl);
 #endif
 
 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) 
index f1a36bb25be4f86646da57bc647739a10f8741ee..ab0f74832f5ad9424793b39564b6636d1ece318f 100644 (file)
@@ -498,6 +498,7 @@ void fix_conditionals( struct kconfig * scfg )
            case token_define_int:
            case token_define_string:
            case token_define_tristate:
+           case token_endmenu:
            case token_hex:
            case token_int:
            case token_mainmenu_option: