]> git.hungrycats.org Git - linux/commitdiff
v2.4.10.2 -> v2.4.10.3
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:20:19 +0000 (20:20 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:20:19 +0000 (20:20 -0800)
  - Al Viro: superblock cleanups, partition handling fixes and cleanups
  - Ben Collins: firewire update
  - Jeff Garzik: network driver updates
  - Urban Widmark: smbfs updates
  - Kai Mäkisara: SCSI tape driver update
  - various: embarrassing lack of error checking in ELF loader
  - Neil Brown: md formatting cleanup.

95 files changed:
Makefile
arch/ppc/mm/fault.c
arch/ppc/mm/init.c
arch/ppc/mm/mmu_context.c
arch/ppc/mm/pgtable.c
drivers/char/sysrq.c
drivers/ide/ide-pmac.c
drivers/ieee1394/highlevel.c
drivers/ieee1394/hosts.c
drivers/ieee1394/hosts.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/ieee1394_hotplug.h
drivers/ieee1394/ieee1394_syms.c
drivers/ieee1394/ieee1394_transactions.c
drivers/ieee1394/ieee1394_types.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/nodemgr.h
drivers/ieee1394/ohci1394.c
drivers/ieee1394/ohci1394.h
drivers/ieee1394/pcilynx.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c
drivers/md/md.c
drivers/net/8139too.c
drivers/net/natsemi.c
drivers/net/tulip/eeprom.c
drivers/net/tulip/interrupt.c
drivers/net/tulip/tulip_core.c
drivers/net/wireless/airo.c
drivers/net/wireless/hermes.c
drivers/net/wireless/hermes.h
drivers/net/wireless/orinoco.c
drivers/net/wireless/orinoco.h
drivers/net/wireless/orinoco_cs.c
drivers/pci/pci.ids
drivers/scsi/st.c
drivers/video/clgenfb.c
drivers/video/controlfb.c
drivers/video/offb.c
fs/binfmt_elf.c
fs/block_dev.c
fs/lockd/svc.c
fs/nfsd/export.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfsfh.c
fs/nfsd/nfsxdr.c
fs/nfsd/vfs.c
fs/partitions/acorn.c
fs/partitions/acorn.h
fs/partitions/amiga.c
fs/partitions/amiga.h
fs/partitions/atari.c
fs/partitions/atari.h
fs/partitions/check.c
fs/partitions/check.h
fs/partitions/ibm.c
fs/partitions/ibm.h
fs/partitions/ldm.c
fs/partitions/ldm.h
fs/partitions/mac.c
fs/partitions/mac.h
fs/partitions/msdos.c
fs/partitions/msdos.h
fs/partitions/osf.c
fs/partitions/osf.h
fs/partitions/sgi.c
fs/partitions/sgi.h
fs/partitions/sun.c
fs/partitions/sun.h
fs/partitions/ultrix.c
fs/partitions/ultrix.h
fs/smbfs/ChangeLog
fs/smbfs/Makefile
fs/smbfs/cache.c
fs/smbfs/dir.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/smbfs/ioctl.c
fs/smbfs/proc.c
fs/smbfs/proto.h [new file with mode: 0644]
fs/smbfs/sock.c
fs/super.c
include/asm-ppc/mmu_context.h
include/linux/fs.h
include/linux/gameport.h
include/linux/genhd.h
include/linux/module.h
include/linux/smb_fs.h
include/linux/smbno.h
include/linux/spinlock.h
init/main.c
lib/dec_and_lock.c

index fa119e79e6fac9a534c44a98b41fc27f1dbaac42..9cbd912ff927912d32899dfad3f0e5643fc99644 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 11
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index 657bd034497187d0e482edd380c30f4dbb375029..9fee4ad0c33d213e9d6f7a223d05c6225c27af4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.fault.c 1.13 06/28/01 15:50:17 paulus
+ * BK Id: SCCS/s.fault.c 1.15 09/24/01 16:35:10 paulus
  */
 /*
  *  arch/ppc/mm/fault.c
@@ -150,6 +150,7 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
+ survive:
         switch (handle_mm_fault(mm, vma, address, is_write)) {
         case 1:
                 current->min_flt++;
@@ -195,6 +196,12 @@ bad_area:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
+       if (current->pid == 1) {
+               current->policy |= SCHED_YIELD;
+               schedule();
+               down_read(&mm->mmap_sem);
+               goto survive;
+       }
        printk("VM: killing process %s\n", current->comm);
        if (user_mode(regs))
                do_exit(SIGKILL);
@@ -346,34 +353,3 @@ get_8xx_pte(struct mm_struct *mm, unsigned long addr)
         return(retval);
 }
 #endif /* CONFIG_8xx */
-
-#if 0
-/*
- * Misc debugging functions.  Please leave them here. -- Cort
- */
-void print_pte(struct _PTE p)
-{
-       printk(
-"%08x %08x vsid: %06x h: %01x api: %02x rpn: %05x rcwimg: %d%d%d%d%d%d pp: %02x\n",
-               *((unsigned long *)(&p)), *((long *)&p+1),
-               p.vsid, p.h, p.api, p.rpn,
-               p.r,p.c,p.w,p.i,p.m,p.g,p.pp);
-}
-
-/*
- * Search the hw hash table for a mapping to the given physical
- * address. -- Cort
- */
-unsigned long htab_phys_to_va(unsigned long address)
-{
-       extern PTE *Hash, *Hash_end;
-       PTE *ptr;
-
-       for ( ptr = Hash ; ptr < Hash_end ; ptr++ )
-       {
-               if ( ptr->rpn == (address>>12) )
-                       printk("phys %08lX -> va ???\n",
-                              address);
-       }
-}
-#endif
index b31b61a897a42ad56dcba958e9779b12fb7308b8..2c8fb53a871c0ec28aeba10a808d77dbd73fbe98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.init.c 1.34 08/20/01 22:12:43 paulus
+ * BK Id: SCCS/s.init.c 1.36 09/22/01 14:03:09 paulus
  */
 /*
  *  PowerPC version 
 #include <asm/smp.h>
 #include <asm/machdep.h>
 #include <asm/btext.h>
+#include <asm/tlb.h>
 
 #include "mem_pieces.h"
 #include "mmu_decl.h"
 
 #define MAX_LOW_MEM    (0xF0000000UL - KERNELBASE)
 
+mmu_gather_t mmu_gathers[NR_CPUS];
+
 void *end_of_DRAM;
 unsigned long total_memory;
 unsigned long total_lowmem;
index cae4b53c7d1a6264918ee33eee9480c46f67135d..ba6784ec812e31b02f823fc092307471097fba6e 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/mmu_context.h>
 
 mm_context_t next_mmu_context;
-unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
+unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
 #ifdef FEW_CONTEXTS
 atomic_t nr_free_contexts;
 struct mm_struct *context_mm[LAST_CONTEXT+1];
@@ -57,7 +57,7 @@ void __init mmu_context_init(void)
        context_map[0] = (1 << FIRST_CONTEXT) - 1;
        next_mmu_context = FIRST_CONTEXT;
 #ifdef FEW_CONTEXTS
-       atomic_set(&nr_free_contexts, LAST_CONTEXT);
+       atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
 #endif /* FEW_CONTEXTS */
 }
 
index d3f35ebbe86084e711d5a8401e71b6f085c3f6d9..d3630a8c1491ccfe40d59210f6948b03a8691096 100644 (file)
@@ -211,12 +211,12 @@ void __init mapin_ram(void)
 #else
                if ((char *) v < _stext || (char *) v >= etext)
                        f |= _PAGE_RW | _PAGE_DIRTY;
-#ifndef CONFIG_8xx
+#ifdef CONFIG_PPC_STD_MMU
                else
-                       /* On the powerpc (not 8xx), no user access
+                       /* On the powerpc (not all), no user access
                           forces R/W kernel access */
                        f |= _PAGE_USER;
-#endif /* CONFIG_8xx */
+#endif /* CONFIG_PPC_STD_MMU */
 #endif /* CONFIG_KGDB */
                map_page(v, p, f);
                v += PAGE_SIZE;
index ebca79af8ce3347bc12668e62b84db2d106a0145..07e235f166b45cdfea424246f91cd0e81945af9a 100644 (file)
@@ -231,12 +231,12 @@ static struct sysrq_key_op sysrq_sync_op = {
 static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
                struct kbd_struct *kbd, struct tty_struct *tty) {
        emergency_sync_scheduled = EMERG_REMOUNT;
-       wakeup_bdflush(0);
+       wakeup_bdflush();
 }
 static struct sysrq_key_op sysrq_mountro_op = {
        handler:        sysrq_handle_mountro,
        help_msg:       "Unmount",
-       action_msg:     "Emergency Remount R/0",
+       action_msg:     "Emergency Remount R/O",
 };
 
 /* END SYNC SYSRQ HANDLERS BLOCK */
index 590645be879dc95904ba4af99984c5725f80f483..af7603af9e84e3db0873ea8c84512a5201d2e7fd 100644 (file)
@@ -5,9 +5,7 @@
  * These IDE interfaces are memory-mapped and have a DBDMA channel
  * for doing DMA.
  *
- *  Copyright (C) 1998 Paul Mackerras.
- *
- *  Bits from Benjamin Herrenschmidt
+ *  Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -99,13 +97,13 @@ static pmac_ide_timing udma_timings[] =
 /* allow up to 256 DBDMA commands per xfer */
 #define MAX_DCMDS              256
 
-/* Wait 1.5s for disk to answer on IDE bus after
+/* Wait 2s for disk to answer on IDE bus after
  * enable operation.
  * NOTE: There is at least one case I know of a disk that needs about 10sec
  *       before anwering on the bus. I beleive we could add a kernel command
  *       line arg to override this delay for such cases.
  */
-#define IDE_WAKEUP_DELAY_MS    1500
+#define IDE_WAKEUP_DELAY_MS    2000
 
 static void pmac_ide_setup_dma(struct device_node *np, int ix);
 static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
@@ -236,13 +234,21 @@ wait_for_ready(ide_drive_t *drive)
        }
        if((stat & ERR_STAT) || timeout <= 0) {
                if (stat & ERR_STAT) {
-                       printk("ide_pmace: wait_for_ready, error status: %x\n", stat);
+                       printk(KERN_ERR "ide_pmac: wait_for_ready, error status: %x\n", stat);
                }
                return 1;
        }
        return 0;
 }
 
+/* Note: We don't use the generic routine here because some of Apple's
+ * controller seem to be very sensitive about how things are done.
+ * We should probably set the NIEN bit, but that's an example of thing
+ * that can cause the controller to hang under some circumstances when
+ * done on the media-bay CD-ROM during boot. We do get occasional
+ * spurrious interrupts because of that.
+ * --BenH
+ */
 static int
 pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
 {
@@ -256,7 +262,7 @@ pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
        SELECT_MASK(HWIF(drive), drive, 0);
        udelay(1);
        if(wait_for_ready(drive)) {
-               printk("pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
+               printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
                goto out;
        }
        OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
@@ -265,7 +271,7 @@ pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
        udelay(1);
        result = wait_for_ready(drive);
        if (result)
-               printk("pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
+               printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
 out:
        restore_flags(flags);
        
@@ -311,7 +317,7 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
        }
 
 #ifdef IDE_PMAC_DEBUG
-       printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
+       printk(KERN_ERR "ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
                pio,  *timings);
 #endif 
                
@@ -562,7 +568,7 @@ pmac_ide_probe(void)
                   fixes in irq.c
                 */
                if (np->n_intrs == 0) {
-                       printk("ide: no intrs for device %s, using 13\n",
+                       printk(KERN_WARNING "ide: no intrs for device %s, using 13\n",
                               np->full_name);
                        irq = 13;
                } else {
@@ -598,7 +604,7 @@ pmac_ide_probe(void)
                         feature_set(np, FEATURE_IDE0_enable);
                } else {
                        /* This is necessary to enable IDE when net-booting */
-                       printk("pmac_ide: enabling IDE bus ID %d\n",
+                       printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",
                                pmac_ide[i].aapl_bus_id);
                        switch(pmac_ide[i].aapl_bus_id) {
                            case 0:
@@ -732,7 +738,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
                        unsigned int tc = (size < 0xfe00)? size: 0xfe00;
 
                        if (++count >= MAX_DCMDS) {
-                               printk("%s: DMA table too small\n",
+                               printk(KERN_WARNING "%s: DMA table too small\n",
                                       drive->name);
                                return 0; /* revert to PIO for this request */
                        }
@@ -804,10 +810,10 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
        int ret;
 
        /* Set feature on drive */
-       printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
+       printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
        ret = pmac_ide_do_setfeature(drive, feature);
        if (ret) {
-               printk("%s: Failed !\n", drive->name);
+               printk(KERN_WARNING "%s: Failed !\n", drive->name);
                return 0;
        }
 
@@ -860,7 +866,7 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
                        (accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
        }
 #ifdef IDE_PMAC_DEBUG
-       printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
+       printk(KERN_INFO "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
                feature & 0xf, *timings);
 #endif
        drive->current_speed = feature; 
@@ -879,10 +885,10 @@ pmac_ide_udma_enable(ide_drive_t *drive, int idx)
        int ret;
 
        /* Set feature on drive */
-       printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
+       printk(KERN_INFO "%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
        ret = pmac_ide_do_setfeature(drive, feature);
        if (ret) {
-               printk("%s: Failed !\n", drive->name);
+               printk(KERN_WARNING "%s: Failed !\n", drive->name);
                return 0;
        }
 
@@ -953,7 +959,7 @@ pmac_ide_check_dma(ide_drive_t *drive)
 
 int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-       int ix, dstat;
+       int ix, dstat, i;
        volatile struct dbdma_regs *dma;
 
        /* Can we stuff a pointer to our intf structure in config_data
@@ -966,7 +972,7 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 
        switch (func) {
        case ide_dma_off:
-               printk("%s: DMA disabled\n", drive->name);
+               printk(KERN_INFO "%s: DMA disabled\n", drive->name);
        case ide_dma_off_quietly:
                drive->using_dma = 0;
                break;
@@ -994,7 +1000,27 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
                /* verify good dma status */
                return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
        case ide_dma_test_irq:
-               return (in_le32(&dma->status) & (RUN|ACTIVE)) == RUN;
+               if ((in_le32(&dma->status) & (RUN|ACTIVE)) == RUN)
+                       return 1;
+               /* That's a bit ugly and dangerous, but works in our case
+                * to workaround a problem with the channel status staying
+                * active if the drive returns an error
+                */
+               if (IDE_CONTROL_REG) {
+                       byte stat;
+                       stat = GET_ALTSTAT();
+                       if (stat & ERR_STAT)
+                               return 1;
+               }
+               /* In some edge cases, some datas may still be in the dbdma
+                * engine fifo, we wait a bit for dbdma to complete
+                */
+               while ((in_le32(&dma->status) & (RUN|ACTIVE)) != RUN) {
+                       if (++i > 100)
+                               return 0;
+                       udelay(1);
+               }
+               return 1;
 
                /* Let's implement tose just in case someone wants them */
        case ide_dma_bad_drive:
@@ -1005,10 +1031,10 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
        case ide_dma_retune:
        case ide_dma_lostirq:
        case ide_dma_timeout:
-               printk("ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func),  func);
+               printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func),  func);
                return 1;
        default:
-               printk("ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
+               printk(KERN_WARNING "ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
                return 1;
        }
        return 0;
@@ -1016,13 +1042,15 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 #ifdef CONFIG_PMAC_PBOOK
-static void idepmac_sleep_disk(int i, unsigned long base)
+static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
 {
-       struct device_node* np = pmac_ide[i].node;
        int j;
-
-       /* FIXME: We only handle the master IDE */
-       if (ide_hwifs[i].drives[0].media == ide_disk) {
+       
+       /* FIXME: We only handle the master IDE disk, we shoud
+        *        try to fix CD-ROMs here
+        */
+       switch (drive->media) {
+       case ide_disk:
                /* Spin down the drive */
                outb(0xa0, base+0x60);
                outb(0x0, base+0x30);
@@ -1038,86 +1066,112 @@ static void idepmac_sleep_disk(int i, unsigned long base)
                        if (!(status & BUSY_STAT) && (status & DRQ_STAT))
                                break;
                }
-       }
-       feature_set(np, FEATURE_IDE0_reset);
-       feature_clear(np, FEATURE_IDE0_enable);
-       switch(pmac_ide[i].aapl_bus_id) {
-           case 0:
-               feature_set(np, FEATURE_IDE0_reset);
-               feature_clear(np, FEATURE_IDE0_enable);
                break;
-           case 1:
-               feature_set(np, FEATURE_IDE1_reset);
-               feature_clear(np, FEATURE_IDE1_enable);
+       case ide_cdrom:
+               // todo
                break;
-           case 2:
-               feature_set(np, FEATURE_IDE2_reset);
+       case ide_floppy:
+               // todo
                break;
        }
-       pmac_ide[i].timings[0] = 0;
-       pmac_ide[i].timings[1] = 0;
 }
 
-static void idepmac_wake_disk(int i, unsigned long base)
+static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
+ {
+       /* We force the IDE subdriver to check for a media change
+        * This must be done first or we may lost the condition
+        *
+        * Problem: This can schedule. I moved the block device
+        * wakeup almost late by priority because of that.
+        */
+       if (DRIVER(drive) && DRIVER(drive)->media_change)
+               DRIVER(drive)->media_change(drive);
+
+       /* We kick the VFS too (see fix in ide.c revalidate) */
+       check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS));
+       
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+       /* We re-enable DMA on the drive if it was active. */
+       /* This doesn't work with the CD-ROM in the media-bay, probably
+        * because of a pending unit attention. The problem if that if I
+        * clear the error, the filesystem dies.
+        */
+       if (used_dma && !ide_spin_wait_hwgroup(drive)) {
+               /* Lock HW group */
+               HWGROUP(drive)->busy = 1;
+               pmac_ide_check_dma(drive);
+               HWGROUP(drive)->busy = 0;
+               spin_unlock_irq(&io_request_lock);
+       }
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+}
+
+static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
 {
        struct device_node* np = pmac_ide[i].node;
-       int j;
 
-       /* Revive IDE disk and controller */
+       /* We clear the timings */
+       pmac_ide[i].timings[0] = 0;
+       pmac_ide[i].timings[1] = 0;
+       
+       /* The media bay will handle itself just fine */
+       if (mediabay)
+               return;
+       
+       /* Disable and reset the bus */
+       feature_set(np, FEATURE_IDE0_reset);
+       feature_clear(np, FEATURE_IDE0_enable);
        switch(pmac_ide[i].aapl_bus_id) {
            case 0:
                feature_set(np, FEATURE_IDE0_reset);
-               mdelay(10);
-               feature_set(np, FEATURE_IDE0_enable);
-               mdelay(10);
-               feature_clear(np, FEATURE_IDE0_reset);
+               feature_clear(np, FEATURE_IDE0_enable);
                break;
            case 1:
                feature_set(np, FEATURE_IDE1_reset);
-               mdelay(10);
-               feature_set(np, FEATURE_IDE1_enable);
-               mdelay(10);
-               feature_clear(np, FEATURE_IDE1_reset);
+               feature_clear(np, FEATURE_IDE1_enable);
                break;
            case 2:
-               /* This one exists only for KL, I don't know
-                  about any enable bit */
                feature_set(np, FEATURE_IDE2_reset);
-               mdelay(10);
-               feature_clear(np, FEATURE_IDE2_reset);
                break;
        }
-       mdelay(IDE_WAKEUP_DELAY_MS);
-
-       /* Reset timings */
-       pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
-       mdelay(10);
-
-       /* Wait up to 10 seconds (enough for recent drives) */
-       for (j = 0; j < 100; j++) {
-               int status;
-               mdelay(100);
-               status = inb(base + 0x70);
-               if (!(status & BUSY_STAT))
-                       break;
-       }
 }
 
-/* Here we handle media bay devices */
-static void
-idepmac_wake_bay(int i, unsigned long base)
+static void idepmac_wake_interface(int i, unsigned long base, int mediabay)
 {
-       int timeout;
+       struct device_node* np = pmac_ide[i].node;
 
+       if (!mediabay) {
+               /* Revive IDE disk and controller */
+               switch(pmac_ide[i].aapl_bus_id) {
+                   case 0:
+                       feature_set(np, FEATURE_IDE0_reset);
+                       feature_set(np, FEATURE_IOBUS_enable);
+                       mdelay(10);
+                       feature_set(np, FEATURE_IDE0_enable);
+                       mdelay(10);
+                       feature_clear(np, FEATURE_IDE0_reset);
+                       break;
+                   case 1:
+                       feature_set(np, FEATURE_IDE1_reset);
+                       feature_set(np, FEATURE_IOBUS_enable);
+                       mdelay(10);
+                       feature_set(np, FEATURE_IDE1_enable);
+                       mdelay(10);
+                       feature_clear(np, FEATURE_IDE1_reset);
+                       break;
+                   case 2:
+                       /* This one exists only for KL, I don't know
+                          about any enable bit */
+                       feature_set(np, FEATURE_IDE2_reset);
+                       mdelay(10);
+                       feature_clear(np, FEATURE_IDE2_reset);
+                       break;
+               }
+       }
+       
        /* Reset timings */
        pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
        mdelay(10);
-
-       timeout = 10000;
-       while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
-               mdelay(1);
-               --timeout;
-       }
 }
 
 /* Note: We support only master drives for now. This will have to be
@@ -1128,6 +1182,8 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
        int i, ret;
        unsigned long base;
+       unsigned long flags;
+       int big_delay;
 
        switch (when) {
        case PBOOK_SLEEP_REQUEST:
@@ -1136,34 +1192,104 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
                break;
        case PBOOK_SLEEP_NOW:
                for (i = 0; i < pmac_ide_count; ++i) {
+                       ide_hwif_t *hwif;
+                       ide_drive_t *drive;
+                       int unlock = 0;
+
                        if ((base = pmac_ide[i].regbase) == 0)
-                               continue;
+                               continue;       
+
+                       hwif = &ide_hwifs[i];
+                       drive = &hwif->drives[0];
+                       
+                       if (drive->present) {
+                               /* Wait for HW group to complete operations */
+                               if (ide_spin_wait_hwgroup(drive)) {
+                                       // What can we do here ? Wake drive we had already
+                                       // put to sleep and return an error ?
+                               } else {
+                                       unlock = 1;
+                                       /* Lock HW group */
+                                       HWGROUP(drive)->busy = 1;
+
+                                       /* Stop the device */
+                                       idepmac_sleep_device(drive, i, base);
+                               
+                               }
+                       }
                        /* Disable irq during sleep */
                        disable_irq(pmac_ide[i].irq);
+                       if (unlock)
+                               spin_unlock_irq(&io_request_lock);
+                       
+                       /* Check if this is a media bay with an IDE device or not
+                        * a media bay.
+                        */
                        ret = check_media_bay_by_base(base, MB_CD);
-                       if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
-                               /* not media bay - put the disk to sleep */
-                               idepmac_sleep_disk(i, base);
+                       if ((ret == 0) || (ret == -ENODEV))
+                               idepmac_sleep_interface(i, base, (ret == 0));
                }
                break;
        case PBOOK_WAKE:
+               big_delay = 0;
+               for (i = 0; i < pmac_ide_count; ++i) {
+
+                       if ((base = pmac_ide[i].regbase) == 0)
+                               continue;
+                               
+                       /* Check if this is a media bay with an IDE device or not
+                        * a media bay
+                        */
+                       ret = check_media_bay_by_base(base, MB_CD);
+                       if ((ret == 0) || (ret == -ENODEV)) {
+                               idepmac_wake_interface(i, base, (ret == 0));                            
+                               big_delay = 1;
+                       }
+
+               }
+               /* Let hardware get up to speed */
+               if (big_delay)
+                       mdelay(IDE_WAKEUP_DELAY_MS);
+       
                for (i = 0; i < pmac_ide_count; ++i) {
                        ide_hwif_t *hwif;
+                       ide_drive_t *drive;                     
+                       int j, used_dma;
+                       
                        if ((base = pmac_ide[i].regbase) == 0)
                                continue;
+                               
                        hwif = &ide_hwifs[i];
-                       /* We don't handle media bay devices this way */
-                       ret = check_media_bay_by_base(base, MB_CD);
-                       if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
-                               idepmac_wake_disk(i, base);
-                       else if (ret == 0)
-                               idepmac_wake_bay(i, base);
-                       enable_irq(pmac_ide[i].irq);
+                       drive = &hwif->drives[0];
+
+                       /* Wait for the drive to come up and set it's DMA */
+                       if (drive->present) {
+                               /* Wait up to 20 seconds */
+                               for (j = 0; j < 200; j++) {
+                                       int status;
+                                       mdelay(100);
+                                       status = inb(base + 0x70);
+                                       if (!(status & BUSY_STAT))
+                                               break;
+                               }
+                       }
+                       
+                       /* We don't have re-configured DMA yet */
+                       used_dma = drive->using_dma;
+                       drive->using_dma = 0;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-                       if (hwif->drives[0].present && hwif->drives[0].using_dma)
-                               pmac_ide_check_dma(&hwif->drives[0]);
-#endif                         
+                       /* We resume processing on the HW group */
+                       spin_lock_irqsave(&io_request_lock, flags);
+                       enable_irq(pmac_ide[i].irq);
+                       if (drive->present)
+                               HWGROUP(drive)->busy = 0;
+                       spin_unlock_irqrestore(&io_request_lock, flags);
+                       
+                       /* Wake the device
+                        * We could handle the slave here
+                        */
+                       if (drive->present)
+                               idepmac_wake_device(drive, used_dma);
                }
                break;
        }
index e33b5ed75db1b887648b8643cef71e08210feb7a..3f337eb5d599963ce6ddf678bc65515adbb964ee 100644 (file)
@@ -154,21 +154,18 @@ void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
 }
 
 
-#define DEFINE_MULTIPLEXER(Function) \
-void highlevel_##Function(struct hpsb_host *host) \
-{ \
-        struct list_head *entry,*next; \
-        void (*funcptr)(struct hpsb_host*); \
-        read_lock(&hl_drivers_lock); \
-        entry = hl_drivers.next; \
-        while (entry != &hl_drivers) { \
-               next = entry->next; \
-                funcptr = list_entry(entry, struct hpsb_highlevel, hl_list) \
-                          ->op->Function; \
-                if (funcptr) funcptr(host); \
-                entry = next; \
-        } \
-        read_unlock(&hl_drivers_lock); \
+#define DEFINE_MULTIPLEXER(Function)                   \
+void highlevel_##Function(struct hpsb_host *host)      \
+{                                                      \
+       struct list_head *lh;                           \
+       void (*funcptr)(struct hpsb_host*);             \
+       read_lock(&hl_drivers_lock);                    \
+       list_for_each(lh, &hl_drivers) {                \
+               funcptr = list_entry(lh, struct hpsb_highlevel, hl_list) \
+                               ->op->Function;         \
+               if (funcptr) funcptr(host);             \
+       }                                               \
+       read_unlock(&hl_drivers_lock);                  \
 }
 
 DEFINE_MULTIPLEXER(add_host)
index 0c1ed7426270336503f80d0d40910a4da95f2da5..01019eddafc688d0326aa38fdf6a0ccc0a4a031d 100644 (file)
@@ -23,8 +23,8 @@
 #include "highlevel.h"
 
 
-static struct hpsb_host_template *templates = NULL;
-spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(templates);
+static spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * This function calls the add_host/remove_host hooks for every host currently
@@ -32,13 +32,16 @@ spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
  */
 void hl_all_hosts(struct hpsb_highlevel *hl, int init)
 {
+       struct list_head *tlh, *hlh;
         struct hpsb_host_template *tmpl;
         struct hpsb_host *host;
 
         spin_lock(&templates_lock);
 
-        for (tmpl = templates; tmpl != NULL; tmpl = tmpl->next) {
-                for (host = tmpl->hosts; host != NULL; host = host->next) {
+       list_for_each(tlh, &templates) {
+                tmpl = list_entry(tlh, struct hpsb_host_template, list);
+               list_for_each(hlh, &tmpl->hosts) {
+                       host = list_entry(hlh, struct hpsb_host, list);
                         if (host->initialized) {
                                 if (init) {
                                         if (hl->op->add_host) {
@@ -58,21 +61,24 @@ void hl_all_hosts(struct hpsb_highlevel *hl, int init)
 
 int hpsb_inc_host_usage(struct hpsb_host *host)
 {
+       struct list_head *tlh, *hlh;
         struct hpsb_host_template *tmpl;
-        struct hpsb_host *h;
         int retval = 0;
        unsigned long flags;
 
         spin_lock_irqsave(&templates_lock, flags);
 
-        for (tmpl = templates; (tmpl != NULL) && !retval; tmpl = tmpl->next) {
-                for (h = tmpl->hosts; h != NULL; h = h->next) {
-                        if (h == host) {
-                                tmpl->devctl(h, MODIFY_USAGE, 1);
+       list_for_each(tlh, &templates) {
+                tmpl = list_entry(tlh, struct hpsb_host_template, list);
+               list_for_each(hlh, &tmpl->hosts) {
+                       if (host == list_entry(hlh, struct hpsb_host, list)) {
+                                tmpl->devctl(host, MODIFY_USAGE, 1);
                                 retval = 1;
                                 break;
                         }
                 }
+               if (retval)
+                       break;
         }
 
         spin_unlock_irqrestore(&templates_lock, flags);
@@ -113,32 +119,22 @@ struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl,
         h->speed_map = (u8 *)(h->csr.speed_map + 2);
 
         h->template = tmpl;
-        if (hd_size) {
+        if (hd_size)
                 h->hostdata = &h->embedded_hostdata[0];
-        }
-
-        if (tmpl->hosts == NULL) {
-                tmpl->hosts = h;
-        } else {
-                struct hpsb_host *last = tmpl->hosts;
 
-                while (last->next != NULL) {
-                        last = last->next;
-                }
-                last->next = h;
-        }
+       list_add_tail(&h->list, &tmpl->hosts);
 
         return h;
 }
 
 static void free_all_hosts(struct hpsb_host_template *tmpl)
 {
-        struct hpsb_host *next, *host = tmpl->hosts;
+       struct list_head *hlh, *next;
+        struct hpsb_host *host;
 
-        while (host) {
-                next = host->next;
+       list_for_each_safe(hlh, next, &tmpl->hosts) {
+               host = list_entry(hlh, struct hpsb_host, list);
                 vfree(host);
-                host = next;
         }
 }
 
@@ -146,11 +142,13 @@ static void free_all_hosts(struct hpsb_host_template *tmpl)
 static void init_hosts(struct hpsb_host_template *tmpl)
 {
         int count;
+       struct list_head *hlh;
         struct hpsb_host *host;
 
         count = tmpl->detect_hosts(tmpl);
 
-        for (host = tmpl->hosts; host != NULL; host = host->next) {
+       list_for_each(hlh, &tmpl->hosts) {
+               host = list_entry(hlh, struct hpsb_host, list);
                 if (tmpl->initialize_host(host)) {
                         host->initialized = 1;
 
@@ -166,9 +164,11 @@ static void init_hosts(struct hpsb_host_template *tmpl)
 
 static void shutdown_hosts(struct hpsb_host_template *tmpl)
 {
+       struct list_head *hlh;
         struct hpsb_host *host;
 
-        for (host = tmpl->hosts; host != NULL; host = host->next) {
+       list_for_each(hlh, &tmpl->hosts) {
+               host = list_entry(hlh, struct hpsb_host, list);
                 if (host->initialized) {
                         host->initialized = 0;
                         abort_requests(host);
@@ -188,68 +188,17 @@ static void shutdown_hosts(struct hpsb_host_template *tmpl)
 }
 
 
-static int add_template(struct hpsb_host_template *new)
-{
-        new->next = NULL;
-        new->hosts = NULL;
-        new->number_of_hosts = 0;
-
-        spin_lock(&templates_lock);
-        if (templates == NULL) {
-                templates = new;
-        } else {
-                struct hpsb_host_template *last = templates;
-                while (last->next != NULL) {
-                        last = last->next;
-                }
-                last->next = new;
-        }
-        spin_unlock(&templates_lock);
-
-        return 0;
-}
-
-static int remove_template(struct hpsb_host_template *tmpl)
-{
-        int retval = 0;
-
-        if (tmpl->number_of_hosts) {
-                HPSB_ERR("attempted to remove busy host template "
-                         "of %s at address 0x%p", tmpl->name, tmpl);
-                return 1;
-        }
-
-        spin_lock(&templates_lock);
-        if (templates == tmpl) {
-                templates = tmpl->next;
-        } else {
-                struct hpsb_host_template *t;
-
-                t = templates;
-                while (t->next != tmpl && t->next != NULL) {
-                        t = t->next;
-                }
-
-                if (t->next == NULL) {
-                        HPSB_ERR("attempted to remove unregistered host template "
-                                 "of %s at address 0x%p", tmpl->name, tmpl);
-                        retval = -1;
-                } else {
-                        t->next = tmpl->next;
-                }
-        }
-        spin_unlock(&templates_lock);
-
-        return retval;
-}
-
-
 /*
  * The following two functions are exported symbols for module usage.
  */
 int hpsb_register_lowlevel(struct hpsb_host_template *tmpl)
 {
-        add_template(tmpl);
+       INIT_LIST_HEAD(&tmpl->hosts);
+       tmpl->number_of_hosts = 0;
+
+        spin_lock(&templates_lock);
+       list_add_tail(&tmpl->list, &templates);
+        spin_unlock(&templates_lock);
 
        /* PCI cards should be smart and use the PCI detection layer, and
         * not this one shot deal. detect_hosts() will be obsoleted soon. */
@@ -265,7 +214,12 @@ void hpsb_unregister_lowlevel(struct hpsb_host_template *tmpl)
 {
         shutdown_hosts(tmpl);
 
-        if (remove_template(tmpl)) {
-                HPSB_PANIC("remove_template failed on %s", tmpl->name);
-        }
+        if (tmpl->number_of_hosts)
+                HPSB_PANIC("attempted to remove busy host template "
+                          "of %s at address 0x%p", tmpl->name, tmpl);
+       else {
+               spin_lock(&templates_lock);
+               list_del(&tmpl->list);
+               spin_unlock(&templates_lock);
+       }
 }
index 2f3c3477191347637727b7d32f4675f4831f2c4e..a58d415ab0b373ad21da15c05494012826317f45 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/wait.h>
 #include <linux/tqueue.h>
+#include <linux/list.h>
 #include <asm/semaphore.h>
 
 #include "ieee1394_types.h"
@@ -13,7 +14,7 @@ struct hpsb_packet;
 
 struct hpsb_host {
 /* private fields (hosts, do not use them) */
-        struct hpsb_host *next;
+       struct list_head list;
 
         atomic_t generation;
 
@@ -109,9 +110,9 @@ enum reset_types {
 };
 
 struct hpsb_host_template {
-        struct hpsb_host_template *next;
+       struct list_head list;
 
-        struct hpsb_host *hosts;
+        struct list_head hosts;
         int number_of_hosts;
 
         /* fields above will be ignored and overwritten after registering */
index fe58e3a33bc005938310f9c3e8446d53db6ab770..b19bd5d439091cccdb76a6a1251920d4c7e046ed 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/semaphore.h>
 #include "csr.h"
 #include "nodemgr.h"
 
+/*
+ * Disable the nodemgr detection and config rom reading functionality.
+ */
+MODULE_PARM(disable_nodemgr, "i");
+MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
+static int disable_nodemgr = 0;
+
 static kmem_cache_t *hpsb_packet_cache;
 
 
@@ -95,7 +103,7 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
         INIT_TQ_HEAD(packet->complete_tq);
         INIT_LIST_HEAD(&packet->list);
         sema_init(&packet->state_change, 0);
-        packet->state = unused;
+        packet->state = hpsb_unused;
         packet->generation = -1;
         packet->data_be = 1;
 
@@ -352,14 +360,14 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
         }
 
         if (ackcode != ACK_PENDING || !packet->expect_response) {
-                packet->state = completed;
+                packet->state = hpsb_complete;
                 up(&packet->state_change);
                 up(&packet->state_change);
                 run_task_queue(&packet->complete_tq);
                 return;
         }
 
-        packet->state = pending;
+        packet->state = hpsb_pending;
         packet->sendtime = jiffies;
 
         spin_lock_irqsave(&host->pending_pkt_lock, flags);
@@ -393,9 +401,9 @@ int hpsb_send_packet(struct hpsb_packet *packet)
                 return 0;
         }
 
-        packet->state = queued;
+        packet->state = hpsb_queued;
 
-        if (packet->type == async && packet->node_id != ALL_NODES) {
+        if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
                 packet->speed_code =
                         host->speed_map[(host->node_id & NODE_MASK) * 64
                                        + (packet->node_id & NODE_MASK)];
@@ -503,14 +511,14 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
                 break;
         }
 
-        packet->state = completed;
+        packet->state = hpsb_complete;
         up(&packet->state_change);
         run_task_queue(&packet->complete_tq);
 }
 
 
-struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
-                                        size_t dsize)
+static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
+                                              quadlet_t *data, size_t dsize)
 {
         struct hpsb_packet *p;
 
@@ -522,13 +530,15 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
                 return NULL;
         }
 
-        p->type = async;
-        p->state = unused;
+        p->type = hpsb_async;
+        p->state = hpsb_unused;
         p->host = host;
         p->node_id = data[1] >> 16;
         p->tlabel = (data[0] >> 10) & 0x3f;
         p->no_waiter = 1;
 
+       p->generation = get_hpsb_generation(host);
+
         if (dsize % 4) {
                 p->data[dsize / 4] = 0;
         }
@@ -540,8 +550,8 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
                 packet = create_reply_packet(host, data, length); \
                 if (packet == NULL) break
 
-void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
-                            size_t size, int write_acked)
+static void handle_incoming_packet(struct hpsb_host *host, int tcode,
+                                  quadlet_t *data, size_t size, int write_acked)
 {
         struct hpsb_packet *packet;
         int length, rcode, extcode;
@@ -720,7 +730,7 @@ void abort_requests(struct hpsb_host *host)
 
         list_for_each(lh, &llist) {
                 packet = list_entry(lh, struct hpsb_packet, list);
-                packet->state = completed;
+                packet->state = hpsb_complete;
                 packet->ack_code = ACKX_ABORTED;
                 up(&packet->state_change);
                 run_task_queue(&packet->complete_tq);
@@ -732,7 +742,7 @@ void abort_timedouts(struct hpsb_host *host)
         unsigned long flags;
         struct hpsb_packet *packet;
         unsigned long expire;
-        struct list_head *lh;
+        struct list_head *lh, *next;
         LIST_HEAD(expiredlist);
 
         spin_lock_irqsave(&host->csr.lock, flags);
@@ -746,8 +756,9 @@ void abort_timedouts(struct hpsb_host *host)
 
         spin_lock_irqsave(&host->pending_pkt_lock, flags);
 
-        list_for_each(lh, &host->pending_packets) {
+       for (lh = host->pending_packets.next; lh != &host->pending_packets; lh = next) {
                 packet = list_entry(lh, struct hpsb_packet, list);
+               next = lh->next;
                 if (time_before(packet->sendtime + expire, jiffies)) {
                         list_del(&packet->list);
                         list_add(&packet->list, &expiredlist);
@@ -761,7 +772,7 @@ void abort_timedouts(struct hpsb_host *host)
 
         list_for_each(lh, &expiredlist) {
                 packet = list_entry(lh, struct hpsb_packet, list);
-                packet->state = completed;
+                packet->state = hpsb_complete;
                 packet->ack_code = ACKX_TIMEOUT;
                 up(&packet->state_change);
                 run_task_queue(&packet->complete_tq);
@@ -775,13 +786,19 @@ static int __init ieee1394_init(void)
                                              0, 0, NULL, NULL);
        init_hpsb_highlevel();
        init_csr();
-       init_ieee1394_nodemgr();
+       if (!disable_nodemgr)
+               init_ieee1394_nodemgr();
+       else
+               HPSB_INFO("nodemgr functionality disabled");
+
        return 0;
 }
 
 static void __exit ieee1394_cleanup(void)
 {
-       cleanup_ieee1394_nodemgr();
+       if (!disable_nodemgr)
+               cleanup_ieee1394_nodemgr();
+
        cleanup_csr();
        kmem_cache_destroy(hpsb_packet_cache);
 }
index c1ebc47ad6264dde23902cc3e0e8eed3ec39af5b..fa5d65fb785b4be5f213a94da4ee3404539197b8 100644 (file)
@@ -20,16 +20,16 @@ struct hpsb_packet {
 
         /* Async and Iso types should be clear, raw means send-as-is, do not
          * CRC!  Byte swapping shall still be done in this case. */
-        enum { async, iso, raw } __attribute__((packed)) type;
+        enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
 
         /* Okay, this is core internal and a no care for hosts.
          * queued   = queued for sending
          * pending  = sent, waiting for response
-         * completed = processing completed, successful or not
+         * complete = processing completed, successful or not
          * incoming = incoming packet
          */
         enum { 
-                unused, queued, pending, completed, incoming 
+                hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete, hpsb_incoming 
         } __attribute__((packed)) state;
 
         /* These are core internal. */
index 6de64a4cc5047d91470ac2f7ca218a0e7585f060..f5933274accd21dc072214625878209f547ee5ed 100644 (file)
@@ -2,32 +2,75 @@
 #define _IEEE1394_HOTPLUG_H
 
 #include "ieee1394_core.h"
+#include "nodemgr.h"
 
-#define IEEE1394_DEVICE_ID_MATCH_VENDOR_ID             0x0001
-#define IEEE1394_DEVICE_ID_MATCH_MODEL_ID              0x0002
-#define IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_ID       0x0004
-#define IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_VERSION  0x0008
+#define IEEE1394_MATCH_VENDOR_ID       0x0001
+#define IEEE1394_MATCH_MODEL_ID                0x0002
+#define IEEE1394_MATCH_SPECIFIER_ID    0x0004
+#define IEEE1394_MATCH_VERSION         0x0008
 
 struct ieee1394_device_id {
        u32 match_flags;
        u32 vendor_id;
        u32 model_id;
-       u32 sw_specifier_id;
-       u32 sw_specifier_version;
+       u32 specifier_id;
+       u32 version;
+       void *driver_data;
 };
 
-#define IEEE1394_PROTOCOL(id, version) {                                      \
-       match_flags:            IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_ID |     \
-                               IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_VERSION, \
-       sw_specifier_id:        id,                                            \
-       sw_specifier_version:   version                                        \
-}
-
-#define IEEE1394_DEVICE(vendor_id, model_id) {                 \
-       match_flags:    IEEE1394_DEVICE_ID_MATCH_VENDOR_ID |    \
-                       IEEE1394_DEVICE_ID_MATCH_MODEL_ID,      \
-       vendor_id:      vendor_id,                              \
-       model_id:       vendor_id,                              \
-}
+struct hpsb_protocol_driver {
+       /* The name of the driver, e.g. SBP2 or IP1394 */
+       const char *name;
+
+       /* 
+        * The device id table describing the protocols and/or devices
+        * supported by this driver.  This is used by the nodemgr to
+        * decide if a driver could support a given node, but the
+        * probe function below can implement further protocol
+        * dependent or vendor dependent checking.
+        */
+       struct ieee1394_device_id *id_table;
+
+       /* 
+        * The probe function is called when a device is added to the
+        * bus and the nodemgr finds a matching entry in the drivers
+        * device id table or when registering this driver and a
+        * previously unhandled device can be handled.  The driver may
+        * decline to handle the device based on further investigation
+        * of the device (or whatever reason) in which case a negative
+        * error code should be returned, otherwise 0 should be
+        * returned. The driver may use the driver_data field in the
+        * unit directory to store per device driver specific data.
+        */
+       int (*probe)(struct unit_directory *ud);
+
+       /* 
+        * The disconnect function is called when a device is removed
+        * from the bus or if it wasn't possible to read the guid
+        * after the last bus reset.
+        */
+       void (*disconnect)(struct unit_directory *ud);
+
+       /* 
+        * The update function is called when the node has just
+        * survived a bus reset, i.e. it is still present on the bus.
+        * However, it may be necessary to reestablish the connection
+        * or login into the node again, depending on the protocol.
+        */
+       void (*update)(struct unit_directory *ud);
+
+       /* Driver in list of all registered drivers */
+       struct list_head list;
+
+       /* The list of unit directories managed by this driver */
+       struct list_head unit_directories;
+};
+
+int hpsb_register_protocol(struct hpsb_protocol_driver *driver);
+void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
+
+int hpsb_claim_unit_directory(struct unit_directory *ud,
+                             struct hpsb_protocol_driver *driver);
+void hpsb_release_unit_directory(struct unit_directory *ud);
 
 #endif /* _IEEE1394_HOTPLUG_H */
index e5a07889a543255018ded021aae0254b52fd3504..4b9324dd9cec2be067067369f8c68dbe4e5781e1 100644 (file)
@@ -18,6 +18,7 @@
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "ieee1394_transactions.h"
+#include "ieee1394_hotplug.h"
 #include "highlevel.h"
 #include "nodemgr.h"
 
@@ -75,8 +76,12 @@ EXPORT_SYMBOL(highlevel_add_host);
 EXPORT_SYMBOL(highlevel_remove_host);
 EXPORT_SYMBOL(highlevel_host_reset);
 EXPORT_SYMBOL(highlevel_add_one_host);
+
 EXPORT_SYMBOL(hpsb_guid_get_entry);
 EXPORT_SYMBOL(hpsb_nodeid_get_entry);
 EXPORT_SYMBOL(hpsb_get_host_by_ne);
 EXPORT_SYMBOL(hpsb_guid_fill_packet);
+EXPORT_SYMBOL(hpsb_register_protocol);
+EXPORT_SYMBOL(hpsb_unregister_protocol);
+EXPORT_SYMBOL(hpsb_release_unit_directory);
 MODULE_LICENSE("GPL");
index 95b85139f0b8868e51b45c5a8db14f1636e8f79f..7086bc7e2caa7b8038362890a3e178978201695e 100644 (file)
@@ -131,7 +131,7 @@ void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
 
         packet->header_size = 4;
         packet->data_size = length;
-        packet->type = iso;
+        packet->type = hpsb_iso;
         packet->tcode = TCODE_ISO_DATA;
 }
 
@@ -142,7 +142,7 @@ void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
         packet->header_size = 8;
         packet->data_size = 0;
         packet->expect_response = 0;
-        packet->type = raw;             /* No CRC added */
+        packet->type = hpsb_raw;             /* No CRC added */
         packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
 }
 
@@ -488,7 +488,9 @@ struct hpsb_packet *hpsb_make_packet (struct hpsb_host *host, nodeid_t node,
         if (!packet)
                 return NULL;
 
-        if (length != 4)
+       /* Sometimes this may be called without data, just to allocate the
+        * packet. */
+        if (length != 4 && buffer)
                 memcpy(packet->data, buffer, length);
 
        return packet;
index 1385070dd9846d3a5972a7dd7c0df624a2ade808..185cecacb444ae9b73a8e33e0013ff1227efa46e 100644 (file)
 #include <linux/spinlock.h>
 #endif
 
+#ifndef list_for_each_safe
+#define list_for_each_safe(pos, n, head) \
+       for (pos = (head)->next, n = pos->next; pos != (head); \
+               pos = n, n = pos->next)
+
+#endif
+
 #ifndef MIN
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #endif
index 37ac83b29244520b74e84f7ff7c4a0f079cd32f0..7b1ee818652a0e64b51239d1b757d38192c13855 100644 (file)
 #include <asm/atomic.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/kmod.h>
 
 #include "ieee1394_types.h"
 #include "ieee1394.h"
 #include "hosts.h"
 #include "ieee1394_transactions.h"
+#include "ieee1394_hotplug.h"
 #include "highlevel.h"
 #include "csr.h"
 #include "nodemgr.h"
 static LIST_HEAD(node_list);
 static rwlock_t node_lock = RW_LOCK_UNLOCKED;
 
+static LIST_HEAD(driver_list);
+static rwlock_t driver_lock = RW_LOCK_UNLOCKED;
+
+/* The rwlock unit_directory_lock is always held when manipulating the
+ * global unit_directory_list, but this also protects access to the
+ * lists of unit directories stored in the protocol drivers.
+ */
+static LIST_HEAD(unit_directory_list);
+static rwlock_t unit_directory_lock = RW_LOCK_UNLOCKED;
+
 static LIST_HEAD(host_info_list);
 static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
 
@@ -56,7 +68,12 @@ struct host_info {
        struct list_head list;
 };
 
-static struct node_entry *create_node_entry(void)
+static void nodemgr_process_config_rom(struct node_entry *ne, 
+                                      quadlet_t busoptions);
+
+
+static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions,
+                                             struct hpsb_host *host, nodeid_t nodeid)
 {
         struct node_entry *ne;
         unsigned long flags;
@@ -66,15 +83,21 @@ static struct node_entry *create_node_entry(void)
 
         INIT_LIST_HEAD(&ne->list);
        INIT_LIST_HEAD(&ne->unit_directories);
-        ne->guid = (u64) -1;
-        ne->host = NULL;
-        ne->nodeid = 0;
-        atomic_set(&ne->generation, -1);
+        ne->host = host;
+        ne->nodeid = nodeid;
+        ne->guid = guid;
+       atomic_set(&ne->generation, get_hpsb_generation(ne->host));
 
         write_lock_irqsave(&node_lock, flags);
         list_add_tail(&ne->list, &node_list);
         write_unlock_irqrestore(&node_lock, flags);
 
+       nodemgr_process_config_rom (ne, busoptions);
+
+       HPSB_DEBUG("%s added: node " NODE_BUS_FMT ", GUID %016Lx",
+                  (host->node_id == nodeid) ? "Local host" : "Device",
+                  NODE_BUS_ARGS(nodeid), (unsigned long long)guid);
+
         return ne;
 }
 
@@ -104,16 +127,20 @@ static struct node_entry *find_entry_by_nodeid(nodeid_t nodeid)
        return NULL;
 }
 
-int nodemgr_read_quadlet(struct node_entry *ne, 
+int nodemgr_read_quadlet(struct node_entry *ne,
                         octlet_t address, quadlet_t *quad)
 {
-       if (hpsb_read(ne->host, ne->nodeid, address, quad, 4)) {
-               HPSB_DEBUG("read of address %Lx failed", address);
-               return -EAGAIN;
+       int i;
+       int ret = 0;
+
+       for (i = 0; i < 3; i++) {
+               ret = hpsb_read(ne->host, ne->nodeid, address, quad, 4);
+               if (ret != -EAGAIN)
+                       break;
        }
        *quad = be32_to_cpu(*quad);
 
-       return 0;
+       return ret;
 }
 
 #define CONFIG_ROM_VENDOR_ID           0x03
@@ -137,13 +164,14 @@ static void nodemgr_process_unit_directory(struct node_entry *ne,
        octlet_t a;
        quadlet_t quad;
        int length, i;
-       
 
        if (!(ud = kmalloc (sizeof *ud, GFP_KERNEL)))
                goto unit_directory_error;
 
        memset (ud, 0, sizeof *ud);
+       ud->ne = ne;
        ud->address = address;
+       ud->arb_count = 0;
 
        if (nodemgr_read_quadlet(ne, address, &quad))
                goto unit_directory_error;
@@ -151,7 +179,8 @@ static void nodemgr_process_unit_directory(struct node_entry *ne,
        a = address + 4;
 
        for (i = 0; i < length; i++, a += 4) {
-               int code, value;
+               int code;
+               quadlet_t value;
 
                if (nodemgr_read_quadlet(ne, a, &quad))
                        goto unit_directory_error;
@@ -183,10 +212,20 @@ static void nodemgr_process_unit_directory(struct node_entry *ne,
                case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
                        /* TODO: read strings... icons? */
                        break;
+
+               default:
+                       if (ud->arb_count < 16) {
+                               /* Place them in the arbitrary pairs */
+                               ud->arb_keys[ud->arb_count] = code;
+                               ud->arb_values[ud->arb_count] = value;
+                               ud->arb_count++;
+                       }
                }
        }
 
-       list_add_tail (&ud->list, &ne->unit_directories);
+       list_add_tail(&ud->node_list, &ne->unit_directories);
+       list_add_tail(&ud->driver_list, &unit_directory_list);
+
        return;
 
 unit_directory_error:  
@@ -194,27 +233,29 @@ unit_directory_error:
                kfree(ud);
 }
 
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 static void dump_directories (struct node_entry *ne)
 {
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
        struct list_head *l;
 
        HPSB_DEBUG("vendor_id=0x%06x, capabilities=0x%06x",
                   ne->vendor_id, ne->capabilities);
        list_for_each (l, &ne->unit_directories) {
-               struct unit_directory *ud = list_entry (l, struct unit_directory, list);
+               struct unit_directory *ud = list_entry (l, struct unit_directory, node_list);
                HPSB_DEBUG("unit directory:");
                if (ud->flags & UNIT_DIRECTORY_VENDOR_ID)
                        HPSB_DEBUG("  vendor_id=0x%06x ", ud->vendor_id);
                if (ud->flags & UNIT_DIRECTORY_MODEL_ID)
                        HPSB_DEBUG("  model_id=0x%06x ", ud->model_id);
                if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
-                       HPSB_DEBUG("  specifier_id=0x%06x ", ud->specifier_id);
+                       HPSB_DEBUG("  sw_specifier_id=0x%06x ", ud->specifier_id);
                if (ud->flags & UNIT_DIRECTORY_VERSION)
-                       HPSB_DEBUG("  version=0x%06x ", ud->version);
+                       HPSB_DEBUG("  sw_version=0x%06x ", ud->version);
        }
-}
+#else
+       return;
 #endif
+}
 
 static void nodemgr_process_root_directory(struct node_entry *ne)
 {
@@ -260,86 +301,383 @@ static void nodemgr_process_root_directory(struct node_entry *ne)
                        break;
                }
        }
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+
        dump_directories(ne);
+}
+
+#ifdef CONFIG_HOTPLUG
+
+static void nodemgr_call_policy(char *verb, struct unit_directory *ud)
+{
+       char *argv [3], **envp, *buf, *scratch;
+       int i = 0, value;
+
+       if (!hotplug_path [0])
+               return;
+       if (!current->fs->root)
+               return;
+       if (!(envp = (char **) kmalloc(20 * sizeof (char *), GFP_KERNEL))) {
+               HPSB_DEBUG ("ENOMEM");
+               return;
+       }
+       if (!(buf = kmalloc(256, GFP_KERNEL))) {
+               kfree(envp);
+               HPSB_DEBUG("ENOMEM2");
+               return;
+       }
+
+       /* only one standardized param to hotplug command: type */
+       argv[0] = hotplug_path;
+       argv[1] = "ieee1394";
+       argv[2] = 0;
+
+       /* minimal command environment */
+       envp[i++] = "HOME=/";
+       envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+       /* hint that policy agent should enter no-stdout debug mode */
+       envp[i++] = "DEBUG=kernel";
+#endif
+       /* extensible set of named bus-specific parameters,
+        * supporting multiple driver selection algorithms.
+        */
+       scratch = buf;
+
+       envp[i++] = scratch;
+       scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+       envp[i++] = scratch;
+       scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->ne->vendor_id) + 1;
+       envp[i++] = scratch;
+       scratch += sprintf(scratch, "GUID=%016Lx", (long long unsigned)ud->ne->guid) + 1;
+       envp[i++] = scratch;
+       scratch += sprintf(scratch, "SPECIFIER_ID=%06x", ud->specifier_id) + 1;
+       envp[i++] = scratch;
+       scratch += sprintf(scratch, "VERSION=%06x", ud->version) + 1;
+       envp[i++] = 0;
+
+       /* NOTE: user mode daemons can call the agents too */
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+       HPSB_DEBUG("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid);
 #endif
+       value = call_usermodehelper(argv[0], argv, envp);
+       kfree(buf);
+       kfree(envp);
+       if (value != 0)
+               HPSB_DEBUG("NodeMgr: hotplug policy returned 0x%x", value);
 }
 
-static void register_node(struct hpsb_host *host, nodeid_t nodeid, u64 guid,
-                         quadlet_t busoptions)
+#else
+
+static inline void
+nodemgr_call_policy(char *verb, struct unit_directory *ud)
 {
-        struct node_entry *ne;
-        unsigned long flags, new = 0;
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+       HPSB_DEBUG("NodeMgr: nodemgr_call_policy(): hotplug not enabled");
+#else
+       return;
+#endif
+} 
 
-        read_lock_irqsave(&node_lock, flags);
-        ne = find_entry_by_guid(guid);
-        read_unlock_irqrestore(&node_lock, flags);
+#endif /* CONFIG_HOTPLUG */
 
-       /* New entry */
-       if (!ne) {
-               if ((ne = create_node_entry()) == NULL)
-                       return;
+static void nodemgr_claim_unit_directory(struct unit_directory *ud,
+                                        struct hpsb_protocol_driver *driver)
+{
+       ud->driver = driver;
+       list_del(&ud->driver_list);
+       list_add_tail(&ud->driver_list, &driver->unit_directories);
+}
+
+static void nodemgr_release_unit_directory(struct unit_directory *ud)
+{
+       ud->driver = NULL;
+       list_del(&ud->driver_list);
+       list_add_tail(&ud->driver_list, &unit_directory_list);
+}
+
+void hpsb_release_unit_directory(struct unit_directory *ud)
+{
+       unsigned long flags;
+
+       write_lock_irqsave(&unit_directory_lock, flags);
+       nodemgr_release_unit_directory(ud);
+       write_unlock_irqrestore(&unit_directory_lock, flags);
+}
+
+static void nodemgr_free_unit_directories(struct node_entry *ne)
+{
+       struct list_head *lh;
+       struct unit_directory *ud;
+
+       lh = ne->unit_directories.next;
+       while (lh != &ne->unit_directories) {
+               ud = list_entry(lh, struct unit_directory, node_list);
+               lh = lh->next;
+               if (ud->driver && ud->driver->disconnect)
+                       ud->driver->disconnect(ud);
+               nodemgr_release_unit_directory(ud);
+               nodemgr_call_policy("remove", ud);
+               list_del(&ud->driver_list);
+               kfree(ud);
+       }
+}
+
+static struct ieee1394_device_id *
+nodemgr_match_driver(struct hpsb_protocol_driver *driver, 
+                    struct unit_directory *ud)
+{
+       struct ieee1394_device_id *id;
+
+       for (id = driver->id_table; id->match_flags != 0; id++) {
+               if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
+                   id->vendor_id != ud->vendor_id)
+                       continue;
+
+               if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
+                   id->model_id != ud->model_id)
+                       continue;
+
+               if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
+                   id->specifier_id != ud->specifier_id)
+                       continue;
+
+               if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
+                   id->version != ud->version)
+                       continue;
+
+               return id;
+       }
+
+       return NULL;
+}
+
+static struct hpsb_protocol_driver *
+nodemgr_find_driver(struct unit_directory *ud)
+{
+       struct list_head *l;
+       struct hpsb_protocol_driver *match, *driver;
+       struct ieee1394_device_id *device_id;
+
+       match = NULL;
+       list_for_each(l, &driver_list) {
+               driver = list_entry(l, struct hpsb_protocol_driver, list);
+               device_id = nodemgr_match_driver(driver, ud);
+
+               if (device_id != NULL) {
+                       match = driver;
+                       break;
+               }
+       }
+
+       return match;
+}
+
+static void nodemgr_bind_drivers (struct node_entry *ne)
+{
+       struct list_head *lh;
+       struct hpsb_protocol_driver *driver;
+       struct unit_directory *ud;
+
+       list_for_each(lh, &ne->unit_directories) {
+               ud = list_entry(lh, struct unit_directory, node_list);
+               driver = nodemgr_find_driver(ud);
+               if (driver != NULL && driver->probe(ud) == 0)
+                       nodemgr_claim_unit_directory(ud, driver);
+               nodemgr_call_policy("add", ud);
+       }
+}
 
-               HPSB_DEBUG("%s added: node " NODE_BUS_FMT
-                          ", GUID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-                          (host->node_id == nodeid) ? "Local host" : "Device",
-                          NODE_BUS_ARGS(nodeid), ((u8 *)&guid)[0],
-                          ((u8 *)&guid)[1], ((u8 *)&guid)[2], ((u8 *)&guid)[3],
-                          ((u8 *)&guid)[4], ((u8 *)&guid)[5], ((u8 *)&guid)[6],
-                          ((u8 *)&guid)[7]);
+int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
+{
+       struct unit_directory *ud;
+       struct list_head *lh;
+       unsigned long flags;
 
-               ne->guid = guid;
-               new = 1;
+        write_lock_irqsave(&driver_lock, flags);
+       list_add_tail(&driver->list, &driver_list);
+       write_unlock_irqrestore(&driver_lock, flags);
+
+       write_lock_irqsave(&unit_directory_lock, flags);
+       INIT_LIST_HEAD(&driver->unit_directories);
+       lh = unit_directory_list.next;
+       while (lh != &unit_directory_list) {
+               ud = list_entry(lh, struct unit_directory, driver_list);
+               lh = lh->next;
+               if (nodemgr_match_driver(driver, ud) && driver->probe(ud) == 0)
+                       nodemgr_claim_unit_directory(ud, driver);
        }
+       write_unlock_irqrestore(&unit_directory_lock, flags);
+
+       /*
+        * Right now registration always succeeds, but maybe we should
+        * detect clashes in protocols handled by other drivers.
+        */
+
+       return 0;
+}
+
+void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
+{
+       struct list_head *lh;
+       struct unit_directory *ud;
+       unsigned long flags;
+
+        write_lock_irqsave(&driver_lock, flags);
+       list_del(&driver->list);
+       write_unlock_irqrestore(&driver_lock, flags);
+
+       write_lock_irqsave(&unit_directory_lock, flags);
+       lh = driver->unit_directories.next;
+       while (lh != &driver->unit_directories) {
+               ud = list_entry(lh, struct unit_directory, driver_list);
+               lh = lh->next;
+               if (ud->driver && ud->driver->disconnect)
+                       ud->driver->disconnect(ud);
+               nodemgr_release_unit_directory(ud);
+       }
+       write_unlock_irqrestore(&unit_directory_lock, flags);
+}
+
+static void nodemgr_process_config_rom(struct node_entry *ne, 
+                                      quadlet_t busoptions)
+{
+       unsigned long flags;
+
+       ne->busopt.irmc         = (busoptions >> 31) & 1;
+       ne->busopt.cmc          = (busoptions >> 30) & 1;
+       ne->busopt.isc          = (busoptions >> 29) & 1;
+       ne->busopt.bmc          = (busoptions >> 28) & 1;
+       ne->busopt.pmc          = (busoptions >> 27) & 1;
+       ne->busopt.cyc_clk_acc  = (busoptions >> 16) & 0xff;
+       ne->busopt.max_rec      = 1 << (((busoptions >> 12) & 0xf) + 1);
+       ne->busopt.generation   = (busoptions >> 4) & 0xf;
+       ne->busopt.lnkspd       = busoptions & 0x7;
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+       HPSB_DEBUG("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
+                  "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
+                  busoptions, ne->busopt.irmc, ne->busopt.cmc,
+                  ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
+                  ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
+                  ne->busopt.generation, ne->busopt.lnkspd);
+#endif
 
-       if (!new && ne->nodeid != nodeid)
+       /*
+        * When the config rom changes we disconnect all drivers and
+        * free the cached unit directories and reread the whole
+        * thing.  If this was a new device, the call to
+        * nodemgr_disconnect_drivers is a no-op and all is well.
+        */
+       write_lock_irqsave(&unit_directory_lock, flags);
+       nodemgr_free_unit_directories(ne);
+       nodemgr_process_root_directory(ne);
+       nodemgr_bind_drivers(ne);
+       write_unlock_irqrestore(&unit_directory_lock, flags);
+}
+
+/*
+ * This function updates nodes that were present on the bus before the
+ * reset and still are after the reset.  The nodeid and the config rom
+ * may have changed, and the drivers managing this device must be
+ * informed that this device just went through a bus reset, to allow
+ * the to take whatever actions required.
+ */
+static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
+                               struct hpsb_host *host, nodeid_t nodeid)
+{
+       struct list_head *lh;
+
+       if (ne->nodeid != nodeid)
                HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT,
                           NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid));
 
        ne->host = host;
-        ne->nodeid = nodeid;
+       ne->nodeid = nodeid;
 
-       /* Now set the bus options. Only do all this crap if this is a new
-        * node, or if the generation number has changed.  */
-       if (new || ne->busopt.generation != ((busoptions >> 6) & 0x3)) {
-               ne->busopt.irmc         = (busoptions >> 31) & 1;
-               ne->busopt.cmc          = (busoptions >> 30) & 1;
-               ne->busopt.isc          = (busoptions >> 29) & 1;
-               ne->busopt.bmc          = (busoptions >> 28) & 1;
-               ne->busopt.pmc          = (busoptions >> 27) & 1;
-               ne->busopt.cyc_clk_acc  = (busoptions >> 16) & 0xff;
-               ne->busopt.max_rec      = 1 << (((busoptions >> 12) & 0xf) + 1);
-               ne->busopt.generation   = (busoptions >> 6) & 0x3;
-               ne->busopt.lnkspd       = busoptions & 0x7;
-
-               /* Now, process the rest of the tree */
-               nodemgr_process_root_directory(ne);
-       }
+       if (ne->busopt.generation != ((busoptions >> 4) & 0xf))
+               nodemgr_process_config_rom (ne, busoptions);
 
        /* Since that's done, we can declare this record current */
-       atomic_set(&ne->generation, get_hpsb_generation(host));
+       atomic_set(&ne->generation, get_hpsb_generation(ne->host));
+
+       list_for_each (lh, &ne->unit_directories) {
+               struct unit_directory *ud;
+
+               ud = list_entry (lh, struct unit_directory, node_list);
+               if (ud->driver != NULL && ud->driver->update != NULL)
+                       ud->driver->update(ud);
+       }
+}
+
+static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid,
+                             quadlet_t *buffer, int buffer_length)
+{
+       octlet_t base = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
+       int retries = 3;
+       int header_count;
+       unsigned header_size;
+       quadlet_t quad;
+
+retry_configrom:
+
+       if (!retries--) {
+               HPSB_ERR("Giving up on node " NODE_BUS_FMT
+                        " for ConfigROM probe, too many errors",
+                        NODE_BUS_ARGS(nodeid));
+               return -1;
+       }
+
+       header_count = 0;
+       header_size = 0;
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-       HPSB_DEBUG("raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d cyc_clk_acc=%d "
-                  "max_rec=%d gen=%d lspd=%d", busoptions,
-                  ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
-                  ne->busopt.pmc, ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
-                  ne->busopt.generation, ne->busopt.lnkspd);
+       HPSB_INFO("Initiating ConfigROM request for node " NODE_BUS_FMT,
+                 NODE_BUS_ARGS(nodeid));
 #endif
 
-       return;
+       /* Now, P1212 says that devices should support 64byte block
+        * reads, aligned on 64byte boundaries. That doesn't seem
+        * to work though, and we are forced to doing quadlet
+        * sized reads.  */
+
+       if (hpsb_read(host, nodeid, base, &quad, 4)) {
+               HPSB_ERR("ConfigROM quadlet transaction error for node " NODE_BUS_FMT,
+                        NODE_BUS_ARGS(nodeid));
+               goto retry_configrom;
+       }
+       buffer[header_count++] = be32_to_cpu(quad);
+
+       header_size = buffer[0] >> 24;
+
+       if (header_size < 4) {
+               HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM format (%d quads), "
+                         "cannot parse", NODE_BUS_ARGS(nodeid), header_size);
+               return -1;
+       }
+
+       while (header_count <= header_size && header_count < buffer_length) {
+               if (hpsb_read(host, nodeid, base + (header_count<<2), &quad, 4)) {
+                       HPSB_ERR("ConfigROM quadlet transaction error for " NODE_BUS_FMT,
+                                NODE_BUS_ARGS(nodeid));
+                       goto retry_configrom;
+               }
+               buffer[header_count++] = be32_to_cpu(quad);
+       }
+
+       return 0;
 }
 
 static void nodemgr_remove_node(struct node_entry *ne)
 {
-       HPSB_DEBUG("Device removed: node " NODE_BUS_FMT ", GUID "
-                  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-                  NODE_BUS_ARGS(ne->nodeid),
-                  ((u8 *)&ne->guid)[0], ((u8 *)&ne->guid)[1],
-                  ((u8 *)&ne->guid)[2], ((u8 *)&ne->guid)[3],
-                  ((u8 *)&ne->guid)[4], ((u8 *)&ne->guid)[5],
-                  ((u8 *)&ne->guid)[6], ((u8 *)&ne->guid)[7]);
+       unsigned long flags;
+
+       HPSB_DEBUG("Device removed: node " NODE_BUS_FMT ", GUID %016Lx",
+                  NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid);
 
+       write_lock_irqsave(&unit_directory_lock, flags);
+       nodemgr_free_unit_directories(ne);
+       write_unlock_irqrestore(&unit_directory_lock, flags);
        list_del(&ne->list);
        kfree(ne);
 
@@ -352,82 +690,26 @@ static void nodemgr_node_probe(void *data)
 {
        struct hpsb_host *host = (struct hpsb_host *)data;
         struct selfid *sid = (struct selfid *)host->topology_map;
-       struct list_head *lh,*spare;
+       struct list_head *lh, *next;
        struct node_entry *ne;
         int nodecount = host->node_count;
         nodeid_t nodeid = LOCAL_BUS;
-       quadlet_t buffer[5], quad;
-       octlet_t base = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
+       quadlet_t buffer[5];
+       octlet_t guid;
        unsigned long flags;
 
        /* We need to detect when the ConfigROM's generation has changed,
         * so we only update the node's info when it needs to be.  */
         for (; nodecount; nodecount--, nodeid++, sid++) {
-               int retries = 3;
-               int header_count;
-               unsigned header_size;
-               octlet_t guid;
-
                /* Skip extended, and non-active node's */
                 while (sid->extended)
                        sid++;
                 if (!sid->link_active)
                        continue;
 
-               /* Just use our local ROM */
-               if (nodeid == host->node_id) {
-                       int i;
-                       for (i = 0; i < 5; i++)
-                               buffer[i] = be32_to_cpu(host->csr.rom[i]);
-                       goto set_options;
-               }
-
-retry_configrom:
-               
-               if (!retries--) {
-                       HPSB_ERR("Giving up on node " NODE_BUS_FMT
-                                " for ConfigROM probe, too many errors",
-                                NODE_BUS_ARGS(nodeid));
+               if (read_businfo_block (host, nodeid, buffer, sizeof(buffer) >> 2))
                        continue;
-               }
 
-               header_count = 0;
-               header_size = 0;
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-               HPSB_INFO("Initiating ConfigROM request for node " NODE_BUS_FMT,
-                         NODE_BUS_ARGS(nodeid));
-#endif
-
-               /* Now, P1212 says that devices should support 64byte block
-                * reads, aligned on 64byte boundaries. That doesn't seem
-                * to work though, and we are forced to doing quadlet
-                * sized reads.  */
-
-               if (hpsb_read(host, nodeid, base, &quad, 4)) {
-                       HPSB_ERR("ConfigROM quadlet transaction error for node " NODE_BUS_FMT,
-                                NODE_BUS_ARGS(nodeid));
-                       goto retry_configrom;
-               }
-               buffer[header_count++] = be32_to_cpu(quad);
-
-               header_size = buffer[0] >> 24;
-
-               if (header_size < 4) {
-                       HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM format (%d quads), "
-                                 "cannot parse", NODE_BUS_ARGS(nodeid), header_size);
-                       continue;
-               }
-
-               while (header_count <= header_size && (header_count<<2) < sizeof(buffer)) {
-                       if (hpsb_read(host, nodeid, base + (header_count<<2), &quad, 4)) {
-                               HPSB_ERR("ConfigROM quadlet transaction error for " NODE_BUS_FMT,
-                                        NODE_BUS_ARGS(nodeid));
-                               goto retry_configrom;
-                       }
-                       buffer[header_count++] = be32_to_cpu(quad);
-               }
-set_options:
                if (buffer[1] != IEEE1394_BUSID_MAGIC) {
                        /* This isn't a 1394 device */
                        HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device",
@@ -435,15 +717,21 @@ set_options:
                        continue;
                }
 
-               guid = be64_to_cpu(((u64)buffer[3] << 32) | buffer[4]);
-               register_node(host, nodeid, guid, buffer[2]);
+               guid = ((u64)buffer[3] << 32) | buffer[4];
+               ne = hpsb_guid_get_entry(guid);
+
+               if (!ne)
+                       nodemgr_create_node(guid, buffer[2], host, nodeid);
+               else
+                       nodemgr_update_node(ne, buffer[2], host, nodeid);
         }
 
        /* Now check to see if we have any nodes that aren't referenced
         * any longer.  */
         write_lock_irqsave(&node_lock, flags);
-       list_for_each_safe(lh, spare, &node_list) {
+       for (lh = node_list.next; lh != &node_list; lh = next) {
                ne = list_entry(lh, struct node_entry, list);
+               next = lh->next;
 
                /* Only checking this host */
                if (ne->host != host)
@@ -453,7 +741,7 @@ set_options:
                 * node was removed, or it failed the above probe. Either
                 * way, we remove references to it, since they are
                 * invalid.  */
-               if (atomic_read(&ne->generation) != get_hpsb_generation(host))
+               if (!hpsb_node_entry_valid(ne))
                        nodemgr_remove_node(ne);
        }
        write_unlock_irqrestore(&node_lock, flags);
@@ -511,7 +799,7 @@ static void nodemgr_add_host(struct hpsb_host *host)
        unsigned long flags;
 
        if (!hi) {
-               HPSB_ERR ("Out of memory in Node Manager");
+               HPSB_ERR ("NodeMgr: out of memory in add host");
                return;
        }
 
@@ -544,7 +832,7 @@ static void nodemgr_host_reset(struct hpsb_host *host)
        }
 
        if (hi == NULL) {
-               HPSB_ERR ("Could not process reset of non-existent host in Node Manager");
+               HPSB_ERR ("NodeMgr: could not process reset of non-existent host");
                goto done_reset_host;
        }
 
@@ -558,8 +846,7 @@ done_reset_host:
 
 static void nodemgr_remove_host(struct hpsb_host *host)
 {
-       struct list_head *lh;
-       struct host_info *hi = NULL;
+       struct list_head *lh, *next;
        struct node_entry *ne;
        unsigned long flags;
 
@@ -568,8 +855,10 @@ static void nodemgr_remove_host(struct hpsb_host *host)
 
        /* First remove all node entries for this host */
        write_lock_irqsave(&node_lock, flags);
-       list_for_each(lh, &node_list) {
+
+       for (lh = node_list.next; lh != &node_list; lh = next) {
                ne = list_entry(lh, struct node_entry, list);
+               next = lh->next;
 
                /* Only checking this host */
                if (ne->host != host)
@@ -581,22 +870,17 @@ static void nodemgr_remove_host(struct hpsb_host *host)
 
        spin_lock_irqsave (&host_info_lock, flags);
        list_for_each(lh, &host_info_list) {
-               struct host_info *myhi = list_entry(lh, struct host_info, list);
-               if (myhi->host == host) {
-                       hi = myhi;
+               struct host_info *hi = list_entry(lh, struct host_info, list);
+               if (hi->host == host) {
+                       list_del(&hi->list);
+                       kfree (hi);
                        break;
                }
        }
 
-       if (hi == NULL) {
-               HPSB_ERR ("Could not remove non-existent host in Node Manager");
-               goto done_remove_host;
-       }
-
-       list_del(&hi->list);
-       kfree (hi);
+       if (lh == host_info_list.next)
+               HPSB_ERR ("NodeMgr: could not remove non-existent host");
 
-done_remove_host:
        spin_unlock_irqrestore (&host_info_lock, flags);
 
        return;
@@ -614,7 +898,7 @@ void init_ieee1394_nodemgr(void)
 {
         hl = hpsb_register_highlevel("Node manager", &nodemgr_ops);
         if (!hl) {
-                HPSB_ERR("Out of memory during ieee1394 initialization");
+               HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization");
         }
 }
 
index 7d91a1a7ccbe6238db3802612837e6a8ec61ca49..46f574e64155a36b00331fc63f3a1f8ef71902ef 100644 (file)
@@ -38,13 +38,23 @@ struct bus_options {
        u16     max_rec;        /* Maximum packet size node can receive */
 };
 
-#define UNIT_DIRECTORY_VENDOR_ID    0x01
-#define UNIT_DIRECTORY_MODEL_ID     0x02
-#define UNIT_DIRECTORY_SPECIFIER_ID 0x04
-#define UNIT_DIRECTORY_VERSION      0x08
+#define UNIT_DIRECTORY_VENDOR_ID       0x01
+#define UNIT_DIRECTORY_MODEL_ID                0x02
+#define UNIT_DIRECTORY_SPECIFIER_ID    0x04
+#define UNIT_DIRECTORY_VERSION         0x08
 
+/*
+ * A unit directory corresponds to a protocol supported by the
+ * node. If a node supports eg. IP/1394 and AV/C, its config rom has a
+ * unit directory for each of these protocols.
+ * 
+ * Unit directories appear on two types of lists: for each node we
+ * maintain a list of the unit directories found in its config rom and
+ * for each driver we maintain a list of the unit directories
+ * (ie. devices) the driver manages.
+ */
 struct unit_directory {
-       struct list_head list;
+       struct node_entry *ne;  /* The node which this directory belongs to */
        octlet_t address;       /* Address of the unit directory on the node */
        u8 flags;               /* Indicates which entries were read */
        quadlet_t vendor_id;
@@ -53,6 +63,20 @@ struct unit_directory {
        char *model_name;
        quadlet_t specifier_id;
        quadlet_t version;
+
+       /* Groupings for arbitrary key/value pairs */
+       int arb_count;                  /* Number of arbitrary key/values */
+       char arb_keys[16];              /* Up to 16 keys */
+       quadlet_t arb_values[16];       /* Same for values */
+
+       struct hpsb_protocol_driver *driver;
+       void *driver_data;
+
+       /* For linking the nodes managed by the driver, or unmanaged nodes */
+       struct list_head driver_list;
+
+       /* For linking directories belonging to a node */
+       struct list_head node_list;
 };
 
 struct node_entry {
@@ -69,6 +93,11 @@ struct node_entry {
        struct list_head unit_directories;
 };
 
+static inline int hpsb_node_entry_valid(struct node_entry *ne)
+{
+       return atomic_read(&ne->generation) == get_hpsb_generation(ne->host);
+}
+
 /*
  * Returns a node entry (which has its reference count incremented) or NULL if
  * the GUID in question is not known.  Getting a valid entry does not mean that
index 8c68f145bdcb233b0b47353f98bcfe171659436c..88c9e4bd91ced6e2698a8b8894bcf544dce44f9c 100644 (file)
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 
+#ifdef CONFIG_ALL_PPC
+#include <asm/feature.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+
+/* Revert to old bus reset algorithm that works on my Pismo until
+ * the new one is fixed
+ */
+#undef BUSRESET_WORKAROUND
+
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "highlevel.h"
 #include "ohci1394.h"
 
-
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 #define OHCI1394_DEBUG
 #endif
 
 #ifdef OHCI1394_DEBUG
 #define DBGMSG(card, fmt, args...) \
-printk(KERN_INFO "ohci1394_%d: " fmt "\n" , card , ## args)
+printk(KERN_INFO "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 #else
 #define DBGMSG(card, fmt, args...)
 #endif
 
 #ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
 #define OHCI_DMA_ALLOC(fmt, args...) \
-       HPSB_ERR("ohci1394("__FUNCTION__")alloc(%d): "fmt, \
+       HPSB_ERR("%s("__FUNCTION__")alloc(%d): "fmt, OHCI1394_DRIVER_NAME, \
                ++global_outstanding_dmas, ## args)
 #define OHCI_DMA_FREE(fmt, args...) \
-       HPSB_ERR("ohci1394("__FUNCTION__")free(%d): "fmt, \
+       HPSB_ERR("%s("__FUNCTION__")free(%d): "fmt, OHCI1394_DRIVER_NAME, \
                --global_outstanding_dmas, ## args)
 u32 global_outstanding_dmas = 0;
 #else
@@ -143,18 +153,11 @@ u32 global_outstanding_dmas = 0;
 
 /* print general (card independent) information */
 #define PRINT_G(level, fmt, args...) \
-printk(level "ohci1394: " fmt "\n" , ## args)
+printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
 
 /* print card specific information */
 #define PRINT(level, card, fmt, args...) \
-printk(level "ohci1394_%d: " fmt "\n" , card , ## args)
-
-#define FAIL(fmt, args...)                             \
-do {                                                   \
-       PRINT_G(KERN_ERR, fmt , ## args);               \
-       remove_card(ohci);                              \
-       return 1;                                       \
-} while(0)
+printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 #define PCI_CLASS_FIREWIRE_OHCI     ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
 
@@ -179,21 +182,48 @@ MODULE_PARM(attempt_root,"i");
 MODULE_PARM_DESC(attempt_root, "Attempt to make the host root.");
 static int attempt_root = 0;
 
-#ifdef __LITTLE_ENDIAN
-/* Don't waste cycles on same sex byte swaps */
-#define packet_swab(w,x,y,z)
-#define block_swab32(x,y)
-#else
-static void packet_swab(quadlet_t *data, char tcode, int len, int payload_swap);
-static __inline__ void block_swab32(quadlet_t *data, size_t size);
-#endif
-
 static unsigned int card_id_counter = 0;
 
 static void dma_trm_tasklet(unsigned long data);
 static void remove_card(struct ti_ohci *ohci);
 static void dma_trm_reset(struct dma_trm_ctx *d);
 
+#ifndef __LITTLE_ENDIAN
+/* Swap a series of quads inplace. */
+static __inline__ void block_swab32(quadlet_t *data, size_t size) {
+       while (size--)
+               data[size] = swab32(data[size]);
+}
+
+static unsigned hdr_sizes[] = 
+{
+       3,      /* TCODE_WRITEQ */
+       4,      /* TCODE_WRITEB */
+       3,      /* TCODE_WRITE_RESPONSE */
+       0,      /* ??? */
+       3,      /* TCODE_READQ */
+       4,      /* TCODE_READB */
+       3,      /* TCODE_READQ_RESPONSE */
+       4,      /* TCODE_READB_RESPONSE */
+       1,      /* TCODE_CYCLE_START (???) */
+       4,      /* TCODE_LOCK_REQUEST */
+       2,      /* TCODE_ISO_DATA */
+       4,      /* TCODE_LOCK_RESPONSE */
+};
+
+/* Swap headers */
+static inline void packet_swab(quadlet_t *data, int tcode, int len)
+{
+       if (tcode > TCODE_LOCK_RESPONSE || hdr_sizes[tcode] == 0)
+               return;
+       block_swab32(data, hdr_sizes[tcode]);
+}
+#else
+/* Don't waste cycles on same sex byte swaps */
+#define packet_swab(w,x,y)
+#define block_swab32(x,y)
+#endif /* !LITTLE_ENDIAN */
+
 /***********************************
  * IEEE-1394 functionality section *
  ***********************************/
@@ -230,7 +260,7 @@ static void set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
 {
        int i;
        unsigned long flags;
-       u32 r;
+       u32 r = 0;
 
        spin_lock_irqsave (&ohci->phy_reg_lock, flags);
 
@@ -376,7 +406,7 @@ static int run_context(struct ti_ohci *ohci, int reg, char *msg)
 }
 
 /* Generate the dma receive prgs and start the context */
-static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d)
+static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d, int generate_irq)
 {
        struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
        int i;
@@ -384,12 +414,17 @@ static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d)
        ohci1394_stop_context(ohci, d->ctrlClear, NULL);
 
        for (i=0; i<d->num_desc; i++) {
+               u32 c;
                
-               d->prg_cpu[i]->control =
-                   cpu_to_le32((0x280C << 16) | d->buf_size);
+               c = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+                       DMA_CTL_BRANCH;
+               if (generate_irq)
+                       c |= DMA_CTL_IRQ;
+                               
+               d->prg_cpu[i]->control = cpu_to_le32(c | d->buf_size);
 
                /* End of descriptor list? */
-               if ((i+1) < d->num_desc) {
+               if (i + 1 < d->num_desc) {
                        d->prg_cpu[i]->branchAddress =
                                cpu_to_le32((d->prg_bus[i+1] & 0xfffffff0) | 0x1);
                } else {
@@ -565,15 +600,15 @@ static int ohci_initialize(struct hpsb_host *host)
        reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
 
        /* Initialize AR dma */
-       initialize_dma_rcv_ctx(ohci->ar_req_context);
-       initialize_dma_rcv_ctx(ohci->ar_resp_context);
+       initialize_dma_rcv_ctx(ohci->ar_req_context, 0);
+       initialize_dma_rcv_ctx(ohci->ar_resp_context, 0);
 
        /* Initialize AT dma */
        initialize_dma_trm_ctx(ohci->at_req_context);
        initialize_dma_trm_ctx(ohci->at_resp_context);
 
        /* Initialize IR dma */
-       initialize_dma_rcv_ctx(ohci->ir_context);
+       initialize_dma_rcv_ctx(ohci->ir_context, 1);
 
         /* Initialize IT dma */
         initialize_dma_trm_ctx(ohci->it_context);
@@ -604,7 +639,6 @@ static int ohci_initialize(struct hpsb_host *host)
        /* Enable interrupts */
        reg_write(ohci, OHCI1394_IntMaskSet, 
                  OHCI1394_masterIntEnable | 
-                 OHCI1394_phyRegRcvd | 
                  OHCI1394_busReset | 
                  OHCI1394_selfIDComplete |
                  OHCI1394_RSPkt |
@@ -674,9 +708,9 @@ static void insert_packet(struct ti_ohci *ohci,
        } else 
                d->prg_cpu[idx]->begin.status = 0;
 
-        if ( (packet->type == async) || (packet->type == raw) ) {
+        if ( (packet->type == hpsb_async) || (packet->type == hpsb_raw) ) {
 
-                if (packet->type == raw) {
+                if (packet->type == hpsb_raw) {
                        d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4);
                         d->prg_cpu[idx]->data[1] = packet->header[0];
                         d->prg_cpu[idx]->data[2] = packet->header[1];
@@ -689,14 +723,18 @@ static void insert_packet(struct ti_ohci *ohci,
                         d->prg_cpu[idx]->data[2] = packet->header[2];
                         d->prg_cpu[idx]->data[3] = packet->header[3];
                        packet_swab(d->prg_cpu[idx]->data, packet->tcode,
-                                       packet->header_size>>2, ohci->payload_swap);
+                                       packet->header_size>>2);
                 }
 
                 if (packet->data_size) { /* block transmit */
                         d->prg_cpu[idx]->begin.control =
-                                cpu_to_le32(OUTPUT_MORE_IMMEDIATE | 0x10);
+                                cpu_to_le32(DMA_CTL_OUTPUT_MORE |
+                                           DMA_CTL_IMMEDIATE | 0x10);
                         d->prg_cpu[idx]->end.control =
-                                cpu_to_le32(OUTPUT_LAST | packet->data_size);
+                                cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+                                           DMA_CTL_IRQ | 
+                                           DMA_CTL_BRANCH |
+                                           packet->data_size);
                         /* 
                          * Check that the packet data buffer
                          * does not cross a page boundary.
@@ -716,9 +754,6 @@ static void insert_packet(struct ti_ohci *ohci,
                                                PCI_DMA_TODEVICE));
                        OHCI_DMA_ALLOC("single, block transmit packet");
 
-                       if (ohci->payload_swap)
-                               block_swab32(packet->data, packet->data_size >> 2);
-
                         d->prg_cpu[idx]->end.branchAddress = 0;
                         d->prg_cpu[idx]->end.status = 0;
                         if (d->branchAddrPtr) 
@@ -727,14 +762,20 @@ static void insert_packet(struct ti_ohci *ohci,
                         d->branchAddrPtr =
                                 &(d->prg_cpu[idx]->end.branchAddress);
                 } else { /* quadlet transmit */
-                        if (packet->type == raw)
-                                d->prg_cpu[idx]->begin.control = cpu_to_le32(
-                                        OUTPUT_LAST_IMMEDIATE |
-                                        (packet->header_size+4));
+                        if (packet->type == hpsb_raw)
+                                d->prg_cpu[idx]->begin.control = 
+                                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+                                                   DMA_CTL_IMMEDIATE |
+                                                   DMA_CTL_IRQ | 
+                                                   DMA_CTL_BRANCH |
+                                                   (packet->header_size + 4));
                         else
-                                d->prg_cpu[idx]->begin.control = cpu_to_le32(
-                                        OUTPUT_LAST_IMMEDIATE |
-                                        packet->header_size);
+                                d->prg_cpu[idx]->begin.control =
+                                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+                                                   DMA_CTL_IMMEDIATE |
+                                                   DMA_CTL_IRQ | 
+                                                   DMA_CTL_BRANCH |
+                                                   packet->header_size);
 
                         if (d->branchAddrPtr) 
                                 *(d->branchAddrPtr) =
@@ -747,20 +788,22 @@ static void insert_packet(struct ti_ohci *ohci,
                 d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
                         (packet->header[0] & 0xFFFF);
                 d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
-               packet_swab(d->prg_cpu[idx]->data, packet->tcode, packet->header_size>>2,
-                               ohci->payload_swap);
+               packet_swab(d->prg_cpu[idx]->data, packet->tcode, packet->header_size>>2);
   
-                d->prg_cpu[idx]->begin.control = cpu_to_le32(OUTPUT_MORE_IMMEDIATE | 0x8);
-                d->prg_cpu[idx]->end.control = cpu_to_le32(
-                        OUTPUT_LAST | 0x08000000 | packet->data_size);
+                d->prg_cpu[idx]->begin.control = 
+                       cpu_to_le32(DMA_CTL_OUTPUT_MORE | 
+                                   DMA_CTL_IMMEDIATE | 0x8);
+                d->prg_cpu[idx]->end.control = 
+                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+                                   DMA_CTL_UPDATE |
+                                   DMA_CTL_IRQ |
+                                   DMA_CTL_BRANCH |
+                                   packet->data_size);
                 d->prg_cpu[idx]->end.address = cpu_to_le32(
                                pci_map_single(ohci->dev, packet->data,
                                packet->data_size, PCI_DMA_TODEVICE));
                OHCI_DMA_ALLOC("single, iso transmit packet");
 
-               if (ohci->payload_swap)
-                       block_swab32(packet->data, packet->data_size>>2);
-
                 d->prg_cpu[idx]->end.branchAddress = 0;
                 d->prg_cpu[idx]->end.status = 0;
                 DBGMSG(ohci->id, "Iso xmit context info: header[%08x %08x]\n"
@@ -947,7 +990,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
 
                if (arg<0 || arg>63) {
                        PRINT(KERN_ERR, ohci->id, __FUNCTION__
-                             "IS0 listne channel %d is out of range", 
+                             "IS0 listen channel %d is out of range", 
                              arg);
                        return -EFAULT;
                }
@@ -1083,13 +1126,16 @@ static void ohci_irq_handler(int irq, void *dev_id,
        int phyid = -1, isroot = 0;
        unsigned long flags;
 
-       /* Read the interrupt event register. We don't clear the bus reset
-        * here. We wait till we get a selfid complete interrupt and clear
-        * it then, and _only_ then.  */
+       /* Read and clear the interrupt event register.  Don't clear
+        * the busReset event, though, this is done when we get the
+        * selfIDComplete interrupt. */
        spin_lock_irqsave(&ohci->event_lock, flags);
        event = reg_read(ohci, OHCI1394_IntEventClear);
-       reg_write(ohci, OHCI1394_IntEventClear,
-                 event & ~(OHCI1394_selfIDComplete | OHCI1394_busReset));
+#ifdef BUSRESET_WORKAROUND
+       reg_write(ohci, OHCI1394_IntEventClear, event);
+#else
+       reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
+#endif
        spin_unlock_irqrestore(&ohci->event_lock, flags);
 
        if (!event) return;
@@ -1103,24 +1149,26 @@ static void ohci_irq_handler(int irq, void *dev_id,
                return;
        }
 
-       /* Someone wants a bus reset. Better watch what you wish for... */
        if (event & OHCI1394_busReset) {
+               /* The busReset event bit can't be cleared during the
+                * selfID phase, so we disable busReset interrupts, to
+                * avoid burying the cpu in interrupt requests. */
+               spin_lock_irqsave(&ohci->event_lock, flags);
+#ifdef BUSRESET_WORKAROUND
+               reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+#else
+               reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
+#endif         
+               spin_unlock_irqrestore(&ohci->event_lock, flags);
                if (!host->in_bus_reset) {
                        DBGMSG(ohci->id, "irq_handler: Bus reset requested%s",
                              ((host->attempt_root || attempt_root) ?
                              " and attempting to become root" : ""));
-                       
-                       /* Wait for the AT fifo to be flushed */
-                       dma_trm_reset(ohci->at_req_context);
-                       dma_trm_reset(ohci->at_resp_context);
 
                        /* Subsystem call */
                        hpsb_bus_reset(ohci->host);
-                       
-                       ohci->NumBusResets++;
                }
-               /* Mask out everything except selfid */
-               event &= OHCI1394_selfIDComplete;
+               event &= ~OHCI1394_busReset;
        }
 
        /* XXX: We need a way to also queue the OHCI1394_reqTxComplete,
@@ -1234,11 +1282,12 @@ static void ohci_irq_handler(int irq, void *dev_id,
 
                                handle_selfid(ohci, host, 
                                              phyid, isroot);
-                       } else 
+                       } else {
                                PRINT(KERN_ERR, ohci->id, 
                                      "SelfID interrupt received, but "
                                      "NodeID is not valid: %08X",
                                      node_id);
+                       }
 
                        /* Accept Physical requests from all nodes. */
                        reg_write(ohci,OHCI1394_AsReqFilterHiSet, 
@@ -1258,21 +1307,15 @@ static void ohci_irq_handler(int irq, void *dev_id,
                        PRINT(KERN_ERR, ohci->id, 
                              "SelfID received outside of bus reset sequence");
 
-               /* Clear everything, it's a new day */
+               /* Finally, we clear the busReset event and reenable
+                * the busReset interrupt. */
+#ifndef BUSRESET_WORKAROUND
                spin_lock_irqsave(&ohci->event_lock, flags);
-               reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+               reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); 
+               reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
                spin_unlock_irqrestore(&ohci->event_lock, flags);
-
-               event &= ~OHCI1394_selfIDComplete;
-       }
-       if (event & OHCI1394_phyRegRcvd) {
-               if (host->in_bus_reset) {
-                       DBGMSG (ohci->id, "PhyControl: %08X", 
-                               reg_read(ohci, OHCI1394_PhyControl));
-               } else
-                       PRINT(KERN_ERR, ohci->id, 
-                             "Physical register received outside of bus reset sequence");
-               event &= ~OHCI1394_phyRegRcvd;
+#endif
+               event &= ~OHCI1394_selfIDComplete;      
        }
 
        /* Make sure we handle everything, just in case we accidentally
@@ -1365,14 +1408,14 @@ static void dma_rcv_tasklet (unsigned long data)
        dma_cache_wback_inv(buf_ptr, bytes_left);
 
        while (bytes_left > 0) {
-               tcode = (cond_le32_to_cpu(buf_ptr[0], ohci->payload_swap) >> 4) & 0xf;
+               tcode = (cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming) >> 4) & 0xf;
 
                /* packet_length() will return < 4 for an error */
-               length = packet_length(d, idx, buf_ptr, offset, tcode, ohci->payload_swap);
+               length = packet_length(d, idx, buf_ptr, offset, tcode, ohci->no_swap_incoming);
 
                if (length < 4) { /* something is wrong */
                        sprintf(msg,"Unexpected tcode 0x%x(0x%08x) in AR ctx=%d, length=%d",
-                               tcode, cond_le32_to_cpu(buf_ptr[0], ohci->payload_swap),
+                               tcode, cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming),
                                d->ctx, length);
                        ohci1394_stop_context(ohci, d->ctrlClear, msg);
                        spin_unlock_irqrestore(&d->lock, flags);
@@ -1448,19 +1491,18 @@ static void dma_rcv_tasklet (unsigned long data)
                /* We get one phy packet to the async descriptor for each
                 * bus reset. We always ignore it.  */
                if (tcode != OHCI1394_TCODE_PHY) {
-                       if (!ohci->payload_swap)
-                               packet_swab(d->spb, tcode, (length - 4) >> 2, 0);
-
+                       if (!ohci->no_swap_incoming)
+                               packet_swab(d->spb, tcode, (length - 4) >> 2);
                        DBGMSG(ohci->id, "Packet received from node"
                                " %d ack=0x%02X spd=%d tcode=0x%X"
                                " length=%d ctx=%d tlabel=%d",
                                (d->spb[1]>>16)&0x3f,
-                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>16)&0x1f,
-                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>21)&0x3,
+                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f,
+                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3,
                                tcode, length, d->ctx,
-                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>10)&0x3f);
+                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>10)&0x3f);
 
-                       ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>16)&0x1f)
+                       ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f)
                                == 0x11) ? 1 : 0;
 
                        hpsb_packet_received(ohci->host, d->spb, 
@@ -1510,7 +1552,7 @@ static void dma_trm_tasklet (unsigned long data)
        while (d->fifo_first) {
                packet = d->fifo_first;
                 datasize = d->fifo_first->data_size;
-               if (datasize && packet->type != raw)
+               if (datasize && packet->type != hpsb_raw)
                        ack = le32_to_cpu(
                                d->prg_cpu[d->sent_ind]->end.status) >> 16;
                else 
@@ -2032,6 +2074,14 @@ static struct hpsb_host_template ohci_template = {
        hw_csr_reg:             ohci_hw_csr_reg,
 };
 
+
+#define FAIL(fmt, args...)                     \
+do {                                           \
+       PRINT_G(KERN_ERR, fmt , ## args);       \
+       remove_card(ohci);                      \
+       return 1;                               \
+} while(0)
+
 static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_device_id *ent)
 {
        struct ti_ohci *ohci;   /* shortcut to currently handled device */
@@ -2075,10 +2125,10 @@ static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_devi
         * noByteSwapData registers to see if they were not cleared to
         * zero. Should this work? Obviously it's not defined what these
         * registers will read when they aren't supported. Bleh! */
-       if (dev->vendor == PCI_VENDOR_ID_APPLE) {
-               ohci->payload_swap = 1;
-               if (dev->device != PCI_DEVICE_ID_APPLE_UNI_N_FW)
-                       ohci->selfid_swap = 1;
+       if (dev->vendor == PCI_VENDOR_ID_APPLE && 
+               dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) {
+                       ohci->no_swap_incoming = 1;
+                       ohci->selfid_swap = 0;
        } else
                ohci->selfid_swap = 1;
 #endif
@@ -2248,6 +2298,23 @@ static void remove_card(struct ti_ohci *ohci)
        release_mem_region (pci_resource_start(ohci->dev, 0),
                            pci_resource_len(ohci->dev, 0));
 
+#ifdef CONFIG_ALL_PPC
+       /* On UniNorth, power down the cable and turn off the
+        * chip clock when the module is removed to save power
+        * on laptops. Turning it back ON is done by the arch
+        * code when pci_enable_device() is called
+        */
+       {
+               struct device_node* of_node;
+
+               of_node = pci_device_to_OF_node(ohci->dev);
+               if (of_node) {
+                       feature_set_firewire_power(of_node, 0);
+                       feature_set_firewire_cable_power(of_node, 0);
+               }
+       }
+#endif /* CONFIG_ALL_PPC */
+
        pci_set_drvdata(ohci->dev, NULL);
 }
 
@@ -2292,68 +2359,6 @@ void ohci1394_unregister_video(struct ti_ohci *ohci,
        }
 }
 
-#ifndef __LITTLE_ENDIAN
-
-/* Swap a series of quads inplace. */
-static __inline__ void block_swab32(quadlet_t *data, size_t size) {
-       while (size--)
-               data[size] = swab32(data[size]);
-}
-
-/* Swap headers and sometimes data too */
-static void packet_swab(quadlet_t *data, char tcode, int len, int payload_swap)
-{
-       if (payload_swap) {
-               block_swab32(data, len);
-               return;
-       }
-
-        switch(tcode)
-        {
-               /* 4 quad header */
-               case TCODE_READB_RESPONSE:
-               case TCODE_LOCK_RESPONSE:
-               case TCODE_LOCK_REQUEST:
-               case TCODE_WRITEB:
-               case TCODE_READB:
-                       block_swab32(data, 4);
-                       break;
-
-               /* 3 quad header, 1 quad payload */
-               case TCODE_WRITEQ:
-               case TCODE_READQ_RESPONSE:
-                       block_swab32(data, 3);
-                       break;
-
-               /* 3 quad header */
-               case TCODE_WRITE_RESPONSE:
-               case TCODE_READQ:
-                       block_swab32(data, 3);
-                       break;
-
-               /* 2 quad header */
-               case TCODE_ISO_DATA:
-                       block_swab32(data, 2);
-                       break;
-
-               case OHCI1394_TCODE_PHY:
-                       break; /* should never happen anyway */
-
-               case TCODE_CYCLE_START:
-                       PRINT_G(KERN_ERR, "Unhandled tcode in packet_swab (0x%x)", tcode);
-                       /* Atleast swap one quad */
-                       block_swab32(data, 1);
-                       break;
-                default:
-                       PRINT_G(KERN_ERR, "Invalid tcode in packet_swab (0x%x)", tcode);
-                        break;
-        }
-       return;
-}
-
-#endif /* !LITTLE_ENDIAN */
-
-
 #if 0
 int ohci1394_request_channel(struct ti_ohci *ohci, int channel)
 {
index 985ce439ec2e643b5fc65e3b9ab85b63e8051c39..3ab491270135363168937790e3f6291a74c447b9 100644 (file)
@@ -191,15 +191,14 @@ struct ti_ohci {
        spinlock_t event_lock;
 
        int self_id_errors;
-        int NumBusResets;
 
        /* video device */
        struct video_template *video_tmpl;
 
        /* Swap the selfid buffer? */
        unsigned int selfid_swap:1;
-       /* Swap the payload? */
-       unsigned int payload_swap:1;
+       /* Some Apple chipset seem to swap incoming headers for us */
+       unsigned int no_swap_incoming:1;
 };
 
 static inline int cross_bound(unsigned long addr, unsigned int size)
@@ -332,14 +331,16 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
 #define OHCI1394_phyRegRcvd              0x04000000
 #define OHCI1394_masterIntEnable         0x80000000
 
-#define OUTPUT_MORE                      0x00000000
-#define OUTPUT_MORE_IMMEDIATE            0x02000000
-#define OUTPUT_LAST                      0x103c0000
-#define OUTPUT_LAST_IMMEDIATE            0x123c0000
-
-#define DMA_SPEED_100                    0x0
-#define DMA_SPEED_200                    0x1
-#define DMA_SPEED_400                    0x2
+/* DMA Control flags */
+#define DMA_CTL_OUTPUT_MORE              0x00000000
+#define DMA_CTL_OUTPUT_LAST              0x10000000
+#define DMA_CTL_INPUT_MORE               0x20000000
+#define DMA_CTL_INPUT_LAST               0x30000000
+#define DMA_CTL_UPDATE                   0x08000000
+#define DMA_CTL_IMMEDIATE                0x02000000
+#define DMA_CTL_IRQ                      0x00300000
+#define DMA_CTL_BRANCH                   0x000c0000
+#define DMA_CTL_WAIT                     0x00030000
 
 #define OHCI1394_TCODE_PHY               0xE
 
index ee7d5b99150cc130bdad27101f70cd99d694da5d..815176c8fc1f621ba4c3fd787fefac7aca1aee51 100644 (file)
@@ -38,6 +38,7 @@
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
+#include "highlevel.h"
 #include "pcilynx.h"
 
 
@@ -393,7 +394,7 @@ static void send_next(struct ti_lynx *lynx, int what)
         struct lynx_send_data *d;
         struct hpsb_packet *packet;
 
-        d = (what == iso ? &lynx->iso_send : &lynx->async);
+        d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
         packet = d->queue;
 
         d->header_dma = pci_map_single(lynx->dev, packet->header,
@@ -419,13 +420,13 @@ static void send_next(struct ti_lynx *lynx, int what)
         pcl.buffer[1].pointer = d->data_dma;
 
         switch (packet->type) {
-        case async:
+        case hpsb_async:
                 pcl.buffer[0].control |= PCL_CMD_XMT;
                 break;
-        case iso:
+        case hpsb_iso:
                 pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
                 break;
-        case raw:
+        case hpsb_raw:
                 pcl.buffer[0].control |= PCL_CMD_UNFXMT;
                 break;
         }                
@@ -606,11 +607,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
         }
 
         switch (packet->type) {
-        case async:
-        case raw:
+        case hpsb_async:
+        case hpsb_raw:
                 d = &lynx->async;
                 break;
-        case iso:
+        case hpsb_iso:
                 d = &lynx->iso_send;
                 break;
         default:
@@ -1227,7 +1228,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
                 }
 
                 if (lynx->async.queue != NULL) {
-                        send_next(lynx, async);
+                        send_next(lynx, hpsb_async);
                 }
 
                 spin_unlock(&lynx->async.queue_lock);
@@ -1259,7 +1260,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
                 }
 
                 if (lynx->iso_send.queue != NULL) {
-                        send_next(lynx, iso);
+                        send_next(lynx, hpsb_iso);
                 }
 
                 spin_unlock(&lynx->iso_send.queue_lock);
@@ -1368,7 +1369,7 @@ static int __devinit add_card(struct pci_dev *dev,
                 FAIL("failed to allocate host structure");
 
         lynx->state = have_host_struct;
-
+       lynx->host->hostdata = lynx;
         lynx->id = num_of_cards-1;
         lynx->dev = dev;
        lynx->host->pdev = dev;
@@ -1501,6 +1502,9 @@ static int __devinit add_card(struct pci_dev *dev,
                 PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");
         }
 
+       /* Tell the highlevel this host is ready */
+       highlevel_add_one_host (lynx->host);
+
         return 0;
 #undef FAIL
 }
@@ -1633,8 +1637,8 @@ MODULE_DEVICE_TABLE(pci, pci_table);
 
 static void __exit pcilynx_cleanup(void)
 {
-        pci_unregister_driver(&lynx_pcidriver);
         hpsb_unregister_lowlevel(&lynx_template);
+       pci_unregister_driver(&lynx_pcidriver);
         PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module");
 }
 
index 03a72ab10eb32849071d6b25efc987e22baf8e89..903ddbcb775598f8ecf04434652bfb3d32fe46a4 100644 (file)
@@ -290,8 +290,11 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
         }
         spin_unlock_irqrestore(&host_info_lock, flags);
 
-        list_for_each(lh, &reqs) {
+        lh = reqs.next;
+        while (lh != &reqs) {
                 req = list_entry(lh, struct pending_request, list);
+                lh = lh->next;
+
                 queue_complete_req(req);
         }
 }
@@ -356,8 +359,11 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
         }
         spin_unlock_irqrestore(&host_info_lock, flags);
 
-        list_for_each(lh, &reqs) {
+        lh = reqs.next;
+        while (lh != &reqs) {
                 req = list_entry(lh, struct pending_request, list);
+                lh = lh->next;
+
                 queue_complete_req(req);
         }
 }
@@ -746,6 +752,8 @@ static int handle_remote_request(struct file_info *fi,
         list_add_tail(&req->list, &fi->req_pending);
         spin_unlock_irq(&fi->reqlists_lock);
 
+       packet->generation = req->req.generation;
+
         if (!hpsb_send_packet(packet)) {
                 req->req.error = RAW1394_ERROR_SEND_ERROR;
                 req->req.length = 0;
@@ -766,7 +774,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
 
         fill_iso_packet(packet, req->req.length, channel & 0x3f,
                         (req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
-        packet->type = iso;
+        packet->type = hpsb_iso;
         packet->speed_code = req->req.address & 0x3;
         packet->host = fi->host;
 
@@ -787,6 +795,9 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
         list_add_tail(&req->list, &fi->req_pending);
         spin_unlock_irq(&fi->reqlists_lock);
 
+       /* Update the generation of the packet just before sending. */
+       packet->generation = get_hpsb_generation(fi->host);
+
         if (!hpsb_send_packet(packet)) {
                 req->req.error = RAW1394_ERROR_SEND_ERROR;
                 queue_complete_req(req);
index a69131f98d823ba39894e7c3cd5762a5ce34400a..594680253913c792e7ae15feb2edb3d96352dac5 100644 (file)
  *       are some stress issues under investigation with deserialized I/O. To enable
  *       deserialized I/O for testing, do "insmod sbp2 serialize_io=0"
  *
- *     - Hot-Plugging: Need to add procfs support and integration with linux
- *       hot-plug support (http://linux-hotplug.sourceforge.net) for auto-mounting 
- *       of drives.
- *
  *     - Error Handling: SCSI aborts and bus reset requests are handled somewhat
  *       but the code needs additional debugging.
  *
- *     - IEEE-1394 Bus Management: There is currently little bus management
- *       in the core IEEE-1394 stack. Because of this, the SBP-2 driver handles
- *       detection of SBP-2 devices itself. This should be moved to the core
- *       stack.
- *
  *     - The SBP-2 driver is currently only supported as a module. It would not take
  *       much work to allow it to be compiled into the kernel, but you'd have to 
  *       add some init code to the kernel to support this... and modules are much
  *       more flexible anyway.   ;-)
  *
- *     - Workaround for PPC pismo firewire chipset (enable SBP2_PPC_PISMO_WORKAROUND
- *       define below).
- *
  *
  * History:
  *
  *                                                      <bcollins@debian.org
  *     07/22/01 - Use NodeMngr to get info about the local host and
  *                attached devices. Ben Collins
+ *
+ *      09/15/01 - Remove detection code, instead subscribe to the nodemgr
+ *                 driver management interface.  This also removes the
+ *                 initial bus scan stuff since the nodemgr calls
+ *                 sbp2_probe for each sbp2 device already on the bus,
+ *                 when we register our driver.  This change 
+ *                 automtically adds hotplug support to the driver.
+ *                                 Kristian Hogsberg <hogsberg@users.sf.net>
  */
     
+\f
+
 /*
  * Includes
  */
 #include "../scsi/sd.h"
 #include "sbp2.h"
 
-/*
- * PPC firewire Pismo chipset workaround!!!
- *
- * This is a workaround for a bug in the firewire pismo chipset. For some odd reason the status
- * fifo address hi/lo must be byteswapped and the response address byteswapped, but no other
- * parts of the structure. Apple's drivers seem to specifically check for the pismo and do
- * the same workaround for sbp2. (Daniel Berlin)
- *
- * Please enable the following define if you're running on the PPC Pismo chipset.
- */
-
-#ifdef CONFIG_IEEE1394_SBP2_PISMO
-#define SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
-#endif
-
 /*
  * Module load parameter definitions
  */
 
 /*
- * Normally the sbp2 driver tries to catch the initial scsi bus scan to pick up any 
- * attached sbp2 devices. Setting no_bus_scan to 1 tells the sbp2 driver not to catch
- * this initial scsi bus scan on module load. You can always either add or remove devices 
- * later through the rescan-scsi-bus.sh script or scsi procfs.
- */
-MODULE_PARM(no_bus_scan,"i");
-MODULE_PARM_DESC(no_bus_scan, "Skip the initial scsi bus scan during module load");
-static int no_bus_scan = 0;
-
-/*
- * Set mode_sense_hack to 1 if you have some sort of unusual sbp2 device, like a 1394 memory 
- * stick reader, compact flash reader, or MO drive that does not support mode sense. Allows
- * you to mount the media rw instead of ro.
+ * Set mode_sense_hack to 1 if you have some sort of unusual sbp2 device,
+ * like a 1394 memory stick reader, compact flash reader, or MO drive that
+ * does not support mode sense. Allows you to mount the media rw instead
+ * of ro.
  */
 MODULE_PARM(mode_sense_hack,"i");
 MODULE_PARM_DESC(mode_sense_hack, "Emulate mode sense for devices like 1394 memory stick readers");
 static int mode_sense_hack = 0;
 
 /*
- * Change max_speed on module load if you have a bad IEEE-1394 controller that has trouble running
- * 2KB packets at 400mb.
+ * Change max_speed on module load if you have a bad IEEE-1394 controller
+ * that has trouble running 2KB packets at 400mb.
  *
- * NOTE: On certain OHCI parts I have seen short packets on async transmit (probably 
- * due to PCI latency/throughput issues with the part). You can bump down the speed if
- * you are running into problems.
+ * NOTE: On certain OHCI parts I have seen short packets on async transmit
+ * (probably due to PCI latency/throughput issues with the part). You can
+ * bump down the speed if you are running into problems.
  *
  * Valid values:
  * max_speed = 2 (default: max speed 400mb)
@@ -319,30 +293,37 @@ MODULE_PARM_DESC(max_speed, "Force down max speed (2 = 400mb default, 1 = 200mb,
 static int max_speed = SPEED_400;
 
 /*
- * Set serialize_io to 1 if you'd like only one scsi command sent down to us at a time (debugging).
+ * Set serialize_io to 1 if you'd like only one scsi command sent down to
+ * us at a time (debugging).
  */
 MODULE_PARM(serialize_io,"i");
 MODULE_PARM_DESC(serialize_io, "Serialize all I/O coming down from the scsi drivers (debugging)");
 static int serialize_io = 1;   /* serialize I/O until stress issues are resolved */
 
 /*
- * Set no_large_packets to 1 if you'd like to limit the size of requests sent down to us (normally
- * the sbp2 driver will break up any requests to any individual devices with 128KB transfer size limits).
- * Sets max s/g list elements to 0x1f in size and disables s/g clustering.
+ * Set no_large_packets to 1 if you'd like to limit the size of requests
+ * sent down to us (normally the sbp2 driver will break up any requests to
+ * any individual devices with 128KB transfer size limits).  Sets max s/g
+ * list elements to 0x1f in size and disables s/g clustering.
  */
 MODULE_PARM(no_large_packets,"i");
 MODULE_PARM_DESC(no_large_packets, "Do not allow large transfers from scsi drivers (debugging)");
 static int no_large_packets = 0;
 
 /*
- * Export information about protocols/devices supported by this driver
+ * Export information about protocols/devices supported by this driver.
  */
 static struct ieee1394_device_id sbp2_id_table[] = {
-       IEEE1394_PROTOCOL(SBP2_UNIT_SPEC_ID_ENTRY, SBP2_SW_VERSION_ENTRY),
+       {
+               match_flags:  IEEE1394_MATCH_SPECIFIER_ID |
+                             IEEE1394_MATCH_VERSION,
+               specifier_id: SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
+               version:      SBP2_SW_VERSION_ENTRY & 0xffffff
+       },
        { }
 };
 
-MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); 
+MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
 
 /*
  * Debug levels, configured via kernel config.
@@ -372,6 +353,7 @@ static u32 global_outstanding_dmas = 0;
 #define SBP2_DMA_FREE(fmt, args...)
 #endif
 
+
 #if CONFIG_IEEE1394_SBP2_DEBUG >= 2
 #define SBP2_DEBUG(fmt, args...)       HPSB_ERR(fmt, ## args)  
 #define SBP2_INFO(fmt, args...)                HPSB_ERR(fmt, ## args)  
@@ -392,12 +374,14 @@ static u32 global_outstanding_dmas = 0;
 #define SBP2_ERR(fmt, args...)         HPSB_ERR(fmt, ## args)
 
 /*
- * Spinlock debugging stuff. I'm playing it safe until the driver has been debugged on SMP. (JSG)
+ * Spinlock debugging stuff. I'm playing it safe until the driver has been
+ * debugged on SMP. (JSG)
  */
 /* #define SBP2_USE_REAL_SPINLOCKS */
 #ifdef SBP2_USE_REAL_SPINLOCKS
 #define sbp2_spin_lock(lock, flags)    spin_lock_irqsave(lock, flags)  
 #define sbp2_spin_unlock(lock, flags)  spin_unlock_irqrestore(lock, flags);
+static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
 #else
 #define sbp2_spin_lock(lock, flags)    do {save_flags(flags); cli();} while (0)        
 #define sbp2_spin_unlock(lock, flags)  do {restore_flags(flags);} while (0)
@@ -411,28 +395,27 @@ Scsi_Host_Template *global_scsi_tpnt = NULL;
 
 static LIST_HEAD(sbp2_host_info_list);
 static int sbp2_host_count = 0;
-static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
 
 static struct hpsb_highlevel *sbp2_hl_handle = NULL;
 
 static struct hpsb_highlevel_ops sbp2_hl_ops = {
-       sbp2_add_host,
-       sbp2_remove_host,
-       sbp2_host_reset,
-       NULL,
-       NULL
+       add_host:       sbp2_add_host,
+       remove_host:    sbp2_remove_host,
 };
 
 static struct hpsb_address_ops sbp2_ops = {
-       write: sbp2_handle_status_write,
+       write: sbp2_handle_status_write
 };
 
-#if 0
-static struct hpsb_address_ops sbp2_physdma_ops = {
-       read: sbp2_handle_physdma_read,
-       write: sbp2_handle_physdma_write,
+static struct hpsb_protocol_driver sbp2_driver = {
+       name:           "SBP2 Driver",
+       id_table:       sbp2_id_table,
+       probe:          sbp2_probe,
+       disconnect:     sbp2_disconnect,
+       update:         sbp2_update
 };
-#endif
+
+\f
 
 /**************************************
  * General utility functions
@@ -472,108 +455,29 @@ static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 #endif
 
 /*
- * This function does quadlet sized reads (used by detection code)
- */
-static int sbp2util_read_quadlet(struct sbp2scsi_host_info *hi, nodeid_t node, u64 addr,
-                                quadlet_t *buffer)
-{
-       int retval = 0;
-       int retry_count = 3;
-
-       /*
-        * Retry a couple times if needed (for slow devices)
-        */
-       do {
-
-               retval = hpsb_read(hi->host, node, addr, buffer, 4);
-
-               if (retval) {
-                       SBP2_DEBUG("sbp2: sbp2util_read_quadlet data packet error");
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(HZ/50);        /* 20ms delay */
-               }
-
-               retry_count--;
-
-       } while (retval && retry_count);
-
-       return(retval);
-}
-
-/*
- * This function returns the address of the unit directory.
- */
-static int sbp2util_unit_directory(struct sbp2scsi_host_info *hi, nodeid_t node_id, u64 *unit_directory_addr)
-{
-       quadlet_t root_directory_length, current_quadlet;
-       u64 current_addr;
-       int length, i;
-
-       /*
-        * First, read the first quadlet of the root directory to determine its size
-        */
-       if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, CONFIG_ROM_ROOT_DIR_BASE, 
-                                 &root_directory_length)) {
-               SBP2_DEBUG("sbp2: Error reading root directory length - bad status");
-               return(-EIO);   
-       }
-
-       current_addr = CONFIG_ROM_ROOT_DIR_BASE;
-       length = be32_to_cpu(root_directory_length) >> 16;
-
-       /*
-        * Step through the root directory and look for the "Unit_Directory entry", which
-        * contains the offset to the unit directory.
-        */
-       for (i=0; i < length; i++) {
-
-               current_addr += 4;
-
-               if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, current_addr, &current_quadlet)) {
-                       SBP2_DEBUG("sbp2: Error reading at address 0x%08x%08x - bad status", 
-                                  (unsigned int) ((current_addr) >> 32), (unsigned int) ((current_addr) & 0xffffffff));
-                       return(-EIO);   
-               }
-
-               /*  
-                * Check for unit directory offset tag 
-                */
-               if ((be32_to_cpu(current_quadlet) >> 24) == SBP2_UNIT_DIRECTORY_OFFSET_KEY) {
-                       *unit_directory_addr = current_addr + 4 * ((be32_to_cpu(current_quadlet) & 0xffffff));
-                       SBP2_DEBUG("sbp2: unit_directory_addr = %lu", *unit_directory_addr);
-               }
-       }
-
-       return(0);
-}
-
-/*
- * This function is called to initially create a packet pool for use in sbp2 I/O requests.
- * This packet pool is used when sending out sbp2 command and agent reset requests, and 
- * allows us to remove all kmallocs/kfrees from the critical I/O paths.
+ * This function is called to initially create a packet pool for use in
+ * sbp2 I/O requests. This packet pool is used when sending out sbp2
+ * command and agent reset requests, and allows us to remove all
+ * kmallocs/kfrees from the critical I/O paths.
  */
 static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi)
 {
        struct hpsb_packet *packet;
        int i;
-       unsigned long flags;
 
-       /*
-        * Create SBP2_MAX_REQUEST_PACKETS number of request packets.
-        */
-       sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags);
+       /* Create SBP2_MAX_REQUEST_PACKETS number of request packets. */
        for (i=0; i<SBP2_MAX_REQUEST_PACKETS; i++) {
 
                /*
-                * Max payload of 8 bytes since the sbp2 command request uses a payload of 
-                * 8 bytes, and agent reset is a quadlet write request. Bump this up if we
-                * plan on using this pool for other stuff.
+                * Max payload of 8 bytes since the sbp2 command request
+                * uses a payload of 8 bytes, and agent reset is a quadlet
+                * write request. Bump this up if we plan on using this
+                * pool for other stuff.
                 */
                packet = alloc_hpsb_packet(8);
 
                if (!packet) {
                        SBP2_ERR("sbp2: sbp2util_create_request_packet_pool - packet allocation failed!");
-                       sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);
                        return(-ENOMEM);
                }
 
@@ -585,13 +489,13 @@ static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi)
                list_add_tail(&hi->request_packet[i].list, &hi->sbp2_req_free);
 
        }
-       sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);
 
        return(0);
 }
 
 /*
- * This function is called to remove the packet pool. It is called when the sbp2 driver is unloaded.
+ * This function is called to remove the packet pool. It is called when
+ * the sbp2 driver is unloaded.
  */
 static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi)
 {
@@ -624,15 +528,17 @@ static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi)
 }
 
 /*
- * This function is called to retrieve a block write packet from our packet pool. This function is
- * used in place of calling alloc_hpsb_packet (which costs us three kmallocs). Instead we 
- * just pull out a free request packet and re-initialize values in it. I'm sure this can still
- * stand some more optimization. 
- */
-static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
-                                                                         nodeid_t node, u64 addr,
-                                                                         size_t data_size,
-                                                                         quadlet_t data) {
+ * This function is called to retrieve a block write packet from our
+ * packet pool. This function is used in place of calling
+ * alloc_hpsb_packet (which costs us three kmallocs). Instead we just pull
+ * out a free request packet and re-initialize values in it. I'm sure this
+ * can still stand some more optimization.
+ */
+static struct sbp2_request_packet *
+sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
+                                      nodeid_t node, u64 addr,
+                                      size_t data_size,
+                                      quadlet_t data) {
        struct list_head *lh;
        struct sbp2_request_packet *request_packet = NULL;
        struct hpsb_packet *packet;
@@ -651,13 +557,14 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
                packet = request_packet->packet;
 
                /*
-                * Initialize the packet (this is really initialization the core 1394 stack should do,
-                * but I'm doing it myself to avoid the overhead).
+                * Initialize the packet (this is really initialization
+                * the core 1394 stack should do, but I'm doing it myself
+                * to avoid the overhead).
                 */
                packet->data_size = data_size;
                INIT_LIST_HEAD(&packet->list);
                sema_init(&packet->state_change, 0);
-               packet->state = unused;
+               packet->state = hpsb_unused;
                packet->generation = get_hpsb_generation(hi->host);
                packet->data_be = 1;
 
@@ -672,8 +579,8 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
                }
 
                /*
-                * Set up a task queue completion routine, which returns the packet to the free list
-                * and releases the tlabel
+                * Set up a task queue completion routine, which returns
+                * the packet to the free list and releases the tlabel.
                 */
                request_packet->tq.routine = (void (*)(void*))sbp2util_free_request_packet;
                request_packet->tq.data = request_packet;
@@ -681,7 +588,7 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
                queue_task(&request_packet->tq, &packet->complete_tq);
 
                /*
-                * Now, put the packet on the in-use list
+                * Now, put the packet on the in-use list.
                 */
                list_add_tail(&request_packet->list, &hi->sbp2_req_inuse);
 
@@ -694,8 +601,8 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
 }
 
 /*
- * This function is called to return a packet to our packet pool. It is also called as a 
- * completion routine when a request packet is completed.
+ * This function is called to return a packet to our packet pool. It is
+ * also called as a completion routine when a request packet is completed.
  */
 static void sbp2util_free_request_packet(struct sbp2_request_packet *request_packet)
 {
@@ -703,7 +610,7 @@ static void sbp2util_free_request_packet(struct sbp2_request_packet *request_pac
        struct sbp2scsi_host_info *hi = request_packet->hi_context;
 
        /*
-        * Free the tlabel, and return the packet to the free pool
+        * Free the tlabel, and return the packet to the free pool.
         */
        sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags);
        free_tlabel(hi->host, LOCAL_BUS | request_packet->packet->node_id,
@@ -716,8 +623,8 @@ static void sbp2util_free_request_packet(struct sbp2_request_packet *request_pac
 }
 
 /*
- * This function is called to create a pool of command orbs used for command processing. It is called
- * when a new sbp2 device is detected.
+ * This function is called to create a pool of command orbs used for
+ * command processing. It is called when a new sbp2 device is detected.
  */
 static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id,
                                            struct sbp2scsi_host_info *hi)
@@ -785,10 +692,11 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_
 }
 
 /* 
- * This functions finds the sbp2_command for a given outstanding
- * command orb. Only looks at the inuse list.
+ * This functions finds the sbp2_command for a given outstanding command
+ * orb. Only looks at the inuse list.
  */
-static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb)
+static struct sbp2_command_info *sbp2util_find_command_for_orb(
+               struct scsi_id_instance_data *scsi_id, dma_addr_t orb)
 {
        struct list_head *lh;
        struct sbp2_command_info *command;
@@ -812,7 +720,8 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_in
 }
 
 /* 
- * This functions finds the sbp2_command for a given outstanding SCpnt. Only looks at the inuse list 
+ * This functions finds the sbp2_command for a given outstanding SCpnt.
+ * Only looks at the inuse list.
  */
 static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
 {
@@ -837,10 +746,11 @@ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_
 /*
  * This function allocates a command orb used to send a scsi command.
  */
-static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id, 
-                                                              Scsi_Cmnd *Current_SCpnt, 
-                                                              void (*Current_done)(Scsi_Cmnd *),
-                                                              struct sbp2scsi_host_info *hi)
+static struct sbp2_command_info *sbp2util_allocate_command_orb(
+               struct scsi_id_instance_data *scsi_id, 
+               Scsi_Cmnd *Current_SCpnt, 
+               void (*Current_done)(Scsi_Cmnd *),
+               struct sbp2scsi_host_info *hi)
 {
        struct list_head *lh;
        struct sbp2_command_info *command = NULL;
@@ -903,13 +813,15 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
        sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
 }
 
+\f
+
 /*********************************************
  * IEEE-1394 core driver stack related section
  *********************************************/
 
 /*
- * This function is called at SCSI init in order to register our driver with the
- * IEEE-1394 stack
+ * This function is called at SCSI init in order to register our driver
+ * with the IEEE-1394 stack.
  */
 int sbp2_init(void)
 {
@@ -931,26 +843,21 @@ int sbp2_init(void)
        hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS,
                                SBP2_STATUS_FIFO_ADDRESS + sizeof(struct sbp2_status_block));
 
-       /*
-        * Register physical dma address space... used for
-        * adapters not supporting hardware phys dma.
-        *
-        * XXX: Disabled for now.
-        */
-       /* hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops,
-                                  0x0ULL, 0xfffffffcULL); */
+       hpsb_register_protocol(&sbp2_driver);
 
-       return(0);
+       return 0;
 }
 
 /*
- * This function is called from cleanup module, or during shut-down, in order to 
- * unregister our driver
+ * This function is called from cleanup module, or during shut-down, in
+ * order to unregister our driver.
  */
 void sbp2_cleanup(void)
 {
        SBP2_DEBUG("sbp2: sbp2_cleanup");
 
+       hpsb_unregister_protocol(&sbp2_driver);
+
        if (sbp2_hl_handle) {
                hpsb_unregister_highlevel(sbp2_hl_handle);
                sbp2_hl_handle = NULL;
@@ -958,73 +865,121 @@ void sbp2_cleanup(void)
        return;
 }
 
-/*
- * This function is called after registering our operations in sbp2_init. We go ahead and
- * allocate some memory for our host info structure, and init some structures.
- */
-static void sbp2_add_host(struct hpsb_host *host)
+static int sbp2_probe(struct unit_directory *ud)
 {
        struct sbp2scsi_host_info *hi;
-       unsigned long flags;
 
-       SBP2_DEBUG("sbp2: sbp2_add_host");
+       SBP2_DEBUG("sbp2: sbp2_probe");
+       hi = sbp2_find_host_info(ud->ne->host);
 
-       /*
-        * Allocate some memory for our host info structure
-        */
-       hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info), GFP_KERNEL);
+       return sbp2_start_device(hi, ud);
+}
 
-       if (hi != NULL) {
+static void sbp2_disconnect(struct unit_directory *ud)
+{
+       struct sbp2scsi_host_info *hi;
+       struct scsi_id_instance_data *scsi_id = ud->driver_data;
 
-               /*
-                * Initialize some host stuff
-                */
-               memset(hi, 0, sizeof(struct sbp2scsi_host_info));
-               INIT_LIST_HEAD(&hi->list);
-               INIT_LIST_HEAD(&hi->sbp2_req_inuse);
-               INIT_LIST_HEAD(&hi->sbp2_req_free);
-               hi->host = host;
-               hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
-               hi->sbp2_request_packet_lock = SPIN_LOCK_UNLOCKED;
+       SBP2_DEBUG("sbp2: sbp2_disconnect");
+       hi = sbp2_find_host_info(ud->ne->host);
 
-               /*
-                * Create our request packet pool (pool of packets for use in I/O)
+       if (hi != NULL)
+               sbp2_remove_device(hi, scsi_id);
+}
+
+static void sbp2_update(struct unit_directory *ud)
+{
+       struct sbp2scsi_host_info *hi;
+       struct scsi_id_instance_data *scsi_id = ud->driver_data;
+       unsigned long flags;
+
+       SBP2_DEBUG("sbp2: sbp2_update");
+       hi = sbp2_find_host_info(ud->ne->host);
+
+       if (sbp2_reconnect_device(hi, scsi_id)) {
+               
+               /* Ok, reconnect has failed.  Perhaps we didn't
+                * reconnect fast enough. Try doing a regular login.
                 */
-               if (sbp2util_create_request_packet_pool(hi)) {
-                       SBP2_ERR("sbp2: sbp2util_create_request_packet_pool failed!");
+               if (sbp2_login_device(hi, scsi_id)) {
+
+                       /* Login failed too... so, just mark him as
+                        * unvalidated, so that he gets cleaned up
+                        * later.
+                        */
+                       SBP2_ERR("sbp2: sbp2_reconnect_device failed!");
+                       sbp2_remove_device(hi, scsi_id);
                        return;
                }
+       }
 
-               sbp2_spin_lock(&sbp2_host_info_lock, flags);
-               list_add_tail(&hi->list, &sbp2_host_info_list);
-               sbp2_host_count++;
-               sbp2_spin_unlock(&sbp2_host_info_lock, flags);
+       /* Set max retries to something large on the device. */
+       sbp2_set_busy_timeout(hi, scsi_id);
 
-               /*
-                * Initialize us to bus reset in progress
-                */
-               hi->bus_reset_in_progress = 1;
+       /* Do a SBP-2 fetch agent reset. */
+       sbp2_agent_reset(hi, scsi_id, 0);
+       
+       /* Get the max speed and packet size that we can use. */
+       sbp2_max_speed_and_size(hi, scsi_id);
 
-               /*
-                * Register our host with the SCSI stack. 
-                */
-               sbp2scsi_register_scsi_host(hi);
+       /* Complete any pending commands with busy (so they get
+        * retried) and remove them from our queue
+        */
+       sbp2_spin_lock(&hi->sbp2_command_lock, flags);
+       sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY);
+       sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+}
 
-               /*
-                * Start our kernel thread to deal with sbp2 device detection
-                */
-               init_waitqueue_head(&hi->sbp2_detection_wait);
-               hi->sbp2_detection_pid = 0;
-               hi->sbp2_detection_pid = kernel_thread(sbp2_detection_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+/*
+ * This function is called after registering our operations in sbp2_init.
+ * We go ahead and allocate some memory for our host info structure, and
+ * init some structures.
+ */
+static void sbp2_add_host(struct hpsb_host *host)
+{
+       struct sbp2scsi_host_info *hi;
+       unsigned long flags;
+
+       SBP2_DEBUG("sbp2: sbp2_add_host");
+
+       /* Allocate some memory for our host info structure */
+       hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info),
+                                                 GFP_KERNEL);
 
+       if (hi == NULL) {
+               SBP2_ERR("sbp2: out of memory in sbp2_add_host");
+               return;
        }
 
+       /* Initialize some host stuff */
+       memset(hi, 0, sizeof(struct sbp2scsi_host_info));
+       INIT_LIST_HEAD(&hi->list);
+       INIT_LIST_HEAD(&hi->sbp2_req_inuse);
+       INIT_LIST_HEAD(&hi->sbp2_req_free);
+       hi->host = host;
+       hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
+       hi->sbp2_request_packet_lock = SPIN_LOCK_UNLOCKED;
+
+       /* Create our request packet pool (pool of packets for use in I/O) */
+       if (sbp2util_create_request_packet_pool(hi)) {
+               SBP2_ERR("sbp2: sbp2util_create_request_packet_pool failed!");
+               return;
+       }
+
+       sbp2_spin_lock(&sbp2_host_info_lock, flags);
+       list_add_tail(&hi->list, &sbp2_host_info_list);
+       sbp2_host_count++;
+       sbp2_spin_unlock(&sbp2_host_info_lock, flags);
+
+       /* Register our host with the SCSI stack. */
+       sbp2scsi_register_scsi_host(hi);
+
        return;
 }
 
 /*
- * This fuction returns a host info structure from the host structure,
- * in case we have multiple hosts
+ * This fuction returns a host info structure from the host structure, in
+ * case we have multiple hosts.
  */
 static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host)
 {
@@ -1047,206 +1002,55 @@ static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host)
 static void sbp2_remove_host(struct hpsb_host *host)
 {
        struct sbp2scsi_host_info *hi;
-       int i;
        unsigned long flags;
+       int i;
 
        SBP2_DEBUG("sbp2: sbp2_remove_host");
 
        sbp2_spin_lock(&sbp2_host_info_lock, flags);
-       hi = sbp2_find_host_info(host);
 
+       hi = sbp2_find_host_info(host);
        if (hi != NULL) {
-
-               /*
-                * Need to remove any attached SBP-2 devices. Also make sure to logout of all devices.
+               /* Here's an annoying hack: we get a disconnect
+                * callback for each device, so this loop shouldn't be
+                * necessary.  However, the sbp2 driver receives the
+                * remove_host callback before the nodemgr, so when we
+                * get the disconnect callback, we've already freed
+                * the host.  Thus, we free the devices here...
                 */
-               for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-                       if (hi->scsi_id[i]) {
+               for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
+                       if (hi->scsi_id[i] != NULL) {
                                sbp2_logout_device(hi, hi->scsi_id[i]);
-                               hi->scsi_id[i]->validated = 0;
+                               sbp2_remove_device(hi, hi->scsi_id[i]);
                        }
                }
-
-               sbp2_remove_unvalidated_devices(hi);
-
-               list_del(&hi->list);
+               sbp2util_remove_request_packet_pool(hi);
                sbp2_host_count--;
+               list_del(&hi->list);
+               kfree(hi);
        }
-       sbp2_spin_unlock(&sbp2_host_info_lock, flags);
-
-       if (hi == NULL) {
+       else
                SBP2_ERR("sbp2: attempt to remove unknown host %p", host);
-               return;
-       }
 
-       /*
-        * Remove the packet pool (release the packets)
-        */
-       sbp2util_remove_request_packet_pool(hi);
-
-       /* 
-        * Kill our detection thread 
-        */
-       if (hi->sbp2_detection_pid >= 0) {
-               kill_proc(hi->sbp2_detection_pid, SIGINT, 1);
-       }
-
-       /*
-        * Give the detection thread a little time to exit
-        */
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(HZ);   /* 1 second delay */
-
-       kfree(hi);
-       hi = NULL;
-
-       return;
-}
-
-/*
- * This is our sbp2 detection thread. It is signalled when bus resets occur
- * so that we can find and initialize any sbp2 devices. 
- */
-static int sbp2_detection_thread(void *__hi)
-{
-       struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)__hi;
-
-       SBP2_DEBUG("sbp2: sbp2_detection_thread");
-
-       lock_kernel();
-
-       /*
-        * This thread doesn't need any user-level access,
-        * so get rid of all our resources
-        */
-#if LINUX_VERSION_CODE > 0x20300
-       daemonize();
-#endif
-
-       /* 
-        * Set-up a nice name
-        */
-       strcpy(current->comm, SBP2_DEVICE_NAME);
-
-       unlock_kernel();
-        
-       while ((!signal_pending(current)) && hi) {
-
-               /*
-                * Process our bus reset now
-                */
-               if (hi) {
-                       MOD_INC_USE_COUNT;
-                       sbp2_bus_reset_handler(hi);
-                       MOD_DEC_USE_COUNT;
-               }
-
-               /*
-                * Sleep until next bus reset
-                */
-               if (hi) {
-                       interruptible_sleep_on(&hi->sbp2_detection_wait);
-               }
-       }
-
-       return(0);
+       sbp2_spin_unlock(&sbp2_host_info_lock, flags);
 }
 
 /*
- * This function is where we first pull the node unique ids, and then allocate memory and register
- * a SBP-2 device
+ * This function is where we first pull the node unique ids, and then
+ * allocate memory and register a SBP-2 device.
  */
-static int sbp2_start_device(struct sbp2scsi_host_info *hi, int node_id)
+static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud)
 {
-       u64 node_unique_id;
        struct scsi_id_instance_data *scsi_id = NULL;
        struct node_entry *ne;
        int i;
 
        SBP2_DEBUG("sbp2: sbp2_start_device");
-
-       /* XXX: This will go away once we start using the nodemgr's
-        * feature subscription API.  */
-       ne = hpsb_nodeid_get_entry(node_id|(hi->host->node_id & BUS_MASK));
-       if (!ne) {
-               HPSB_ERR("sbp2: Could not find device node");
-               return -ENXIO;
-       }
-
-       node_unique_id = ne->guid;
+       ne = ud->ne;
 
        /*
-        * First, we need to find out whether this is a "new" SBP-2 device plugged in, or one that already
-        * exists and is initialized. We do this by looping through our scsi id instance data structures
-        * looking for matching node unique ids.
-        */
-       for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-
-               if (hi->scsi_id[i]) {
-
-                       if (hi->scsi_id[i]->node_unique_id == node_unique_id) {
-
-                               /*
-                                * Update our node id
-                                */
-                               hi->scsi_id[i]->node_id = node_id;
-
-                               /*
-                                * Mark the device as validated, since it still exists on the bus
-                                */
-                               hi->scsi_id[i]->validated = 1;
-                               SBP2_DEBUG("sbp2: SBP-2 device re-validated, SCSI ID = %x", (unsigned int) i);
-
-                               /*
-                                * Reconnect to the sbp-2 device
-                                */
-                               if (sbp2_reconnect_device(hi, hi->scsi_id[i])) {
-
-                                       /*
-                                        * Ok, reconnect has failed. Perhaps we didn't reconnect fast enough. Try
-                                        * doing a regular login.
-                                        */
-                                       if (sbp2_login_device(hi, hi->scsi_id[i])) {
-
-                                               /*
-                                                * Login failed too... so, just mark him as unvalidated, so that he gets cleaned up
-                                                * later
-                                                */
-                                               SBP2_ERR("sbp2: sbp2_reconnect_device failed!");
-                                               hi->scsi_id[i]->validated = 0;
-                                       }
-                               }
-
-                               if (hi->scsi_id[i]->validated) {
-
-                                       /*
-                                        * Set max retries to something large on the device
-                                        */
-                                       sbp2_set_busy_timeout(hi, hi->scsi_id[i]);
-
-                                       /*
-                                        * Do a SBP-2 fetch agent reset
-                                        */
-                                       sbp2_agent_reset(hi, hi->scsi_id[i], 0);
-
-                                       /*
-                                        * Get the max speed and packet size that we can use
-                                        */
-                                       sbp2_max_speed_and_size(hi, hi->scsi_id[i]);
-
-                               }
-
-                               /*
-                                * Nothing more to do, since we found the device
-                                */
-                               return(0);
-
-                       }
-               }
-       }
-
-       /*
-        * This really is a "new" device plugged in. Let's allocate memory for our scsi id instance data
+        * This really is a "new" device plugged in. Let's allocate memory
+        * for our scsi id instance data.
         */
        scsi_id = (struct scsi_id_instance_data *)kmalloc(sizeof(struct scsi_id_instance_data),
                                                          GFP_KERNEL);
@@ -1292,509 +1096,195 @@ alloc_fail:
                        SBP2_DMA_FREE("logout ORB DMA");
                }
 
-               if (scsi_id->reconnect_orb) {
-                       pci_free_consistent(hi->host->pdev,
-                                       sizeof(struct sbp2_reconnect_orb),
-                                       scsi_id->reconnect_orb,
-                                       scsi_id->reconnect_orb_dma);
-                       SBP2_DMA_FREE("reconnect ORB DMA");
-               }
-
-               if (scsi_id->login_response) {
-                       pci_free_consistent(hi->host->pdev,
-                                       sizeof(struct sbp2_login_response),
-                                       scsi_id->login_response,
-                                       scsi_id->login_response_dma);
-                       SBP2_DMA_FREE("login FIFO DMA");
-               }
-
-               kfree(scsi_id);
-alloc_fail_first:
-               SBP2_ERR ("sbp2: Could not allocate memory for scsi_id");
-               return(-ENOMEM);
-       }
-       SBP2_DMA_ALLOC("consistent DMA region for login ORB");
-
-       /*
-        * Initialize some of the fields in this structure
-        */
-       scsi_id->node_id = node_id;
-       scsi_id->node_unique_id = node_unique_id;
-       scsi_id->validated = 1;
-       scsi_id->speed_code = SPEED_100;
-       scsi_id->max_payload_size = MAX_PAYLOAD_S100;
-
-       init_waitqueue_head(&scsi_id->sbp2_login_wait);
-
-       /* 
-        * Initialize structures needed for the command orb pool.
-        */
-       INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
-       INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
-       scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED;
-       scsi_id->sbp2_total_command_orbs = 0;
-
-       /*
-        * Make sure that we've gotten ahold of the sbp2 management agent address. Also figure out the
-        * command set being used (SCSI or RBC).
-        */
-       if (sbp2_parse_unit_directory(hi, scsi_id)) {
-               SBP2_ERR("sbp2: Error while parsing sbp2 unit directory");
-               hi->scsi_id[i]->validated = 0;
-               return(-EIO);
-       }
-
-       scsi_id->sbp2_total_command_orbs = SBP2_MAX_COMMAND_ORBS;
-
-       /* 
-        * Knock the total command orbs down if we are serializing I/O
-        */
-       if (serialize_io) {
-               scsi_id->sbp2_total_command_orbs = 2;   /* one extra for good measure */
-       }
-
-       /*
-        * Allocate some extra command orb structures for devices with 128KB limit
-        */
-       if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) {
-               scsi_id->sbp2_total_command_orbs *= 4;
-       } 
-
-       /*
-        * Create our command orb pool
-        */
-       if (sbp2util_create_command_orb_pool(scsi_id, hi)) {
-               SBP2_ERR("sbp2: sbp2util_create_command_orb_pool failed!");
-               hi->scsi_id[i]->validated = 0;
-               return (-ENOMEM);
-       }
-
-       /*
-        * Find an empty spot to stick our scsi id instance data. 
-        */
-       for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-               if (!hi->scsi_id[i]) {
-                       hi->scsi_id[i] = scsi_id;
-                       SBP2_DEBUG("sbp2: New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
-                       break;
-               }
-       }
-
-       /*
-        * Make sure we are not out of space
-        */
-       if (i >= SBP2SCSI_MAX_SCSI_IDS) {
-               SBP2_ERR("sbp2: No slots left for SBP-2 device");
-               hi->scsi_id[i]->validated = 0;
-               return(-EBUSY);
-       }
-
-       /*
-        * Login to the sbp-2 device
-        */
-       if (sbp2_login_device(hi, hi->scsi_id[i])) {
-
-               /*
-                * Login failed... so, just mark him as unvalidated, so that he gets cleaned up later
-                */
-               SBP2_ERR("sbp2: sbp2_login_device failed");
-               hi->scsi_id[i]->validated = 0;
-       }
-
-       if (hi->scsi_id[i]->validated) {
-
-               /*
-                * Set max retries to something large on the device
-                */
-               sbp2_set_busy_timeout(hi, hi->scsi_id[i]);
-
-               /*
-                * Do a SBP-2 fetch agent reset
-                */
-               sbp2_agent_reset(hi, hi->scsi_id[i], 0);
-
-               /*
-                * Get the max speed and packet size that we can use
-                */
-               sbp2_max_speed_and_size(hi, hi->scsi_id[i]);
-
-       }
-
-       return(0);
-}
-
-/*
- * This function tries to determine if a device is a valid SBP-2 device
- */
-static int sbp2_check_device(struct sbp2scsi_host_info *hi, int node_id)
-{
-       quadlet_t unit_spec_id_data = 0, unit_sw_ver_data = 0;
-       quadlet_t unit_directory_length, current_quadlet;
-       u64 unit_directory_addr, current_addr;
-       unsigned int i, length;
-
-       SBP2_DEBUG("sbp2: sbp2_check_device");
-
-       /*
-        * Let's try and read the unit spec id and unit sw ver to determine if this is an SBP2 device...
-        */
-
-       if (sbp2util_unit_directory(hi, LOCAL_BUS | node_id, &unit_directory_addr)) {
-               SBP2_DEBUG("sbp2: Error reading unit directory address - bad status");
-               return(-EIO);   
-       }
-
-       /*
-        * Read the size of the unit directory
-        */
-       if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, unit_directory_addr, 
-                                 &unit_directory_length)) {
-               SBP2_DEBUG("sbp2: Error reading root directory length - bad status");
-               return(-EIO);   
-       }
-
-       current_addr = unit_directory_addr;
-       length = be32_to_cpu(unit_directory_length) >> 16;
-
-       /*
-        * Now, step through the unit directory and look for the unit_spec_ID and the unit_sw_version
-        */
-       for (i=0; i < length; i++) {
-
-               current_addr += 4;
-
-               if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, current_addr, &current_quadlet)) {
-                       SBP2_DEBUG("sbp2: Error reading at address 0x%08x%08x - bad status", 
-                                  (unsigned int) ((current_addr) >> 32), (unsigned int) ((current_addr) & 0xffffffff));
-                       return(-EIO);   
-               }
-
-               /* 
-                * Check for unit_spec_ID tag 
-                */
-               if ((be32_to_cpu(current_quadlet) >> 24) == SBP2_UNIT_SPEC_ID_KEY) {
-                       unit_spec_id_data = current_quadlet;
-                       SBP2_DEBUG("sbp2: Node %x, unit spec id = %x", (LOCAL_BUS | node_id), 
-                                  (unsigned int) be32_to_cpu(unit_spec_id_data));
-               }
-
-               /* 
-                * Check for unit_sw_version tag 
-                */
-               if ((be32_to_cpu(current_quadlet) >> 24) == SBP2_UNIT_SW_VERSION_KEY) {
-                       unit_sw_ver_data = current_quadlet;
-                       SBP2_DEBUG("sbp2: Node %x, unit sw version = %x", (LOCAL_BUS | node_id), 
-                                  (unsigned int) be32_to_cpu(unit_sw_ver_data));
-               }
-       }
-
-       /*
-        * Validate unit spec id and unit sw ver to see if this is an SBP-2 device
-        */
-       if ((be32_to_cpu(unit_spec_id_data) != SBP2_UNIT_SPEC_ID_ENTRY) ||
-           (be32_to_cpu(unit_sw_ver_data) != SBP2_SW_VERSION_ENTRY)) {
-
-               /*
-                * Not an sbp2 device
-                */
-               return(-ENXIO);
-       }
-
-       /*
-        * This device is a valid SBP-2 device
-        */
-       SBP2_INFO("sbp2: Node 0x%04x, Found SBP-2 device", (LOCAL_BUS | node_id));
-       return(0);
-}
-
-/*
- * This function removes (cleans-up after) any unvalidated sbp2 devices
- */
-static void sbp2_remove_unvalidated_devices(struct sbp2scsi_host_info *hi)
-{
-       int i;
-
-       /*
-        * Loop through and free any unvalidated scsi id instance data structures
-        */
-       for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-               if (hi->scsi_id[i]) {
-                       if (!hi->scsi_id[i]->validated) {
-
-                               /*
-                                * Complete any pending commands with selection timeout
-                                */
-                               sbp2scsi_complete_all_commands(hi, hi->scsi_id[i], DID_NO_CONNECT);
-                               
-                               /* 
-                                * Clean up any other structures
-                                */
-                               if (hi->scsi_id[i]->sbp2_total_command_orbs) {
-                                       sbp2util_remove_command_orb_pool(hi->scsi_id[i], hi);
-                               }
-                               if (hi->scsi_id[i]->login_response) {
-                                       pci_free_consistent(hi->host->pdev,
-                                                           sizeof(struct sbp2_login_response),
-                                                           hi->scsi_id[i]->login_response,
-                                                           hi->scsi_id[i]->login_response_dma);
-                                       SBP2_DMA_FREE("single login FIFO");
-                               }
-
-                               if (hi->scsi_id[i]->login_orb) {
-                                       pci_free_consistent(hi->host->pdev,
-                                                           sizeof(struct sbp2_login_orb),
-                                                           hi->scsi_id[i]->login_orb,
-                                                           hi->scsi_id[i]->login_orb_dma);
-                                       SBP2_DMA_FREE("single login ORB");
-                               }
-
-                               if (hi->scsi_id[i]->reconnect_orb) {
-                                       pci_free_consistent(hi->host->pdev,
-                                                           sizeof(struct sbp2_reconnect_orb),
-                                                           hi->scsi_id[i]->reconnect_orb,
-                                                           hi->scsi_id[i]->reconnect_orb_dma);
-                                       SBP2_DMA_FREE("single reconnect orb");
-                               }
-
-                               if (hi->scsi_id[i]->logout_orb) {
-                                       pci_free_consistent(hi->host->pdev,
-                                                           sizeof(struct sbp2_logout_orb),
-                                                           hi->scsi_id[i]->logout_orb,
-                                                           hi->scsi_id[i]->reconnect_orb_dma);
-                                       SBP2_DMA_FREE("single logout orb");
-                               }
-
-                               kfree(hi->scsi_id[i]);
-                               hi->scsi_id[i] = NULL;
-                               SBP2_DEBUG("sbp2: Unvalidated SBP-2 device removed, SCSI ID = %x", (unsigned int) i);
-                       }
-               }
-       }
-
-       return;
-}
-
-/*
- * This function is our reset handler. It is run out of a thread, since we get 
- * notified of a bus reset from a bh (or interrupt).
- */
-static void sbp2_bus_reset_handler(void *context)
-{
-       struct sbp2scsi_host_info *hi = context;
-       quadlet_t signature_data;
-       int i;
-       unsigned long flags;
-       struct scsi_id_instance_data *scsi_id;
-
-       SBP2_DEBUG("sbp2: sbp2_bus_reset_handler");
-
-       /*
-        * TODO. Check and keep track of generation number of all requests, in case a
-        * bus reset occurs while trying to find and login to SBP-2 devices.
-        */
-
-       /*
-        * First thing to do. Invalidate all SBP-2 devices. This is needed so that
-        * we stop sending down I/O requests to the device, and also so that we can
-        * figure out which devices have disappeared after a bus reset.
-        */
-       for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-               if (hi->scsi_id[i]) {
-                       hi->scsi_id[i]->validated = 0;
+               if (scsi_id->reconnect_orb) {
+                       pci_free_consistent(hi->host->pdev,
+                                       sizeof(struct sbp2_reconnect_orb),
+                                       scsi_id->reconnect_orb,
+                                       scsi_id->reconnect_orb_dma);
+                       SBP2_DMA_FREE("reconnect ORB DMA");
+               }
+
+               if (scsi_id->login_response) {
+                       pci_free_consistent(hi->host->pdev,
+                                       sizeof(struct sbp2_login_response),
+                                       scsi_id->login_response,
+                                       scsi_id->login_response_dma);
+                       SBP2_DMA_FREE("login FIFO DMA");
                }
+
+               kfree(scsi_id);
+alloc_fail_first:
+               SBP2_ERR ("sbp2: Could not allocate memory for scsi_id");
+               return(-ENOMEM);
        }
+       SBP2_DMA_ALLOC("consistent DMA region for login ORB");
 
        /*
-        * Give the sbp2 devices a little time to recover after the bus reset
+        * Initialize some of the fields in this structure
         */
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(HZ/2);         /* 1/2 second delay */
+       scsi_id->ne = ne;
+       scsi_id->ud = ud;
+       scsi_id->speed_code = SPEED_100;
+       scsi_id->max_payload_size = MAX_PAYLOAD_S100;
+       ud->driver_data = scsi_id;
 
-       /*
-        * Spit out what we know from the host
+       init_waitqueue_head(&scsi_id->sbp2_login_wait);
+
+       /* 
+        * Initialize structures needed for the command orb pool.
         */
-       SBP2_DEBUG("host: node_count = %x", (unsigned int) hi->host->node_count);
-       SBP2_DEBUG("host: selfid_count = %x", (unsigned int) hi->host->selfid_count);
-       SBP2_DEBUG("host: node_id = %x", (unsigned int) hi->host->node_id);
-       SBP2_DEBUG("host: irm_id = %x", (unsigned int) hi->host->irm_id);
-       SBP2_DEBUG("host: busmgr_id = %x", (unsigned int) hi->host->busmgr_id);
-       SBP2_DEBUG("host: is_root = %x", (unsigned int) hi->host->is_root);
-       SBP2_DEBUG("host: is_cycmst = %x", (unsigned int) hi->host->is_cycmst);
-       SBP2_DEBUG("host: is_irm = %x", (unsigned int) hi->host->is_irm);
-       SBP2_DEBUG("host: is_busmgr = %x", (unsigned int) hi->host->is_busmgr);
+       INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
+       INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
+       scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED;
+       scsi_id->sbp2_total_command_orbs = 0;
 
        /*
-        * Let's try and figure out which devices out there are SBP-2 devices! Loop through all 
-        * nodes out there.
+        * Make sure that we've gotten ahold of the sbp2 management agent
+        * address. Also figure out the command set being used (SCSI or
+        * RBC).
         */
-       for (i=0; i<hi->host->node_count; i++) {
-
-               /*
-                * Don't read from ourselves!
-                */
-               if (i != ((hi->host->node_id) & NODE_MASK)) {
-
-                       /*
-                        * Try and send a request for a config rom signature. This is expected to fail for
-                        * some nodes, as they might be repeater phys or not be initialized.
-                        */
-                       if (!sbp2util_read_quadlet(hi, LOCAL_BUS | i, CONFIG_ROM_SIGNATURE_ADDRESS, &signature_data)) {
+       sbp2_parse_unit_directory(scsi_id);
 
-                               if (be32_to_cpu(signature_data) == IEEE1394_CONFIG_ROM_SIGNATURE) {
-
-                                       /*
-                                        * Hey, we've got a valid responding IEEE1394 node. Need to now see if it's an SBP-2 device
-                                        */
-                                       if (!sbp2_check_device(hi, i)) {
+       scsi_id->sbp2_total_command_orbs = SBP2_MAX_COMMAND_ORBS;
 
-                                               /*
-                                                * Found an SBP-2 device. Now, actually start the device.
-                                                */
-                                               sbp2_start_device(hi, i);
-                                       }
-                               }
-                       }
-               }
+       /* 
+        * Knock the total command orbs down if we are serializing I/O
+        */
+       if (serialize_io) {
+               scsi_id->sbp2_total_command_orbs = 2;   /* one extra for good measure */
        }
 
        /*
-        * This code needs protection
+        * Allocate some extra command orb structures for devices with
+        * 128KB limit.
         */
-       sbp2_spin_lock(&hi->sbp2_command_lock, flags);
+       if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) {
+               scsi_id->sbp2_total_command_orbs *= 4;
+       } 
 
        /*
-        * Ok, we've discovered and re-validated all SBP-2 devices out there. Let's remove structures of all
-        * devices not re-validated (meaning they've been removed).
+        * Find an empty spot to stick our scsi id instance data. 
         */
-       sbp2_remove_unvalidated_devices(hi);
+       for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
+               if (!hi->scsi_id[i]) {
+                       hi->scsi_id[i] = scsi_id;
+                       scsi_id->id = i;
+                       SBP2_DEBUG("sbp2: New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
+                       break;
+               }
+       }
 
        /*
-        * Complete any pending commands with busy (so they get retried) and remove them from our queue
+        * Create our command orb pool
         */
-       for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-               if (hi->scsi_id[i]) {
-                       sbp2scsi_complete_all_commands(hi, hi->scsi_id[i], DID_BUS_BUSY);
-               }
+       if (sbp2util_create_command_orb_pool(scsi_id, hi)) {
+               SBP2_ERR("sbp2: sbp2util_create_command_orb_pool failed!");
+               sbp2_remove_device(hi, scsi_id);
+               return -ENOMEM;
        }
 
        /*
-        * Now, note that the bus reset is complete (finally!)
+        * Make sure we are not out of space
         */
-       hi->bus_reset_in_progress = 0;
+       if (i == SBP2SCSI_MAX_SCSI_IDS) {
+               SBP2_ERR("sbp2: No slots left for SBP-2 device");
+               sbp2_remove_device(hi, scsi_id);
+               return -EBUSY;
+       }
 
        /*
-        * Deal with the initial scsi bus scan if needed (since we only now know if there are
-        * any sbp2 devices attached)
+        * Login to the sbp-2 device
         */
-       if (!no_bus_scan && !hi->initial_scsi_bus_scan_complete && hi->bus_scan_SCpnt) {
+       if (sbp2_login_device(hi, scsi_id)) {
 
-               hi->initial_scsi_bus_scan_complete = 1;                 
-               scsi_id = hi->scsi_id[hi->bus_scan_SCpnt->target];
-
-               /* 
-                * If the sbp2 device exists, then let's now execute the command.
-                * If not, then just complete it as a selection time-out. 
+               /*
+                * Login failed... so, just mark him as unvalidated, so
+                * that he gets cleaned up later.
                 */
-                if (scsi_id) {
-                       if (sbp2_send_command(hi, scsi_id, hi->bus_scan_SCpnt, hi->bus_scan_done)) {
-                               SBP2_ERR("sbp2: Error sending SCSI command");
-                               sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
-                                                         hi->bus_scan_SCpnt, hi->bus_scan_done);
-                       }
-               } else {
-                       void (*done)(Scsi_Cmnd *) = hi->bus_scan_done;
-                       hi->bus_scan_SCpnt->result = DID_NO_CONNECT << 16;
-                       done (hi->bus_scan_SCpnt);
-               }
+               SBP2_ERR("sbp2: sbp2_login_device failed");
+               sbp2_remove_device(hi, scsi_id);
+               return -EBUSY;
        }
 
-       sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+       /*
+        * Set max retries to something large on the device
+        */
+       sbp2_set_busy_timeout(hi, scsi_id);
+       
+       /*
+        * Do a SBP-2 fetch agent reset
+        */
+       sbp2_agent_reset(hi, scsi_id, 0);
+       
+       /*
+        * Get the max speed and packet size that we can use
+        */
+       sbp2_max_speed_and_size(hi, scsi_id);
 
-       return;
+       return 0;
 }
 
-
 /*
- * This is called from the host's bh when a bus reset is complete. We wake up our detection thread
- * to deal with the reset
+ * This function removes (cleans-up after) any unvalidated sbp2 devices
  */
-static void sbp2_host_reset(struct hpsb_host *host)
+static void sbp2_remove_device(struct sbp2scsi_host_info *hi, 
+                              struct scsi_id_instance_data *scsi_id)
 {
-       unsigned long flags;
-       struct sbp2scsi_host_info *hi;
-       int i;
-
-       SBP2_INFO("sbp2: IEEE-1394 bus reset");
-       sbp2_spin_lock(&sbp2_host_info_lock, flags);
-       hi = sbp2_find_host_info(host);
-
-       if (hi != NULL) {
-
-               /*
-                * Wake up our detection thread, only if it's not already handling a reset
-                */
-               if (!hi->bus_reset_in_progress) {
-
-                       /*
-                        * First thing to do. Invalidate all SBP-2 devices. This is needed so that
-                        * we stop sending down I/O requests to the device, and also so that we can
-                        * figure out which devices have disappeared after a bus reset.
-                        */
-                       for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-                               if (hi->scsi_id[i]) {
-                                       hi->scsi_id[i]->validated = 0;
-                               }
-                       }
+       /* Complete any pending commands with selection timeout */
+       sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT);
+                               
+       /* Clean up any other structures */
+       if (scsi_id->sbp2_total_command_orbs) {
+               sbp2util_remove_command_orb_pool(scsi_id, hi);
+       }
 
-                       hi->bus_reset_in_progress = 1;
+       if (scsi_id->login_response) {
+               pci_free_consistent(hi->host->pdev,
+                                   sizeof(struct sbp2_login_response),
+                                   scsi_id->login_response,
+                                   scsi_id->login_response_dma);
+               SBP2_DMA_FREE("single login FIFO");
+       }
 
-                       wake_up(&hi->sbp2_detection_wait);
-               }
+       if (scsi_id->login_orb) {
+               pci_free_consistent(hi->host->pdev,
+                                   sizeof(struct sbp2_login_orb),
+                                   scsi_id->login_orb,
+                                   scsi_id->login_orb_dma);
+               SBP2_DMA_FREE("single login ORB");
        }
-       sbp2_spin_unlock(&sbp2_host_info_lock, flags);
-       return;
-}
 
-/* XXX: How best to handle these with DMA interface? */
+       if (scsi_id->reconnect_orb) {
+               pci_free_consistent(hi->host->pdev,
+                                   sizeof(struct sbp2_reconnect_orb),
+                                   scsi_id->reconnect_orb,
+                                   scsi_id->reconnect_orb_dma);
+               SBP2_DMA_FREE("single reconnect orb");
+       }
 
-#if 0
-/*
- * This function deals with physical dma write requests (for adapters that do not support
- * physical dma in hardware).
- */
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, quadlet_t *data,
-                                    u64 addr, unsigned int length)
-{
+       if (scsi_id->logout_orb) {
+               pci_free_consistent(hi->host->pdev,
+                                   sizeof(struct sbp2_logout_orb),
+                                   scsi_id->logout_orb,
+                                   scsi_id->reconnect_orb_dma);
+               SBP2_DMA_FREE("single logout orb");
+       }
 
-       /*
-        * Manually put the data in the right place.
-        */
-       memcpy(bus_to_virt((u32)addr), data, length);
-       return(RCODE_COMPLETE);
+       SBP2_DEBUG("sbp2: Unvalidated SBP-2 device removed, SCSI ID = %d", 
+                  scsi_id->id);
+       hi->scsi_id[scsi_id->id] = NULL;
+       kfree(scsi_id);
 }
 
-/*
- * This function deals with physical dma read requests (for adapters that do not support
- * physical dma in hardware).
- */
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
-                                   u64 addr, unsigned int length)
-{
-
-       /*
-        * Grab data from memory and send a read response.
-        */
-       memcpy(data, bus_to_virt((u32)addr), length);
-       return(RCODE_COMPLETE);
-}
-#endif
+\f
 
 /**************************************
  * SBP-2 protocol related section
  **************************************/
 
 /*
- * This function is called in order to login to a particular SBP-2 device, after a bus reset
+ * This function is called in order to login to a particular SBP-2 device,
+ * after a bus reset.
  */
 static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) 
 {
@@ -1808,34 +1298,28 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
                return(-EIO);
        }
 
-       /*
-        * Set-up login ORB
-        */
-       scsi_id->login_orb->password_hi = 0;            /* Assume no password */
+       /* Set-up login ORB, assume no password */
+       scsi_id->login_orb->password_hi = 0; 
        scsi_id->login_orb->password_lo = 0;
        SBP2_DEBUG("sbp2: sbp2_login_device: password_hi/lo initialized");
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
-       scsi_id->login_orb->login_response_lo = cpu_to_le32(scsi_id->login_response_dma);
-       scsi_id->login_orb->login_response_hi = cpu_to_le32(ORB_SET_NODE_ID(hi->host->node_id));
-#else
+
        scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
        scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
-#endif
        SBP2_DEBUG("sbp2: sbp2_login_device: login_response_hi/lo initialized");
+
        scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(LOGIN_REQUEST);
        scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);   /* One second reconnect time */
        scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(1);   /* Exclusive access to device */
        scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);              /* Notify us of login complete */
        SBP2_DEBUG("sbp2: sbp2_login_device: lun_misc initialized");
-       scsi_id->login_orb->passwd_resp_lengths = ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
+
+       scsi_id->login_orb->passwd_resp_lengths =
+               ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
        SBP2_DEBUG("sbp2: sbp2_login_device: passwd_resp_lengths initialized");
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
-       scsi_id->login_orb->status_FIFO_lo = cpu_to_le32((u32)SBP2_STATUS_FIFO_ADDRESS_LO);
-       scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | cpu_to_le16(SBP2_STATUS_FIFO_ADDRESS_HI));
-#else
+
        scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
-       scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
-#endif
+       scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
+                                             SBP2_STATUS_FIFO_ADDRESS_HI);
        SBP2_DEBUG("sbp2: sbp2_login_device: status FIFO initialized");
 
        /*
@@ -1861,25 +1345,26 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
        sbp2util_cpu_to_be32_buffer(data, 8);
 
        SBP2_DEBUG("sbp2: sbp2_login_device: prepared to write");
-
-       hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, scsi_id->sbp2_management_agent_addr, data, 8);
+       hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
+       SBP2_DEBUG("sbp2: sbp2_login_device: written");
 
        /*
-        * Wait for login status... but, only if the device has not already logged-in (some devices are fast)
+        * Wait for login status... but, only if the device has not
+        * already logged-in (some devices are fast)
         */
 
-       SBP2_DEBUG("sbp2: sbp2_login_device: written");
        save_flags(flags);
        cli();
-       if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
-               interruptible_sleep_on_timeout(&scsi_id->sbp2_login_wait, 10*HZ);               /* 10 second timeout */
-       }
+       /* 10 second timeout */
+       if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma)
+               sleep_on_timeout(&scsi_id->sbp2_login_wait, 10*HZ);
        restore_flags(flags);
 
        SBP2_DEBUG("sbp2: sbp2_login_device: initial check");
 
        /*
-        * Match status to the login orb. If they do not match, it's probably because the login timed-out
+        * Match status to the login orb. If they do not match, it's
+        * probably because the login timed-out.
         */
        if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
                SBP2_ERR("sbp2: Error logging into SBP-2 device - login timed-out");
@@ -1900,17 +1385,21 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
        }
 
        /*
-        * Byte swap the login response, for use when reconnecting or logging out.
+        * Byte swap the login response, for use when reconnecting or
+        * logging out.
         */
        sbp2util_cpu_to_be32_buffer(scsi_id->login_response, sizeof(struct sbp2_login_response));
 
        /*
-        * Grab our command block agent address from the login response
+        * Grab our command block agent address from the login response.
         */
-       SBP2_DEBUG("sbp2: command_block_agent_hi = %x", (unsigned int)scsi_id->login_response->command_block_agent_hi);
-       SBP2_DEBUG("sbp2: command_block_agent_lo = %x", (unsigned int)scsi_id->login_response->command_block_agent_lo);
+       SBP2_DEBUG("sbp2: command_block_agent_hi = %x",
+                  (unsigned int)scsi_id->login_response->command_block_agent_hi);
+       SBP2_DEBUG("sbp2: command_block_agent_lo = %x",
+                  (unsigned int)scsi_id->login_response->command_block_agent_lo);
 
-       scsi_id->sbp2_command_block_agent_addr = ((u64)scsi_id->login_response->command_block_agent_hi) << 32;
+       scsi_id->sbp2_command_block_agent_addr =
+               ((u64)scsi_id->login_response->command_block_agent_hi) << 32;
        scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo);
        scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;
 
@@ -1921,8 +1410,8 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
 }
 
 /*
- * This function is called in order to logout from a particular SBP-2 device, usually called during driver
- * unload
+ * This function is called in order to logout from a particular SBP-2
+ * device, usually called during driver unload.
  */
 static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) 
 {
@@ -1937,17 +1426,17 @@ static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_inst
        scsi_id->logout_orb->reserved2 = 0x0;
        scsi_id->logout_orb->reserved3 = 0x0;
        scsi_id->logout_orb->reserved4 = 0x0;
+
        scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(LOGOUT_REQUEST);
        scsi_id->logout_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
-       scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);                /* Notify us when complete */
+
+       /* Notify us when complete */
+       scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
+
        scsi_id->logout_orb->reserved5 = 0x0;
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
-       scsi_id->logout_orb->status_FIFO_lo = cpu_to_le32((u32)SBP2_STATUS_FIFO_ADDRESS_LO);
-       scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | cpu_to_le16(SBP2_STATUS_FIFO_ADDRESS_HI));
-#else
        scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
-       scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
-#endif
+       scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
+                                              SBP2_STATUS_FIFO_ADDRESS_HI);
 
        /*
         * Byte swap ORB if necessary
@@ -1961,12 +1450,10 @@ static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_inst
        data[1] = scsi_id->logout_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, scsi_id->sbp2_management_agent_addr, data, 8);
+       hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
 
-       /*
-        * Wait for device to logout... 
-        */
-       interruptible_sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);          /* 1 second timeout */
+       /* Wait for device to logout...1 second. */
+       sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);
 
        SBP2_INFO("sbp2: Logged out of SBP-2 device");
 
@@ -1975,7 +1462,8 @@ static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_inst
 }
 
 /*
- * This function is called in order to reconnect to a particular SBP-2 device, after a bus reset
+ * This function is called in order to reconnect to a particular SBP-2
+ * device, after a bus reset.
  */
 static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) 
 {
@@ -1991,18 +1479,19 @@ static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_i
        scsi_id->reconnect_orb->reserved2 = 0x0;
        scsi_id->reconnect_orb->reserved3 = 0x0;
        scsi_id->reconnect_orb->reserved4 = 0x0;
+
        scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(RECONNECT_REQUEST);
-       scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
-       scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);             /* Notify us when complete */
+       scsi_id->reconnect_orb->login_ID_misc |=
+               ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
+
+       /* Notify us when complete */
+       scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
+
        scsi_id->reconnect_orb->reserved5 = 0x0;
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
-       scsi_id->reconnect_orb->status_FIFO_lo = cpu_to_le32((u32)SBP2_STATUS_FIFO_ADDRESS_LO);
-       scsi_id->reconnect_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | cpu_to_le16(SBP2_STATUS_FIFO_ADDRESS_HI));
-#else
        scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
-       scsi_id->reconnect_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
-#endif
-       
+       scsi_id->reconnect_orb->status_FIFO_hi =
+               (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
+
        /*
         * Byte swap ORB if necessary
         */
@@ -2020,20 +1509,22 @@ static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_i
        data[1] = scsi_id->reconnect_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, scsi_id->sbp2_management_agent_addr, data, 8);
+       hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
 
        /*
-        * Wait for reconnect status... but, only if the device has not already reconnected (some devices are fast)
+        * Wait for reconnect status... but, only if the device has not
+        * already reconnected (some devices are fast).
         */
        save_flags(flags);
        cli();
-       if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
-               interruptible_sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);          /* one second timeout */
-       }
+       /* One second timout */
+       if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma)
+               sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);
        restore_flags(flags);
 
        /*
-        * Match status to the reconnect orb. If they do not match, it's probably because the reconnect timed-out
+        * Match status to the reconnect orb. If they do not match, it's
+        * probably because the reconnect timed-out.
         */
        if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
                SBP2_ERR("sbp2: Error reconnecting to SBP-2 device - reconnect timed-out");
@@ -2058,7 +1549,8 @@ static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_i
 }
 
 /*
- * This function is called in order to set the busy timeout (number of retries to attempt) on the sbp2 device. 
+ * This function is called in order to set the busy timeout (number of
+ * retries to attempt) on the sbp2 device. 
  */
 static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
 {      
@@ -2071,7 +1563,7 @@ static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_i
         */
        data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
 
-       if (hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
+       if (hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
                SBP2_ERR("sbp2: sbp2_set_busy_timeout error");
        }
 
@@ -2079,158 +1571,100 @@ static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_i
 }
 
 /*
- * This function is called to parse sbp2 device's config rom unit directory. Used to determine
- * things like sbp2 management agent offset, and command set used (SCSI or RBC). 
+ * This function is called to parse sbp2 device's config rom unit
+ * directory. Used to determine things like sbp2 management agent offset,
+ * and command set used (SCSI or RBC). 
  */
-static int sbp2_parse_unit_directory(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
+static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id)
 {
-       quadlet_t unit_directory_length, unit_directory_data;
-       u64 unit_directory_addr;
-       u32 i;
+       struct unit_directory *ud;
+       int i;
 
        SBP2_DEBUG("sbp2: sbp2_parse_unit_directory");
 
-       if (sbp2util_unit_directory(hi, LOCAL_BUS | scsi_id->node_id, &unit_directory_addr)) {
-               SBP2_DEBUG("sbp2: Error reading unit directory address - bad status");
-               return(-EIO);   
-       }
-
-       /*
-        * Read the size of the unit directory
-        */
-       if (sbp2util_read_quadlet(hi, LOCAL_BUS | scsi_id->node_id, unit_directory_addr, 
-                                 &unit_directory_length)) {
-               SBP2_DEBUG("sbp2: Error reading unit directory length - bad status");
-               return(-EIO);   
-       }
-
-       unit_directory_length = ((be32_to_cpu(unit_directory_length)) >> 16);
-
-       /*
-        * Now, sweep through the unit directory looking for the management agent offset
-        * Give up if we hit any error or somehow miss it...
-        */
-       for (i=0; i<unit_directory_length; i++) {
-
-               if (sbp2util_read_quadlet(hi, LOCAL_BUS | scsi_id->node_id, unit_directory_addr + (i<<2) + 4, 
-                                         &unit_directory_data)) {
-                       SBP2_DEBUG("sbp2: Error reading unit directory - bad status");
-                       return(-EIO);
-               }
-
-               /* 
-                * Handle different fields in the unit directory, based on keys
-                */
-               unit_directory_data = be32_to_cpu(unit_directory_data);
-               switch (unit_directory_data >> 24) {
-                       
-                       case SBP2_CSR_OFFSET_KEY:
-
-                               /*
-                                * Save off the management agent address
-                                */
-                               scsi_id->sbp2_management_agent_addr = CONFIG_ROM_INITIAL_MEMORY_SPACE + 
-                                                                     ((unit_directory_data & 0x00ffffff) << 2);
-
-                               SBP2_DEBUG("sbp2: sbp2_management_agent_addr = %x", (unsigned int) scsi_id->sbp2_management_agent_addr);
-                               break;
-
-                       case SBP2_COMMAND_SET_SPEC_ID_KEY:
-
-                               /*
-                                * Command spec organization
-                                */
-                               scsi_id->sbp2_command_set_spec_id = unit_directory_data & 0xffffff;
-                               SBP2_DEBUG("sbp2: sbp2_command_set_spec_id = %x", (unsigned int) scsi_id->sbp2_command_set_spec_id);
-                               break;
-
-                       case SBP2_COMMAND_SET_KEY:
-
-                               /*
-                                * Command set used by sbp2 device
-                                */
-                               scsi_id->sbp2_command_set = unit_directory_data & 0xffffff;
-                               SBP2_DEBUG("sbp2: sbp2_command_set = %x", (unsigned int) scsi_id->sbp2_command_set);
-                               break;
-
-                       case SBP2_UNIT_CHARACTERISTICS_KEY:
-
-                               /*
-                                * Unit characterisitcs (orb related stuff that I'm not yet paying attention to)
-                                */
-                               scsi_id->sbp2_unit_characteristics = unit_directory_data & 0xffffff;
-                               SBP2_DEBUG("sbp2: sbp2_unit_characteristics = %x", (unsigned int) scsi_id->sbp2_unit_characteristics);
-                               break;
+       ud = scsi_id->ud;
 
-                       case SBP2_DEVICE_TYPE_AND_LUN_KEY:
+       /* Handle different fields in the unit directory, based on keys */
+       for (i = 0; i < ud->arb_count; i++) {
+               switch (ud->arb_keys[i]) {
+               case SBP2_CSR_OFFSET_KEY:
+                       /* Save off the management agent address */
+                       scsi_id->sbp2_management_agent_addr =
+                               CONFIG_ROM_INITIAL_MEMORY_SPACE + 
+                               (ud->arb_values[i] << 2);
 
-                               /*
-                                * Device type and lun (used for detemining type of sbp2 device)
-                                */
-                               scsi_id->sbp2_device_type_and_lun = unit_directory_data & 0xffffff;
-                               SBP2_DEBUG("sbp2: sbp2_device_type_and_lun = %x", (unsigned int) scsi_id->sbp2_device_type_and_lun);
-                               break;
-
-                       case SBP2_UNIT_SPEC_ID_KEY:
+                       SBP2_DEBUG("sbp2: sbp2_management_agent_addr = %x",
+                                  (unsigned int) scsi_id->sbp2_management_agent_addr);
+                       break;
 
-                               /*
-                                * Unit spec id (used for protocol detection)
-                                */
-                               scsi_id->sbp2_unit_spec_id = unit_directory_data & 0xffffff;
-                               SBP2_DEBUG("sbp2: sbp2_unit_spec_id = %x", (unsigned int) scsi_id->sbp2_unit_spec_id);
-                               break;
+               case SBP2_COMMAND_SET_SPEC_ID_KEY:
+                       /* Command spec organization */
+                       scsi_id->sbp2_command_set_spec_id = ud->arb_values[i];
+                       SBP2_DEBUG("sbp2: sbp2_command_set_spec_id = %x",
+                                  (unsigned int) scsi_id->sbp2_command_set_spec_id);
+                       break;
 
-                       case SBP2_UNIT_SW_VERSION_KEY:
+               case SBP2_COMMAND_SET_KEY:
+                       /* Command set used by sbp2 device */
+                       scsi_id->sbp2_command_set = ud->arb_values[i];
+                       SBP2_DEBUG("sbp2: sbp2_command_set = %x",
+                                  (unsigned int) scsi_id->sbp2_command_set);
+                       break;
 
-                               /*
-                                * Unit sw version (used for protocol detection) 
-                                */
-                               scsi_id->sbp2_unit_sw_version = unit_directory_data & 0xffffff;
-                               SBP2_DEBUG("sbp2: sbp2_unit_sw_version = %x", (unsigned int) scsi_id->sbp2_unit_sw_version);
-                               break;
+               case SBP2_UNIT_CHARACTERISTICS_KEY:
+                       /*
+                        * Unit characterisitcs (orb related stuff
+                        * that I'm not yet paying attention to)
+                        */
+                       scsi_id->sbp2_unit_characteristics = ud->arb_values[i];
+                       SBP2_DEBUG("sbp2: sbp2_unit_characteristics = %x",
+                                  (unsigned int) scsi_id->sbp2_unit_characteristics);
+                       break;
 
-                       case SBP2_FIRMWARE_REVISION_KEY:
+               case SBP2_DEVICE_TYPE_AND_LUN_KEY:
+                       /*
+                        * Device type and lun (used for
+                        * detemining type of sbp2 device)
+                        */
+                       scsi_id->sbp2_device_type_and_lun = ud->arb_values[i];
+                       SBP2_DEBUG("sbp2: sbp2_device_type_and_lun = %x",
+                                  (unsigned int) scsi_id->sbp2_device_type_and_lun);
+                       break;
 
-                               /*
-                                * Firmware revision (used to find broken devices). If the vendor id is 0xa0b8 
-                                * (Symbios vendor id), then we have a bridge with 128KB max transfer size limitation.
-                                */
-                               scsi_id->sbp2_firmware_revision = unit_directory_data & 0xffff00;
-                               if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) {
-                                       SBP2_WARN("sbp2: warning: Bridge chipset supports 128KB max transfer size");
-                               }
-                               break;
+               case SBP2_FIRMWARE_REVISION_KEY:
+                       /*
+                        * Firmware revision (used to find broken
+                        * devices). If the vendor id is 0xa0b8
+                        * (Symbios vendor id), then we have a
+                        * bridge with 128KB max transfer size
+                        * limitation.
+                        */
+                       scsi_id->sbp2_firmware_revision = ud->arb_values[i];
+                       if (scsi_id->sbp2_firmware_revision ==
+                           SBP2_128KB_BROKEN_FIRMWARE) {
+                               SBP2_WARN("sbp2: warning: Bridge chipset supports 128KB max transfer size");
+                       }
+                       break;
 
-                       default:
-                               break;
+               default:
+                       break;
                }
-
        }
-
-       return(0);
 }
 
 /*
- * This function is called in order to determine the max speed and packet size we can use in our ORBs. 
+ * This function is called in order to determine the max speed and packet
+ * size we can use in our ORBs. 
  */
 static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
 {
        u8 speed_code;
-       struct node_entry *ne;
+       unsigned int max_rec;
 
        SBP2_DEBUG("sbp2: sbp2_max_speed_and_size");
 
-       /* Get this nodes information */
-       ne = hpsb_nodeid_get_entry(hi->host->node_id);
-
-       if (!ne) {
-               HPSB_ERR("sbp2: Unknown device, using S100, payload 512 bytes");
-               scsi_id->speed_code = SPEED_100;
-               scsi_id->max_payload_size = MAX_PAYLOAD_S100;
-               return(0);
-       }
-
-       speed_code = ne->busopt.lnkspd;
+       speed_code = scsi_id->ne->busopt.lnkspd;
+       max_rec = scsi_id->ne->busopt.max_rec;
 
        /* Bump down our speed if there is a module parameter forcing us slower */
        if (speed_code > max_speed) {
@@ -2240,11 +1674,11 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id
 
        /* Support the devices max_rec and max speed. We choose a setting
         * that fits both values, since they may differ.  */
-       if (speed_code >= SPEED_400 && ne->busopt.max_rec >= MAX_REC_S400) {
+       if (speed_code >= SPEED_400 && max_rec >= MAX_REC_S400) {
                HPSB_INFO("sbp2: SBP-2 device max speed S400 and payload 2KB");
                scsi_id->speed_code = SPEED_400;
                scsi_id->max_payload_size = MAX_PAYLOAD_S400;
-       } else if (speed_code >= SPEED_200 && ne->busopt.max_rec >= MAX_REC_S200) {
+       } else if (speed_code >= SPEED_200 && max_rec >= MAX_REC_S200) {
                HPSB_INFO("sbp2: SBP-2 device max speed S200 and payload 1KB");
                scsi_id->speed_code = SPEED_200;
                scsi_id->max_payload_size = MAX_PAYLOAD_S200;
@@ -2269,9 +1703,11 @@ static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instan
        /*
         * Ok, let's write to the target's management agent register
         */
-       agent_reset_request_packet = sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->node_id,
-                                                                           scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET,
-                                                                           0, ntohl(SBP2_AGENT_RESET_DATA));
+       agent_reset_request_packet =
+               sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->ne->nodeid,
+                                                      scsi_id->sbp2_command_block_agent_addr +
+                                                      SBP2_AGENT_RESET_OFFSET,
+                                                      0, ntohl(SBP2_AGENT_RESET_DATA));
 
        if (!agent_reset_request_packet) {
                SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
@@ -2299,8 +1735,8 @@ static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instan
 }
 
 /*
- * This function is called to create the actual command orb and s/g list out of the 
- * scsi command itself. 
+ * This function is called to create the actual command orb and s/g list
+ * out of the scsi command itself.
  */
 static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi, 
                                   struct scsi_id_instance_data *scsi_id,
@@ -2321,9 +1757,10 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
        /*
         * Set-up our command ORB..
         *
-        * NOTE: We're doing unrestricted page tables (s/g), as this is best performance 
-        * (at least with the devices I have). This means that data_size becomes the number 
-        * of s/g elements, and page_size should be zero (for unrestricted).
+        * NOTE: We're doing unrestricted page tables (s/g), as this is
+        * best performance (at least with the devices I have). This means
+        * that data_size becomes the number of s/g elements, and
+        * page_size should be zero (for unrestricted).
         */
        command_orb->next_ORB_hi = 0xffffffff;
        command_orb->next_ORB_lo = 0xffffffff;
@@ -2332,8 +1769,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
        command_orb->misc |= ORB_SET_NOTIFY(1);         /* Notify us when complete */
 
        /*
-        * Set-up our pagetable stuff... unfortunately, this has become messier than I'd like. Need to 
-        * clean this up a bit.   ;-)
+        * Set-up our pagetable stuff... unfortunately, this has become
+        * messier than I'd like. Need to clean this up a bit.   ;-)
         */
        if (sbp2scsi_direction_table[*scsi_cmd] == ORB_DIRECTION_NO_DATA_TRANSFER) {
 
@@ -2405,13 +1842,15 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
                                }
                        }
 
-                       command_orb->misc |= ORB_SET_DATA_SIZE(sg_count); /* number of page table (s/g) elements */
+                       /* Number of page table (s/g) elements */
+                       command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
 
                        /*
                         * Byte swap page tables if necessary
                         */
                        sbp2util_cpu_to_be32_buffer(scatter_gather_element, 
-                                                   (sizeof(struct sbp2_unrestricted_page_table)) * sg_count);
+                                                   (sizeof(struct sbp2_unrestricted_page_table)) *
+                                                   sg_count);
 
                }
 
@@ -2427,8 +1866,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
                SBP2_DMA_ALLOC("single bulk");
 
                /*
-                * Handle case where we get a command w/o s/g enabled (but check
-                * for transfers larger than 64K)
+                * Handle case where we get a command w/o s/g enabled (but
+                * check for transfers larger than 64K)
                 */
                if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
 
@@ -2438,7 +1877,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
                        command_orb->misc |= ORB_SET_DIRECTION(sbp2scsi_direction_table[*scsi_cmd]);
 
                        /*
-                        * Sanity, in case our direction table is not up-to-date
+                        * Sanity, in case our direction table is not
+                        * up-to-date
                         */
                        if (!scsi_request_bufflen) {
                                command_orb->data_descriptor_hi = 0xffffffff;
@@ -2448,15 +1888,19 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
 
                } else {
                        /*
-                        * Need to turn this into page tables, since the buffer is too large.
+                        * Need to turn this into page tables, since the
+                        * buffer is too large.
                         */                     
                        command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
                        command_orb->data_descriptor_lo = command->sge_dma;
-                       command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);   /* use page tables (s/g) */
+
+                       /* Use page tables (s/g) */
+                       command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
                        command_orb->misc |= ORB_SET_DIRECTION(sbp2scsi_direction_table[*scsi_cmd]);
 
                        /*
-                        * fill out our sbp-2 page tables (and split up the large buffer)
+                        * fill out our sbp-2 page tables (and split up
+                        * the large buffer)
                         */
                        sg_count = 0;
                        sg_len = scsi_request_bufflen;
@@ -2476,7 +1920,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
                                sg_count++;
                        }
 
-                       command_orb->misc |= ORB_SET_DATA_SIZE(sg_count); /* number of page table (s/g) elements */
+                       /* Number of page table (s/g) elements */
+                       command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
 
                        /*
                         * Byte swap page tables if necessary
@@ -2524,11 +1969,12 @@ static int sbp2_link_orb_command(struct sbp2scsi_host_info *hi, struct scsi_id_i
                /*
                 * Ok, let's write to the target's management agent register
                 */
-               if (!hi->bus_reset_in_progress) {
+               if (hpsb_node_entry_valid(scsi_id->ne)) {
 
-                       command_request_packet = sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->node_id,
-                                                                                       scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET,
-                                                                                       8, 0);
+                       command_request_packet =
+                               sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->ne->nodeid,
+                                                               scsi_id->sbp2_command_block_agent_addr +
+                                                               SBP2_ORB_POINTER_OFFSET, 8, 0);
                
                        if (!command_request_packet) {
                                SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
@@ -2561,16 +2007,19 @@ static int sbp2_link_orb_command(struct sbp2scsi_host_info *hi, struct scsi_id_i
                 * modifying these next orb pointers, as they are accessed
                 * both by the sbp2 device and us.
                 */
-               scsi_id->last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma);
-               scsi_id->last_orb->next_ORB_hi = 0x0;   /* Tells hardware that this pointer is valid */
-               
+               scsi_id->last_orb->next_ORB_lo =
+                       cpu_to_be32(command->command_orb_dma);
+               /* Tells hardware that this pointer is valid */
+               scsi_id->last_orb->next_ORB_hi = 0x0;
+
                /*
-                * Only ring the doorbell if we need to (first parts of linked orbs don't need this)
+                * Only ring the doorbell if we need to (first parts of
+                * linked orbs don't need this).
                 */
-               if (!command->linked && !hi->bus_reset_in_progress) {
+               if (!command->linked && hpsb_node_entry_valid(scsi_id->ne)) {
 
                        command_request_packet = sbp2util_allocate_write_request_packet(hi,
-                               LOCAL_BUS | scsi_id->node_id,
+                               LOCAL_BUS | scsi_id->ne->nodeid,
                                scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET,
                                0, cpu_to_be32(command->command_orb_dma));
        
@@ -2610,8 +2059,8 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
        SBP2_DEBUG("sbp2: SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
 
        /*
-        * Check for broken devices that can't handle greater than 128K transfers, and deal with them in a 
-        * hacked ugly way.
+        * Check for broken devices that can't handle greater than 128K
+        * transfers, and deal with them in a hacked ugly way.
         */
        if ((scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) && 
            (SCpnt->request_bufflen > SBP2_BROKEN_FIRMWARE_MAX_TRANSFER) && 
@@ -2620,7 +2069,8 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
            (*cmd == 0x28 || *cmd == 0x2a || *cmd == 0x0a || *cmd == 0x08)) {
 
                /*
-                * Darn, a broken device. We'll need to split up the transfer ourselves
+                * Darn, a broken device. We'll need to split up the
+                * transfer ourselves.
                 */
                sbp2_send_split_command(hi, scsi_id, SCpnt, done);
                return(0);
@@ -2637,13 +2087,12 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
        /*
         * Now actually fill in the comamnd orb and sbp2 s/g list
         */
-       sbp2_create_command_orb(hi, scsi_id, command, cmd, SCpnt->use_sg, 
-                               SCpnt->request_bufflen, SCpnt->request_buffer,
-                               scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-       
+       sbp2_create_command_orb(hi, scsi_id, command, cmd, SCpnt->use_sg,
+                       SCpnt->request_bufflen, SCpnt->request_buffer,
+                       scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); 
        /*
-        * Update our cdb if necessary (to handle sbp2 RBC command set differences).
-        * This is where the command set hacks go!   =)
+        * Update our cdb if necessary (to handle sbp2 RBC command set
+        * differences).  This is where the command set hacks go!   =)
         */
        if ((device_type == TYPE_DISK) ||
            (device_type == TYPE_SDAD) ||
@@ -2665,7 +2114,8 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
 }
 
 /*
- * This function is called for broken sbp2 device, where we have to break up large transfers. 
+ * This function is called for broken sbp2 device, where we have to break
+ * up large transfers.
  */
 static int sbp2_send_split_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
                                   Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
@@ -2779,8 +2229,8 @@ static int sbp2_send_split_command(struct sbp2scsi_host_info *hi, struct scsi_id
 }
 
 /*
- * This function deals with command set differences between Linux scsi command set and sbp2 RBC
- * command set.
+ * This function deals with command set differences between Linux scsi
+ * command set and sbp2 RBC command set.
  */
 static void sbp2_check_sbp2_command(unchar *cmd)
 {
@@ -3001,9 +2451,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
         */
        for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
                if (hi->scsi_id[i]) {
-                       if (hi->scsi_id[i]->node_id == (nodeid & NODE_MASK)) {
+                       if ((hi->scsi_id[i]->ne->nodeid & NODE_MASK) == (nodeid & NODE_MASK)) {
                                scsi_id = hi->scsi_id[i];
-                               SBP2_DEBUG("sbp2: SBP-2 status write from node %x", scsi_id->node_id);
+                               SBP2_DEBUG("sbp2: SBP-2 status write from node %x", scsi_id->ne->nodeid);
                                break;
                        }
                }
@@ -3089,6 +2539,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
        return(RCODE_COMPLETE);
 }
 
+\f
 
 /**************************************
  * SCSI interface related section
@@ -3121,18 +2572,8 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        scsi_id = hi->scsi_id[SCpnt->target];
 
        /*
-        * Save off the command if this is the initial bus scan... so that we can
-        * complete it after we find all our sbp2 devices on the 1394 bus
-        */
-       if (!no_bus_scan && !hi->initial_scsi_bus_scan_complete) {
-               hi->bus_scan_SCpnt = SCpnt;
-               hi->bus_scan_done = done;
-               return(0);
-       }
-
-       /*
-        * If scsi_id is null, it means there is no device in this slot, so we should return 
-        * selection timeout.
+        * If scsi_id is null, it means there is no device in this slot,
+        * so we should return selection timeout.
         */
        if (!scsi_id) {
                SCpnt->result = DID_NO_CONNECT << 16;
@@ -3141,7 +2582,8 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        }
 
        /*
-        * Until we handle multiple luns, just return selection time-out to any IO directed at non-zero LUNs
+        * Until we handle multiple luns, just return selection time-out
+        * to any IO directed at non-zero LUNs
         */
        if (SCpnt->lun) {
                SCpnt->result = DID_NO_CONNECT << 16;
@@ -3150,7 +2592,8 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        }
 
        /*
-        * Check for request sense command, and handle it here (autorequest sense)
+        * Check for request sense command, and handle it here
+        * (autorequest sense)
         */
        if (SCpnt->cmnd[0] == REQUEST_SENSE) {
                SBP2_DEBUG("sbp2: REQUEST_SENSE");
@@ -3161,9 +2604,10 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        }
 
        /*
-        * Check to see if there is a command in progress and just return busy (to be queued later)
+        * Check to see if there is a command in progress and just return
+        * busy (to be queued later)
         */
-       if (hi->bus_reset_in_progress) {
+       if (!hpsb_node_entry_valid(scsi_id->ne)) {
                SBP2_ERR("sbp2: Bus reset in progress - rejecting command");
                SCpnt->result = DID_BUS_BUSY << 16;
                done (SCpnt);
@@ -3184,9 +2628,11 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 }
 
 /*
- * This function is called in order to complete all outstanding SBP-2 commands (in case of resets, etc.). 
+ * This function is called in order to complete all outstanding SBP-2
+ * commands (in case of resets, etc.).
  */
-static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, 
+static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi,
+                                          struct scsi_id_instance_data *scsi_id, 
                                           u32 status)
 {
        struct list_head *lh;
@@ -3210,7 +2656,7 @@ static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct
 }
 
 /*
- * This function is called in order to complete a regular SBP-2 command. 
+ * This function is called in order to complete a regular SBP-2 command.
  */
 static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status,
                                      Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
@@ -3226,10 +2672,11 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
        }
 
        /*
-        * If a bus reset is in progress and there was an error, don't complete the command,
-        * just let it get retried at the end of the bus reset.
+        * If a bus reset is in progress and there was an error, don't
+        * complete the command, just let it get retried at the end of the
+        * bus reset.
         */
-       if ((hi->bus_reset_in_progress) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+       if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
                SBP2_ERR("sbp2: Bus reset in progress - retry command later");
                return;
        }
@@ -3283,9 +2730,10 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
        }
 
        /*
-        * One more quick hack (not enabled by default). Some sbp2 devices do not support 
-        * mode sense. Turn-on this hack to allow the device to pass the sd driver's 
-        * write-protect test (so that you can mount the device rw).
+        * One more quick hack (not enabled by default). Some sbp2 devices
+        * do not support mode sense. Turn-on this hack to allow the
+        * device to pass the sd driver's write-protect test (so that you
+        * can mount the device rw).
         */
        if (mode_sense_hack && SCpnt->result != DID_OK && SCpnt->cmnd[0] == MODE_SENSE) {
                SBP2_INFO("sbp2: Returning success to mode sense command");
@@ -3295,17 +2743,18 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
        }
 
        /*
-        * If a bus reset is in progress and there was an error, complete the command
-        * as busy so that it will get retried.
+        * If a bus reset is in progress and there was an error, complete
+        * the command as busy so that it will get retried.
         */
-       if ((hi->bus_reset_in_progress) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+       if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
                SBP2_ERR("sbp2: Completing command with busy (bus reset)");
                SCpnt->result = DID_BUS_BUSY << 16;
        }
 
        /*
-        * If a unit attention occurs, return busy status so it gets retried... it could have happened because
-        * of a 1394 bus reset or hot-plug...
+        * If a unit attention occurs, return busy status so it gets
+        * retried... it could have happened because of a 1394 bus reset
+        * or hot-plug...
         */
        if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) {
                SBP2_INFO("sbp2: UNIT ATTENTION - return busy");
@@ -3321,8 +2770,8 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
 }
 
 /*
- * Called by scsi stack when something has really gone wrong.
- * Usually called when a command has timed-out for some reason. 
+ * Called by scsi stack when something has really gone wrong.  Usually
+ * called when a command has timed-out for some reason.
  */
 static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) 
 {
@@ -3336,8 +2785,9 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
        if (scsi_id) {
 
                /*
-                * Right now, just return any matching command structures to the free pool (there may
-                * be more than one because of broken up/linked commands).
+                * Right now, just return any matching command structures
+                * to the free pool (there may be more than one because of
+                * broken up/linked commands).
                 */
                sbp2_spin_lock(&hi->sbp2_command_lock, flags);
                do {
@@ -3445,10 +2895,6 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt)
                global_scsi_tpnt->use_clustering = DISABLE_CLUSTERING;
        }
 
-       if (no_bus_scan) {
-               SBP2_ERR("sbp2: Initial scsi bus scan deferred (no_bus_scan = 1)");
-       }
-
        if (mode_sense_hack) {
                SBP2_ERR("sbp2: Mode sense emulation enabled (mode_sense_hack = 1)");
        }
@@ -3457,21 +2903,19 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt)
 
        if (!sbp2_host_count) {
                SBP2_ERR("sbp2: Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2...");
-               if (sbp2_hl_handle) {
-                       hpsb_unregister_highlevel(sbp2_hl_handle);
-                       sbp2_hl_handle = NULL;
-               }
+               sbp2_cleanup();
        }
 
        /*
-        * Since we are returning this count, it means that sbp2 must be loaded "after" the 
-        * host adapter module...        
+        * Since we are returning this count, it means that sbp2 must be
+        * loaded "after" the host adapter module...
         */
        return(sbp2_host_count);
 }
 
 /*
- * This function is called from sbp2_add_host, and is where we register our scsi host
+ * This function is called from sbp2_add_host, and is where we register
+ * our scsi host
  */
 static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi)
 {
@@ -3488,7 +2932,8 @@ static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi)
                shpnt = scsi_register (global_scsi_tpnt, sizeof(void *));
 
                /*
-                * If successful, save off a context (to be used when SCSI commands are received)
+                * If successful, save off a context (to be used when SCSI
+                * commands are received)
                 */
                if (shpnt) {
                        shpnt->hostdata[0] = (unsigned long)hi;
index 9df0ecc354b3b933c3bb0495e304b9492bd185e8..c1fc8dd29fe36e7d9c1f3453da4efe07744d1ce2 100644 (file)
 #define ORB_DIRECTION_READ_FROM_MEDIA   0x1
 #define ORB_DIRECTION_NO_DATA_TRANSFER  0x2
 
-#define SPEED_S100                     0x0
-#define SPEED_S200                     0x1
-#define SPEED_S400                     0x2
-#define SPEED_S800                     0x3
-#define SPEED_S1600                    0x4
-#define SPEED_S3200                    0x5
-
 /* 2^(MAX_PAYLOAD+1) = Maximum data transfer length */
 #define MAX_PAYLOAD_S100               0x7
 #define MAX_PAYLOAD_S200               0x8
@@ -232,8 +225,8 @@ struct sbp2_status_block {
  * Unit spec id and sw version entry for SBP-2 devices
  */
 
-#define SBP2_UNIT_SPEC_ID_ENTRY                                        0x1200609e
-#define SBP2_SW_VERSION_ENTRY                                  0x13010483
+#define SBP2_UNIT_SPEC_ID_ENTRY                                        0x0000609e
+#define SBP2_SW_VERSION_ENTRY                                  0x00010483
 
 /*
  * Miscellaneous general config rom related defines
@@ -243,11 +236,8 @@ struct sbp2_status_block {
 
 #define CONFIG_ROM_BASE_ADDRESS                                        0xfffff0000400ULL
 #define CONFIG_ROM_ROOT_DIR_BASE                               0xfffff0000414ULL
-#define CONFIG_ROM_SIGNATURE_ADDRESS                           0xfffff0000404ULL
 #define CONFIG_ROM_UNIT_DIRECTORY_OFFSET                       0xfffff0000424ULL
 
-#define IEEE1394_CONFIG_ROM_SIGNATURE                          0x31333934
-
 #define SBP2_128KB_BROKEN_FIRMWARE                             0xa0b800
 #define SBP2_BROKEN_FIRMWARE_MAX_TRANSFER                      0x20000
 
@@ -350,6 +340,8 @@ struct sbp2_command_info {
  * Information needed on a per scsi id basis (one for each sbp2 device)
  */
 struct scsi_id_instance_data {
+       /* SCSI ID */
+       int id;
 
        /*
         * Various sbp2 specific structures
@@ -368,18 +360,15 @@ struct scsi_id_instance_data {
        /*
         * Stuff we need to know about the sbp2 device itself
         */
-       u64 node_unique_id;
        u64 sbp2_management_agent_addr;
        u64 sbp2_command_block_agent_addr;
-       u32 node_id;
        u32 speed_code;
        u32 max_payload_size;
 
        /*
         * Values pulled from the device's unit directory
         */
-       u32 sbp2_unit_spec_id;
-       u32 sbp2_unit_sw_version;
+       struct unit_directory *ud;
        u32 sbp2_command_set_spec_id;
        u32 sbp2_command_set;
        u32 sbp2_unit_characteristics;
@@ -391,12 +380,6 @@ struct scsi_id_instance_data {
         */
        wait_queue_head_t sbp2_login_wait;
 
-       /*
-        * Flag noting whether the sbp2 device is currently validated (for use during
-        * bus resets).
-        */
-       u32 validated;
-
        /* 
         * Pool of command orbs, so we can have more than overlapped command per id
         */
@@ -405,6 +388,8 @@ struct scsi_id_instance_data {
        struct list_head sbp2_command_orb_completed;
        u32 sbp2_total_command_orbs;
 
+       /* Node entry, as retrieved from NodeMgr entries */
+       struct node_entry *ne;
 };
 
 /*
@@ -424,22 +409,6 @@ struct sbp2scsi_host_info {
        spinlock_t sbp2_command_lock;
        spinlock_t sbp2_request_packet_lock;
 
-       /*
-        * Flag indicating if a bus reset (or device detection) is in progress
-        */
-       u32 bus_reset_in_progress;
-
-       /*
-        * We currently use a kernel thread for dealing with bus resets and sbp2
-        * device detection. We use this to wake up the thread when needed.
-        */
-       wait_queue_head_t sbp2_detection_wait;
-
-       /* 
-        * PID of sbp2 detection kernel thread 
-        */
-       int sbp2_detection_pid;
-
        /*
         * Lists keeping track of inuse/free sbp2_request_packets. These structures are
         * used for sending out sbp2 command and agent reset packets. We initially create
@@ -449,13 +418,6 @@ struct sbp2scsi_host_info {
        struct list_head sbp2_req_inuse;
        struct list_head sbp2_req_free;
 
-       /*
-        * Stuff to keep track of the initial scsi bus scan (so that we don't miss it)
-        */
-       u32 initial_scsi_bus_scan_complete;
-       Scsi_Cmnd *bus_scan_SCpnt;
-       void (*bus_scan_done)(Scsi_Cmnd *);
-
        /*
         * Here is the pool of request packets. All the hpsb packets (for 1394 bus transactions)
         * are allocated at init and simply re-initialized when needed.
@@ -476,9 +438,6 @@ struct sbp2scsi_host_info {
 /*
  * Various utility prototypes
  */
-static int sbp2util_read_quadlet(struct sbp2scsi_host_info *hi, nodeid_t node, u64 addr,
-                                quadlet_t *buffer);
-static int sbp2util_unit_directory(struct sbp2scsi_host_info *hi, nodeid_t node, u64 *addr);
 static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi);
 static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi);
 static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
@@ -500,23 +459,19 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
 /*
  * IEEE-1394 core driver related prototypes
  */
-static void sbp2_remove_unvalidated_devices(struct sbp2scsi_host_info *hi);
-static int sbp2_start_device(struct sbp2scsi_host_info *hi, int node_id);
-static int sbp2_check_device(struct sbp2scsi_host_info *hi, int node_id);
-static void sbp2_bus_reset_handler(void *context);
 static void sbp2_add_host(struct hpsb_host *host);
 static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
 static void sbp2_remove_host(struct hpsb_host *host);
-static void sbp2_host_reset(struct hpsb_host *host);
-static int sbp2_detection_thread(void *__sbp2);
 int sbp2_init(void);
 void sbp2_cleanup(void);
-#if 0
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, quadlet_t *data,
-                                    u64 addr, unsigned int length);
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
-                                   u64 addr, unsigned int length);
-#endif
+static int sbp2_probe(struct unit_directory *ud);
+static void sbp2_disconnect(struct unit_directory *ud);
+static void sbp2_update(struct unit_directory *ud);
+static int sbp2_start_device(struct sbp2scsi_host_info *hi, 
+                            struct unit_directory *ud);
+static void sbp2_remove_device(struct sbp2scsi_host_info *hi, 
+                              struct scsi_id_instance_data *scsi_id);
+
 /*
  * SBP-2 protocol related prototypes
  */
@@ -543,7 +498,7 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
 static void sbp2_check_sbp2_command(unchar *cmd);
 static void sbp2_check_sbp2_response(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, 
                                     Scsi_Cmnd *SCpnt);
-static int sbp2_parse_unit_directory(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
+static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id);
 static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
 static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
 
index 810d6ffb76593678cf15c252656c4602a6eb1fd9..d3df29b05d4c5bcfbbbfdd5d4ad9d7e205333116 100644 (file)
@@ -103,7 +103,7 @@ struct dma_iso_ctx {
        int ctxMatch;
        wait_queue_head_t waitq;
         spinlock_t lock;
-       unsigned int syt_offset;
+    unsigned int syt_offset;
        int flags;
 };
 
@@ -488,24 +488,27 @@ static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
        int i;
 
        /* the first descriptor will read only 4 bytes */
-       ir_prg[0].control = (0x280C << 16) | 4;
+       ir_prg[0].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+               DMA_CTL_BRANCH | 4;
 
        /* set the sync flag */
        if (flags & VIDEO1394_SYNC_FRAMES)
-               ir_prg[0].control |= 0x00030000;
+               ir_prg[0].control |= DMA_CTL_WAIT;
 
        ir_prg[0].address = kvirt_to_bus(buf);
        ir_prg[0].branchAddress =  (virt_to_bus(&(ir_prg[1].control)) 
                                    & 0xfffffff0) | 0x1;
 
        /* the second descriptor will read PAGE_SIZE-4 bytes */
-       ir_prg[1].control = (0x280C << 16) | (PAGE_SIZE-4);
+       ir_prg[1].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+               DMA_CTL_BRANCH | (PAGE_SIZE-4);
        ir_prg[1].address = kvirt_to_bus(buf+4);
        ir_prg[1].branchAddress =  (virt_to_bus(&(ir_prg[2].control)) 
                                    & 0xfffffff0) | 0x1;
        
        for (i=2;i<d->nb_cmd-1;i++) {
-               ir_prg[i].control = (0x280C << 16) | PAGE_SIZE;
+               ir_prg[i].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+                       DMA_CTL_BRANCH | PAGE_SIZE;
                ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
 
                ir_prg[i].branchAddress =  
@@ -514,7 +517,8 @@ static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
        }
 
        /* the last descriptor will generate an interrupt */
-       ir_prg[i].control = (0x283C << 16) | d->left_size;
+       ir_prg[i].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+               DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size;
        ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
 }
        
@@ -691,13 +695,14 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
        d->last_used_cmd[n] = d->nb_cmd - 1;
        for (i=0;i<d->nb_cmd;i++) {
                                 
-               it_prg[i].begin.control = OUTPUT_MORE_IMMEDIATE | 8 ;
+               it_prg[i].begin.control = DMA_CTL_OUTPUT_MORE |
+                       DMA_CTL_IMMEDIATE | 8 ;
                it_prg[i].begin.address = 0;
                
                it_prg[i].begin.status = 0;
                
                it_prg[i].data[0] = 
-                       (DMA_SPEED_100 << 16) 
+                       (SPEED_100 << 16) 
                        | (/* tag */ 1 << 14)
                        | (d->channel << 8) 
                        | (TCODE_ISO_DATA << 4);
@@ -706,7 +711,7 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
                it_prg[i].data[2] = 0;
                it_prg[i].data[3] = 0;
                
-               it_prg[i].end.control = 0x100c0000;
+               it_prg[i].end.control = DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
                it_prg[i].end.address =
                        kvirt_to_bus(buf+i*d->packet_size);
 
@@ -721,7 +726,8 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
                }
                else {
                        /* the last prg generates an interrupt */
-                       it_prg[i].end.control |= 0x08300000 | d->left_size;
+                       it_prg[i].end.control |= DMA_CTL_UPDATE | 
+                               DMA_CTL_IRQ | d->left_size;
                        /* the last prg doesn't branch */
                        it_prg[i].begin.branchAddress = 0;
                        it_prg[i].end.branchAddress = 0;
@@ -761,7 +767,7 @@ static void initialize_dma_it_prg_var_packet_queue(
                        size = packet_sizes[i];
                }
                it_prg[i].data[1] = size << 16; 
-               it_prg[i].end.control = 0x100c0000;
+               it_prg[i].end.control = DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
 
                if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
                        it_prg[i].end.control |= size;
@@ -773,7 +779,8 @@ static void initialize_dma_it_prg_var_packet_queue(
                                 & 0xfffffff0) | 0x3;
                } else {
                        /* the last prg generates an interrupt */
-                       it_prg[i].end.control |= 0x08300000 | size;
+                       it_prg[i].end.control |= DMA_CTL_UPDATE | 
+                               DMA_CTL_IRQ | size;
                        /* the last prg doesn't branch */
                        it_prg[i].begin.branchAddress = 0;
                        it_prg[i].end.branchAddress = 0;
@@ -1560,7 +1567,6 @@ static int video1394_init(struct ti_ohci *ohci)
 static void remove_card(struct video_card *video)
 {
        int i;
-       unsigned long flags;
 
        ohci1394_unregister_video(video->ohci, &video_tmpl);
 
@@ -1581,9 +1587,7 @@ static void remove_card(struct video_card *video)
                }
                kfree(video->it_context);
        }
-       spin_lock_irqsave(&video1394_cards_lock, flags);
        list_del(&video->list);
-       spin_unlock_irqrestore(&video1394_cards_lock, flags);
 
        kfree(video);
 }
@@ -1607,7 +1611,7 @@ static void video1394_remove_host (struct hpsb_host *host)
                        p = list_entry(lh, struct video_card, list);
                        if (p ->ohci == ohci) {
                                remove_card(p);
-                               return;
+                               break;
                        }
                }
        }
index 19c30390d0894c8f3393499f2349f8048a00987c..01bc86ed9aae2628444657fd99c1705cc038b20c 100644 (file)
@@ -140,7 +140,7 @@ static MD_LIST_HEAD(all_mddevs);
  */
 dev_mapping_t mddev_map[MAX_MD_DEVS];
 
-void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data)
+void add_mddev_mapping(mddev_t * mddev, kdev_t dev, void *data)
 {
        unsigned int minor = MINOR(dev);
 
@@ -148,7 +148,7 @@ void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data)
                MD_BUG();
                return;
        }
-       if (mddev_map[minor].mddev != NULL) {
+       if (mddev_map[minor].mddev) {
                MD_BUG();
                return;
        }
@@ -156,7 +156,7 @@ void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data)
        mddev_map[minor].data = data;
 }
 
-void del_mddev_mapping (mddev_t * mddev, kdev_t dev)
+void del_mddev_mapping(mddev_t * mddev, kdev_t dev)
 {
        unsigned int minor = MINOR(dev);
 
@@ -172,7 +172,7 @@ void del_mddev_mapping (mddev_t * mddev, kdev_t dev)
        mddev_map[minor].data = NULL;
 }
 
-static int md_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
+static int md_make_request(request_queue_t *q, int rw, struct buffer_head * bh)
 {
        mddev_t *mddev = kdev_to_mddev(bh->b_rdev);
 
@@ -184,7 +184,7 @@ static int md_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
        }
 }
 
-static mddev_t * alloc_mddev (kdev_t dev)
+static mddev_t * alloc_mddev(kdev_t dev)
 {
        mddev_t *mddev;
 
@@ -195,7 +195,7 @@ static mddev_t * alloc_mddev (kdev_t dev)
        mddev = (mddev_t *) kmalloc(sizeof(*mddev), GFP_KERNEL);
        if (!mddev)
                return NULL;
-               
+
        memset(mddev, 0, sizeof(*mddev));
 
        mddev->__minor = MINOR(dev);
@@ -245,7 +245,7 @@ mdk_rdev_t * find_rdev(mddev_t * mddev, kdev_t dev)
 
 static MD_LIST_HEAD(device_names);
 
-char * partition_name (kdev_t dev)
+char * partition_name(kdev_t dev)
 {
        struct gendisk *hd;
        static char nomem [] = "<nomem>";
@@ -282,7 +282,7 @@ char * partition_name (kdev_t dev)
        return dname->name;
 }
 
-static unsigned int calc_dev_sboffset (kdev_t dev, mddev_t *mddev,
+static unsigned int calc_dev_sboffset(kdev_t dev, mddev_t *mddev,
                                                int persistent)
 {
        unsigned int size = 0;
@@ -294,7 +294,7 @@ static unsigned int calc_dev_sboffset (kdev_t dev, mddev_t *mddev,
        return size;
 }
 
-static unsigned int calc_dev_size (kdev_t dev, mddev_t *mddev, int persistent)
+static unsigned int calc_dev_size(kdev_t dev, mddev_t *mddev, int persistent)
 {
        unsigned int size;
 
@@ -308,7 +308,7 @@ static unsigned int calc_dev_size (kdev_t dev, mddev_t *mddev, int persistent)
        return size;
 }
 
-static unsigned int zoned_raid_size (mddev_t *mddev)
+static unsigned int zoned_raid_size(mddev_t *mddev)
 {
        unsigned int mask;
        mdk_rdev_t * rdev;
@@ -338,7 +338,7 @@ static unsigned int zoned_raid_size (mddev_t *mddev)
  * provide data have to be able to deal with loss of individual
  * disks, so they do their checking themselves.
  */
-int md_check_ordering (mddev_t *mddev)
+int md_check_ordering(mddev_t *mddev)
 {
        int i, c;
        mdk_rdev_t *rdev;
@@ -349,8 +349,8 @@ int md_check_ordering (mddev_t *mddev)
         */
        ITERATE_RDEV(mddev,rdev,tmp) {
                if (rdev->faulty) {
-                       printk("md: md%d's device %s faulty, aborting.\n",
-                               mdidx(mddev), partition_name(rdev->dev));
+                       printk(KERN_ERR "md: md%d's device %s faulty, aborting.\n",
+                              mdidx(mddev), partition_name(rdev->dev));
                        goto abort;
                }
        }
@@ -364,7 +364,7 @@ int md_check_ordering (mddev_t *mddev)
                goto abort;
        }
        if (mddev->nb_dev != mddev->sb->raid_disks) {
-               printk("md: md%d, array needs %d disks, has %d, aborting.\n",
+               printk(KERN_ERR "md: md%d, array needs %d disks, has %d, aborting.\n",
                        mdidx(mddev), mddev->sb->raid_disks, mddev->nb_dev);
                goto abort;
        }
@@ -378,13 +378,13 @@ int md_check_ordering (mddev_t *mddev)
                                c++;
                }
                if (!c) {
-                       printk("md: md%d, missing disk #%d, aborting.\n",
-                               mdidx(mddev), i);
+                       printk(KERN_ERR "md: md%d, missing disk #%d, aborting.\n",
+                              mdidx(mddev), i);
                        goto abort;
                }
                if (c > 1) {
-                       printk("md: md%d, too many disks #%d, aborting.\n",
-                               mdidx(mddev), i);
+                       printk(KERN_ERR "md: md%d, too many disks #%d, aborting.\n",
+                              mdidx(mddev), i);
                        goto abort;
                }
        }
@@ -393,7 +393,7 @@ abort:
        return 1;
 }
 
-static void remove_descriptor (mdp_disk_t *disk, mdp_super_t *sb)
+static void remove_descriptor(mdp_disk_t *disk, mdp_super_t *sb)
 {
        if (disk_active(disk)) {
                sb->working_disks--;
@@ -426,7 +426,7 @@ static void remove_descriptor (mdp_disk_t *disk, mdp_super_t *sb)
 #define BAD_CSUM KERN_WARNING \
 "md: invalid superblock checksum on %s\n"
 
-static int alloc_array_sb (mddev_t * mddev)
+static int alloc_array_sb(mddev_t * mddev)
 {
        if (mddev->sb) {
                MD_BUG();
@@ -440,14 +440,14 @@ static int alloc_array_sb (mddev_t * mddev)
        return 0;
 }
 
-static int alloc_disk_sb (mdk_rdev_t * rdev)
+static int alloc_disk_sb(mdk_rdev_t * rdev)
 {
        if (rdev->sb)
                MD_BUG();
 
        rdev->sb = (mdp_super_t *) __get_free_page(GFP_KERNEL);
        if (!rdev->sb) {
-               printk (OUT_OF_MEM);
+               printk(OUT_OF_MEM);
                return -EINVAL;
        }
        md_clear_page(rdev->sb);
@@ -455,7 +455,7 @@ static int alloc_disk_sb (mdk_rdev_t * rdev)
        return 0;
 }
 
-static void free_disk_sb (mdk_rdev_t * rdev)
+static void free_disk_sb(mdk_rdev_t * rdev)
 {
        if (rdev->sb) {
                free_page((unsigned long) rdev->sb);
@@ -468,7 +468,7 @@ static void free_disk_sb (mdk_rdev_t * rdev)
        }
 }
 
-static int read_disk_sb (mdk_rdev_t * rdev)
+static int read_disk_sb(mdk_rdev_t * rdev)
 {
        int ret = -EINVAL;
        struct buffer_head *bh = NULL;
@@ -479,15 +479,14 @@ static int read_disk_sb (mdk_rdev_t * rdev)
        if (!rdev->sb) {
                MD_BUG();
                goto abort;
-       }       
-       
+       }
+
        /*
         * Calculate the position of the superblock,
         * it's at the end of the disk
         */
        sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1);
        rdev->sb_offset = sb_offset;
-       printk("(read) %s's sb offset: %ld", partition_name(dev), sb_offset);
        fsync_dev(dev);
        set_blocksize (dev, MD_SB_BYTES);
        bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
@@ -496,10 +495,10 @@ static int read_disk_sb (mdk_rdev_t * rdev)
                sb = (mdp_super_t *) bh->b_data;
                memcpy (rdev->sb, sb, MD_SB_BYTES);
        } else {
-               printk (NO_SB,partition_name(rdev->dev));
+               printk(NO_SB,partition_name(rdev->dev));
                goto abort;
        }
-       printk(" [events: %08lx]\n", (unsigned long)rdev->sb->events_lo);
+       printk(KERN_INFO " [events: %08lx]\n", (unsigned long)rdev->sb->events_lo);
        ret = 0;
 abort:
        if (bh)
@@ -507,7 +506,7 @@ abort:
        return ret;
 }
 
-static unsigned int calc_sb_csum (mdp_super_t * sb)
+static unsigned int calc_sb_csum(mdp_super_t * sb)
 {
        unsigned int disk_csum, csum;
 
@@ -522,7 +521,7 @@ static unsigned int calc_sb_csum (mdp_super_t * sb)
  * Check one RAID superblock for generic plausibility
  */
 
-static int check_disk_sb (mdk_rdev_t * rdev)
+static int check_disk_sb(mdk_rdev_t * rdev)
 {
        mdp_super_t *sb;
        int ret = -EINVAL;
@@ -534,13 +533,12 @@ static int check_disk_sb (mdk_rdev_t * rdev)
        }
 
        if (sb->md_magic != MD_SB_MAGIC) {
-               printk (BAD_MAGIC, partition_name(rdev->dev));
+               printk(BAD_MAGIC, partition_name(rdev->dev));
                goto abort;
        }
 
        if (sb->md_minor >= MAX_MD_DEVS) {
-               printk (BAD_MINOR, partition_name(rdev->dev),
-                                                       sb->md_minor);
+               printk(BAD_MINOR, partition_name(rdev->dev), sb->md_minor);
                goto abort;
        }
 
@@ -590,7 +588,7 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
 static MD_LIST_HEAD(all_raid_disks);
 static MD_LIST_HEAD(pending_raid_disks);
 
-static void bind_rdev_to_array (mdk_rdev_t * rdev, mddev_t * mddev)
+static void bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 {
        mdk_rdev_t *same_pdev;
 
@@ -603,16 +601,16 @@ static void bind_rdev_to_array (mdk_rdev_t * rdev, mddev_t * mddev)
                printk( KERN_WARNING
 "md%d: WARNING: %s appears to be on the same physical disk as %s. True\n"
 "     protection against single-disk failure might be compromised.\n",
-                       mdidx(mddev), partition_name(rdev->dev),
+                       mdidx(mddev), partition_name(rdev->dev),
                                partition_name(same_pdev->dev));
-               
+
        md_list_add(&rdev->same_set, &mddev->disks);
        rdev->mddev = mddev;
        mddev->nb_dev++;
-       printk("md: bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev);
+       printk(KERN_INFO "md: bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev);
 }
 
-static void unbind_rdev_from_array (mdk_rdev_t * rdev)
+static void unbind_rdev_from_array(mdk_rdev_t * rdev)
 {
        if (!rdev->mddev) {
                MD_BUG();
@@ -621,7 +619,7 @@ static void unbind_rdev_from_array (mdk_rdev_t * rdev)
        md_list_del(&rdev->same_set);
        MD_INIT_LIST_HEAD(&rdev->same_set);
        rdev->mddev->nb_dev--;
-       printk("md: unbind<%s,%d>\n", partition_name(rdev->dev),
+       printk(KERN_INFO "md: unbind<%s,%d>\n", partition_name(rdev->dev),
                                                 rdev->mddev->nb_dev);
        rdev->mddev = NULL;
 }
@@ -633,13 +631,13 @@ static void unbind_rdev_from_array (mdk_rdev_t * rdev)
  * inode is not enough, the SCSI module usage code needs
  * an explicit open() on the device]
  */
-static int lock_rdev (mdk_rdev_t *rdev)
+static int lock_rdev(mdk_rdev_t *rdev)
 {
        int err = 0;
        struct block_device *bdev;
 
        bdev = bdget(rdev->dev);
-       if (bdev == NULL)
+       if (!bdev)
                return -ENOMEM;
        err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW);
        if (!err)
@@ -647,7 +645,7 @@ static int lock_rdev (mdk_rdev_t *rdev)
        return err;
 }
 
-static void unlock_rdev (mdk_rdev_t *rdev)
+static void unlock_rdev(mdk_rdev_t *rdev)
 {
        struct block_device *bdev = rdev->bdev;
        rdev->bdev = NULL;
@@ -656,11 +654,11 @@ static void unlock_rdev (mdk_rdev_t *rdev)
        blkdev_put(bdev, BDEV_RAW);
 }
 
-void md_autodetect_dev (kdev_t dev);
+void md_autodetect_dev(kdev_t dev);
 
-static void export_rdev (mdk_rdev_t * rdev)
+static void export_rdev(mdk_rdev_t * rdev)
 {
-       printk("md: export_rdev(%s)\n",partition_name(rdev->dev));
+       printk(KERN_INFO "md: export_rdev(%s)\n",partition_name(rdev->dev));
        if (rdev->mddev)
                MD_BUG();
        unlock_rdev(rdev);
@@ -668,7 +666,8 @@ static void export_rdev (mdk_rdev_t * rdev)
        md_list_del(&rdev->all);
        MD_INIT_LIST_HEAD(&rdev->all);
        if (rdev->pending.next != &rdev->pending) {
-               printk("md: (%s was pending)\n",partition_name(rdev->dev));
+               printk(KERN_INFO "md: (%s was pending)\n",
+                       partition_name(rdev->dev));
                md_list_del(&rdev->pending);
                MD_INIT_LIST_HEAD(&rdev->pending);
        }
@@ -680,13 +679,13 @@ static void export_rdev (mdk_rdev_t * rdev)
        kfree(rdev);
 }
 
-static void kick_rdev_from_array (mdk_rdev_t * rdev)
+static void kick_rdev_from_array(mdk_rdev_t * rdev)
 {
        unbind_rdev_from_array(rdev);
        export_rdev(rdev);
 }
 
-static void export_array (mddev_t *mddev)
+static void export_array(mddev_t *mddev)
 {
        struct md_list_head *tmp;
        mdk_rdev_t *rdev;
@@ -708,7 +707,7 @@ static void export_array (mddev_t *mddev)
                MD_BUG();
 }
 
-static void free_mddev (mddev_t *mddev)
+static void free_mddev(mddev_t *mddev)
 {
        if (!mddev) {
                MD_BUG();
@@ -751,45 +750,47 @@ static void print_sb(mdp_super_t *sb)
 {
        int i;
 
-       printk("md:  SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n",
+       printk(KERN_INFO "md:  SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n",
                sb->major_version, sb->minor_version, sb->patch_version,
                sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3,
                sb->ctime);
-       printk("md:     L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level,
+       printk(KERN_INFO "md:     L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level,
                sb->size, sb->nr_disks, sb->raid_disks, sb->md_minor,
                sb->layout, sb->chunk_size);
-       printk("md:     UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n",
+       printk(KERN_INFO "md:     UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n",
                sb->utime, sb->state, sb->active_disks, sb->working_disks,
                sb->failed_disks, sb->spare_disks,
                sb->sb_csum, (unsigned long)sb->events_lo);
 
+       printk(KERN_INFO);
        for (i = 0; i < MD_SB_DISKS; i++) {
                mdp_disk_t *desc;
 
                desc = sb->disks + i;
-               if (desc->number || desc->major || desc->minor || desc->raid_disk || (desc->state && (desc->state != 4))) {
+               if (desc->number || desc->major || desc->minor ||
+                   desc->raid_disk || (desc->state && (desc->state != 4))) {
                        printk("     D %2d: ", i);
                        print_desc(desc);
                }
        }
-       printk("md:     THIS: ");
+       printk(KERN_INFO "md:     THIS: ");
        print_desc(&sb->this_disk);
 
 }
 
 static void print_rdev(mdk_rdev_t *rdev)
 {
-       printk("md: rdev %s: O:%s, SZ:%08ld F:%d DN:%d ",
+       printk(KERN_INFO "md: rdev %s: O:%s, SZ:%08ld F:%d DN:%d ",
                partition_name(rdev->dev), partition_name(rdev->old_dev),
                rdev->size, rdev->faulty, rdev->desc_nr);
        if (rdev->sb) {
-               printk("md: rdev superblock:\n");
+               printk(KERN_INFO "md: rdev superblock:\n");
                print_sb(rdev->sb);
        } else
-               printk("md: no rdev superblock!\n");
+               printk(KERN_INFO "md: no rdev superblock!\n");
 }
 
-void md_print_devices (void)
+void md_print_devices(void)
 {
        struct md_list_head *tmp, *tmp2;
        mdk_rdev_t *rdev;
@@ -818,7 +819,7 @@ void md_print_devices (void)
        printk("\n");
 }
 
-static int sb_equal ( mdp_super_t *sb1, mdp_super_t *sb2)
+static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
 {
        int ret;
        mdp_super_t *tmp1, *tmp2;
@@ -867,7 +868,7 @@ static int uuid_equal(mdk_rdev_t *rdev1, mdk_rdev_t *rdev2)
        return 0;
 }
 
-static mdk_rdev_t * find_rdev_all (kdev_t dev)
+static mdk_rdev_t * find_rdev_all(kdev_t dev)
 {
        struct md_list_head *tmp;
        mdk_rdev_t *rdev;
@@ -908,8 +909,8 @@ static int write_disk_sb(mdk_rdev_t * rdev)
        dev = rdev->dev;
        sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1);
        if (rdev->sb_offset != sb_offset) {
-               printk("%s's sb offset has changed from %ld to %ld, skipping\n",
-                       partition_name(dev), rdev->sb_offset, sb_offset);
+               printk(KERN_INFO "%s's sb offset has changed from %ld to %ld, skipping\n",
+                      partition_name(dev), rdev->sb_offset, sb_offset);
                goto skip;
        }
        /*
@@ -919,12 +920,12 @@ static int write_disk_sb(mdk_rdev_t * rdev)
         */
        size = calc_dev_size(dev, rdev->mddev, 1);
        if (size != rdev->size) {
-               printk("%s's size has changed from %ld to %ld since import, skipping\n",
-                       partition_name(dev), rdev->size, size);
+               printk(KERN_INFO "%s's size has changed from %ld to %ld since import, skipping\n",
+                      partition_name(dev), rdev->size, size);
                goto skip;
        }
 
-       printk("(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset);
+       printk(KERN_INFO "(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset);
        fsync_dev(dev);
        set_blocksize(dev, MD_SB_BYTES);
        bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
@@ -945,7 +946,7 @@ static int write_disk_sb(mdk_rdev_t * rdev)
 skip:
        return 0;
 }
-#undef GETBLK_FAILED 
+#undef GETBLK_FAILED
 
 static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 {
@@ -1025,7 +1026,7 @@ repeat:
 
        err = 0;
        ITERATE_RDEV(mddev,rdev,tmp) {
-               printk("md: ");
+               printk(KERN_INFO "md: ");
                if (rdev->faulty)
                        printk("(skipping faulty ");
                if (rdev->alias_device)
@@ -1041,10 +1042,10 @@ repeat:
        }
        if (err) {
                if (--count) {
-                       printk("md: errors occurred during superblock update, repeating\n");
+                       printk(KERN_ERR "md: errors occurred during superblock update, repeating\n");
                        goto repeat;
                }
-               printk("md: excessive errors occurred during superblock update, exiting\n");
+               printk(KERN_ERR "md: excessive errors occurred during superblock update, exiting\n");
        }
        return 0;
 }
@@ -1059,7 +1060,7 @@ repeat:
  *
  * a faulty rdev _never_ has rdev->sb set.
  */
-static int md_import_device (kdev_t newdev, int on_disk)
+static int md_import_device(kdev_t newdev, int on_disk)
 {
        int err;
        mdk_rdev_t *rdev;
@@ -1070,13 +1071,13 @@ static int md_import_device (kdev_t newdev, int on_disk)
 
        rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
        if (!rdev) {
-               printk("md: could not alloc mem for %s!\n", partition_name(newdev));
+               printk(KERN_ERR "md: could not alloc mem for %s!\n", partition_name(newdev));
                return -ENOMEM;
        }
        memset(rdev, 0, sizeof(*rdev));
 
        if (is_mounted(newdev)) {
-               printk("md: can not import %s, has active inodes!\n",
+               printk(KERN_WARNING "md: can not import %s, has active inodes!\n",
                        partition_name(newdev));
                err = -EBUSY;
                goto abort_free;
@@ -1087,7 +1088,7 @@ static int md_import_device (kdev_t newdev, int on_disk)
 
        rdev->dev = newdev;
        if (lock_rdev(rdev)) {
-               printk("md: could not lock %s, zero-size? Marking faulty.\n",
+               printk(KERN_ERR "md: could not lock %s, zero-size? Marking faulty.\n",
                        partition_name(newdev));
                err = -EINVAL;
                goto abort_free;
@@ -1099,7 +1100,7 @@ static int md_import_device (kdev_t newdev, int on_disk)
        if (blk_size[MAJOR(newdev)])
                size = blk_size[MAJOR(newdev)][MINOR(newdev)];
        if (!size) {
-               printk("md: %s has zero size, marking faulty!\n",
+               printk(KERN_WARNING "md: %s has zero size, marking faulty!\n",
                                partition_name(newdev));
                err = -EINVAL;
                goto abort_free;
@@ -1107,13 +1108,13 @@ static int md_import_device (kdev_t newdev, int on_disk)
 
        if (on_disk) {
                if ((err = read_disk_sb(rdev))) {
-                       printk("md: could not read %s's sb, not importing!\n",
-                                       partition_name(newdev));
+                       printk(KERN_WARNING "md: could not read %s's sb, not importing!\n",
+                              partition_name(newdev));
                        goto abort_free;
                }
                if ((err = check_disk_sb(rdev))) {
-                       printk("md: %s has invalid sb, not importing!\n",
-                                       partition_name(newdev));
+                       printk(KERN_WARNING "md: %s has invalid sb, not importing!\n",
+                              partition_name(newdev));
                        goto abort_free;
                }
 
@@ -1162,7 +1163,7 @@ abort_free:
 #define UNKNOWN_LEVEL KERN_ERR \
 "md: md%d: unsupported raid level %d\n"
 
-static int analyze_sbs (mddev_t * mddev)
+static int analyze_sbs(mddev_t * mddev)
 {
        int out_of_date = 0, i, first;
        struct md_list_head *tmp, *tmp2;
@@ -1197,7 +1198,7 @@ static int analyze_sbs (mddev_t * mddev)
                        continue;
                }
                if (!sb_equal(sb, rdev->sb)) {
-                       printk (INCONSISTENT, partition_name(rdev->dev));
+                       printk(INCONSISTENT, partition_name(rdev->dev));
                        kick_rdev_from_array(rdev);
                        continue;
                }
@@ -1227,7 +1228,8 @@ static int analyze_sbs (mddev_t * mddev)
                                        rdev->sb->events_hi--;
                }
 
-               printk("md: %s's event counter: %08lx\n", partition_name(rdev->dev),
+               printk(KERN_INFO "md: %s's event counter: %08lx\n",
+                      partition_name(rdev->dev),
                        (unsigned long)rdev->sb->events_lo);
                if (!freshest) {
                        freshest = rdev;
@@ -1246,7 +1248,7 @@ static int analyze_sbs (mddev_t * mddev)
        }
        if (out_of_date) {
                printk(OUT_OF_DATE);
-               printk("md: freshest: %s\n", partition_name(freshest->dev));
+               printk(KERN_INFO "md: freshest: %s\n", partition_name(freshest->dev));
        }
        memcpy (sb, freshest->sb, sizeof(*sb));
 
@@ -1265,7 +1267,7 @@ static int analyze_sbs (mddev_t * mddev)
                ev2 = md_event(sb);
                ++ev1;
                if (ev1 < ev2) {
-                       printk("md: kicking non-fresh %s from array!\n",
+                       printk(KERN_WARNING "md: kicking non-fresh %s from array!\n",
                                                partition_name(rdev->dev));
                        kick_rdev_from_array(rdev);
                        continue;
@@ -1291,7 +1293,8 @@ static int analyze_sbs (mddev_t * mddev)
                        ((ev1 == ev2) || (ev1 == ev3))) {
                        mdp_disk_t *desc;
 
-                       printk("md: device name has changed from %s to %s since last import!\n", partition_name(rdev->old_dev), partition_name(rdev->dev));
+                       printk(KERN_WARNING "md: device name has changed from %s to %s since last import!\n",
+                              partition_name(rdev->old_dev), partition_name(rdev->dev));
                        if (rdev->desc_nr == -1) {
                                MD_BUG();
                                goto abort;
@@ -1338,7 +1341,7 @@ static int analyze_sbs (mddev_t * mddev)
                        ITERATE_RDEV(mddev,rdev,tmp) {
                                if (rdev->desc_nr != desc->number)
                                        continue;
-                               printk("md%d: kicking faulty %s!\n",
+                               printk(KERN_WARNING "md%d: kicking faulty %s!\n",
                                        mdidx(mddev),partition_name(rdev->dev));
                                kick_rdev_from_array(rdev);
                                found = 1;
@@ -1347,7 +1350,7 @@ static int analyze_sbs (mddev_t * mddev)
                        if (!found) {
                                if (dev == MKDEV(0,0))
                                        continue;
-                               printk("md%d: removing former faulty %s!\n",
+                               printk(KERN_WARNING "md%d: removing former faulty %s!\n",
                                        mdidx(mddev), partition_name(dev));
                        }
                        remove_descriptor(desc, sb);
@@ -1389,7 +1392,8 @@ static int analyze_sbs (mddev_t * mddev)
                if (found)
                        continue;
 
-               printk("md%d: former device %s is unavailable, removing from array!\n", mdidx(mddev), partition_name(dev));
+               printk(KERN_WARNING "md%d: former device %s is unavailable, removing from array!\n",
+                      mdidx(mddev), partition_name(dev));
                remove_descriptor(desc, sb);
        }
 
@@ -1436,7 +1440,7 @@ static int analyze_sbs (mddev_t * mddev)
                                first = 0;
                }
        }
+
        /*
         * Kick all rdevs that are not in the
         * descriptor array:
@@ -1445,7 +1449,7 @@ static int analyze_sbs (mddev_t * mddev)
                if (rdev->desc_nr == -1)
                        kick_rdev_from_array(rdev);
        }
+
        /*
         * Do a final reality check.
         */
@@ -1484,14 +1488,14 @@ static int analyze_sbs (mddev_t * mddev)
        if (sb->major_version != MD_MAJOR_VERSION ||
                        sb->minor_version > MD_MINOR_VERSION) {
 
-               printk (OLD_VERSION, mdidx(mddev), sb->major_version,
+               printk(OLD_VERSION, mdidx(mddev), sb->major_version,
                                sb->minor_version, sb->patch_version);
                goto abort;
        }
 
        if ((sb->state != (1 << MD_SB_CLEAN)) && ((sb->level == 1) ||
                        (sb->level == 4) || (sb->level == 5)))
-               printk (NOT_CLEAN_IGNORE, mdidx(mddev));
+               printk(NOT_CLEAN_IGNORE, mdidx(mddev));
 
        return 0;
 abort:
@@ -1503,7 +1507,7 @@ abort:
 #undef OLD_VERSION
 #undef OLD_LEVEL
 
-static int device_size_calculation (mddev_t * mddev)
+static int device_size_calculation(mddev_t * mddev)
 {
        int data_disks = 0, persistent;
        unsigned int readahead;
@@ -1526,7 +1530,7 @@ static int device_size_calculation (mddev_t * mddev)
                }
                rdev->size = calc_dev_size(rdev->dev, mddev, persistent);
                if (rdev->size < sb->chunk_size / 1024) {
-                       printk (KERN_WARNING
+                       printk(KERN_WARNING
                                "md: Dev %s smaller than chunk_size: %ldk < %dk\n",
                                partition_name(rdev->dev),
                                rdev->size, sb->chunk_size / 1024);
@@ -1560,7 +1564,7 @@ static int device_size_calculation (mddev_t * mddev)
                        data_disks = sb->raid_disks-1;
                        break;
                default:
-                       printk (UNKNOWN_LEVEL, mdidx(mddev), sb->level);
+                       printk(UNKNOWN_LEVEL, mdidx(mddev), sb->level);
                        goto abort;
        }
        if (!md_size[mdidx(mddev)])
@@ -1599,7 +1603,7 @@ abort:
 #define BAD_CHUNKSIZE KERN_ERR \
 "no chunksize specified, see 'man raidtab'\n"
 
-static int do_md_run (mddev_t * mddev)
+static int do_md_run(mddev_t * mddev)
 {
        int pnum, err;
        int chunk_size;
@@ -1663,7 +1667,8 @@ static int do_md_run (mddev_t * mddev)
                }
        } else
                if (chunk_size)
-                       printk(KERN_INFO "md: RAID level %d does not need chunksize! Continuing anyway.\n", mddev->sb->level);
+                       printk(KERN_INFO "md: RAID level %d does not need chunksize! Continuing anyway.\n",
+                              mddev->sb->level);
 
        if (pnum >= MAX_PERSONALITY) {
                MD_BUG();
@@ -1700,7 +1705,7 @@ static int do_md_run (mddev_t * mddev)
                        continue;
                invalidate_device(rdev->dev, 1);
                if (get_hardsect_size(rdev->dev)
-                       > md_hardsect_sizes[mdidx(mddev)]) 
+                       > md_hardsect_sizes[mdidx(mddev)])
                        md_hardsect_sizes[mdidx(mddev)] =
                                get_hardsect_size(rdev->dev);
        }
@@ -1711,7 +1716,7 @@ static int do_md_run (mddev_t * mddev)
 
        err = mddev->pers->run(mddev);
        if (err) {
-               printk("md: pers->run() failed ...\n");
+               printk(KERN_ERR "md: pers->run() failed ...\n");
                mddev->pers = NULL;
                return -EINVAL;
        }
@@ -1736,7 +1741,7 @@ static int do_md_run (mddev_t * mddev)
 
 #define OUT(x) do { err = (x); goto out; } while (0)
 
-static int restart_array (mddev_t *mddev)
+static int restart_array(mddev_t *mddev)
 {
        int err = 0;
 
@@ -1753,7 +1758,7 @@ static int restart_array (mddev_t *mddev)
                mddev->ro = 0;
                set_device_ro(mddev_to_kdev(mddev), 0);
 
-               printk (KERN_INFO
+               printk(KERN_INFO
                        "md: md%d switched to read-write mode.\n", mdidx(mddev));
                /*
                 * Kick recovery or resync if necessary
@@ -1762,7 +1767,7 @@ static int restart_array (mddev_t *mddev)
                if (mddev->pers->restart_resync)
                        mddev->pers->restart_resync(mddev);
        } else {
-               printk (KERN_ERR "md: md%d has no personality assigned.\n",
+               printk(KERN_ERR "md: md%d has no personality assigned.\n",
                        mdidx(mddev));
                err = -EINVAL;
        }
@@ -1776,15 +1781,15 @@ out:
 #define        STILL_IN_USE \
 "md: md%d still in use.\n"
 
-static int do_md_stop (mddev_t * mddev, int ro)
+static int do_md_stop(mddev_t * mddev, int ro)
 {
        int err = 0, resync_interrupted = 0;
        kdev_t dev = mddev_to_kdev(mddev);
 
-       if (atomic_read(&mddev->active)>1) {
-               printk(STILL_IN_USE, mdidx(mddev));
-               OUT(-EBUSY);
-       }
+       if (atomic_read(&mddev->active)>1) {
+               printk(STILL_IN_USE, mdidx(mddev));
+               OUT(-EBUSY);
+       }
 
        if (mddev->pers) {
                /*
@@ -1831,7 +1836,7 @@ static int do_md_stop (mddev_t * mddev, int ro)
                         * interrupted.
                         */
                        if (!mddev->recovery_running && !resync_interrupted) {
-                               printk("md: marking sb clean...\n");
+                               printk(KERN_INFO "md: marking sb clean...\n");
                                mddev->sb->state |= 1 << MD_SB_CLEAN;
                        }
                        md_update_sb(mddev);
@@ -1844,12 +1849,11 @@ static int do_md_stop (mddev_t * mddev, int ro)
         * Free resources if final stop
         */
        if (!ro) {
-               printk (KERN_INFO "md: md%d stopped.\n", mdidx(mddev));
+               printk(KERN_INFO "md: md%d stopped.\n", mdidx(mddev));
                free_mddev(mddev);
 
        } else
-               printk (KERN_INFO
-                       "md: md%d switched to read-only mode.\n", mdidx(mddev));
+               printk(KERN_INFO "md: md%d switched to read-only mode.\n", mdidx(mddev));
 out:
        return err;
 }
@@ -1859,7 +1863,7 @@ out:
 /*
  * We have to safely support old arrays too.
  */
-int detect_old_array (mdp_super_t *sb)
+int detect_old_array(mdp_super_t *sb)
 {
        if (sb->major_version > 0)
                return 0;
@@ -1870,7 +1874,7 @@ int detect_old_array (mdp_super_t *sb)
 }
 
 
-static void autorun_array (mddev_t *mddev)
+static void autorun_array(mddev_t *mddev)
 {
        mdk_rdev_t *rdev;
        struct md_list_head *tmp;
@@ -1881,7 +1885,7 @@ static void autorun_array (mddev_t *mddev)
                return;
        }
 
-       printk("md: running: ");
+       printk(KERN_INFO "md: running: ");
 
        ITERATE_RDEV(mddev,rdev,tmp) {
                printk("<%s>", partition_name(rdev->dev));
@@ -1890,7 +1894,7 @@ static void autorun_array (mddev_t *mddev)
 
        err = do_md_run (mddev);
        if (err) {
-               printk("md :do_md_run() returned %d\n", err);
+               printk(KERN_WARNING "md :do_md_run() returned %d\n", err);
                /*
                 * prevent the writeback of an unrunnable array
                 */
@@ -1911,7 +1915,7 @@ static void autorun_array (mddev_t *mddev)
  *
  * If "unit" is allocated, then bump its reference count
  */
-static void autorun_devices (kdev_t countdev)
+static void autorun_devices(kdev_t countdev)
 {
        struct md_list_head candidates;
        struct md_list_head *tmp;
@@ -1920,20 +1924,22 @@ static void autorun_devices (kdev_t countdev)
        kdev_t md_kdev;
 
 
-       printk("md: autorun ...\n");
+       printk(KERN_INFO "md: autorun ...\n");
        while (pending_raid_disks.next != &pending_raid_disks) {
                rdev0 = md_list_entry(pending_raid_disks.next,
                                         mdk_rdev_t, pending);
 
-               printk("md: considering %s ...\n", partition_name(rdev0->dev));
+               printk(KERN_INFO "md: considering %s ...\n", partition_name(rdev0->dev));
                MD_INIT_LIST_HEAD(&candidates);
                ITERATE_RDEV_PENDING(rdev,tmp) {
                        if (uuid_equal(rdev0, rdev)) {
                                if (!sb_equal(rdev0->sb, rdev->sb)) {
-                                       printk("md: %s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+                                       printk(KERN_WARNING
+                                              "md: %s has same UUID as %s, but superblocks differ ...\n",
+                                              partition_name(rdev->dev), partition_name(rdev0->dev));
                                        continue;
                                }
-                               printk("md:  adding %s ...\n", partition_name(rdev->dev));
+                               printk(KERN_INFO "md:  adding %s ...\n", partition_name(rdev->dev));
                                md_list_del(&rdev->pending);
                                md_list_add(&rdev->pending, &candidates);
                        }
@@ -1946,20 +1952,20 @@ static void autorun_devices (kdev_t countdev)
                md_kdev = MKDEV(MD_MAJOR, rdev0->sb->md_minor);
                mddev = kdev_to_mddev(md_kdev);
                if (mddev) {
-                       printk("md: md%d already running, cannot run %s\n",
-                                mdidx(mddev), partition_name(rdev0->dev));
+                       printk(KERN_WARNING "md: md%d already running, cannot run %s\n",
+                              mdidx(mddev), partition_name(rdev0->dev));
                        ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp)
                                export_rdev(rdev);
                        continue;
                }
                mddev = alloc_mddev(md_kdev);
-               if (mddev == NULL) {
-                       printk("md: cannot allocate memory for md drive.\n");
-                       break;
-               }
-               if (md_kdev == countdev)
-                       atomic_inc(&mddev->active);
-               printk("md: created md%d\n", mdidx(mddev));
+               if (!mddev) {
+                       printk(KERN_ERR "md: cannot allocate memory for md drive.\n");
+                       break;
+               }
+               if (md_kdev == countdev)
+                       atomic_inc(&mddev->active);
+               printk(KERN_INFO "md: created md%d\n", mdidx(mddev));
                ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {
                        bind_rdev_to_array(rdev, mddev);
                        md_list_del(&rdev->pending);
@@ -1967,7 +1973,7 @@ static void autorun_devices (kdev_t countdev)
                }
                autorun_array(mddev);
        }
-       printk("md: ... autorun DONE.\n");
+       printk(KERN_INFO "md: ... autorun DONE.\n");
 }
 
 /*
@@ -2002,14 +2008,14 @@ static void autorun_devices (kdev_t countdev)
 #define AUTORUNNING KERN_INFO \
 "md: auto-running md%d.\n"
 
-static int autostart_array (kdev_t startdev, kdev_t countdev)
+static int autostart_array(kdev_t startdev, kdev_t countdev)
 {
        int err = -EINVAL, i;
        mdp_super_t *sb = NULL;
        mdk_rdev_t *start_rdev = NULL, *rdev;
 
        if (md_import_device(startdev, 1)) {
-               printk("md: could not import %s!\n", partition_name(startdev));
+               printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev));
                goto abort;
        }
 
@@ -2019,7 +2025,7 @@ static int autostart_array (kdev_t startdev, kdev_t countdev)
                goto abort;
        }
        if (start_rdev->faulty) {
-               printk("md: can not autostart based on faulty %s!\n",
+               printk(KERN_WARNING "md: can not autostart based on faulty %s!\n",
                                                partition_name(startdev));
                goto abort;
        }
@@ -2029,7 +2035,9 @@ static int autostart_array (kdev_t startdev, kdev_t countdev)
 
        err = detect_old_array(sb);
        if (err) {
-               printk("md: array version is too old to be autostarted, use raidtools 0.90 mkraid --upgrade\nto upgrade the array without data loss!\n");
+               printk(KERN_WARNING "md: array version is too old to be autostarted ,"
+                      "use raidtools 0.90 mkraid --upgrade to upgrade the array "
+                      "without data loss!\n");
                goto abort;
        }
 
@@ -2045,7 +2053,8 @@ static int autostart_array (kdev_t startdev, kdev_t countdev)
                if (dev == startdev)
                        continue;
                if (md_import_device(dev, 1)) {
-                       printk("md: could not import %s, trying to run array nevertheless.\n", partition_name(dev));
+                       printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n",
+                              partition_name(dev));
                        continue;
                }
                rdev = find_rdev_all(dev);
@@ -2078,7 +2087,7 @@ abort:
 #undef AUTORUNNING
 
 
-static int get_version (void * arg)
+static int get_version(void * arg)
 {
        mdu_version_t ver;
 
@@ -2093,7 +2102,7 @@ static int get_version (void * arg)
 }
 
 #define SET_FROM_SB(x) info.x = mddev->sb->x
-static int get_array_info (mddev_t * mddev, void * arg)
+static int get_array_info(mddev_t * mddev, void * arg)
 {
        mdu_array_info_t info;
 
@@ -2131,7 +2140,7 @@ static int get_array_info (mddev_t * mddev, void * arg)
 #undef SET_FROM_SB
 
 #define SET_FROM_SB(x) info.x = mddev->sb->disks[nr].x
-static int get_disk_info (mddev_t * mddev, void * arg)
+static int get_disk_info(mddev_t * mddev, void * arg)
 {
        mdu_disk_info_t info;
        unsigned int nr;
@@ -2160,7 +2169,7 @@ static int get_disk_info (mddev_t * mddev, void * arg)
 
 #define SET_SB(x) mddev->sb->disks[nr].x = info->x
 
-static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
+static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
 {
        int err, size, persistent;
        mdk_rdev_t *rdev;
@@ -2169,15 +2178,15 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
        dev = MKDEV(info->major,info->minor);
 
        if (find_rdev_all(dev)) {
-               printk("md: device %s already used in a RAID array!\n",
-                               partition_name(dev));
+               printk(KERN_WARNING "md: device %s already used in a RAID array!\n",
+                      partition_name(dev));
                return -EBUSY;
        }
        if (!mddev->sb) {
                /* expecting a device which has a superblock */
                err = md_import_device(dev, 1);
                if (err) {
-                       printk("md: md_import_device returned %d\n", err);
+                       printk(KERN_WARNING "md: md_import_device returned %d\n", err);
                        return -EINVAL;
                }
                rdev = find_rdev_all(dev);
@@ -2189,12 +2198,14 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
                        mdk_rdev_t *rdev0 = md_list_entry(mddev->disks.next,
                                                        mdk_rdev_t, same_set);
                        if (!uuid_equal(rdev0, rdev)) {
-                               printk("md: %s has different UUID to %s\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+                               printk(KERN_WARNING "md: %s has different UUID to %s\n",
+                                      partition_name(rdev->dev), partition_name(rdev0->dev));
                                export_rdev(rdev);
                                return -EINVAL;
                        }
                        if (!sb_equal(rdev0->sb, rdev->sb)) {
-                               printk("md: %s has same UUID but different superblock to %s\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+                               printk(KERN_WARNING "md: %s has same UUID but different superblock to %s\n",
+                                      partition_name(rdev->dev), partition_name(rdev0->dev));
                                export_rdev(rdev);
                                return -EINVAL;
                        }
@@ -2219,7 +2230,7 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
        if ((info->state & (1<<MD_DISK_FAULTY))==0) {
                err = md_import_device (dev, 0);
                if (err) {
-                       printk("md: error, md_import_device() returned %d\n", err);
+                       printk(KERN_WARNING "md: error, md_import_device() returned %d\n", err);
                        return -EINVAL;
                }
                rdev = find_rdev_all(dev);
@@ -2235,7 +2246,7 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
 
                persistent = !mddev->sb->not_persistent;
                if (!persistent)
-                       printk("md: nonpersistent superblock ...\n");
+                       printk(KERN_INFO "md: nonpersistent superblock ...\n");
 
                size = calc_dev_size(dev, mddev, persistent);
                rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent);
@@ -2253,24 +2264,24 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
 }
 #undef SET_SB
 
-static int hot_generate_error (mddev_t * mddev, kdev_t dev)
+static int hot_generate_error(mddev_t * mddev, kdev_t dev)
 {
        struct request_queue *q;
        mdk_rdev_t *rdev;
        mdp_disk_t *disk;
+
        if (!mddev->pers)
                return -ENODEV;
-       printk("md: trying to generate %s error in md%d ... \n",
+
+       printk(KERN_INFO "md: trying to generate %s error in md%d ... \n",
                partition_name(dev), mdidx(mddev));
+
        rdev = find_rdev(mddev, dev);
        if (!rdev) {
                MD_BUG();
                return -ENXIO;
        }
+
        if (rdev->desc_nr == -1) {
                MD_BUG();
                return -EINVAL;
@@ -2278,19 +2289,19 @@ static int hot_generate_error (mddev_t * mddev, kdev_t dev)
        disk = &mddev->sb->disks[rdev->desc_nr];
        if (!disk_active(disk))
                return -ENODEV;
+
        q = blk_get_queue(rdev->dev);
        if (!q) {
                MD_BUG();
                return -ENODEV;
        }
-       printk("md: okay, generating error!\n");
+       printk(KERN_INFO "md: okay, generating error!\n");
 //     q->oneshot_error = 1; // disabled for now
+
        return 0;
 }
 
-static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
+static int hot_remove_disk(mddev_t * mddev, kdev_t dev)
 {
        int err;
        mdk_rdev_t *rdev;
@@ -2299,12 +2310,12 @@ static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
        if (!mddev->pers)
                return -ENODEV;
 
-       printk("md: trying to remove %s from md%d ... \n",
+       printk(KERN_INFO "md: trying to remove %s from md%d ... \n",
                partition_name(dev), mdidx(mddev));
 
        if (!mddev->pers->diskop) {
-               printk("md%d: personality does not support diskops!\n",
-                                                                mdidx(mddev));
+               printk(KERN_WARNING "md%d: personality does not support diskops!\n",
+                      mdidx(mddev));
                return -EINVAL;
        }
 
@@ -2325,7 +2336,7 @@ static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
                MD_BUG();
                return -EINVAL;
        }
-       
+
        err = mddev->pers->diskop(mddev, &disk, DISKOP_HOT_REMOVE_DISK);
        if (err == -EBUSY) {
                MD_BUG();
@@ -2343,12 +2354,12 @@ static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
 
        return 0;
 busy:
-       printk("md: cannot remove active disk %s from md%d ... \n",
+       printk(KERN_WARNING "md: cannot remove active disk %s from md%d ... \n",
                partition_name(dev), mdidx(mddev));
        return -EBUSY;
 }
 
-static int hot_add_disk (mddev_t * mddev, kdev_t dev)
+static int hot_add_disk(mddev_t * mddev, kdev_t dev)
 {
        int i, err, persistent;
        unsigned int size;
@@ -2358,12 +2369,12 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
        if (!mddev->pers)
                return -ENODEV;
 
-       printk("md: trying to hot-add %s to md%d ... \n",
+       printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n",
                partition_name(dev), mdidx(mddev));
 
        if (!mddev->pers->diskop) {
-               printk("md%d: personality does not support diskops!\n",
-                                                                mdidx(mddev));
+               printk(KERN_WARNING "md%d: personality does not support diskops!\n",
+                      mdidx(mddev));
                return -EINVAL;
        }
 
@@ -2371,7 +2382,7 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
        size = calc_dev_size(dev, mddev, persistent);
 
        if (size < mddev->sb->size) {
-               printk("md%d: disk size %d blocks < array size %d\n",
+               printk(KERN_WARNING "md%d: disk size %d blocks < array size %d\n",
                                mdidx(mddev), size, mddev->sb->size);
                return -ENOSPC;
        }
@@ -2382,7 +2393,7 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
 
        err = md_import_device (dev, 0);
        if (err) {
-               printk("md: error, md_import_device() returned %d\n", err);
+               printk(KERN_WARNING "md: error, md_import_device() returned %d\n", err);
                return -EINVAL;
        }
        rdev = find_rdev_all(dev);
@@ -2391,7 +2402,7 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
                return -EINVAL;
        }
        if (rdev->faulty) {
-               printk("md: can not hot-add faulty %s disk to md%d!\n",
+               printk(KERN_WARNING "md: can not hot-add faulty %s disk to md%d!\n",
                                partition_name(dev), mdidx(mddev));
                err = -EINVAL;
                goto abort_export;
@@ -2416,7 +2427,8 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
                        break;
        }
        if (i == MD_SB_DISKS) {
-               printk("md%d: can not hot-add to full array!\n", mdidx(mddev));
+               printk(KERN_WARNING "md%d: can not hot-add to full array!\n",
+                      mdidx(mddev));
                err = -EBUSY;
                goto abort_unbind_export;
        }
@@ -2470,7 +2482,7 @@ abort_export:
 }
 
 #define SET_SB(x) mddev->sb->x = info->x
-static int set_array_info (mddev_t * mddev, mdu_array_info_t *info)
+static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
 {
 
        if (alloc_array_sb(mddev))
@@ -2511,37 +2523,37 @@ static int set_array_info (mddev_t * mddev, mdu_array_info_t *info)
 }
 #undef SET_SB
 
-static int set_disk_info (mddev_t * mddev, void * arg)
+static int set_disk_info(mddev_t * mddev, void * arg)
 {
-       printk("md: not yet");
+       printk(KERN_INFO "md: not yet");
        return -EINVAL;
 }
 
-static int clear_array (mddev_t * mddev)
+static int clear_array(mddev_t * mddev)
 {
-       printk("md: not yet");
+       printk(KERN_INFO "md: not yet");
        return -EINVAL;
 }
 
-static int write_raid_info (mddev_t * mddev)
+static int write_raid_info(mddev_t * mddev)
 {
-       printk("md: not yet");
+       printk(KERN_INFO "md: not yet");
        return -EINVAL;
 }
 
-static int protect_array (mddev_t * mddev)
+static int protect_array(mddev_t * mddev)
 {
-       printk("md: not yet");
+       printk(KERN_INFO "md: not yet");
        return -EINVAL;
 }
 
-static int unprotect_array (mddev_t * mddev)
+static int unprotect_array(mddev_t * mddev)
 {
-       printk("md: not yet");
+       printk(KERN_INFO "md: not yet");
        return -EINVAL;
 }
 
-static int set_disk_faulty (mddev_t *mddev, kdev_t dev)
+static int set_disk_faulty(mddev_t *mddev, kdev_t dev)
 {
        int ret;
 
@@ -2549,7 +2561,7 @@ static int set_disk_faulty (mddev_t *mddev, kdev_t dev)
        return ret;
 }
 
-static int md_ioctl (struct inode *inode, struct file *file,
+static int md_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        unsigned int minor;
@@ -2627,7 +2639,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
                case SET_ARRAY_INFO:
                case START_ARRAY:
                        if (mddev) {
-                               printk("md: array md%d already exists!\n",
+                               printk(KERN_WARNING "md: array md%d already exists!\n",
                                                                mdidx(mddev));
                                err = -EEXIST;
                                goto abort;
@@ -2649,12 +2661,13 @@ static int md_ioctl (struct inode *inode, struct file *file,
                         */
                        err = lock_mddev(mddev);
                        if (err) {
-                               printk("md: ioctl, reason %d, cmd %d\n", err, cmd);
+                               printk(KERN_WARNING "md: ioctl, reason %d, cmd %d\n",
+                                      err, cmd);
                                goto abort;
                        }
 
                        if (mddev->sb) {
-                               printk("md: array md%d already has a superblock!\n",
+                               printk(KERN_WARNING "md: array md%d already has a superblock!\n",
                                        mdidx(mddev));
                                err = -EBUSY;
                                goto abort_unlock;
@@ -2667,7 +2680,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
                                }
                                err = set_array_info(mddev, &info);
                                if (err) {
-                                       printk("md: couldnt set array info. %d\n", err);
+                                       printk(KERN_WARNING "md: couldnt set array info. %d\n", err);
                                        goto abort_unlock;
                                }
                        }
@@ -2679,7 +2692,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
                         */
                        err = autostart_array((kdev_t)arg, dev);
                        if (err) {
-                               printk("md: autostart %s failed!\n",
+                               printk(KERN_WARNING "md: autostart %s failed!\n",
                                        partition_name((kdev_t)arg));
                                goto abort;
                        }
@@ -2698,7 +2711,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
        }
        err = lock_mddev(mddev);
        if (err) {
-               printk("md: ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);
+               printk(KERN_INFO "md: ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);
                goto abort;
        }
        /* if we don't have a superblock yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */
@@ -2839,7 +2852,9 @@ static int md_ioctl (struct inode *inode, struct file *file,
                }
 
                default:
-                       printk(KERN_WARNING "md: %s(pid %d) used obsolete MD ioctl, upgrade your software to use new ictls.\n", current->comm, current->pid);
+                       printk(KERN_WARNING "md: %s(pid %d) used obsolete MD ioctl, "
+                              "upgrade your software to use new ictls.\n",
+                              current->comm, current->pid);
                        err = -EINVAL;
                        goto abort_unlock;
        }
@@ -2852,12 +2867,12 @@ abort_unlock:
        return err;
 done:
        if (err)
-               printk("md: huh12?\n");
+               MD_BUG();
 abort:
        return err;
 }
 
-static int md_open (struct inode *inode, struct file *file)
+static int md_open(struct inode *inode, struct file *file)
 {
        /*
         * Always succeed, but increment the usage count
@@ -2868,7 +2883,7 @@ static int md_open (struct inode *inode, struct file *file)
        return (0);
 }
 
-static int md_release (struct inode *inode, struct file * file)
+static int md_release(struct inode *inode, struct file * file)
 {
        mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
        if (mddev)
@@ -2937,11 +2952,8 @@ int md_thread(void * arg)
                        run(thread->data);
                        run_task_queue(&tq_disk);
                }
-               if (md_signal_pending(current)) {
-                       printk("md: %8s(%d) flushing signals.\n", current->comm,
-                               current->pid);
+               if (md_signal_pending(current))
                        md_flush_signals();
-               }
        }
        complete(thread->event);
        return 0;
@@ -2954,22 +2966,22 @@ void md_wakeup_thread(mdk_thread_t *thread)
        wake_up(&thread->wqueue);
 }
 
-mdk_thread_t *md_register_thread (void (*run) (void *),
+mdk_thread_t *md_register_thread(void (*run) (void *),
                                                void *data, const char *name)
 {
        mdk_thread_t *thread;
        int ret;
        struct completion event;
-       
+
        thread = (mdk_thread_t *) kmalloc
                                (sizeof(mdk_thread_t), GFP_KERNEL);
        if (!thread)
                return NULL;
-       
+
        memset(thread, 0, sizeof(mdk_thread_t));
        md_init_waitqueue_head(&thread->wqueue);
 
-       init_completion(&event);        
+       init_completion(&event);
        thread->event = &event;
        thread->run = run;
        thread->data = data;
@@ -2983,22 +2995,22 @@ mdk_thread_t *md_register_thread (void (*run) (void *),
        return thread;
 }
 
-void md_interrupt_thread (mdk_thread_t *thread)
+void md_interrupt_thread(mdk_thread_t *thread)
 {
        if (!thread->tsk) {
                MD_BUG();
                return;
        }
-       printk("md: interrupting MD-thread pid %d\n", thread->tsk->pid);
+       dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
        send_sig(SIGKILL, thread->tsk, 1);
 }
 
-void md_unregister_thread (mdk_thread_t *thread)
+void md_unregister_thread(mdk_thread_t *thread)
 {
        struct completion event;
 
        init_completion(&event);
-       
+
        thread->event = &event;
        thread->run = NULL;
        thread->name = NULL;
@@ -3007,7 +3019,7 @@ void md_unregister_thread (mdk_thread_t *thread)
        kfree(thread);
 }
 
-void md_recover_arrays (void)
+void md_recover_arrays(void)
 {
        if (!md_recovery_thread) {
                MD_BUG();
@@ -3017,12 +3029,15 @@ void md_recover_arrays (void)
 }
 
 
-int md_error (mddev_t *mddev, kdev_t rdev)
+int md_error(mddev_t *mddev, kdev_t rdev)
 {
        mdk_rdev_t * rrdev;
 
-/*     printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
- */
+       dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
+               MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev),
+               __builtin_return_address(0),__builtin_return_address(1),
+               __builtin_return_address(2),__builtin_return_address(3));
+
        if (!mddev) {
                MD_BUG();
                return 0;
@@ -3030,7 +3045,7 @@ int md_error (mddev_t *mddev, kdev_t rdev)
        rrdev = find_rdev(mddev, rdev);
        if (!rrdev || rrdev->faulty)
                return 0;
-       if (mddev->pers->error_handler == NULL
+       if (!mddev->pers->error_handler
                        || mddev->pers->error_handler(mddev,rdev) <= 0) {
                free_disk_sb(rrdev);
                rrdev->faulty = 1;
@@ -3048,7 +3063,7 @@ int md_error (mddev_t *mddev, kdev_t rdev)
        return 0;
 }
 
-static int status_unused (char * page)
+static int status_unused(char * page)
 {
        int sz = 0, i = 0;
        mdk_rdev_t *rdev;
@@ -3074,7 +3089,7 @@ static int status_unused (char * page)
 }
 
 
-static int status_resync (char * page, mddev_t * mddev)
+static int status_resync(char * page, mddev_t * mddev)
 {
        int sz = 0;
        unsigned long max_blocks, resync, res, dt, db, rt;
@@ -3084,7 +3099,7 @@ static int status_resync (char * page, mddev_t * mddev)
 
        /*
         * Should not happen.
-        */             
+        */
        if (!max_blocks) {
                MD_BUG();
                return 0;
@@ -3126,7 +3141,7 @@ static int status_resync (char * page, mddev_t * mddev)
        if (!dt) dt++;
        db = resync - (mddev->resync_mark_cnt/2);
        rt = (dt * ((max_blocks-resync) / (db/100+1)))/100;
-       
+
        sz += sprintf(page + sz, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
 
        sz += sprintf(page + sz, " speed=%ldK/sec", db/dt);
@@ -3160,7 +3175,7 @@ static int md_status_read_proc(char *page, char **start, off_t off,
                sz += sprintf(page + sz, "md%d : %sactive", mdidx(mddev),
                                                mddev->pers ? "" : "in");
                if (mddev->pers) {
-                       if (mddev->ro)  
+                       if (mddev->ro)
                                sz += sprintf(page + sz, " (read-only)");
                        sz += sprintf(page + sz, " %s", mddev->pers->name);
                }
@@ -3200,12 +3215,12 @@ static int md_status_read_proc(char *page, char **start, off_t off,
                }
                sz += sprintf(page + sz, "\n");
        }
-       sz += status_unused (page + sz);
+       sz += status_unused(page + sz);
 
        return sz;
 }
 
-int register_md_personality (int pnum, mdk_personality_t *p)
+int register_md_personality(int pnum, mdk_personality_t *p)
 {
        if (pnum >= MAX_PERSONALITY) {
                MD_BUG();
@@ -3222,7 +3237,7 @@ int register_md_personality (int pnum, mdk_personality_t *p)
        return 0;
 }
 
-int unregister_md_personality (int pnum)
+int unregister_md_personality(int pnum)
 {
        if (pnum >= MAX_PERSONALITY) {
                MD_BUG();
@@ -3273,7 +3288,7 @@ void md_sync_acct(kdev_t dev, unsigned long nr_sectors)
        sync_io[major][index] += nr_sectors;
 }
 
-static int is_mddev_idle (mddev_t *mddev)
+static int is_mddev_idle(mddev_t *mddev)
 {
        mdk_rdev_t * rdev;
        struct md_list_head *tmp;
@@ -3291,9 +3306,7 @@ static int is_mddev_idle (mddev_t *mddev)
                curr_events = kstat.dk_drive_rblk[major][idx] +
                                                kstat.dk_drive_wblk[major][idx] ;
                curr_events -= sync_io[major][idx];
-//             printk("md: events(major: %d, idx: %d): %ld\n", major, idx, curr_events);
                if ((curr_events - rdev->last_events) > 32) {
-//                     printk("!I(%ld)%x", curr_events - rdev->last_events, rdev->dev);
                        rdev->last_events = curr_events;
                        idle = 0;
                }
@@ -3321,7 +3334,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
        unsigned int max_sectors, currspeed,
                j, window, err, serialize;
        unsigned long mark[SYNC_MARKS];
-       unsigned long mark_cnt[SYNC_MARKS];     
+       unsigned long mark_cnt[SYNC_MARKS];
        int last_mark,m;
        struct md_list_head *tmp;
        unsigned long last_check;
@@ -3337,7 +3350,9 @@ recheck:
                if (mddev2 == mddev)
                        continue;
                if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) {
-                       printk(KERN_INFO "md: delaying resync of md%d until md%d has finished resync (they share one or more physical units)\n", mdidx(mddev), mdidx(mddev2));
+                       printk(KERN_INFO "md: delaying resync of md%d until md%d "
+                              "has finished resync (they share one or more physical units)\n",
+                              mdidx(mddev), mdidx(mddev2));
                        serialize = 1;
                        break;
                }
@@ -3359,7 +3374,9 @@ recheck:
        printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev));
        printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed: %d KB/sec/disc.\n",
                                                sysctl_speed_limit_min);
-       printk(KERN_INFO "md: using maximum available idle IO bandwith (but not more than %d KB/sec) for reconstruction.\n", sysctl_speed_limit_max);
+       printk(KERN_INFO "md: using maximum available idle IO bandwith "
+              "(but not more than %d KB/sec) for reconstruction.\n",
+              sysctl_speed_limit_max);
 
        /*
         * Resync has low priority.
@@ -3379,7 +3396,8 @@ recheck:
         * Tune reconstruction:
         */
        window = MAX_READAHEAD*(PAGE_SIZE/512);
-       printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",window/2,max_sectors/2);
+       printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",
+              window/2,max_sectors/2);
 
        atomic_set(&mddev->recovery_active, 0);
        init_waitqueue_head(&mddev->recovery_wait);
@@ -3401,14 +3419,14 @@ recheck:
                        continue;
 
                last_check = j;
-               
+
                run_task_queue(&tq_disk);
 
        repeat:
                if (jiffies >= mark[last_mark] + SYNC_MARK_STEP ) {
                        /* step marks */
                        int next = (last_mark+1) % SYNC_MARKS;
-                       
+
                        mddev->resync_mark = mark[next];
                        mddev->resync_mark_cnt = mark_cnt[next];
                        mark[next] = jiffies;
@@ -3422,7 +3440,7 @@ recheck:
                         * got a signal, exit.
                         */
                        mddev->curr_resync = 0;
-                       printk("md: md_do_sync() got signal ... exiting\n");
+                       printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n");
                        md_flush_signals();
                        err = -EINTR;
                        goto out;
@@ -3476,7 +3494,7 @@ out_nolock:
  * of my root partition with the first 0.5 gigs of my /home partition ... so
  * i'm a bit nervous ;)
  */
-void md_do_recovery (void *data)
+void md_do_recovery(void *data)
 {
        int err;
        mddev_t *mddev;
@@ -3495,15 +3513,18 @@ restart:
                if (sb->active_disks == sb->raid_disks)
                        continue;
                if (!sb->spare_disks) {
-                       printk(KERN_ERR "md%d: no spare disk to reconstruct array! -- continuing in degraded mode\n", mdidx(mddev));
+                       printk(KERN_ERR "md%d: no spare disk to reconstruct array! "
+                              "-- continuing in degraded mode\n", mdidx(mddev));
                        continue;
                }
                /*
                 * now here we get the spare and resync it.
                 */
-               if ((spare = get_spare(mddev)) == NULL)
+               spare = get_spare(mddev);
+               if (!spare)
                        continue;
-               printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
+               printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n",
+                      mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
                if (!mddev->pers->diskop)
                        continue;
                if (mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_WRITE))
@@ -3512,7 +3533,8 @@ restart:
                mddev->recovery_running = 1;
                err = md_do_sync(mddev, spare);
                if (err == -EIO) {
-                       printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
+                       printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n",
+                              mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
                        if (!disk_faulty(spare)) {
                                mddev->pers->diskop(mddev,&spare,DISKOP_SPARE_INACTIVE);
                                mark_disk_faulty(spare);
@@ -3556,7 +3578,7 @@ restart:
                goto restart;
        }
        printk(KERN_INFO "md: recovery thread finished ...\n");
-       
+
 }
 
 int md_notify_reboot(struct notifier_block *this,
@@ -3589,7 +3611,7 @@ struct notifier_block md_notifier = {
        priority:       INT_MAX, /* before any real devices */
 };
 
-static void md_geninit (void)
+static void md_geninit(void)
 {
        int i;
 
@@ -3611,18 +3633,18 @@ static void md_geninit (void)
 #endif
 }
 
-int md__init md_init (void)
+int md__init md_init(void)
 {
        static char * name = "mdrecoveryd";
        int minor;
-       
-       printk (KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
+
+       printk(KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
                        MD_MAJOR_VERSION, MD_MINOR_VERSION,
                        MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
 
        if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops))
        {
-               printk (KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
+               printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
                return (-1);
        }
        devfs_handle = devfs_mk_dir (NULL, "md", NULL);
@@ -3637,7 +3659,7 @@ int md__init md_init (void)
 
        /* forward all md request to md_make_request */
        blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), md_make_request);
-       
+
 
        read_ahead[MAJOR_NR] = INT_MAX;
 
@@ -3678,14 +3700,14 @@ struct {
 static int detected_devices[128];
 static int dev_cnt;
 
-void md_autodetect_dev (kdev_t dev)
+void md_autodetect_dev(kdev_t dev)
 {
        if (dev_cnt >= 0 && dev_cnt < 127)
                detected_devices[dev_cnt++] = dev;
 }
 
 
-static void autostart_arrays (void)
+static void autostart_arrays(void)
 {
        mdk_rdev_t *rdev;
        int i;
@@ -3753,21 +3775,22 @@ static int md__init md_setup(char *str)
        char *str1 = str;
 
        if (get_option(&str, &minor) != 2) {    /* MD Number */
-               printk("md: Too few arguments supplied to md=.\n");
+               printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
                return 0;
        }
        if (minor >= MAX_MD_DEVS) {
-               printk ("md: md=%d, Minor device number too high.\n", minor);
+               printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor);
                return 0;
        } else if (md_setup_args.device_names[minor]) {
-               printk ("md: md=%d, Specified more then once. Replacing previous definition.\n", minor);
+               printk(KERN_WARNING "md: md=%d, Specified more then once. "
+                      "Replacing previous definition.\n", minor);
        }
        switch (get_option(&str, &level)) {     /* RAID Personality */
        case 2: /* could be 0 or -1.. */
                if (level == 0 || level == -1) {
                        if (get_option(&str, &factor) != 2 ||   /* Chunk Size */
                                        get_option(&str, &fault) != 2) {
-                               printk("md: Too few arguments supplied to md=.\n");
+                               printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
                                return 0;
                        }
                        md_setup_args.pers[minor] = level;
@@ -3782,8 +3805,9 @@ static int md__init md_setup(char *str)
                                pername = "raid0";
                                break;
                        default:
-                               printk ("md: The kernel has not been configured for raid%d"
-                                       " support!\n", level);
+                               printk(KERN_WARNING
+                                      "md: The kernel has not been configured for raid%d support!\n",
+                                      level);
                                return 0;
                        }
                        md_setup_args.pers[minor] = level;
@@ -3797,11 +3821,11 @@ static int md__init md_setup(char *str)
                md_setup_args.pers[minor] = 0;
                pername="super-block";
        }
-       
-       printk ("md: Will configure md%d (%s) from %s, below.\n",
+
+       printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
                minor, pername, str);
        md_setup_args.device_names[minor] = str;
-                       
+
        return 1;
 }
 
@@ -3819,13 +3843,14 @@ void md__init md_setup_drive(void)
                mdu_disk_info_t dinfo;
 
                if ((devname = md_setup_args.device_names[minor]) == 0) continue;
-       
+
                for (i = 0; i < MD_SB_DISKS && devname != 0; i++) {
 
                        char *p;
                        void *handle;
-       
-                       if ((p = strchr(devname, ',')) != NULL)
+
+                       p = strchr(devname, ',');
+                       if (p)
                                *p++ = 0;
 
                        dev = name_to_kdev_t(devname);
@@ -3837,29 +3862,31 @@ void md__init md_setup_drive(void)
                                dev = MKDEV(major, minor);
                        }
                        if (dev == 0) {
-                               printk ("md: Unknown device name: %s\n", devname);
+                               printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
                                break;
                        }
-                       
+
                        devices[i] = dev;
                        md_setup_args.device_set[minor] = 1;
-                       
+
                        devname = p;
                }
                devices[i] = 0;
-               
+
                if (md_setup_args.device_set[minor] == 0)
                        continue;
-               
+
                if (mddev_map[minor].mddev) {
-                       printk("md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n", minor);
+                       printk(KERN_WARNING
+                              "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n",
+                              minor);
                        continue;
                }
-               printk("md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]);
-               
+               printk(KERN_INFO "md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]);
+
                mddev = alloc_mddev(MKDEV(MD_MAJOR,minor));
-               if (mddev == NULL) {
-                       printk("md: kmalloc failed - cannot start array %d\n", minor);
+               if (!mddev) {
+                       printk(KERN_ERR "md: kmalloc failed - cannot start array %d\n", minor);
                        continue;
                }
                if (md_setup_args.pers[minor]) {
@@ -3905,7 +3932,7 @@ void md__init md_setup_drive(void)
                if (err) {
                        mddev->sb_dirty = 0;
                        do_md_stop(mddev, 0);
-                       printk("md: starting md%d failed\n", minor);
+                       printk(KERN_WARNING "md: starting md%d failed\n", minor);
                }
        }
 }
@@ -3950,7 +3977,7 @@ __initcall(md_run_setup);
 
 #else /* It is a MODULE */
 
-int init_module (void)
+int init_module(void)
 {
        return md_init();
 }
@@ -3965,7 +3992,7 @@ static void free_device_names(void)
 }
 
 
-void cleanup_module (void)
+void cleanup_module(void)
 {
        md_unregister_thread(md_recovery_thread);
        devfs_unregister(devfs_handle);
@@ -3984,7 +4011,7 @@ void cleanup_module (void)
        blk_size[MAJOR_NR] = NULL;
        max_readahead[MAJOR_NR] = NULL;
        hardsect_size[MAJOR_NR] = NULL;
-       
+
        free_device_names();
 
 }
index 68b3035ff28973ef074b048ff81f9f0bed829dee..952c0225e216db5a34e9fe114367f04fcfc850f8 100644 (file)
@@ -137,7 +137,7 @@ an MMIO register read.
 */
 
 #define DRV_NAME       "8139too"
-#define DRV_VERSION    "0.9.18a"
+#define DRV_VERSION    "0.9.19"
 
 
 #include <linux/config.h>
@@ -620,6 +620,7 @@ static int netdev_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);
+static void __set_rx_mode (struct net_device *dev);
 static void rtl8139_hw_start (struct net_device *dev);
 
 #ifdef USE_IO_OPS
@@ -962,6 +963,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        dev->do_ioctl = netdev_ioctl;
        dev->tx_timeout = rtl8139_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
+       dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
        dev->irq = pdev->irq;
 
@@ -1725,18 +1727,21 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
        assert (tp->tx_info[entry].mapping == 0);
 
        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);
-               dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
-       } else {
+       if ( !((unsigned long)skb->data & 3) && skb_shinfo(skb)->nr_frags == 0 &&
+                       skb->ip_summed != CHECKSUM_HW) {
                tp->xstats.tx_buf_mapped++;
                tp->tx_info[entry].mapping =
                    pci_map_single (tp->pci_dev, skb->data, skb->len,
                                    PCI_DMA_TODEVICE);
                dma_addr = tp->tx_info[entry].mapping;
-       }
-
+       } else if (skb->len < TX_BUF_SIZE) {
+               skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
+               dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
+       } else {
+               dev_kfree_skb(skb);
+               tp->tx_info[entry].skb = NULL;
+               return 0;
+       }
        /* Note: the chip doesn't have auto-pad! */
        spin_lock_irq(&tp->lock);
        RTL_W32_F (TxAddr0 + (entry * 4), dma_addr);
@@ -1847,8 +1852,8 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
                            struct rtl8139_private *tp, void *ioaddr)
 {
        u8 tmp8;
-       int tmp_work = 1000;
-
+       int tmp_work;
+    
        DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
                 dev->name, rx_status);
        if (rx_status & RxTooLong) {
@@ -1863,33 +1868,52 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
                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;
 
        /* disable receive */
-       RTL_W8 (ChipCmd, CmdTxEnb);
-
-       /* A.C.: Reset the multicast list. */
-       rtl8139_set_rx_mode (dev);
-
-       /* XXX potentially temporary hack to
-        * restart hung receiver */
+       RTL_W8_F (ChipCmd, CmdTxEnb);
+       tmp_work = 200;
        while (--tmp_work > 0) {
-               barrier();
+               udelay(1);
+               tmp8 = RTL_R8 (ChipCmd);
+               if (!(tmp8 & CmdRxEnb))
+                       break;
+       }
+       if (tmp_work <= 0)
+               printk (KERN_WARNING PFX "rx stop wait too long\n");
+       /* restart receive */
+       tmp_work = 200;
+       while (--tmp_work > 0) {
+               RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb);
+               udelay(1);
                tmp8 = RTL_R8 (ChipCmd);
                if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
                        break;
-               RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
        }
-
-       /* G.S.: Re-enable receiver */
-       /* XXX temporary hack to work around receiver hang */
-       rtl8139_set_rx_mode (dev);
-
        if (tmp_work <= 0)
                printk (KERN_WARNING PFX "tx/rx enable wait too long\n");
-}
 
+       /* and reinitialize all rx related registers */
+       RTL_W8_F (Cfg9346, Cfg9346_Unlock);
+       /* Must enable Tx/Rx before setting transfer thresholds! */
+       RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+
+       tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
+       RTL_W32 (RxConfig, tp->rx_config);
+       tp->cur_rx = 0;
+
+       DPRINTK("init buffer addresses\n");
+
+       /* Lock Config[01234] and BMCR register writes */
+       RTL_W8 (Cfg9346, Cfg9346_Lock);
+
+       /* init Rx ring buffer DMA address */
+       RTL_W32_F (RxBuf, tp->rx_ring_dma);
+
+       /* A.C.: Reset the multicast list. */
+       __set_rx_mode (dev);
+}
 
 static void rtl8139_rx_interrupt (struct net_device *dev,
                                  struct rtl8139_private *tp, void *ioaddr)
@@ -2312,11 +2336,10 @@ static inline u32 ether_crc (int length, unsigned char *data)
 }
 
 
-static void rtl8139_set_rx_mode (struct net_device *dev)
+static void __set_rx_mode (struct net_device *dev)
 {
        struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
-       unsigned long flags;
        u32 mc_filter[2];       /* Multicast hash filter */
        int i, rx_mode;
        u32 tmp;
@@ -2353,22 +2376,28 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
                }
        }
 
-       spin_lock_irqsave (&tp->lock, flags);
-
        /* We can safely update without stopping the chip. */
        tmp = rtl8139_rx_config | rx_mode;
        if (tp->rx_config != tmp) {
-               RTL_W32 (RxConfig, tmp);
+               RTL_W32_F (RxConfig, tmp);
                tp->rx_config = tmp;
        }
        RTL_W32_F (MAR0 + 0, mc_filter[0]);
        RTL_W32_F (MAR0 + 4, mc_filter[1]);
 
-       spin_unlock_irqrestore (&tp->lock, flags);
 
        DPRINTK ("EXIT\n");
 }
 
+static void rtl8139_set_rx_mode (struct net_device *dev)
+{
+       unsigned long flags;
+       struct rtl8139_private *tp = dev->priv;
+
+       spin_lock_irqsave (&tp->lock, flags);
+       __set_rx_mode(dev);
+       spin_unlock_irqrestore (&tp->lock, flags);
+}
 
 #ifdef CONFIG_PM
 
index 422894612d64843571c60ae09f93d0c5b27a6df4..c73bd6401356dcdfc0c355beced8df17851019a5 100644 (file)
                * Wake on lan support (Erik Gilling)
                * MXDMA fixes for serverworks
                * EEPROM reload
+
+       version 1.0.9 (Manfred Spraul)
+               * Main change: fix lack of synchronize
+               netif_close/netif_suspend against a last interrupt
+               or packet.
+               * do not enable superflous interrupts (e.g. the
+               drivers relies on TxDone - TxIntr not needed)
+               * wait that the hardware has really stopped in close
+               and suspend.
+               * workaround for the (at least) gcc-2.95.1 compiler
+               problem. Also simplifies the code a bit.
+               * disable_irq() in tx_timeout - needed to protect
+               against rx interrupts.
+               * stop the nic before switching into silent rx mode
+               for wol (required according to docu).
+
+
        TODO:
        * big endian support with CFG:BEM instead of cpu_to_le32
        * support for an external PHY
@@ -72,8 +89,8 @@
 */
 
 #define DRV_NAME       "natsemi"
-#define DRV_VERSION    "1.07+LK1.0.8"
-#define DRV_RELDATE    "Aug 07, 2001"
+#define DRV_VERSION    "1.07+LK1.0.9"
+#define DRV_RELDATE    "Oct 02, 2001"
 
 
 /* Updated to recommendations in pci-skeleton v2.03. */
@@ -345,6 +362,8 @@ enum intr_status_bits {
        IntrNormalSummary=0x025f, IntrAbnormalSummary=0xCD20,
 };
 
+#define DEFAULT_INTR 0x00f1cd65
+
 /* Bits in the RxMode register. */
 enum rx_mode_bits {
        AcceptErr=0x20, AcceptRunt=0x10,
@@ -435,6 +454,7 @@ struct netdev_private {
 static int  eeprom_read(long ioaddr, int location);
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void natsemi_reset(struct net_device *dev);
+static void natsemi_stop_rxtx(struct net_device *dev);
 static int  netdev_open(struct net_device *dev);
 static void check_link(struct net_device *dev);
 static void netdev_timer(unsigned long data);
@@ -460,6 +480,7 @@ static int netdev_set_sopass(struct net_device *dev, u8 *newval);
 static int netdev_get_sopass(struct net_device *dev, u8 *data);
 static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);
 static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);
+static void enable_wol_mode(struct net_device *dev, int enable_intr);
 static int  netdev_close(struct net_device *dev);
 
 \f
@@ -709,7 +730,26 @@ static void natsemi_reset(struct net_device *dev)
        }
 }
 
-\f
+static void natsemi_stop_rxtx(struct net_device *dev)
+{
+       long ioaddr = dev->base_addr;
+       int i;
+
+       writel(RxOff | TxOff, ioaddr + ChipCmd);
+       for(i=0;i< NATSEMI_HW_TIMEOUT;i++) {
+               if ((readl(ioaddr + ChipCmd) & (TxOn|RxOn)) == 0)
+                       break;
+               udelay(5);
+       }
+       if (i==NATSEMI_HW_TIMEOUT && debug) {
+               printk(KERN_INFO "%s: Tx/Rx process did not stop in %d usec.\n",
+                               dev->name, i*5);
+       } else if (debug > 2) {
+               printk(KERN_DEBUG "%s: Tx/Rx process stopped in %d usec.\n",
+                               dev->name, i*5);
+       }
+}
+
 static int netdev_open(struct net_device *dev)
 {
        struct netdev_private *np = dev->priv;
@@ -731,7 +771,9 @@ static int netdev_open(struct net_device *dev)
                return i;
        }
        init_ring(dev);
+       spin_lock_irq(&np->lock);
        init_registers(dev);
+       spin_unlock_irq(&np->lock);
 
        netif_start_queue(dev);
 
@@ -865,7 +907,7 @@ static void init_registers(struct net_device *dev)
        __set_rx_mode(dev);
 
        /* Enable interrupts by setting the interrupt mask. */
-       writel(IntrNormalSummary | IntrAbnormalSummary, ioaddr + IntrMask);
+       writel(DEFAULT_INTR, ioaddr + IntrMask);
        writel(1, ioaddr + IntrEnable);
 
        writel(RxOn | TxOn, ioaddr + ChipCmd);
@@ -892,30 +934,51 @@ static void netdev_timer(unsigned long data)
        add_timer(&np->timer);
 }
 
-static void tx_timeout(struct net_device *dev)
+static void dump_ring(struct net_device *dev)
 {
        struct netdev_private *np = dev->priv;
-       long ioaddr = dev->base_addr;
 
-       printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
-                  " resetting...\n", dev->name, (int)readl(ioaddr + TxRingPtr));
-
-       {
+       if (debug > 2) {
                int i;
-               printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
-               for (i = 0; i < RX_RING_SIZE; i++)
-                       printk(" %8.8x", (unsigned int)np->rx_ring[i].cmd_status);
-               printk("\n"KERN_DEBUG"  Tx ring %p: ", np->tx_ring);
+               printk(KERN_DEBUG "  Tx ring at %8.8x:\n",
+                          (int)np->tx_ring);
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" %4.4x", np->tx_ring[i].cmd_status);
-               printk("\n");
+                       printk(KERN_DEBUG " #%d desc. %8.8x %8.8x %8.8x.\n",
+                                  i, np->tx_ring[i].next_desc,
+                                  np->tx_ring[i].cmd_status, np->tx_ring[i].addr);
+               printk(KERN_DEBUG "  Rx ring %8.8x:\n",
+                          (int)np->rx_ring);
+               for (i = 0; i < RX_RING_SIZE; i++) {
+                       printk(KERN_DEBUG " #%d desc. %8.8x %8.8x %8.8x.\n",
+                                  i, np->rx_ring[i].next_desc,
+                                  np->rx_ring[i].cmd_status, np->rx_ring[i].addr);
+               }
        }
+}
+
+static void tx_timeout(struct net_device *dev)
+{
+       struct netdev_private *np = dev->priv;
+       long ioaddr = dev->base_addr;
+
+
+       disable_irq(dev->irq);
        spin_lock_irq(&np->lock);
-       natsemi_reset(dev);
-       drain_ring(dev);
-       init_ring(dev);
-       init_registers(dev);
+       if (netif_device_present(dev)) {
+               printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
+                          " resetting...\n", dev->name, readl(ioaddr + IntrStatus));
+               dump_ring(dev);
+
+               natsemi_reset(dev);
+               drain_ring(dev);
+               init_ring(dev);
+               init_registers(dev);
+       } else {
+               printk(KERN_WARNING "%s: tx_timeout while in suspended state?\n",
+                               dev->name);
+       }
        spin_unlock_irq(&np->lock);
+       enable_irq(dev->irq);
 
        dev->trans_start = jiffies;
        np->stats.tx_errors++;
@@ -946,14 +1009,17 @@ static void init_ring(struct net_device *dev)
        np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
        np->rx_head_desc = &np->rx_ring[0];
 
+       /* Please be carefull before changing this loop - at least gcc-2.95.1
+        * miscompiles it otherwise.
+        */
        /* Initialize all Rx descriptors. */
        for (i = 0; i < RX_RING_SIZE; i++) {
-               np->rx_ring[i].next_desc = cpu_to_le32(np->ring_dma+sizeof(struct netdev_desc)*(i+1));
+               np->rx_ring[i].next_desc = cpu_to_le32(np->ring_dma
+                               +sizeof(struct netdev_desc)
+                                *((i+1)%RX_RING_SIZE));
                np->rx_ring[i].cmd_status = cpu_to_le32(DescOwn);
                np->rx_skbuff[i] = NULL;
        }
-       /* Mark the last entry as wrapping the ring. */
-       np->rx_ring[i-1].next_desc = cpu_to_le32(np->ring_dma);
 
        /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
@@ -965,18 +1031,18 @@ static void init_ring(struct net_device *dev)
                np->rx_dma[i] = pci_map_single(np->pci_dev,
                                                skb->data, skb->len, PCI_DMA_FROMDEVICE);
                np->rx_ring[i].addr = cpu_to_le32(np->rx_dma[i]);
-               np->rx_ring[i].cmd_status = cpu_to_le32(DescIntr | np->rx_buf_sz);
+               np->rx_ring[i].cmd_status = cpu_to_le32(np->rx_buf_sz);
        }
        np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 
        for (i = 0; i < TX_RING_SIZE; i++) {
                np->tx_skbuff[i] = NULL;
                np->tx_ring[i].next_desc = cpu_to_le32(np->ring_dma
-                                       +sizeof(struct netdev_desc)*(i+1+RX_RING_SIZE));
+                                       +sizeof(struct netdev_desc)
+                                        *((i+1)%TX_RING_SIZE+RX_RING_SIZE));
                np->tx_ring[i].cmd_status = 0;
        }
-       np->tx_ring[i-1].next_desc = cpu_to_le32(np->ring_dma
-                                       +sizeof(struct netdev_desc)*(RX_RING_SIZE));
+       dump_ring(dev);
 }
 
 static void drain_ring(struct net_device *dev)
@@ -1035,25 +1101,25 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]);
 
        spin_lock_irq(&np->lock);
-
-#if 0
-       np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | DescIntr | skb->len);
-#else
-       np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len);
-#endif
-       /* StrongARM: Explicitly cache flush np->tx_ring and skb->data,skb->len. */
-       wmb();
-       np->cur_tx++;
-       if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) {
-               netdev_tx_done(dev);
-               if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1)
-                       netif_stop_queue(dev);
+       
+       if (netif_device_present(dev)) {
+               np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len);
+               /* StrongARM: Explicitly cache flush np->tx_ring and skb->data,skb->len. */
+               wmb();
+               np->cur_tx++;
+               if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) {
+                       netdev_tx_done(dev);
+                       if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1)
+                               netif_stop_queue(dev);
+               }
+               /* Wake the potentially-idle transmit channel. */
+               writel(TxOn, dev->base_addr + ChipCmd);
+       } else {
+               dev_kfree_skb_irq(skb);
+               np->stats.tx_dropped++;
        }
        spin_unlock_irq(&np->lock);
 
-       /* Wake the potentially-idle transmit channel. */
-       writel(TxOn, dev->base_addr + ChipCmd);
-
        dev->trans_start = jiffies;
 
        if (debug > 4) {
@@ -1115,7 +1181,9 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 
        ioaddr = dev->base_addr;
        np = dev->priv;
-
+       
+       if (!netif_device_present(dev))
+               return;
        do {
                /* Reading automatically acknowledges all int sources. */
                u32 intr_status = readl(ioaddr + IntrStatus);
@@ -1239,7 +1307,7 @@ static void netdev_rx(struct net_device *dev)
                        np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]);
                }
                np->rx_ring[entry].cmd_status =
-                       cpu_to_le32(DescIntr | np->rx_buf_sz);
+                       cpu_to_le32(np->rx_buf_sz);
        }
 
        /* Restart Rx engine if stopped. */
@@ -1305,11 +1373,13 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 
        /* The chip only need report frame silently dropped. */
        spin_lock_irq(&np->lock);
-       __get_stats(dev);
+       if (netif_running(dev) && netif_device_present(dev))
+               __get_stats(dev);
        spin_unlock_irq(&np->lock);
 
        return &np->stats;
 }
+
 /* The little-endian AUTODIN II ethernet CRC calculations.
    A big-endian version is also available.
    This is slow but compact code.  Do not use this routine for bulk data,
@@ -1408,7 +1478,8 @@ static void set_rx_mode(struct net_device *dev)
 {
        struct netdev_private *np = dev->priv;
        spin_lock_irq(&np->lock);
-       __set_rx_mode(dev);
+       if (netif_device_present(dev))
+               __set_rx_mode(dev);
        spin_unlock_irq(&np->lock);
 }
 
@@ -1718,76 +1789,94 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        }
 }
 
+static void enable_wol_mode(struct net_device *dev, int enable_intr)
+{
+       long ioaddr = dev->base_addr;
+
+       if (debug > 1)
+               printk(KERN_INFO "%s: remaining active for wake-on-lan\n", 
+                       dev->name);
+       /* For WOL we must restart the rx process in silent mode.
+        * Write NULL to the RxRingPtr. Only possible if
+        * rx process is stopped
+        */
+       writel(0, ioaddr + RxRingPtr);
+
+       /* and restart the rx process */
+       writel(RxOn, ioaddr + ChipCmd);
+
+       if (enable_intr) {
+               /* enable the WOL interrupt.
+                * Could be used to send a netlink message.
+                */
+               writel(readl(ioaddr + IntrMask) | WOLPkt, ioaddr + IntrMask);
+       }
+}
+
 static int netdev_close(struct net_device *dev)
 {
        long ioaddr = dev->base_addr;
        struct netdev_private *np = dev->priv;
-       u32 wol = readl(ioaddr + WOLCmd) & WakeOptsSummary;
-       u32 clkrun;
 
        netif_stop_queue(dev);
-       netif_carrier_off(dev);
 
        if (debug > 1) {
-               printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.",
+               printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
                           dev->name, (int)readl(ioaddr + ChipCmd));
                printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",
                           dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx);
        }
 
-       /* Only shut down chip if wake on lan is not set */
-       if (!wol) {
-               /* Disable interrupts using the mask. */
-               writel(0, ioaddr + IntrMask);
-               writel(0, ioaddr + IntrEnable);
-               writel(2, ioaddr + StatsCtrl);  /* Freeze Stats */
-           
-               /* Stop the chip's Tx and Rx processes. */
-               writel(RxOff | TxOff, ioaddr + ChipCmd);
-       } else if (debug > 1) {
-               printk(KERN_INFO "%s: remaining active for wake-on-lan\n", 
-                       dev->name);
-               /* spec says write 0 here */
-               writel(0, ioaddr + RxRingPtr);
-               /* allow wake-event interrupts now */
-               writel(readl(ioaddr + IntrMask) | WOLPkt, ioaddr + IntrMask);
-       }
        del_timer_sync(&np->timer);
 
-#ifdef __i386__
-       if (debug > 2) {
-               int i;
-               printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
-                          (int)np->tx_ring);
-               for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" #%d desc. %8.8x %8.8x.\n",
-                                  i, np->tx_ring[i].cmd_status, np->tx_ring[i].addr);
-               printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
-                          (int)np->rx_ring);
-               for (i = 0; i < RX_RING_SIZE; i++) {
-                       printk(KERN_DEBUG " #%d desc. %8.8x %8.8x\n",
-                                  i, np->rx_ring[i].cmd_status, np->rx_ring[i].addr);
-               }
-       }
-#endif /* __i386__ debugging only */
+       disable_irq(dev->irq);
+       spin_lock_irq(&np->lock);
+
+       writel(0, ioaddr + IntrEnable);
+       writel(0, ioaddr + IntrMask);
+       writel(2, ioaddr + StatsCtrl);  /* Freeze Stats */
+           
+       /* Stop the chip's Tx and Rx processes. */
+       natsemi_stop_rxtx(dev);
 
+       __get_stats(dev);
+       spin_unlock_irq(&np->lock);
+
+       /* race: shared irq and as most nics the DP83815
+        * reports _all_ interrupt conditions in IntrStatus, even
+        * disabled ones.
+        * packet received after disable_irq, but before stop_rxtx
+        * --> race. intr_handler would restart the rx process.
+        * netif_device_{de,a}tach around {enable,free}_irq.
+        */
+       netif_device_detach(dev);
+       enable_irq(dev->irq);
        free_irq(dev->irq, dev);
+       netif_device_attach(dev);
+       /* clear the carrier last - an interrupt could reenable it otherwise */
+       netif_carrier_off(dev);
+
+       dump_ring(dev);
        drain_ring(dev);
        free_ring(dev);
 
-       clkrun = np->SavedClkRun;
-       if (wol) {
-               /* make sure to enable PME */
-               clkrun |= 0x100;
-       }
-
-       /* Restore PME enable bit */
-       writel(np->SavedClkRun, ioaddr + ClkRun);
-       
+        {
+               u32 wol = readl(ioaddr + WOLCmd) & WakeOptsSummary;
+               u32 clkrun = np->SavedClkRun;
+               /* Restore PME enable bit */
+               if (wol) {
+                       /* restart the NIC in WOL mode.
+                        * The nic must be stopped for this.
+                        */
+                       enable_wol_mode(dev, 0);
+                       /* make sure to enable PME */
+                       clkrun |= 0x100;
+               }
+               writel(clkrun, ioaddr + ClkRun);
 #if 0
-       writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */
+               writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */
 #endif
-
+       }
        return 0;
 }
 
@@ -1805,49 +1894,71 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
 
 #ifdef CONFIG_PM
 
+/*
+ * suspend/resume synchronization:
+ * entry points:
+ *   netdev_open, netdev_close, netdev_ioctl, set_rx_mode, intr_handler,
+ *   start_tx, tx_timeout
+ * Reading from some registers can restart the nic!
+ * No function accesses the hardware without checking netif_device_present().
+ *     the check occurs under spin_lock_irq(&np->lock);
+ * exceptions:
+ *     * netdev_ioctl, netdev_open.
+ *             net/core checks netif_device_present() before calling them.
+ *     * netdev_close: doesn't hurt.
+ *     * netdev_timer: timer stopped by natsemi_suspend.
+ *     * intr_handler: doesn't acquire the spinlock. suspend calls
+ *             disable_irq() to enforce synchronization.
+ *
+ * netif_device_detach must occur under spin_unlock_irq(), interrupts from a detached
+ * device would cause an irq storm.
+ */
+
 static int natsemi_suspend (struct pci_dev *pdev, u32 state)
 {
        struct net_device *dev = pci_get_drvdata (pdev);
        struct netdev_private *np = dev->priv;
        long ioaddr = dev->base_addr;
 
-       netif_device_detach(dev);
-       /* no more calls to tx_timeout, hard_start_xmit, set_rx_mode */
        rtnl_lock();
-       rtnl_unlock();
-       /* noone within ->open */
        if (netif_running (dev)) {
-               int i;
                del_timer_sync(&np->timer);
-               /* no more link beat timer calls */
+
+               disable_irq(dev->irq);
                spin_lock_irq(&np->lock);
-               writel(RxOff | TxOff, ioaddr + ChipCmd);
-               for(i=0;i< NATSEMI_HW_TIMEOUT;i++) {
-                       if ((readl(ioaddr + ChipCmd) & (TxOn|RxOn)) == 0)
-                               break;
-                       udelay(5);
-               }
-               if (i==NATSEMI_HW_TIMEOUT && debug) {
-                       printk(KERN_INFO "%s: Tx/Rx process did not stop in %d usec.\n",
-                                       dev->name, i*5);
-               } else if (debug > 2) {
-                       printk(KERN_DEBUG "%s: Tx/Rx process stopped in %d usec.\n",
-                                       dev->name, i*5);
-               }
-               /* Tx and Rx processes stopped */
 
                writel(0, ioaddr + IntrEnable);
-               /* all irq events disabled. */
-               spin_unlock_irq(&np->lock);
-
-               synchronize_irq();
+               natsemi_stop_rxtx(dev);
+               netif_stop_queue(dev);
+               netif_device_detach(dev);
 
+               spin_unlock_irq(&np->lock);
+               enable_irq(dev->irq);
+               
                /* Update the error counts. */
                __get_stats(dev);
 
                /* pci_power_off(pdev, -1); */
                drain_ring(dev);
+               {
+                       u32 wol = readl(ioaddr + WOLCmd) & WakeOptsSummary;
+                       u32 clkrun = np->SavedClkRun;
+                       /* Restore PME enable bit */
+                       if (wol) {
+                               /* restart the NIC in WOL mode.
+                                * The nic must be stopped for this.
+                                * FIXME: use the WOL interupt 
+                                */
+                               enable_wol_mode(dev, 0);
+                               /* make sure to enable PME */
+                               clkrun |= 0x100;
+                       }
+                       writel(clkrun, ioaddr + ClkRun);
+               }
+       } else {
+               netif_device_detach(dev);
        }
+       rtnl_unlock();
        return 0;
 }
 
@@ -1857,18 +1968,27 @@ static int natsemi_resume (struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata (pdev);
        struct netdev_private *np = dev->priv;
 
-       if (netif_running (dev)) {
+       rtnl_lock();
+       if (netif_device_present(dev))
+               goto out;
+       if (netif_running(dev)) {
                pci_enable_device(pdev);
        /*      pci_power_on(pdev); */
                
                natsemi_reset(dev);
                init_ring(dev);
+               spin_lock_irq(&np->lock);
                init_registers(dev);
+               netif_device_attach(dev);
+               spin_unlock_irq(&np->lock);
 
                np->timer.expires = jiffies + 1*HZ;
                add_timer(&np->timer);
+       } else {
+               netif_device_attach(dev);
        }
-       netif_device_attach(dev);
+out:
+       rtnl_unlock();
        return 0;
 }
 
index 3bee3b574fc21d1f977ac742c0d87a37cf5f9e08..beb1430cc4318bad1e71b6a2d881551b98874931 100644 (file)
@@ -148,10 +148,10 @@ subsequent_board:
                for (i = 0; i < count; i++) {
                        unsigned char media_block = *p++;
                        int media_code = media_block & MEDIA_MASK;
-                       if (media_code & 0x40)
+                       if (media_block & 0x40)
                                p += 6;
                        printk(KERN_INFO "%s:  21041 media #%d, %s.\n",
-                                  dev->name, media_code & 15, medianame[media_code & 15]);
+                                  dev->name, media_code, medianame[media_code]);
                }
        } else {
                unsigned char *p = (void *)ee_data + ee_data[27];
index 797e1d83281c21d3f6cba35830858d8eb1f5eb49..053fdc3bdd0659ce22d38ae8011afb0580b8bd30 100644 (file)
@@ -301,7 +301,7 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
        long ioaddr = dev->base_addr;
        int csr5;
        int entry;
-       int missed;
+       int csr8;
        int rx = 0;
        int tx = 0;
        int oi = 0;
@@ -434,7 +434,6 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                }
                        }
                        if (csr5 & RxDied) {            /* Missed a Rx frame. */
-                                tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
 #ifdef CONFIG_NET_HW_FLOWCONTROL
                                if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
                                        tp->stats.rx_errors++;
@@ -548,9 +547,8 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                }
        }
 
-       if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
-               tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
-       }
+       csr8 = inl(ioaddr + CSR8);
+       tp->stats.rx_dropped += (csr8 & 0x1ffff) + ((csr8 >> 17) & 0xfff);
 
        if (tulip_debug > 4)
                printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
index f130784958ffdaf9e3d525130f2897c6f68f3d2e..810ceaad146a7e27fea70ad0d2d6d265d81ddaa2 100644 (file)
@@ -15,8 +15,8 @@
 */
 
 #define DRV_NAME       "tulip"
-#define DRV_VERSION    "0.9.15-pre6"
-#define DRV_RELDATE    "July 2, 2001"
+#define DRV_VERSION    "0.9.15-pre7"
+#define DRV_RELDATE    "Oct 2, 2001"
 
 #include <linux/config.h>
 #include <linux/module.h>
index 6a90f5b5f1b5ad0ed358978680398774f68453f5..3066566e819961a0995b35987a427b14c1d9623b 100644 (file)
@@ -341,6 +341,7 @@ static int do8bitIO = 0;
 
 /* The RIDs */
 #define RID_CAPABILITIES 0xFF00
+#define RID_RSSI       0xFF04
 #define RID_CONFIG     0xFF10
 #define RID_SSID       0xFF11
 #define RID_APLIST     0xFF12
@@ -627,6 +628,16 @@ typedef struct {
   u16 atimWindow;
 } BSSListRid;
 
+typedef struct {
+  u8 rssipct;
+  u8 rssidBm;
+} tdsRssiEntry;
+
+typedef struct {
+  u16 len;
+  tdsRssiEntry x[256];
+} tdsRssiRid;
+
 #pragma pack()
 
 #define TXCTL_TXOK (1<<1) /* report if tx is ok */
@@ -774,6 +785,7 @@ struct airo_info {
                        int whichbap);
        int (*header_parse)(struct sk_buff*, unsigned char *);
        unsigned short *flash;
+       tdsRssiEntry *rssi;
 #ifdef WIRELESS_EXT
        int                     need_commit;    // Need to set config
        struct iw_statistics    wstats;         // wireless stats
@@ -1076,6 +1088,8 @@ void stop_airo_card( struct net_device *dev, int freeres )
        struct airo_info *ai = (struct airo_info*)dev->priv;
        if (ai->flash)
                kfree(ai->flash);
+       if (ai->rssi)
+               kfree(ai->rssi);
        takedown_proc_entry( dev, ai );
        if (ai->registered) {
                unregister_netdev( dev );
@@ -1382,7 +1396,10 @@ static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
                                        if (!memcmp(sa,apriv->spy_address[i],6))
                                        {
                                                apriv->spy_stat[i].qual = hdr.rssi[0];
-                                               apriv->spy_stat[i].level = hdr.rssi[1];
+                                               if (apriv->rssi)
+                                                       apriv->spy_stat[i].level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
+                                               else
+                                                       apriv->spy_stat[i].level = (hdr.rssi[1] + 321) / 2;
                                                apriv->spy_stat[i].noise = 0;
                                                apriv->spy_stat[i].updated = 3;
                                                break;
@@ -1568,9 +1585,29 @@ static u16 setup_card(struct airo_info *ai, u8 *mac,
        if ( config->len ) {
                cfg = *config;
        } else {
+               tdsRssiRid rssi_rid;
+       
                // general configuration (read/modify/write)
                status = readConfigRid(ai, &cfg);
                if ( status != SUCCESS ) return ERROR;
+
+               status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid));
+               if ( status == SUCCESS ) {
+                       if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
+                               memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);
+               }
+               else {
+                       CapabilityRid cap_rid;
+                       if (ai->rssi) {
+                               kfree(ai->rssi);
+                               ai->rssi = NULL;
+                       }
+                       status = readCapabilityRid(ai, &cap_rid);
+                       if ((status == SUCCESS) && (cap_rid.softCap & 8))
+                               cfg.rmode |= RXMODE_NORMALIZED_RSSI;
+                       else
+                               printk(KERN_WARNING "airo: unknown received signal level\n");
+               }
                cfg.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
     
                /* Save off the MAC */
@@ -3814,7 +3851,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
                        /* Hum... Should put the right values there */
                        range.max_qual.qual = 10;
-                       range.max_qual.level = 100;
+                       range.max_qual.level = 0;
                        range.max_qual.noise = 0;
                        range.sensitivity = 65535;
 
@@ -3976,7 +4013,10 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                loseSync = 0;
                                memcpy(s[i].sa_data, BSSList.bssid, 6);
                                s[i].sa_family = ARPHRD_ETHER;
-                               qual[i].level = BSSList.rssi;
+                               if (local->rssi)
+                                       qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm;
+                               else
+                                       qual[i].level = (BSSList.rssi + 321) / 2;
                                qual[i].qual = qual[i].noise = 0;
                                qual[i].updated = 2;
                                if (BSSList.index == 0xffff) break;
@@ -4190,7 +4230,10 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 
        /* Signal quality and co. But where is the noise level ??? */
        local->wstats.qual.qual = status_rid.signalQuality;
-       local->wstats.qual.level = status_rid.normalizedSignalStrength;
+       if (local->rssi)
+               local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
+       else
+               local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
        local->wstats.qual.noise = 0;
        local->wstats.qual.updated = 3;
 
index 3c567682930ccdaa49aea467f724743d6e39e117..17a34777739228e47c35f64a03074c5df056b223 100644 (file)
  * particular order).
  *
  * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ * Copyright (C) 2001, David Gibson, IBM <hermes@gibson.dropbear.id.au>
  * 
- * This file distributed under the GPL, version 2.  */
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above.  If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#include <linux/config.h>
 
 #include <linux/module.h>
 #include <linux/types.h>
 
 #include "hermes.h"
 
-static char version[] __initdata = "hermes.c: 1 Aug 2001 David Gibson <hermes@gibson.dropbear.id.au>";
+static char version[] __initdata = "hermes.c: 3 Oct 2001 David Gibson <hermes@gibson.dropbear.id.au>";
 MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual MPL/GPL");
 
 /* These are maximum timeouts. Most often, card wil react much faster */
 #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
@@ -42,9 +65,6 @@ MODULE_LICENSE("GPL");
 #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
 #define BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
 
-#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
-
 /*
  * Debugging helpers
  */
@@ -292,7 +312,7 @@ int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid)
  * from firmware
  *
  * Callable from any context */
-static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
+int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
 {
        int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
        int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
@@ -305,9 +325,14 @@ static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
 
        k = BAP_BUSY_TIMEOUT;
        reg = hermes_read_reg(hw, oreg);
+       while ((reg & HERMES_OFFSET_BUSY) & k) {
+               k--;
+               udelay(1);
+               reg = hermes_read_reg(hw, oreg);
+       }
 
        if (reg & HERMES_OFFSET_BUSY)
-               return -EBUSY;
+               return -ETIMEDOUT;
 
        /* Now we actually set up the transfer */
        hermes_write_reg(hw, sreg, id);
@@ -342,7 +367,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
  *
  * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
  */
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
                     uint16_t id, uint16_t offset)
 {
        int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -356,7 +381,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
                goto out;
 
        /* Actually do the transfer */
-       hermes_read_data(hw, dreg, buf, len/2);
+       hermes_read_words(hw, dreg, buf, len/2);
 
  out:
        return err;
@@ -368,7 +393,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
  *
  * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
  */
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
                      uint16_t id, uint16_t offset)
 {
        int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -382,7 +407,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
                goto out;
        
        /* Actually do the transfer */
-       hermes_write_data(hw, dreg, buf, len/2);
+       hermes_write_words(hw, dreg, buf, len/2);
 
  out:  
        return err;
@@ -434,17 +459,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
           lengths in the records seem to be wrong, frequently */
        count = buflen / 2;
 
-#if 0
-       if (length)
-               count = (MIN(buflen, rlength) + 1) / 2;
-       else {
-               count = buflen / 2;
-               if (rlength != buflen)
-                       printk(KERN_WARNING "hermes_read_ltv(): Incorrect \
-record length %d instead of %d on RID 0x%04x\n", rlength, buflen, rid);
-       }
-#endif
-       hermes_read_data(hw, dreg, buf, count);
+       hermes_read_words(hw, dreg, buf, count);
 
  out:
        return err;
@@ -470,7 +485,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid,
 
        count = length - 1;
 
-       hermes_write_data(hw, dreg, value, count);
+       hermes_write_words(hw, dreg, value, count);
 
        err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, 
                                rid, &resp);
index 58c663331b5b904c92b454a7935d6656665dfceb..a8cfaf4f7d566077d49cd9c157ac1ead3dc71465 100644 (file)
@@ -50,6 +50,7 @@
 #define                HERMES_FRAME_LEN_MAX            (2304)
 #define                HERMES_MAX_MULTICAST            (16)
 #define                HERMES_MAGIC                    (0x7d1f)
+#define                HERMES_SYMBOL_MAX_VER           (14)
 
 /*
  * Hermes register offsets
 #define                HERMES_RID_WEP_AVAIL            (0xfd4f)
 #define                HERMES_RID_CURRENT_CHANNEL      (0xfdc1)
 #define                HERMES_RID_DATARATES            (0xfdc6)
-#define                HERMES_RID_SYMBOL_PRIMARY_VER   (0xfd03)
-#define                HERMES_RID_SYMBOL_SECONDARY_VER (0xfd21)
+#define                HERMES_RID_SYMBOL_SECONDARY_VER (0xfd24)
 #define                HERMES_RID_SYMBOL_KEY_LENGTH    (0xfc2B)
 
 /*
  * Frame structures and constants
  */
 
-#define __PACKED__ __attribute__ ((packed))
-
 typedef struct hermes_frame_desc {
        /* Hermes - i.e. little-endian byte-order */
-       uint16_t status __PACKED__;
-       uint16_t res1, res2 __PACKED__;
-       uint16_t q_info __PACKED__;
-       uint16_t res3, res4 __PACKED__;
-       uint16_t tx_ctl __PACKED__;
-} hermes_frame_desc_t;
+       uint16_t status;
+       uint16_t res1, res2;
+       uint16_t q_info;
+       uint16_t res3, res4;
+       uint16_t tx_ctl;
+} __attribute__ ((packed)) hermes_frame_desc_t;
 
 #define                HERMES_RXSTAT_ERR               (0x0003)
 #define                HERMES_RXSTAT_MACPORT           (0x0700)
@@ -265,20 +263,16 @@ typedef struct hermes_multicast {
 #define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name))
 #define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val)))
 
-/* Note that for the next two, the count is in 16-bit words, not bytes */
-#define hermes_read_data(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
-#define hermes_write_data(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
-
 /* Function prototypes */
 void hermes_struct_init(hermes_t *hw, uint io);
 int hermes_reset(hermes_t *hw);
 int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp);
 int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid);
 
-
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
+int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset);
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
                       uint16_t id, uint16_t offset);
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
                        uint16_t id, uint16_t offset);
 int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
                    uint16_t *length, void *buf);
@@ -323,6 +317,10 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
 #define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 )
 #define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
 
+/* Note that for the next two, the count is in 16-bit words, not bytes */
+#define hermes_read_words(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
+#define hermes_write_words(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
+
 #define HERMES_READ_RECORD(hw, bap, rid, buf) \
        (hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
 #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
index 777faa3e56b89b814ace88232600d6350cc0188c..3d5505048ef23e21548c542143dfbc7db3ddd31f 100644 (file)
@@ -1,4 +1,4 @@
-/* orinoco.c 0.07      - (formerly known as dldwd_cs.c and orinoco_cs.c)
+/* orinoco.c 0.08      - (formerly known as dldwd_cs.c and orinoco_cs.c)
  *
  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
  *       Rx path, but don't make as much noise about it.
  *     o Firmware detection cleanups.
  *
+ * v0.07 -> v0.08 - 3/10/2001 - David Gibson
+ *     o Fixed a possible buffer overrun found by the Stanford checker (in
+ *       dldwd_ioctl_setiwencode()).  Can only be called by root anyway, so not
+ *       a big problem.
+ *     o Turned has_big_wep on for Intersil cards.  That's not true for all of them
+ *       but we should at least let the capable ones try.
+ *     o Wait for BUSY to clear at the beginning of hermes_bap_seek().  I
+ *       realised that my assumption that the driver's serialization
+ *       would prevent the BAP being busy on entry was possibly false, because
+ *       things other than seeks may make the BAP busy.
+ *     o Use "alternate" (oui 00:00:00) encapsulation by default.
+ *       Setting use_old_encaps will mimic the old behaviour, but I
+ *       think we will be able to eliminate this.
+ *     o Don't try to make __initdata const (the version string).
+ *       This can't work because of the way the __initdata sectioning
+ *        works.
+ *     o Added MODULE_LICENSE tags.
+ *     o Support for PLX (transparent PCMCIA->PCI brdge) cards.
+ *     o Improved support for Symbol firmware - we can actually tell
+ *        the version now.
  *
  * TODO - Jean II
- *     o inline functions (lot's of candidate, need to reorder code)
+ *     o inline functions (lots of candidate, need to reorder code)
  *     o Test PrismII/Symbol cards & firmware versions
  *     o Mini-PCI support (some people have reported success - JII)
  */
 
+#include <linux/config.h>
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include "hermes.h"
 #include "orinoco.h"
 
-static char version[] __initdata = "orinoco.c 0.07 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = "orinoco.c 0.08 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
 MODULE_LICENSE("Dual MPL/GPL");
@@ -238,10 +260,8 @@ int dldwd_debug = ORINOCO_DEBUG;
 MODULE_PARM(dldwd_debug, "i");
 #endif
 
-/* FIXME: We need a better way of handling this */
-/* Set this flag to use 00:00:00 for the encapsulation oui instead of 00:00:F8 */
-static int use_alternate_encaps; /* =0 */
-MODULE_PARM(use_alternate_encaps, "i");
+int use_old_encaps = 0;
+MODULE_PARM(use_old_encaps, "i");
 
 const long channel_frequency[] = {
        2412, 2417, 2422, 2427, 2432, 2437, 2442,
@@ -307,12 +327,13 @@ struct dldwd_frame_hdr {
 
 /* 802.2 LLL header SNAP used for SNAP encapsulation over 802.11 */
 struct p8022_hdr encaps_hdr = {
-       0xaa, 0xaa, 0x03, {0x00, 0x00, 0xf8}
-};
-struct p8022_hdr alternate_encaps_hdr = {
        0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}
 };
 
+struct p8022_hdr old_encaps_hdr = {
+       0xaa, 0xaa, 0x03, {0x00, 0x00, 0xf8}
+};
+
 /* How many times to retry if we get an EIO reading the BAP in the Rx path */
 #define RX_EIO_RETRY           10
 
@@ -881,7 +902,7 @@ static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates,
        
        num = le16_to_cpu(list.len);
        *numrates = num;
-       num = MIN(num, max);
+       num = min(num, max);
 
        for (i = 0; i < num; i++) {
                rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
@@ -1286,7 +1307,7 @@ static void determine_firmware(struct net_device *dev)
 
        if (sta_id.vendor == 1) {
                /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
-                  ELSE, Meloc, HP, IBM, Dell 1150 */
+                  ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
                printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "
                       "version %d.%02d\n", dev->name,
                       sta_id.major, sta_id.minor);
@@ -1303,7 +1324,7 @@ static void determine_firmware(struct net_device *dev)
                priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
                                          Gold cards from the others? */
                priv->has_mwo = (firmver >= 0x60000);
-               priv->has_pm = (firmver >= 0x40020);
+               priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
                priv->has_preamble = 0;
                priv->ibss_port = 1;
                /* Tested with Lucent firmware :
@@ -1314,27 +1335,59 @@ static void determine_firmware(struct net_device *dev)
                /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
                /* Intel MAC : 00:02:B3:* */
                /* 3Com MAC : 00:50:DA:* */
+               union symbol_sta_id {
+                       char raw[HERMES_SYMBOL_MAX_VER];
+                       char string[HERMES_SYMBOL_MAX_VER + 1];
+               } symbol_sta_id;
+
+               /* Get the Symbol firmware version */
+               err = HERMES_READ_RECORD(hw, USER_BAP,
+                                        HERMES_RID_SYMBOL_SECONDARY_VER,
+                                        &(symbol_sta_id.raw));
+               if (err) {
+                       printk(KERN_WARNING "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
+                              dev->name, err);
+                       firmver = 0;
+                       symbol_sta_id.string[0] = '\0';
+               } else {
+                       /* The firmware revision is a string, the format is
+                        * something like : "V2.20-01".
+                        * Quick and dirty parsing... - Jean II
+                        */
+                       firmver = ((symbol_sta_id.raw[1] - '0') << 16)
+                         | ((symbol_sta_id.raw[3] - '0') << 12)
+                         | ((symbol_sta_id.raw[4] - '0') << 8)
+                         | ((symbol_sta_id.raw[6] - '0') << 4)
+                         | (symbol_sta_id.raw[7] - '0');
+
+                       symbol_sta_id.string[HERMES_SYMBOL_MAX_VER] = '\0';
+               }
+
                printk(KERN_DEBUG "%s: Looks like a Symbol firmware "
-                      "(unknown version)\n", dev->name);
+                      "version [%s] (parsing to %X)\n", dev->name,
+                      symbol_sta_id.string, firmver);
 
-               /* FIXME : we need to get Symbol firmware revision.
-                * I tried to use SYMBOL_***ARY_VER, but it didn't
-                * returned anything proper... */
                priv->firmware_type = FIRMWARE_TYPE_SYMBOL;
                priv->tx_rate_ctrl = 0xF;       /* 11 Mb/s auto */
                priv->need_card_reset = 1;
                priv->broken_reset = 0;
                priv->broken_allocate = 1;
                priv->has_port3 = 1;
-               priv->has_ibss = 1; /* FIXME */
-               priv->has_wep = 1; /* FIXME */
-               priv->has_big_wep = 1;  /* RID_SYMBOL_KEY_LENGTH */
+               priv->has_ibss = (firmver >= 0x20000);
+               priv->has_wep = (firmver >= 0x15012);
+               priv->has_big_wep = (firmver >= 0x20000);
                priv->has_mwo = 0;
-               priv->has_pm = 1; /* FIXME */
-               priv->has_preamble = 0; /* FIXME */
+               priv->has_pm = (firmver >= 0x20000) && (firmver < 0x22000);
+               priv->has_preamble = (firmver >= 0x20000);
                priv->ibss_port = 4;
-               /* Tested with Intel firmware : v15 => Jean II */
+               /* Tested with Intel firmware : 0x20015 => Jean II */
+               /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
        } else {
+               /* D-Link, Linksys, Adtron, ZoomAir, and many others...
+                * Samsung, Compaq 100/200 and Proxim are slightly
+                * different and less well tested */
+               /* D-Link MAC : 00:40:05:* */
+               /* Addtron MAC : 00:90:D1:* */
                printk(KERN_DEBUG "%s: Looks like an Intersil firmware "
                       "version %d.%02d\n", dev->name,
                       sta_id.major, sta_id.minor);
@@ -1347,7 +1400,7 @@ static void determine_firmware(struct net_device *dev)
                priv->has_port3 = 1;
                priv->has_ibss = (firmver >= 0x00007); /* FIXME */
                priv->has_wep = (firmver >= 0x00008);
-               priv->has_big_wep = 0;
+               priv->has_big_wep = priv->has_wep;
                priv->has_mwo = 0;
                priv->has_pm = (firmver >= 0x00007);
                priv->has_preamble = 0;
@@ -1427,9 +1480,9 @@ dldwd_init(struct net_device *dev)
                goto out;
        }
        if ( nickbuf.len )
-               len = MIN(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len));
+               len = min(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len));
        else
-               len = MIN(IW_ESSID_MAX_SIZE, 2 * reclen);
+               len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
        memcpy(priv->nick, &nickbuf.val, len);
        priv->nick[len] = '\0';
 
@@ -1556,20 +1609,12 @@ dldwd_get_wireless_stats(struct net_device *dev)
                err = HERMES_READ_RECORD(hw, USER_BAP,
                                         HERMES_RID_COMMSQUALITY, &cq);
                
-               le16_to_cpus(&cq.qual);
-               le16_to_cpus(&cq.signal);
-               le16_to_cpus(&cq.noise);
-               
                DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name,
                      cq.qual, cq.signal, cq.noise);
 
-               /* Why are we using MIN/MAX ? We don't really care
-                * if the value goes above max, because we export the
-                * raw dBm values anyway. The normalisation should be done
-                * in user space - Jean II */
-               wstats->qual.qual = MAX(MIN(cq.qual, 0x8b-0x2f), 0);
-               wstats->qual.level = MAX(MIN(cq.signal, 0x8a), 0x2f) - 0x95;
-               wstats->qual.noise = MAX(MIN(cq.noise, 0x8a), 0x2f) - 0x95;
+               wstats->qual.qual = le16_to_cpu(cq.qual);
+               wstats->qual.level = le16_to_cpu(cq.signal);
+               wstats->qual.noise = le16_to_cpu(cq.noise);
                wstats->qual.updated = 7;
        }
 
@@ -1593,9 +1638,9 @@ static inline void dldwd_spy_gather(struct net_device *dev,
         * source address with out list, and if match, get the stats... */
        for (i = 0; i < priv->spy_number; i++)
                if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
-                       priv->spy_stat[i].qual = MAX(MIN(cq->qual, 0x8b-0x2f), 0);
-                       priv->spy_stat[i].level = MAX(MIN(cq->signal, 0x8a), 0x2f) - 0x95;
-                       priv->spy_stat[i].noise = MAX(MIN(cq->noise, 0x8a), 0x2f) - 0x95;
+                       priv->spy_stat[i].qual = cq->qual;
+                       priv->spy_stat[i].level = cq->signal;
+                       priv->spy_stat[i].noise = cq->noise;
                        priv->spy_stat[i].updated = 7;
                }
 }
@@ -1674,7 +1719,7 @@ dldwd_xmit(struct sk_buff *skb, struct net_device *dev)
        dldwd_lock(priv);
 
        /* Length of the packet body */
-       len = MAX(skb->len - ETH_HLEN, ETH_ZLEN);
+       len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN);
 
        eh = (struct ethhdr *)skb->data;
 
@@ -1699,12 +1744,13 @@ dldwd_xmit(struct sk_buff *skb, struct net_device *dev)
                hdr.p8023.h_proto = htons(data_len + ENCAPS_OVERHEAD);
                
                /* 802.2 header */
-               /* FIXME: ugh, what a hack for the 00:00:00 APs.  Need to find a better way */
-               if (use_alternate_encaps)
-                       memcpy(&hdr.p8022, &alternate_encaps_hdr, sizeof(alternate_encaps_hdr));
+               if (! use_old_encaps) 
+                       memcpy(&hdr.p8022, &encaps_hdr,
+                              sizeof(encaps_hdr));
                else
-                       memcpy(&hdr.p8022, &encaps_hdr, sizeof(encaps_hdr));
-
+                       memcpy(&hdr.p8022, &encaps_hdr,
+                              sizeof(old_encaps_hdr));
+                       
                hdr.ethertype = eh->h_proto;
                err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
                                         txfid, 0);
@@ -1933,12 +1979,12 @@ static int dldwd_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq)
        uint16_t xlen = 0;
        int err = 0;
        char keybuf[MAX_KEY_SIZE];
-
+       
        if (erq->pointer) {
                /* We actually have a key to set */
-               if(erq->length > MAX_KEY_SIZE)
+               if ( (erq->length < SMALL_KEY_SIZE) || (erq->length > MAX_KEY_SIZE) )
                        return -EINVAL;
-
+               
                if (copy_from_user(keybuf, erq->pointer, erq->length))
                        return -EFAULT;
        }
@@ -3512,7 +3558,7 @@ dldwd_proc_get_hermes_recs(char *page, char **start, off_t requested_offset,
 
                buf += sprintf(buf, "%-15s (0x%04x): length=%d (%d bytes)\tvalue=", record_table[i].name,
                               rid, length, (length-1)*2);
-               len = MIN( MAX(minlen, (length-1)*2), maxlen);
+               len = min( (int)max(minlen, ((int)length-1)*2), maxlen);
 
                switch (record_table[i].displaytype) {
                case DISPLAY_WORDS:
@@ -3531,7 +3577,7 @@ dldwd_proc_get_hermes_recs(char *page, char **start, off_t requested_offset,
                        break;
 
                case DISPLAY_STRING:
-                       len = MIN(len, le16_to_cpu(val16[0])+2);
+                       len = min(len, le16_to_cpu(val16[0])+2);
                        val8[len] = '\0';
                        buf += sprintf(buf, "\"%s\"", (char *)&val16[1]);
                        break;
index 07d94110e4867b601e3c4987639f843578189165..c5f30c36cd9dbda9b36f4220ddf042b8d1dd20de 100644 (file)
@@ -25,7 +25,7 @@
 #define DLDWD_MACPORT          0
 #define IRQ_LOOP_MAX           10
 #define TX_NICBUF_SIZE         2048
-#define TX_NICBUF_SIZE_BUG     1585            /* Bug in Intel firmware */
+#define TX_NICBUF_SIZE_BUG     1585            /* Bug in Symbol firmware */
 #define MAX_KEYS               4
 #define MAX_KEY_SIZE           14
 #define LARGE_KEY_SIZE         13
@@ -110,7 +110,7 @@ extern struct list_head dldwd_instances;
 
 #ifdef ORINOCO_DEBUG
 extern int dldwd_debug;
-#define DEBUG(n, args...) if (dldwd_debug>(n)) printk(KERN_DEBUG args)
+#define DEBUG(n, args...) do { if (dldwd_debug>(n)) printk(KERN_DEBUG args); } while(0)
 #define DEBUGMORE(n, args...) do { if (dldwd_debug>(n)) printk(args); } while (0)
 #else
 #define DEBUG(n, args...) do { } while (0)
@@ -120,9 +120,6 @@ extern int dldwd_debug;
 #define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname);
 #define TRACE_EXIT(devname)  DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname);
 
-#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
-
 #define RUP_EVEN(a) ( (a) % 2 ? (a) + 1 : (a) )
 
 /* struct net_device methods */
index 651ee6c81925669dcc082fc309de2172aa9f0429..996eb4c6f68079217d603fb0a1ae48f24d06010a 100644 (file)
@@ -1,4 +1,4 @@
-/* orinoco_cs.c 0.07   - (formerly known as dldwd_cs.c)
+/* orinoco_cs.c 0.08   - (formerly known as dldwd_cs.c)
  *
  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -10,6 +10,8 @@
  * Copyright notice & release notes in file orinoco.c
  */
 
+#include <linux/config.h>
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -42,7 +44,7 @@
 
 /*====================================================================*/
 
-static char version[] __initdata = "orinoco_cs.c 0.07 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = "orinoco_cs.c 0.08 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
 
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
index b1f338e0aea579ddc91e9c2a30fed590a477d839..45966f06cb69c56c434b0211eea04f03fcf08698 100644 (file)
@@ -27,6 +27,8 @@
 0e11  Compaq Computer Corporation
        0001  PCI to EISA Bridge
        0002  PCI to ISA Bridge
+       0049  NC7132 Gigabit Upgrade Module
+       004a  NC6136 Gigabit Server Adapter
        0508  Netelligent 4/16 Token Ring
        1000  Triflex/Pentium Bridge, Model 1000
        2000  Triflex/Pentium Bridge, Model 2000
@@ -40,6 +42,8 @@
        a0f0  Advanced System Management Controller
        a0f3  Triflex PCI to ISA Bridge
        a0f7  PCI Hotplug Controller
+               8086 002a  PCI Hotplug Controller A
+               8086 002b  PCI Hotplug Controller B
        a0f8  USB Open Host Controller
        ae10  Smart-2/P RAID Controller
                0e11 4030  Smart-2/P Array Controller
        ae6d  NorthStar CPU to PCI Bridge
        b011  Integrated Netelligent 10/100
        b012  Netelligent 10 T/2
+       b01e  NC3120 Fast Ethernet NIC
+       b01f  NC3122 Fast Ethernet NIC
+       b02f  NC1120 Ethernet NIC
        b030  Netelligent WS 5100
-       b04a  10/100TX WOL UTP Controller
-       b0c6  10/100TX Embedded WOL UTP Controller
-       b0d7  NC3121 (Rev A & B)
+       b04a  10/100 TX PCI Intel WOL UTP Controller
+       b0c6  NC3161 Fast Ethernet NIC
+       b0c7  NC3160 Fast Ethernet NIC
+       b0d7  NC3121 Fast Ethernet NIC
+       b0dd  NC3131 Fast Ethernet NIC
+       b0de  NC3132 Fast Ethernet Module
+       b0df  NC6132 Gigabit Module
+       b0e0  NC6133 Gigabit Module
+       b0e1  NC3133 Fast Ethernet Module
+       b123  NC6134 Gigabit NIC
+       b134  NC3163 Fast Ethernet NIC
+       b13c  NC3162 Fast Ethernet NIC
+       b144  NC3123 Fast Ethernet NIC
+       b163  NC3134 Fast Ethernet NIC
+       b164  NC3135 Fast Ethernet Upgrade Module
+       b1a4  NC7131 Gigabit Server Adapter
        f130  NetFlex-3/P ThunderLAN 1.0
        f150  NetFlex-3/P ThunderLAN 2.3
-1000  Symbios Logic Inc. (formerly NCR)
+1000  LSI Logic / Symbios Logic (formerly NCR)
        0001  53c810
                1000 1000  8100S
        0002  53c820
                0e11 b10e  3D Rage LT Pro (Compaq Armada 1750)
                1028 0085  Rage 3D LT Pro
        4c44  3D Rage LT Pro AGP-66
-       4c46  Mobility M3 AGP 2x
+       4c45  Rage Mobility M3 AGP
+       4c46  Rage Mobility M3 AGP 2x
        4c47  3D Rage LT-G 215LG
        4c49  3D Rage LT Pro
-       4c4d  3D Rage P/M Mobility AGP 2x
-       4c4e  3D Rage L Mobility AGP 2x
+       4c4d  Rage Mobility P/M AGP 2x
+       4c4e  Rage Mobility L AGP 2x
        4c50  3D Rage LT Pro
        4c51  3D Rage LT Pro
-       4c52  3D Rage P/M Mobility
-       4c53  3D Rage L Mobility
+       4c52  Rage Mobility P/M
+       4c53  Rage Mobility L
        4c54  264LT [Mach64 LT]
+       4d46  Rage Mobility M4 AGP
+       4d4c  Rage Mobility M4 AGP
        5041  Rage 128 PA
        5042  Rage 128 PB
        5043  Rage 128 PC
        000f  OHCI Compliant FireWire Controller
        0011  National PCI System I/O
        0012  USB Controller
-       0020  DP83815 (MacPhyter) Ethernet Controller
+       0020  DP83815
        d001  87410 IDE
 100c  Tseng Labs Inc
        3202  ET4000/W32p rev A
                1113 1207  EN-1207-TX Fast Ethernet
                1186 1100  DFE-500TX Fast Ethernet
                1186 1112  DFE-570TX Fast Ethernet
+               1186 1140  DFE-660 Cardbus Ethernet 10/100
+               1186 1142  DFE-660 Cardbus Ethernet 10/100
                1282 9100  AEF-380TXD Fast Ethernet
                1385 1100  FA310TX Fast Ethernet
                2646 0001  KNE100TX Fast Ethernet
        0020  MCA
        0022  IBM27-82351
        002d  Python
-       002e  ServeRAID controller
+       002e  ServeRAID-3x
        0036  Miami
        003a  CPU to PCI Bridge
        003e  16/4 Token ring UTP/STP controller
        0144  Yotta Video Compositor Output
                1014 0145 Yotta Output Controller (ytout)
        0156  405GP PLB to PCI Bridge
+       01bd  Netfinity ServeRAID controller
+       01be  ServeRAID-4M
+       01bf  ServeRAID-4L
+       022e  ServeRAID-4H
        ffff  MPIC-2 interrupt controller
 1015  LSI Logic Corp of Canada
 1016  ICL Personal Systems
        9712  Pipeline 9712
        c24a  90C
 101e  American Megatrends Inc.
+       1960  MegaRAID
+               1028 0471 PowerEdge RAID Controller 3/QC
+               1028 0493 PowerEdge RAID Controller 3/DC
        9010  MegaRAID
        9030  EIDE Controller
        9031  EIDE Controller
        0005  PowerEdge Expandable RAID Controller 3/Di
        0006  PowerEdge Expandable RAID Controller 3/Di
        0008  PowerEdge Expandable RAID Controller 3/Di
+       000a  PowerEdge Expandable RAID Controller 3/Di
 1029  Siemens Nixdorf IS
 102a  LSI Logic
        0000  HYDRA
                0e11 b16f  Matrox MGA-G400 AGP
                102b 0328  Millennium G400 16Mb SDRAM
                102b 0338  Millennium G400 16Mb SDRAM
+               102b 0378  Millennium G400 32Mb SDRAM
+               102b 0641  Millennium G450 32Mb SDRAM
                102b 19d8  Millennium G400 16Mb SGRAM
                102b 19f8  Millennium G400 32Mb SGRAM
                102b 2159  Millennium G400 Dual Head 16Mb
                102b ff05  MGA-G100 Productiva AGP Multi-Monitor
                110a 001e  MGA-G100 AGP
        2007  MGA Mistral
+       2527  MGA G550 AGP
+               102b 0f84  Millennium G550 Dual Head DDR 32Mb
        4536  VIA Framegrabber
        6573  Shark 10/100 Multiport SwitchNIC
 102c  Chips and Technologies
        4802  Falcon
        4803  Hawk
        4806  CPX8216
+       4d68  20268
        5600  SM56 PCI Modem
                1057 0300  SM56 PCI Speakerphone Modem
                1057 0301  SM56 PCI Voice Modem
        0012  YMF-754 [DS-1E Audio Controller]
                1073 0012  DS-XG PCI Audio Codec
        0020  DS-1 Audio
+       2000  DS2416 Digital Mixing Card
+               1073 2000  DS2416 Digital Mixing Card
 1074  NexGen Microsystems
        4e78  82c500/1
 1075  Advanced Integrations Research
 1076  Chaintech Computer Co. Ltd
-1077  Q Logic
+1077  QLogic Corp.
+       1016  QLA10160
        1020  ISP1020
        1022  ISP1022
-       1080  ISP1080
-       1240  ISP1240
-       1280  ISP1280
+       1080  QLA1080
+       1216  QLA12160
+               101e 8471 QLA12160 on AMI MegaRAID
+               101e 8493 QLA12160 on AMI MegaRAID
+       1240  QLA1240
+       1280  QLA1280
        2020  ISP2020A
-       2100  ISP2100
-       2200  ISP2200
+       2100  QLA2100
+       2200  QLA2200
+       2300  QLA2300
 1078  Cyrix Corporation
        0000  5510 [Grappa]
        0001  PCI Master
 109e  Brooktree Corporation
        0350  Bt848 TV with DMA push
        0351  Bt849A Video capture
-       036c  Bt879(?) Video Capture
+       036c  Bt879(??) Video Capture
                13e9 0070  Win/TV (Video Section)
        036e  Bt878
                0070 13eb  WinTV/GO
        906e  9060ES
        9080  9080
                10b5 9080  9080 [real subsystem ID not set]
+       a001  GTEK Jetport II 2 port serial adaptor
+       c001  GTEK Cyclone 16/32 port serial adaptor
 10b6  Madge Networks
        0001  Smart 16/4 PCI Ringnode
        0002  Smart 16/4 PCI Ringnode Mk2
                10b7 3590  TokenLink Velocity XL Adapter
        4500  3c450 Cyclone/unknown
        5055  3c555 Laptop Hurricane
-       6055  3c556 Laptop Tornado
+       6055  3c556 Laptop Hurricane
        6056  3c556B Laptop Hurricane
        5057  3c575 [Megahertz] 10/100 LAN CardBus
                10b7 5a57  3C575 Megahertz 10/100 LAN Cardbus PC Card
-       5157  3CCFE575BT Cyclone CardBus
+       5157  3c575 [Megahertz] 10/100 LAN CardBus
                10b7 5b57  3C575 Megahertz 10/100 LAN Cardbus PC Card
-       5257  3CCFE575CT Tornado CardBus
+       5257  3CCFE575CT Cyclone CardBus
        5900  3c590 10BaseT [Vortex]
        5920  3c592 EISA 10mbps Demon/Vortex
        5950  3c595 100BaseTX [Vortex]
        5b57  3c595 [Megahertz] 10/100 LAN CardBus
                10b7 5b57  3C575 Megahertz 10/100 LAN Cardbus PC Card
        6560  3CCFE656 Cyclone CardBus
-       6562  3CCFEM656B Cyclone CardBus
-       6564  3CXFEM656C Tornado CardBus
+       6562  3CCFEM656 [id 6562] Cyclone CardBus
+       6564  3CCFEM656 [id 6564] Cyclone CardBus
        7646  3cSOHO100-TX Hurricane
        8811  Token ring
        9000  3c900 10BaseT [Boomerang]
                10b7 1000  3C905C-TX Fast Etherlink for PC Management NIC
        9800  3c980-TX [Fast Etherlink XL Server Adapter]
                10b7 9800  3c980-TX Fast Etherlink XL Server Adapter
-       9805  3c982 Dual Port Server Cyclone
-               10b7 9805  3c982 Dual Port Server Cyclone
+       9805  3c980-TX 10/100baseTX NIC [Python-T]
+               10b7 9805  3c980 10/100baseTX NIC [Python-T]
 10b8  Standard Microsystems Corp [SMC]
        0005  83C170QF
                1055 e000  LANEPIC
                10f7 8312  MagicGraph 128XD
        0005  [MagicMedia 256AV]
        0006  NM2360 [MagicMedia 256ZX]
+       0016  NM2380 [MagicMedia 256XL+]
+               10c8 0016  MagicMedia 256XL+
        0083  [MagicGraph 128ZV Plus]
        8005  [MagicMedia 256AV Audio]
                0e11 b0d1  MagicMedia 256AV Audio Device on Discovery
        0008  EDGE 3D [NV1]
        0009  EDGE 3D [NV1]
        0010  Mutara V08 [NV2]
-       0020  Riva TnT 128 [NV04]
+       0020  Riva TnT [NV04]
                1043 0200  V3400 TNT
                1048 0c18  Erazor II SGRAM
                1092 0550  Viper V550
                1102 102e  CT6971 GeForce 256 DDR
                14af 5021  3D Prophet DDR-DVI
        0103  Quadro (GeForce 256 GL)
-       0110  NV11
-       0111  NV11 DDR
-       0113  NV11 GL
-       0150  NV15 (Geforce2 GTS)
+       0110  NV11 (GeForce2 MX)
+       0111  NV11 (GeForce2 MX DDR)
+       0112  GeForce2 Go
+       0113  NV11 (GeForce2 MXR)
+       0150  NV15 (Geforce2 Pro)
                107d 2840  WinFast GeForce2 GTS with TV output
        0151  NV15 DDR (Geforce2 GTS)
-       0152  NV15 Bladerunner (Geforce2 GTS)
-       0153  NV15 GL (Quadro2)
+       0152  NV15 Bladerunner (Geforce2 Ultra)
+       0153  NV15 GL (Quadro2 Pro)
+       0203  Quadro DCC
 10df  Emulex Corporation
        10df  Light Pulse Fibre Channel Adapter
        1ae5  LP6000 Fibre Channel Host Adapter
        9128  IMS9129 [Twin turbo 128]
 10e1  Tekram Technology Co.,Ltd.
        0391  TRM-S1040
+               10e1 0391  DC-315U SCSI-3 Host Adapter
        690c  DC-690c
        dc29  DC-290
 10e2  Aptix Corporation
                1025 8921  ALN-325
                10bd 0320  EP-320X-R
                10ec 8139  RT8139
+               1186 1300  DFE-538TX
                1186 1320  SN5200
                1259 2500  AT-2500TX
                1429 d010  ND010
        9401  INI-950
        9500  360P
 1102  Creative Labs
-       0002  SB Live! EMU10000
+       0002  SB Live! EMU10k1
                1102 0020  CT4850 SBLive! Value
                1102 0021  CT4620 SBLive!
                1102 002f  SBLive! mainboard implementation 
                1102 8051  CT4850 SBLive! Value
        7002  SB Live!
                1102 0020  Gameport Joystick
-1103  HighPoint Technologies, Inc.
-       0003  HPT343 UltraDMA 33 IDE Controller
-       0004  HPT366/370 UltraDMA 66/100 IDE Controller
+1103  Triones Technologies, Inc.
+       0003  HPT343
+       0004  HPT366 / HPT370
+               1103 0005  HPT370 UDMA100
 1104  RasterOps Corp.
 1105  Sigma Designs, Inc.
        8300  REALmagic Hollywood Plus DVD Decoder
        0505  VT82C505
        0561  VT82C561
        0571  Bus Master IDE
-       0576  VT82C576 [Apollo Master]
+       0576  VT82C576 3V [Apollo Master]
        0585  VT82C585VP [Apollo VP1/VPX]
        0586  VT82C586/A/B PCI-to-ISA [Apollo VP]
                1106 0000  MVP3 ISA Bridge
                1106 0686  VT82C686/A PCI to ISA Bridge
        0691  VT82C693A/694x [Apollo PRO133x]
                1458 0691  VT82C691 Apollo Pro System Controller
-       0698  VT82C693A [Apollo Pro133 AGP]
        0693  VT82C693 [Apollo Pro Plus]
+       0698  VT82C693A [Apollo Pro133 AGP]
        0926  VT82C926 [Amazon]
        1000  VT82C570MV
        1106  VT82C570MV
-       1571  VT82C576 IDE [Apollo Master]
+       1571  VT82C416MV
        1595  VT82C595/97 [Apollo VP2/97]
        3038  UHCI USB
                1234 0925  MVP3 USB Controller
        8598  VT82C598/694x [Apollo MVP3/Pro133x AGP]
        8601  VT8601 [Apollo ProMedia AGP]
        8605  VT8605 [PM133 AGP]
-       B091  VT8633 [Apollo Pro266 AGP]
-       B099  VT8367 [KT266 AGP]
+       b091  VT8633 [Apollo Pro266 AGP]
+       b099  VT8367 [KT266 AGP]
        8691  VT82C691 [Apollo Pro]
 1107  Stratus Computers
        0576  VIA VT82C570MV [Apollo] (Wrong vendor ID!)
 1118  Berg Electronics
 1119  ICP Vortex Computersysteme GmbH
        0000  GDT 6000/6020/6050
-       0001  GDT 6000b/6010
+       0001  GDT 6000B/6010
        0002  GDT 6110/6510
        0003  GDT 6120/6520
        0004  GDT 6530
        0006  GDT 6x17
        0007  GDT 6x27
        0008  GDT 6537
-       0009  GDT 5557
-       000a  GDT 6x15
-       000b  GDT 6x25
+       0009  GDT 6557
+       000a  GDT 6115/6515
+       000b  GDT 6125/6525
        000c  GDT 6535
        000d  GDT 6555
        0100  GDT 6117RP/6517RP
        0103  GDT 6557RP
        0104  GDT 6111RP/6511RP
        0105  GDT 6121RP/6521RP
-       0110  GDT 6117RP1/6517RP1
-       0111  GDT 6127RP1/6527RP1
-       0112  GDT 6537RP1
-       0113  GDT 6557RP1
-       0114  GDT 6111RP1/6511RP1
-       0115  GDT 6121RP1/6521RP1
-       0118  GDT 6x18RD
-       0119  GDT 6x28RD
-       011a  GDT 6x38RD
-       011b  GDT 6x58RD
-       0120  GDT 6117RP2/6517RP2
-       0121  GDT 6127RP2/6527RP2
-       0122  GDT 6537RP2
-       0123  GDT 6557RP2
-       0124  GDT 6111RP2/6511RP2
-       0125  GDT 6121RP2/6521RP2
-       0168  GDT 7x18RN
-       0169  GDT 7x28RN
-       016a  GDT 7x38RN
-       016b  GDT 7x58RN
-       0210  GDT 6x19RD
-       0211  GDT 6x29RD
-       0260  GDT 7x19RN
-       0261  GDT 7x29RN
+       0110  GDT 6117RD/6517RD
+       0111  GDT 6127RD/6527RD
+       0112  GDT 6537RD
+       0113  GDT 6557RD
+       0114  GDT 6111RD/6511RD
+       0115  GDT 6121RD/6521RD
+       0118  GDT 6118RD/6518RD/6618RD
+       0119  GDT 6128RD/6528RD/6628RD
+       011a  GDT 6538RD/6638RD
+       011b  GDT 6558RD/6658RD
+       0138  GDT 6118RS/6518RS/6618RS
+       0139  GDT 6128RS/6528RS/6628RS
+       013a  GDT 6538RS/6638RS
+       013b  GDT 6558RS/6658RS
+       0166  GDT 7113RN/7513RN/7613RN
+       0167  GDT 7123RN/7523RN/7623RN
+       0168  GDT 7118RN/7518RN/7518RN
+       0169  GDT 7128RN/7528RN/7628RN
+       016a  GDT 7538RN/7638RN
+       016b  GDT 7558RN/7658RN
+       016c  GDT 7533RN/7633RN
+       016d  GDT 7543RN/7643RN
+       016e  GDT 7553RN/7653RN
+       016f  GDT 7563RN/7663RN
+       0210  GDT 6519RD/6619RD
+       0211  GDT 6529RD/6629RD
+       0260  GDT 7519RN/7619RN
+       0261  GDT 7529RN/7629RN
 111a  Efficient Networks, Inc
        0000  155P-MF1 (FPGA)
        0002  155P-MF1 (ASIC)
 1145  Workbit Corporation
 1146  Force Computers
 1147  Interface Corp
-1148  SysKonnect GmbH
+1148  Syskonnect (Schneider & Koch)
        4000  FDDI Adapter
                0e11 b03b  Netelligent 100 FDDI DAS Fibre SC
                0e11 b03c  Netelligent 100 FDDI SAS Fibre SC
                1148 5841  FDDI SK-5841 (SK-NET FDDI-FP64)
                1148 5843  FDDI SK-5843 (SK-NET FDDI-LP64)
                1148 5844  FDDI SK-5844 (SK-NET FDDI-LP64 DAS)
-       4200  Token Ring adapter
+       4200  Token ring adaptor
        4300  Gigabit Ethernet
                1148 9821  SK-9821 (1000Base-T single link)
                1148 9822  SK-9822 (1000Base-T dual link)
 118b  Hypertec Pty Limited
 118c  Corollary, Inc
        0014  PCIB [C-bus II to PCI bus host bridge chip]
+       1117  Intel 8-way XEON Profusion Chipset [Cache Coherency Filter]
 118d  BitFlow Inc
        0001  Raptor-PCI framegrabber
        0012  Model 12 Road Runner Frame Grabber
        1221  82C092G
 119c  Information Technology Inst.
 119d  Bug, Inc. Sapporo Japan
-119e  Fujitsu Microelectronics Europe GMBH
+119e  Fujitsu Microelectronics Ltd.
        0001 FireStream 155
        0003 FireStream 50
 119f  Bull HN Information Systems
 11f5  Computing Devices International
 11f6  Compex
        0112  ENet100VG4
+       0113  FreedomLine 100
        1401  ReadyLink 2000
        2011  RL100-ATX 10/100
        2201  ReadyLink 100TX (Winbond W89C840)
                121a 0060  Voodoo3 3500 TV (NTSC)
                121a 0061  Voodoo3 3500 TV (PAL)
                121a 0062  Voodoo3 3500 TV (SECAM)
-       0009  Voodoo 4
+       0009  Voodoo 4 / Voodoo 5
+               121a 0009  Voodoo5 AGP 5500/6000
 121b  Advanced Telecommunications Modules
 121c  Nippon Texaco., Ltd
 121d  Lippert Automationstechnik GmbH
                8086 5753  ES1371, ES1373 AudioPCI On Motherboard WS440BX
        5000  ES1370 [AudioPCI]
                4942 4c4c  Creative Sound Blaster AudioPCI128
-       5880  CT5880 [AudioPCI]
+       5880  5880 AudioPCI
                1274 2000  Creative Sound Blaster AudioPCI128
                1274 5880  Creative Sound Blaster AudioPCI128
-               1462 6880  CT5880 AudioPCI On Motherboard MS-6188 1.00
-               270f 2001  CT5880 AudioPCI On Motherboard 6CTR
-               270f 2200  CT5880 AudioPCI On Motherboard 6WTX
-               270f 7040  CT5880 AudioPCI On Motherboard 6ATA4
+               1462 6880  5880 AudioPCI On Motherboard MS-6188 1.00
+               270f 2001  5880 AudioPCI On Motherboard 6CTR
+               270f 2200  5880 AudioPCI On Motherboard 6WTX
+               270f 7040  5880 AudioPCI On Motherboard 6ATA4
 1275  Network Appliance Corporation
 1276  Switched Network Technologies, Inc.
 1277  Comstream
 12ac  Measurex Corporation
 12ad  Multidata GmbH
 12ae  Alteon Networks Inc.
-       0001  AceNIC Gigabit Ethernet
+       0001  AceNIC Gigabit Ethernet (Fibre)
                1410 0104  Gigabit Ethernet-SX PCI Adapter (14100401)
+       0002  AceNIC Gigabit Ethernet (Copper)
 12af  TDK USA Corp
 12b0  Jorge Scientific Corp
 12b1  GammaLink
 1312  Acuity Imaging, Inc
 1313  Yaskawa Electric Co.
 1316  Teradyne Inc
-1317  Bridgecom, Inc
+1317  Linksys
+       0985  Network Everywhere Fast Ethernet 10/100 model NC100
 1318  Packet Engines Inc.
        0911  PCI Ethernet Adapter
 1319  Fortemedia, Inc
 1384  Reality Simulation Systems Inc
 1385  Netgear
        620a  GA620
+       f311  FA311
 1386  Video Domain Technologies
 1387  Systran Corp
 1388  Hitachi Information Technology Co Ltd
 14e2  INFOLIBRIA
 14e3  AMTELCO
 14e4  BROADCOM Corporation
-       1644  Tigon3
+       1644  NetXtreme BCM5700 Gigabit Ethernet
+               10b7 1000  3C996-T 1000BaseTX
+               10b7 1001  3C996B-T 1000BaseTX
+               10b7 1002  3C996C-T 1000BaseTX
+               10b7 1003  3C997-T 1000BaseTX
+               10b7 1004  3C996-SX 1000BaseSX
+               10b7 1005  3C997-SX 1000BaseSX
+               14e4 0002  NetXtreme 1000BaseSX
+               14e4 0003  NetXtreme 1000BaseSX
+               14e4 0004  NetXtreme 1000BaseTX
+               14e4 1644  NetXtreme BCM5700 1000BaseTX
+       1645  NetXtreme BCM5701 Gigabit Ethernet
+               0e11 007d  NC6770 1000BaseSX
+               0e11 007c  NC7770 1000BaseTX
+               0e11 0085  NC7780 1000BaseTX
+               10b7 1004  3C996-SX 1000BaseSX
+               10b7 1006  3C996B-T 1000BaseTX
+               10b7 1007  3C1000-T 1000BaseTX
+               10b7 1008  3C940-BR01 1000BaseTX
+               14e4 0001  NetXtreme BCM5701 1000BaseTX
+               14e4 0005  NetXtreme BCM5701 1000BaseTX
+               14e4 0006  NetXtreme BCM5701 1000BaseTX
+               14e4 0007  NetXtreme BCM5701 1000BaseSX
+               14e4 0008  NetXtreme BCM5701 1000BaseTX
+               14e4 8008  NetXtreme BCM5701 1000BaseTX
 14e5  Pixelfusion Ltd
 14e6  SHINING Technology Inc
 14e7  3CX
                14f1 2015  SoftK56 Speakerphone Winmodem
        2016  SoftK56 Speakerphone Winmodem
                14f1 2016  SoftK56 Speakerphone Winmodem
+       2443  SoftK56 Speakerphone Winmodem
+               14f1 2443  SoftK56 Speakerphone Winmodem
 14f2  MOBILITY Electronics
 14f3  BROADLOGIC
 14f4  TOKYO Electronic Industry CO Ltd
 # 1507  HTEC Ltd
 # Commented out because there are no known HTEC chips and 1507 is already
 # used by mistake by Motorola (see vendor ID 1057)
-1507  Motorola ? / HTEC
+1507  Motorola ?? / HTEC
        0001  MPC105 [Eagle]
        0002  MPC106 [Grackle]
        0003  MPC8240 [Kahlua]
 270b  Xantel Corporation
 270f  Chaintech Computer Co. Ltd
 2711  AVID Technology Inc.
-2a15  3D Vision(?)
+2a15  3D Vision(???)
 3000  Hansol Electronics Inc.
 3142  Post Impression Systems.
 3388  Hint Corp
                3d3d 0125  Oxygen VX1
                3d3d 0127  Permedia3 Create!
        000a  GLINT R3
+               3d3d 0121  Oxygen VX1
        0100  Permedia II 2D+3D
        1004  Permedia
        3d04  Permedia
                5333 9125  86C394-397 Savage4 SGRAM 125
                5333 9143  86C394-397 Savage4 SGRAM 143
        8a23  Savage 4
+       8a25  ProSavage PM133
+       8a26  ProSavage KM133
        8c00  ViRGE/M3
        8c01  ViRGE/MX
        8c02  ViRGE/MX+
        8c03  ViRGE/MX+MV
-       8c10  86C270-294 Savage/MX-/IX
-       8c12  86C270-294 Savage/MX-/IX
+       8c10  86C270-294 Savage/MX-MV
+       8c11  82C270-294 Savage/MX
+       8c12  86C270-294 Savage/IX-MV
+       8c13  86C270-294 Savage/IX
        9102  86C410 Savage 2000
                1092 5932  Viper II Z200
                1092 5934  Viper II Z200
 5455  Technische University Berlin
        4458  S5933
 5519  Cnet Technologies, Inc.
+5544  Dunord Technologies
+       0001  I-30xx Scanner Interface
 5555  Genroco, Inc
        0003  TURBOstor HFP-832 [HiPPI NIC]
 5700  Netpower
        04a3  82434LX [Mercury/Neptune]
        04d0  82437FX [Triton FX]
        0960  80960RP [i960 RP Microprocessor/Bridge]
-       1000  82542 Gigabit Ethernet Adapter
+       0964  80960RP [i960 RP Microprocessor/Bridge]
+       1000  82542 Gigabit Ethernet Controller
                0e11 b0df  NC1632 Gigabit Ethernet Adapter
                0e11 b0e0  NC1633 Gigabit Ethernet Adapter
                0e11 b123  NC1634 Gigabit Ethernet Adapter
                1014 0119  Netfinity Gigabit Ethernet SX Adapter
-               8086 1000  EtherExpress PRO/1000 Gigabit Server Adapter
+       1001  82543GC Gigabit Ethernet Controller
+       1004  82543GC Gigabit Ethernet Controller
+       1008  82544EI Gigabit Ethernet Controller
+       100c  82544GC Gigabit Ethernet Controller
+       100d  82544GC Gigabit Ethernet Controller
        1030  82559 InBusiness 10/100
+       1031  82801CAM (ICH3) Chipset Ethernet Controller
+       1032  82801CAM (ICH3) Chipset Ethernet Controller
+       1033  82801CAM (ICH3) Chipset Ethernet Controller
+       1034  82801CAM (ICH3) Chipset Ethernet Controller
+       1035  82801CAM (ICH3) Chipset Ethernet Controller
+       1036  82801CAM (ICH3) Chipset Ethernet Controller
+       1037  82801CAM (ICH3) Chipset Ethernet Controller
+       1038  82801CAM (ICH3) Chipset Ethernet Controller
+       1130  82815 815 Chipset Host Bridge and Memory Controller Hub
+       1132  82815 CGC [Chipset Graphics Controller] 
        1161  82806AA PCI64 Hub Advanced Programmable Interrupt Controller
        1209  82559ER
        1221  82092AA_0
        1222  82092AA_1
        1223  SAA7116
        1225  82452KX/GX [Orion]
-       1226  82596
-       1227  82865 [Ether Express Pro 100]
-       1228  82556 [Ether Express Pro 100 Smart]
+       1226  82596 PRO/10 PCI
+       1227  82865 EtherExpress PRO/100A
+       1228  82556 EtherExpress PRO/100 Smart
        1229  82557 [Ethernet Pro 100]
                0e11 b01e  NC3120
                0e11 b01f  NC3122
                0e11 b0dd  NC3131
                0e11 b0de  NC3132
                0e11 b0e1  NC3133
+               0e11 b144  NC3123 (82559)
                1014 005c  82558B Ethernet Pro 10/100
                1014 105c  Netfinity 10/100
                1033 8000  PC-9821X-B06
        1960  80960RP [i960RP Microprocessor]
                101e 0438  MegaRaid 438
                101e 0466  MegaRaid 466
+               101e 0467  MegaRaid 467
+               1028 0467  PowerEdge Expandable RAID Controller 2/DC
+               1028 1111  PowerEdge Expandable RAID Controller 2/SC
                103c 10c6  MegaRaid 438
                103c 10c7  MegaRaid T5
                1111 1111  MegaRaid 466
                11d4 0048  SoundMAX Integrated Digital Audio
        2426  82801AB AC'97 Modem
        2428  82801AB PCI Bridge
-       2440  82801BA ISA Bridge (ICH2)
-       2442  82801BA(M) USB (Hub A)
-       2443  82801BA(M) SMBus
-       2444  82801BA(M) USB (Hub B)
-       2445  82801BA(M) AC'97 Audio
-       2446  82801BA(M) AC'97 Modem
-       2448  82801BA PCI
-       2449  82801BA(M) Ethernet
-       244a  82801BAM IDE U100
-       244b  82801BA IDE U100
-       244c  82801BAM ISA Bridge (ICH2)
-       244e  82801BAM PCI
+       2440  82820 820 (Camino 2) Chipset ISA Bridge (ICH2)
+       2442  82820 820 (Camino 2) Chipset USB (Hub A)
+       2443  82820 820 (Camino 2) Chipset SMBus
+       2444  82820 820 (Camino 2) Chipset USB (Hub B)
+       2445  82820 820 (Camino 2) Chipset AC'97 Audio Controller
+       2446  82820 820 (Camino 2) Chipset AC'97 Modem Controller
+       2448  82820 820 (Camino 2) Chipset PCI (-M)
+       2449  82820 (ICH2) Chipset Ethernet Controller
+       244a  82820 820 (Camino 2) Chipset IDE U100 (-M)
+       244b  82820 820 (Camino 2) Chipset IDE U100
+       244c  82820 820 (Camino 2) Chipset ISA Bridge (ICH2-M)
+       244e  82820 820 (Camino 2) Chipset PCI
        2500  82820 820 (Camino) Chipset Host Bridge (MCH)
                1043 801c  P3C-2000 system chipset
        2501  82820 820 (Camino) Chipset Host Bridge (MCH)
        2520  82805AA MTH Memory Translator Hub
        2521  82804AA MRH-S Memory Repeater Hub for SDRAM
        2530  82850 850 (Tehama) Chipset Host Bridge (MCH)
+       2531  82850 860 (Wombat) Chipset Host Bridge (MCH)
        2532  82850 850 (Tehama) Chipset AGP Bridge
-       5200  EtherExpress PRO/100
-       5201  EtherExpress PRO/100
+       2533  82860 860 (Wombat) Chipset AGP Bridge
+       5200  EtherExpress PRO/100 Intelligent Server
+       5201  EtherExpress PRO/100 Intelligent Server
                8086 0001  EtherExpress PRO/100 Server Ethernet Adapter
+       530d  80310 IOP [IO Processor]
        7000  82371SB PIIX3 ISA [Natoma/Triton II]
        7010  82371SB PIIX3 IDE [Natoma/Triton II]
        7020  82371SB PIIX3 USB [Natoma/Triton II]
 9004  Adaptec
 # FIXME: [dj] In one document I have, lot of these AIC's are actually AHA's
        1078  AIC-7810
-       1160  AIC-1160 [Family Fiber Channel Adapter]
+       1160  AIC-1160 [Family Fibre Channel Adapter]
        2178  AIC-7821
        3860  AHA-2930CU
        3b78  AHA-4844W/4844UW
        00c0  7899A
        00c1  7899B
        00c3  7899D
+       00c5  RAID subsystem HBA
        00cf  7899P
 907f  Atronics
        2015  IDE-2015PL
@@ -5017,7 +5137,7 @@ C 0c  Serial bus controller
                10  OHCI
                80  Unspecified
                Fe  USB Device
-       04  Fiber Channel
+       04  Fibre Channel
        05  SMBus
        06  InfiniBand
 C 0d  Wireless controller
index 83368d4cc5f228f0ca15d74bd7c3cccf962b15e9..488e7d496f92a4e6cdf092070286e40c36d5bf25 100644 (file)
@@ -12,7 +12,7 @@
    Copyright 1992 - 2001 Kai Makisara
    email Kai.Makisara@metla.fi
 
-   Last modified: Sun Aug 12 12:34:28 2001 by makisara@kai.makisara.local
+   Last modified: Wed Oct  3 22:17:59 2001 by makisara@kai.makisara.local
    Some small formal changes - aeb, 950809
 
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
@@ -21,7 +21,7 @@
    error handling will be discarded.
  */
 
-static char *verstr = "20010812";
+static char *verstr = "20011003";
 
 #include <linux/module.h>
 
@@ -89,6 +89,8 @@ MODULE_PARM_DESC(max_buffers, "Maximum number of buffer allocated at initialisat
 MODULE_PARM(max_sg_segs, "i");
 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (32)");
 
+EXPORT_NO_SYMBOLS;
+
 #ifndef MODULE
 static struct st_dev_parm {
        char *name;
@@ -669,6 +671,7 @@ static int st_open(struct inode *inode, struct file *filp)
 
        if (STp->device->host->hostt->module)
                __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
+       STp->device->access_count++;
 
        if (!scsi_block_when_processing_errors(STp->device)) {
                retval = (-ENXIO);
@@ -909,6 +912,7 @@ static int st_open(struct inode *inode, struct file *filp)
                STp->buffer = NULL;
        }
        STp->in_use = 0;
+       STp->device->access_count--;
        if (STp->device->host->hostt->module)
            __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
        return retval;
@@ -1066,6 +1070,7 @@ static int st_release(struct inode *inode, struct file *filp)
 
        STp->in_use = 0;
        write_unlock_irqrestore(&st_dev_arr_lock, flags);
+       STp->device->access_count--;
        if (STp->device->host->hostt->module)
                __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
 
index 6b220143dc9058887fc35cf623be732173d550c2..b0235faa4e1e38a7e45510309c9c226eacbc1f27 100644 (file)
@@ -31,7 +31,7 @@
  *
  */
 
-#define CLGEN_VERSION "1.9.8"
+#define CLGEN_VERSION "1.9.9"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -273,6 +273,7 @@ static const struct {
        { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_8 },
        { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_4 },
        { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */
+       { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7543 },
        { BT_GD5480, NULL, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */
        { BT_PICASSO4, NULL, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */
        { BT_LAGUNA, "CL Laguna", PCI_DEVICE_ID_CIRRUS_5462 },
index a3ca017d6c23fa0b944bbe5cc77cb96dc7ac8261..52ca30f5a42ab0b396d986e984825bfaaa82a594 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/pgtable.h>
+#include <asm/btext.h>
 
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -757,6 +758,12 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
                console_fb_info = &p->info;
        }
 #endif /* CONFIG_FB_COMPAT_XPMAC */
+#ifdef CONFIG_BOOTX_TEXT
+       btext_update_display(p->frame_buffer_phys + CTRLFB_OFF,
+                            p->par.xres, p->par.yres,
+                            (cmode == CMODE_32? 32: cmode == CMODE_16? 16: 8),
+                            p->par.pitch);
+#endif /* CONFIG_BOOTX_TEXT */
 }
 
 
index 4aa1d3f6b36cf5444134beb5e1cc8e55a57c9281..80621868bd1cca4ece3a7c0ad288af9b0e14f08e 100644 (file)
@@ -32,7 +32,9 @@
 #endif
 #include <asm/io.h>
 #include <asm/prom.h>
+#ifdef CONFIG_BOOTX_TEXT
 #include <asm/bootx.h>
+#endif
 
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -95,8 +97,9 @@ static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
                        struct fb_info *info);
 static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
                        struct fb_info *info);
-
+#ifdef CONFIG_BOOTX_TEXT
 extern boot_infos_t *boot_infos;
+#endif
 
 static void offb_init_nodriver(struct device_node *);
 static void offb_init_fb(const char *name, const char *full_name, int width,
@@ -253,6 +256,7 @@ int __init offb_init(void)
 {
     struct device_node *dp;
     unsigned int dpy;
+#ifdef CONFIG_BOOTX_TEXT
     struct device_node *displays = find_type_devices("display");
     struct device_node *macos_display = NULL;
 
@@ -315,6 +319,7 @@ int __init offb_init(void)
                     boot_infos->dispDeviceDepth,
                     boot_infos->dispDeviceRowBytes, addr, NULL);
     }
+#endif
 
     for (dpy = 0; dpy < prom_num_displays; dpy++) {
        if ((dp = find_path_device(prom_display_paths[dpy])))
@@ -426,7 +431,8 @@ static void __init offb_init_fb(const char *name, const char *full_name,
                unsigned long regbase = dp->addrs[2].address;
                info->cmap_adr = ioremap(regbase, 0x1FFF);
                info->cmap_type = cmap_r128;
-       } else if (dp && !strncmp(name, "ATY,RageM3pA", 12)) {
+       } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
+               || !strncmp(name, "ATY,RageM3p12A", 14))) {
                unsigned long regbase = dp->parent->addrs[2].address;
                info->cmap_adr = ioremap(regbase, 0x1FFF);
                info->cmap_type = cmap_M3A;
index 76b6c22490d783b618f2499611cbbba5be606db7..ee93f1f75d83caaca04ce9a19a2f3eb22f64ede9 100644 (file)
@@ -76,6 +76,8 @@ static struct linux_binfmt elf_format = {
        NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE
 };
 
+#define BAD_ADDR(x)    ((unsigned long)(x) > TASK_SIZE)
+
 static void set_brk(unsigned long start, unsigned long end)
 {
        start = ELF_PAGEALIGN(start);
@@ -298,6 +300,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
                elf_type |= MAP_FIXED;
 
            map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
+           if (BAD_ADDR(map_addr))
+               goto out_close;
 
            if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
                load_addr = map_addr - ELF_PAGESTART(vaddr);
@@ -649,6 +653,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                }
 
                error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
+               if (BAD_ADDR(error))
+                       continue;
 
                if (!load_addr_set) {
                        load_addr_set = 1;
@@ -697,7 +703,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                fput(interpreter);
                kfree(elf_interpreter);
 
-               if (elf_entry == ~0UL) {
+               if (BAD_ADDR(elf_entry)) {
                        printk(KERN_ERR "Unable to load interpreter\n");
                        kfree(elf_phdata);
                        send_sig(SIGSEGV, current, 0);
index 8ce2918bf78d7a6aad454feaf598b55a897c4e96..2df9d2a006866df8a358e7ab4f726769823cbab0 100644 (file)
@@ -549,36 +549,23 @@ int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
        return res;
 }
 
-int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+static int do_open(struct block_device *bdev, struct inode *inode, struct file *file)
 {
-       int ret = -ENODEV;
-       kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
-       down(&bdev->bd_sem);
+       int ret = -ENXIO;
+       kdev_t dev = to_kdev_t(bdev->bd_dev);
 
+       down(&bdev->bd_sem);
        lock_kernel();
        if (!bdev->bd_op)
-               bdev->bd_op = get_blkfops(MAJOR(rdev));
+               bdev->bd_op = get_blkfops(MAJOR(dev));
        if (bdev->bd_op) {
-               /*
-                * This crockload is due to bad choice of ->open() type.
-                * It will go away.
-                * For now, block device ->open() routine must _not_
-                * examine anything in 'inode' argument except ->i_rdev.
-                */
-               struct file fake_file = {};
-               struct dentry fake_dentry = {};
-               ret = -ENOMEM;
-               fake_file.f_mode = mode;
-               fake_file.f_flags = flags;
-               fake_file.f_dentry = &fake_dentry;
-               fake_dentry.d_inode = bdev->bd_inode;
                ret = 0;
                if (bdev->bd_op->open)
-                       ret = bdev->bd_op->open(bdev->bd_inode, &fake_file);
+                       ret = bdev->bd_op->open(inode, file);
                if (!ret) {
                        bdev->bd_openers++;
-                       bdev->bd_inode->i_size = blkdev_size(rdev);
-                       bdev->bd_inode->i_blkbits = blksize_bits(block_size(rdev));
+                       bdev->bd_inode->i_size = blkdev_size(dev);
+                       bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
                } else if (!bdev->bd_openers)
                        bdev->bd_op = NULL;
        }
@@ -589,9 +576,26 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
        return ret;
 }
 
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+{
+       /*
+        * This crockload is due to bad choice of ->open() type.
+        * It will go away.
+        * For now, block device ->open() routine must _not_
+        * examine anything in 'inode' argument except ->i_rdev.
+        */
+       struct file fake_file = {};
+       struct dentry fake_dentry = {};
+       fake_file.f_mode = mode;
+       fake_file.f_flags = flags;
+       fake_file.f_dentry = &fake_dentry;
+       fake_dentry.d_inode = bdev->bd_inode;
+
+       return do_open(bdev, bdev->bd_inode, &fake_file);
+}
+
 int blkdev_open(struct inode * inode, struct file * filp)
 {
-       int ret;
        struct block_device *bdev;
 
        /*
@@ -604,29 +608,8 @@ int blkdev_open(struct inode * inode, struct file * filp)
 
        bd_acquire(inode);
        bdev = inode->i_bdev;
-       down(&bdev->bd_sem);
 
-       ret = -ENXIO;
-       lock_kernel();
-       if (!bdev->bd_op)
-               bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev));
-
-       if (bdev->bd_op) {
-               ret = 0;
-               if (bdev->bd_op->open)
-                       ret = bdev->bd_op->open(inode,filp);
-               if (!ret) {
-                       bdev->bd_openers++;
-                       bdev->bd_inode->i_size = blkdev_size(inode->i_rdev);
-               } else if (!bdev->bd_openers)
-                       bdev->bd_op = NULL;
-       }       
-
-       unlock_kernel();
-       up(&bdev->bd_sem);
-       if (ret)
-               bdput(bdev);
-       return ret;
+       return do_open(bdev, inode, filp);
 }      
 
 int blkdev_put(struct block_device *bdev, int kind)
index d3339912a25d6b9f1d3b9e3eec1bc81daa95dc7c..7b2eaba253e62cb4745d1dc43c8d31fb0eb7698b 100644 (file)
@@ -15,6 +15,7 @@
 #define __KERNEL_SYSCALLS__
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <linux/sched.h>
 #include <linux/errno.h>
@@ -55,6 +56,7 @@ static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
  */
 unsigned long                  nlm_grace_period;
 unsigned long                  nlm_timeout = LOCKD_DFLT_TIMEO;
+unsigned long                  nlm_udpport, nlm_tcpport;
 
 static unsigned long set_grace_period(void)
 {
@@ -241,9 +243,9 @@ lockd_up(void)
                goto out;
        }
 
-       if ((error = svc_makesock(serv, IPPROTO_UDP, 0)) < 0 
+       if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0 
 #ifdef CONFIG_NFSD_TCP
-        || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0
+        || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0
 #endif
                ) {
                if (warned++ == 0) 
@@ -323,6 +325,8 @@ MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
 MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
 MODULE_PARM(nlm_grace_period, "10-240l");
 MODULE_PARM(nlm_timeout, "3-20l");
+MODULE_PARM(nlm_udpport, "0-65535l");
+MODULE_PARM(nlm_tcpport, "0-65535l");
 
 int
 init_module(void)
@@ -340,6 +344,24 @@ cleanup_module(void)
        /* FIXME: delete all NLM clients */
        nlm_shutdown_hosts();
 }
+#else
+/* not a module, so process bootargs
+ * lockd.udpport and lockd.tcpport
+ */
+
+static int __init udpport_set(char *str)
+{
+       nlm_udpport = simple_strtoul(str, NULL, 0);
+       return 1;
+}
+static int __init tcpport_set(char *str)
+{
+       nlm_tcpport = simple_strtoul(str, NULL, 0);
+       return 1;
+}
+__setup("lockd.udpport=", udpport_set);
+__setup("lockd.tcpport=", tcpport_set);
+
 #endif
 
 /*
index 46340e88f1c8c49fca82adea6d12badf01e4586f..537b685ce57689665ad5c2e81d68d589c5e67cc7 100644 (file)
@@ -550,15 +550,15 @@ struct flags {
        { NFSEXP_INSECURE_PORT, {"insecure", ""}},
        { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
        { NFSEXP_ALLSQUASH, {"all_squash", ""}},
-       { NFSEXP_ASYNC, {"async", ""}},
-       { NFSEXP_GATHERED_WRITES, {"wdelay", ""}},
+       { NFSEXP_ASYNC, {"async", "sync"}},
+       { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
        { NFSEXP_UIDMAP, {"uidmap", ""}},
        { NFSEXP_KERBEROS, { "kerberos", ""}},
        { NFSEXP_SUNSECURE, { "sunsecure", ""}},
        { NFSEXP_CROSSMNT, {"nohide", ""}},
        { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
        { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
-#ifdef NSMFS
+#ifdef MSNFS
        { NFSEXP_MSNFS, {"msnfs", ""}},
 #endif
        { 0, {"", ""}}
index aa35c9aae007e709a530047b5627266189dba27f..e3b037803b0e6df12e1120a7364a234ffffc3ff0 100644 (file)
@@ -99,7 +99,7 @@ decode_pathname(u32 *p, char **namp, int *lenp)
        char            *name;
        int             i;
 
-       if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
+       if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
                for (i = 0, name = *namp; i < *lenp; i++, name++) {
                        if (*name == '\0')
                                return NULL;
index bc7315c87c05aece59f17c15788968c766e15c19..417b4173c477ad1f79c77766226cb77a90c51567 100644 (file)
@@ -731,8 +731,10 @@ inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
 {
        struct super_block *sb = dentry->d_inode->i_sb;
        
-       if (dentry == exp->ex_dentry)
+       if (dentry == exp->ex_dentry) {
+               *maxsize = 0;
                return 0;
+       }
 
        if (sb->s_op->dentry_to_fh) {
                int need_parent = !S_ISDIR(dentry->d_inode->i_mode) &&
index 25d8ddf63af6e3b7b800414b4082d0112620175f..debae923e8f26a21be451584adea8ad6c5936587 100644 (file)
@@ -65,7 +65,7 @@ decode_filename(u32 *p, char **namp, int *lenp)
        char            *name;
        int             i;
 
-       if ((p = xdr_decode_string(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
+       if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
                for (i = 0, name = *namp; i < *lenp; i++, name++) {
                        if (*name == '\0' || *name == '/')
                                return NULL;
index 2aaa9149758a5930162df9d8c3a81a606b9d333a..015ef90095e07d3b9fba7aa97065ad997abf45af 100644 (file)
@@ -227,7 +227,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 #define        MAX_TOUCH_TIME_ERROR (30*60)
        if (err
            && (iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET
-           && iap->ia_mtime == iap->ia_ctime
+           && iap->ia_mtime == iap->ia_atime
            ) {
            /* looks good.  now just make sure time is in the right ballpark.
             * solaris, at least, doesn't seem to care what the time request is
index d0afb47eec09258d84704d6cf5839028fb9ae191..e87f0a7173142d1753c1281eec97eae15127e613 100644 (file)
 #include "acorn.h"
 
 static void
-adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads,
-                    unsigned long totalblocks)
+adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
 {
+#ifdef CONFIG_BLK_DEV_MFM
        extern void xd_set_geometry(kdev_t dev, unsigned char, unsigned char,
                                    unsigned long, unsigned int);
 
-#ifdef CONFIG_BLK_DEV_MFM
-       if (MAJOR(dev) == MFM_ACORN_MAJOR)
+       if (MAJOR(dev) == MFM_ACORN_MAJOR) {
+               unsigned long totalblocks = hd->part[MINOR(dev)].nr_sects;
                xd_set_geometry(dev, secspertrack, heads, totalblocks, 1);
+       }
 #endif
 }
 
@@ -60,32 +61,26 @@ adfs_partition(struct gendisk *hd, char *name, char *data,
 
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
 static int
-riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
-                int minor, unsigned long nr_sects)
+riscix_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sect, int minor, unsigned long nr_sects)
 {
-       struct buffer_head *bh;
+       Sector sect;
        struct riscix_record *rr;
-       unsigned int riscix_minor;
        
-       if(get_ptable_blocksize(dev)!=1024)
-               return 0;
+       rr = (struct riscix_record *)read_dev_sector(bdev, first_sect, &sect);
+       if (!rr)
+               return -1;
 
        printk(" [RISCiX]");
 
-       add_gd_partition(hd, riscix_minor = minor++, first_sect, nr_sects);
-       hd->sizes[riscix_minor] = hd->part[riscix_minor].nr_sects >>
-                                       (BLOCK_SIZE_BITS - 9);
-       dev = MKDEV(hd->major, riscix_minor);
-
-       if (!(bh = bread(dev, 0, 1024)))
-               return -1;
 
-       rr = (struct riscix_record *)bh->b_data;
        if (rr->magic == RISCIX_MAGIC) {
+               unsigned long size = nr_sects > 2 ? 2 : nr_sects;
                int part;
 
                printk(" <");
 
+               add_gd_partition(hd, minor++, first_sect, size);
                for (part = 0; part < 8; part++) {
                        if (rr->part[part].one &&
                            memcmp(rr->part[part].name, "All\0", 4)) {
@@ -97,38 +92,32 @@ riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
                }
 
                printk(" >\n");
-
-               if (hd->part[riscix_minor].nr_sects > 2)
-                       hd->part[riscix_minor].nr_sects = 2;
+       } else {
+               add_gd_partition(hd, minor++, first_sect, nr_sects);
        }
 
-       brelse(bh);
+       put_dev_sector(sect);
        return minor;
 }
 #endif
 
 static int
-linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
-               int minor, unsigned long nr_sects)
+linux_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sect, int minor, unsigned long nr_sects)
 {
-       struct buffer_head *bh;
+       Sector sect;
        struct linux_part *linuxp;
-       unsigned int linux_minor, mask = (1 << hd->minor_shift) - 1;
+       unsigned int mask = (1 << hd->minor_shift) - 1;
+       unsigned long size = nr_sects > 2 ? 2 : nr_sects;
 
-       if(get_ptable_blocksize(dev)!=1024)
-               return 0;
-               
        printk(" [Linux]");
 
-       add_gd_partition(hd, linux_minor = minor++, first_sect, nr_sects);
-       hd->sizes[linux_minor] = hd->part[linux_minor].nr_sects >>
-                                       (BLOCK_SIZE_BITS - 9);
-       dev = MKDEV(hd->major, linux_minor);
+       add_gd_partition(hd, minor++, first_sect, size);
 
-       if (!(bh = bread(dev, 0, 1024)))
+       linuxp = (struct linux_part *)read_dev_sector(bdev, first_sect, &sect);
+       if (!linuxp)
                return -1;
 
-       linuxp = (struct linux_part *)bh->b_data;
        printk(" <");
        while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) ||
               linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) {
@@ -140,29 +129,22 @@ linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
                linuxp ++;
        }
        printk(" >");
-       /*
-        * Prevent someone doing a mkswap or mkfs on this partition
-        */
-       if(hd->part[linux_minor].nr_sects > 2)
-               hd->part[linux_minor].nr_sects = 2;
 
-       brelse(bh);
+       put_dev_sector(sect);
        return minor;
 }
 
 #ifdef CONFIG_ACORN_PARTITION_CUMANA
 static int
-adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
+adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
                      unsigned long first_sector, int minor)
 {
        unsigned int start_blk = 0, mask = (1 << hd->minor_shift) - 1;
-       struct buffer_head *bh = NULL;
+       Sector sect;
+       unsigned char *data;
        char *name = "CUMANA/ADFS";
        int first = 1;
 
-       if(get_ptable_blocksize(dev)!=1024)
-               return 0;
-
        /*
         * Try Cumana style partitions - sector 3 contains ADFS boot block
         * with pointer to next 'drive'.
@@ -183,16 +165,17 @@ adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
                if (!(minor & mask))
                        break;
 
-               if (!(bh = bread(dev, start_blk + 3, 1024)))
+               data = read_dev_sector(bdev, start_blk * 2 + 6, &sect);
+               if (!data)
                        return -1;
 
-               dr = adfs_partition(hd, name, bh->b_data,
-                                   first_sector, minor++);
+               dr = adfs_partition(hd, name, data, first_sector, minor++);
                if (!dr)
                        break;
+
                name = NULL;
 
-               nr_sects = (bh->b_data[0x1fd] + (bh->b_data[0x1fe] << 8)) *
+               nr_sects = (data[0x1fd] + (data[0x1fe] << 8)) *
                           (dr->heads + (dr->lowsector & 0x40 ? 1 : 0)) *
                           dr->secspertrack;
 
@@ -204,30 +187,28 @@ adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
                start_blk += nr_sects >> (BLOCK_SIZE_BITS - 9);
                nr_sects = 0; /* hmm - should be partition size */
 
-               switch (bh->b_data[0x1fc] & 15) {
+               switch (data[0x1fc] & 15) {
                case 0: /* No partition / ADFS? */
                        break;
 
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
                case PARTITION_RISCIX_SCSI:
                        /* RISCiX - we don't know how to find the next one. */
-                       minor = riscix_partition(hd, dev, first_sector,
+                       minor = riscix_partition(hd, bdev, first_sector,
                                                 minor, nr_sects);
                        break;
 #endif
 
                case PARTITION_LINUX:
-                       minor = linux_partition(hd, dev, first_sector,
+                       minor = linux_partition(hd, bdev, first_sector,
                                                minor, nr_sects);
                        break;
                }
-               brelse(bh);
-               bh = NULL;
+               put_dev_sector(sect);
                if (minor == -1)
                        return minor;
        } while (1);
-       if (bh)
-               bforget(bh);
+       put_dev_sector(sect);
        return first ? 0 : 1;
 }
 #endif
@@ -248,73 +229,73 @@ adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
  *         hda2 = non-ADFS partition.
  */
 static int
-adfspart_check_ADFS(struct gendisk *hd, kdev_t dev,
+adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
                   unsigned long first_sector, int minor)
 {
        unsigned long start_sect, nr_sects, sectscyl, heads;
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        struct adfs_discrecord *dr;
+       unsigned char id;
 
-       if(get_ptable_blocksize(dev)!=1024)
-               return 0;
-
-       if (!(bh = bread(dev, 3, 1024)))
+       data = read_dev_sector(bdev, 6, &sect);
+       if (!data)
                return -1;
 
-       dr = adfs_partition(hd, "ADFS", bh->b_data, first_sector, minor++);
+       dr = adfs_partition(hd, "ADFS", data, first_sector, minor++);
        if (!dr) {
-               bforget(bh);
+               put_dev_sector(sect);
                return 0;
        }
 
        heads = dr->heads + ((dr->lowsector >> 6) & 1);
-       adfspart_setgeometry(dev, dr->secspertrack, heads,
-                            hd->part[MINOR(dev)].nr_sects);
        sectscyl = dr->secspertrack * heads;
+       start_sect = ((data[0x1fe] << 8) + data[0x1fd]) * sectscyl;
+       id = data[0x1fc] & 15;
+       put_dev_sector(sect);
+
+       adfspart_setgeometry(to_kdev_t(bdev->bd_dev), dr->secspertrack, heads);
+       invalidate_bdev(bdev, 1);
+       truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
 
        /*
         * Work out start of non-adfs partition.
         */
-       start_sect = ((bh->b_data[0x1fe] << 8) + bh->b_data[0x1fd]) * sectscyl;
-       nr_sects = hd->part[MINOR(dev)].nr_sects - start_sect;
+       nr_sects = hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects - start_sect;
 
        if (start_sect) {
                first_sector += start_sect;
 
-               switch (bh->b_data[0x1fc] & 15) {
+               switch (id) {
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
                case PARTITION_RISCIX_SCSI:
                case PARTITION_RISCIX_MFM:
-                       minor = riscix_partition(hd, dev, first_sector,
+                       minor = riscix_partition(hd, bdev, first_sector,
                                                 minor, nr_sects);
                        break;
 #endif
 
                case PARTITION_LINUX:
-                       minor = linux_partition(hd, dev, first_sector,
+                       minor = linux_partition(hd, bdev, first_sector,
                                                minor, nr_sects);
                        break;
                }
        }
-       brelse(bh);
        return 1;
 }
 #endif
 
 #ifdef CONFIG_ACORN_PARTITION_ICS
-static int adfspart_check_ICSLinux(kdev_t dev, unsigned long block)
+static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
 {
-       struct buffer_head *bh;
-       unsigned int offset = block & 1 ? 512 : 0;
+       Sector sect;
+       unsigned char *data = read_dev_sector(bdev, block, &sect);
        int result = 0;
 
-       bh = bread(dev, block >> 1, 1024);
-
-       if (bh != NULL) {
-               if (memcmp(bh->b_data + offset, "LinuxPart", 9) == 0)
+       if (data) {
+               if (memcmp(data, "LinuxPart", 9) == 0)
                        result = 1;
-
-               brelse(bh);
+               put_dev_sector(sect);
        }
 
        return result;
@@ -333,38 +314,37 @@ static int adfspart_check_ICSLinux(kdev_t dev, unsigned long block)
  *             ..etc..
  */
 static int
-adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
+adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
                   unsigned long first_sector, int minor)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        unsigned long sum;
        unsigned int i, mask = (1 << hd->minor_shift) - 1;
        struct ics_part *p;
 
-       if(get_ptable_blocksize(dev)!=1024)
-               return 0;
-               
        /*
         * Try ICS style partitions - sector 0 contains partition info.
         */
-       if (!(bh = bread(dev, 0, 1024)))
+       data = read_dev_sector(bdev, 0, &sect);
+       if (!data)
                return -1;
 
        /*
         * check for a valid checksum
         */
        for (i = 0, sum = 0x50617274; i < 508; i++)
-               sum += bh->b_data[i];
+               sum += data[i];
 
-       sum -= le32_to_cpu(*(__u32 *)(&bh->b_data[508]));
+       sum -= le32_to_cpu(*(__u32 *)(&data[508]));
        if (sum) {
-               bforget(bh);
+               put_dev_sector(sect);
                return 0; /* not ICS partition table */
        }
 
        printk(" [ICS]");
 
-       for (p = (struct ics_part *)bh->b_data; p->size; p++) {
+       for (p = (struct ics_part *)data; p->size; p++) {
                unsigned long start;
                long size;
 
@@ -381,7 +361,7 @@ adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
                         * We use the first sector to identify what type
                         * this partition is...
                         */
-                       if (size > 1 && adfspart_check_ICSLinux(dev, start)) {
+                       if (size > 1 && adfspart_check_ICSLinux(bdev, start)) {
                                start += 1;
                                size -= 1;
                        }
@@ -393,12 +373,11 @@ adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
                }
        }
 
-       brelse(bh);
+       put_dev_sector(sect);
        return 1;
 }
 #endif
 
-#ifdef CONFIG_ACORN_PARTITION_POWERTEC
 /*
  * Purpose: allocate ICS partitions.
  * Params : hd         - pointer to gendisk structure to store partition info.
@@ -411,29 +390,32 @@ adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
  *         hda2 = ADFS partition 1 on first drive.
  *             ..etc..
  */
+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
 static int
-adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev,
+adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
                        unsigned long first_sector, int minor)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        struct ptec_partition *p;
        unsigned char checksum;
        int i;
 
-       if (!(bh = bread(dev, 0, 1024)))
+       data = read_dev_sector(bdev, 0, &sect);
+       if (!data)
                return -1;
 
        for (checksum = 0x2a, i = 0; i < 511; i++)
-               checksum += bh->b_data[i];
+               checksum += data[i];
 
-       if (checksum != bh->b_data[511]) {
-               bforget(bh);
+       if (checksum != data[511]) {
+               put_dev_sector(sect);
                return 0;
        }
 
        printk(" [POWERTEC]");
 
-       for (i = 0, p = (struct ptec_partition *)bh->b_data; i < 12; i++, p++) {
+       for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
                unsigned long start;
                unsigned long size;
 
@@ -446,23 +428,23 @@ adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev,
                minor++;
        }
 
-       brelse(bh);
+       put_dev_sector(sect);
        return 1;
 }
 #endif
 
-static int (*partfn[])(struct gendisk *, kdev_t, unsigned long, int) = {
+static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, int) = {
 #ifdef CONFIG_ACORN_PARTITION_ICS
        adfspart_check_ICS,
 #endif
+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
+       adfspart_check_POWERTEC,
+#endif
 #ifdef CONFIG_ACORN_PARTITION_CUMANA
        adfspart_check_CUMANA,
 #endif
 #ifdef CONFIG_ACORN_PARTITION_ADFS
        adfspart_check_ADFS,
-#endif
-#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-       adfspart_check_POWERTEC,
 #endif
        NULL
 };
@@ -478,17 +460,18 @@ static int (*partfn[])(struct gendisk *, kdev_t, unsigned long, int) = {
  *
  * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
  */
-int acorn_partition(struct gendisk *hd, kdev_t dev,
+int acorn_partition(struct gendisk *hd, struct block_device *bdev,
                    unsigned long first_sect, int first_minor)
 {
-       int r = 0, i;
-
-       for (i = 0; partfn[i] && r == 0; i++)
-               r = partfn[i](hd, dev, first_sect, first_minor);
+       int i;
 
-       if (r < 0 && warn_no_part)
-               printk(" unable to read boot sectors / partition sectors\n");
-       if (r > 0)
-               printk("\n");
-       return r;
+       for (i = 0; partfn[i]; i++) {
+               int r = partfn[i](hd, bdev, first_sect, first_minor);
+               if (r) {
+                       if (r > 0)
+                               printk("\n");
+                       return r;
+               }
+       }
+       return 0;
 }
index e1d0a3830e8ba816cf908734487004e1a89969e8..f4b3b80d383c96d340fef1e0120848551d1803b3 100644 (file)
@@ -50,6 +50,6 @@ struct ptec_partition {
 };
        
 
-int acorn_partition(struct gendisk *hd, kdev_t dev,
+int acorn_partition(struct gendisk *hd, struct block_device *bdev,
                   unsigned long first_sect, int first_minor);
 
index 4717a1b5f0a02ffce72e0b9cb1149286a8e819f6..3ecf9c4f88b427c405b1ed2acf8f5304a0fffe7f 100644 (file)
@@ -31,90 +31,82 @@ checksum_block(u32 *m, int size)
 }
 
 int
-amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+amiga_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sector, int first_part_minor)
 {
-       struct buffer_head      *bh;
-       struct RigidDiskBlock   *rdb;
-       struct PartitionBlock   *pb;
-       int                      start_sect;
-       int                      nr_sects;
-       int                      blk;
-       int                      part, res;
-       int                      old_blocksize;
-       int                      blocksize;
+       Sector sect;
+       unsigned char *data;
+       struct RigidDiskBlock *rdb;
+       struct PartitionBlock *pb;
+       int start_sect, nr_sects, blk, part, res = 0;
+       kdev_t dev = to_kdev_t(bdev->bd_dev);
 
-       old_blocksize = get_ptable_blocksize(dev);
-       blocksize = get_hardsect_size(dev);
+       for (blk = 0; ; blk++, put_dev_sector(sect)) {
+               if (blk == RDB_ALLOCATION_LIMIT)
+                       goto rdb_done;
+               data = read_dev_sector(bdev, blk, &sect);
+               if (!data) {
+                       if (warn_no_part)
+                               printk("Dev %s: unable to read RDB block %d\n",
+                                      bdevname(dev), blk);
+                       goto rdb_done;
+               }
+               if (*(u32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
+                       continue;
 
-       if (blocksize < 512)
-               blocksize = 512;
+               rdb = (struct RigidDiskBlock *)data;
+               if (checksum_block((u32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
+                       break;
+               /* Try again with 0xdc..0xdf zeroed, Windows might have
+                * trashed it.
+                */
+               *(u32 *)(data+0xdc) = 0;
+               if (checksum_block((u32 *)data,
+                               be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
+                       printk("Warning: Trashed word at 0xd0 in block %d "
+                               "ignored in checksum calculation\n",blk);
+                       break;
+               }
 
-       set_blocksize(dev,blocksize);
-       res = 0;
+               printk("Dev %s: RDB in block %d has bad checksum\n",
+                              bdevname(dev),blk);
+       }
 
-       for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
-               if(!(bh = bread(dev,blk,blocksize))) {
-                       if (warn_no_part) printk("Dev %s: unable to read RDB block %d\n",
-                              kdevname(dev),blk);
+       printk(" RDSK");
+       blk = be32_to_cpu(rdb->rdb_PartitionList);
+       put_dev_sector(sect);
+       for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
+               data = read_dev_sector(bdev, blk, &sect);
+               if (!data) {
+                       if (warn_no_part)
+                               printk("Dev %s: unable to read partition block %d\n",
+                                      bdevname(dev),blk);
                        goto rdb_done;
                }
-               if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
-                       rdb = (struct RigidDiskBlock *)bh->b_data;
-                       if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
-                               /* Try again with 0xdc..0xdf zeroed, Windows might have
-                                * trashed it.
-                                */
-                               *(u32 *)(&bh->b_data[0xdc]) = 0;
-                               if (checksum_block((u32 *)bh->b_data,
-                                               be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
-                                       brelse(bh);
-                                       printk("Dev %s: RDB in block %d has bad checksum\n",
-                                              kdevname(dev),blk);
-                                       continue;
-                               }
-                               printk("Warning: Trashed word at 0xd0 in block %d "
-                                       "ignored in checksum calculation\n",blk);
-                       }
-                       printk(" RDSK");
-                       blk = be32_to_cpu(rdb->rdb_PartitionList);
-                       brelse(bh);
-                       for (part = 1; blk > 0 && part <= 16; part++) {
-                               if (!(bh = bread(dev,blk,blocksize))) {
-                                       if (warn_no_part) printk("Dev %s: unable to read partition block %d\n",
-                                                      kdevname(dev),blk);
-                                       goto rdb_done;
-                               }
-                               pb  = (struct PartitionBlock *)bh->b_data;
-                               blk = be32_to_cpu(pb->pb_Next);
-                               if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
-                                   (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
+               pb  = (struct PartitionBlock *)data;
+               blk = be32_to_cpu(pb->pb_Next);
+               if (pb->pb_ID != cpu_to_be32(IDNAME_PARTITION))
+                       continue;
+               if (checksum_block((u32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
+                       continue;
 
-                                       /* Tell Kernel about it */
+               /* Tell Kernel about it */
 
-                                       if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
-                                                         be32_to_cpu(pb->pb_Environment[9])) *
-                                                        be32_to_cpu(pb->pb_Environment[3]) *
-                                                        be32_to_cpu(pb->pb_Environment[5]))) {
-                                               brelse(bh);
-                                               continue;
-                                       }
-                                       start_sect = be32_to_cpu(pb->pb_Environment[9]) *
-                                                    be32_to_cpu(pb->pb_Environment[3]) *
-                                                    be32_to_cpu(pb->pb_Environment[5]);
-                                       add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
-                                       first_part_minor++;
-                                       res = 1;
-                               }
-                               brelse(bh);
-                       }
-                       printk("\n");
-                       break;
-               }
-               else
-                       brelse(bh);
+               nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
+                           be32_to_cpu(pb->pb_Environment[9])) *
+                          be32_to_cpu(pb->pb_Environment[3]) *
+                          be32_to_cpu(pb->pb_Environment[5]);
+               if (!nr_sects)
+                       continue;
+               start_sect = be32_to_cpu(pb->pb_Environment[9]) *
+                            be32_to_cpu(pb->pb_Environment[3]) *
+                            be32_to_cpu(pb->pb_Environment[5]);
+               add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
+               first_part_minor++;
+               res = 1;
        }
+       printk("\n");
 
 rdb_done:
-       set_blocksize(dev,old_blocksize);
        return res;
 }
index 37c6ec14462711bd52d785ae592e231be955bea1..4f4f8a2772d970b5f6d3245b3da0906001f8d23c 100644 (file)
@@ -3,6 +3,6 @@
  */
 
 int
-amiga_partition(struct gendisk *hd, kdev_t dev,
+amiga_partition(struct gendisk *hd, struct block_device *bdev,
                unsigned long first_sector, int first_part_minor);
 
index 0180daca8ef469ad5aaa17000a14e8ffafb30a73..11a7b4a79625e901933466af582021d0fcb3c221 100644 (file)
      be32_to_cpu((pi)->st) <= (hdsiz) &&                                    \
      be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
 
-int atari_partition (struct gendisk *hd, kdev_t dev,
+static inline int OK_id(char *s)
+{
+       return  memcmp (s, "GEM", 3) == 0 || memcmp (s, "BGM", 3) == 0 ||
+               memcmp (s, "LNX", 3) == 0 || memcmp (s, "SWP", 3) == 0 ||
+               memcmp (s, "RAW", 3) == 0 ;
+}
+
+int atari_partition (struct gendisk *hd, struct block_device *bdev,
                     unsigned long first_sector, int minor)
 {
-  int m_lim = minor + hd->max_p;
-  struct buffer_head *bh;
-  struct rootsector *rs;
-  struct partition_info *pi;
-  u32 extensect;
-  u32 hd_size;
+       int m_lim = minor + hd->max_p;
+       Sector sect;
+       struct rootsector *rs;
+       struct partition_info *pi;
+       u32 extensect;
+       u32 hd_size;
 #ifdef ICD_PARTS
-  int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
+       int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
 #endif
 
-  bh = bread (dev, 0, get_ptable_blocksize(dev));
-  if (!bh) {
-      if (warn_no_part) printk (" unable to read block 0 (partition table)\n");
-      return -1;
-  }
-
-  /* Verify this is an Atari rootsector: */
-  rs = (struct rootsector *) bh->b_data;
-  hd_size = hd->part[minor - 1].nr_sects;
-  if (!VALID_PARTITION(&rs->part[0], hd_size) &&
-      !VALID_PARTITION(&rs->part[1], hd_size) &&
-      !VALID_PARTITION(&rs->part[2], hd_size) &&
-      !VALID_PARTITION(&rs->part[3], hd_size)) {
-      /* if there's no valid primary partition, assume that no Atari
-        format partition table (there's no reliable magic or the like
-        :-() */
-      brelse(bh);
-      return 0;
-  }
-
-  pi = &rs->part[0];
-  printk (" AHDI");
-  for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
-    {
-      if (pi->flg & 1)
-       /* active partition */
-       {
-         if (memcmp (pi->id, "XGM", 3) == 0)
-           /* extension partition */
-           {
-             struct rootsector *xrs;
-             struct buffer_head *xbh;
-             ulong partsect;
+       rs = (struct rootsector *) read_dev_sector(bdev, 0, &sect);
+       if (!rs)
+               return -1;
+
+       /* Verify this is an Atari rootsector: */
+       hd_size = hd->part[minor - 1].nr_sects;
+       if (!VALID_PARTITION(&rs->part[0], hd_size) &&
+           !VALID_PARTITION(&rs->part[1], hd_size) &&
+           !VALID_PARTITION(&rs->part[2], hd_size) &&
+           !VALID_PARTITION(&rs->part[3], hd_size)) {
+               /*
+                * if there's no valid primary partition, assume that no Atari
+                * format partition table (there's no reliable magic or the like
+                * :-()
+                */
+               put_dev_sector(sect);
+               return 0;
+       }
 
+       pi = &rs->part[0];
+       printk (" AHDI");
+       for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++) {
+               struct rootsector *xrs;
+               Sector sect2;
+               ulong partsect;
+
+               if ( !(pi->flg & 1) )
+                       continue;
+               /* active partition */
+               if (memcmp (pi->id, "XGM", 3) != 0) {
+                       /* we don't care about other id's */
+                       add_gd_partition (hd, minor, be32_to_cpu(pi->st),
+                                       be32_to_cpu(pi->siz));
+                       continue;
+               }
+               /* extension partition */
 #ifdef ICD_PARTS
-             part_fmt = 1;
+               part_fmt = 1;
 #endif
-             printk(" XGM<");
-             partsect = extensect = be32_to_cpu(pi->st);
-             while (1)
-               {
-                 xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
-                 if (!xbh)
-                   {
-                     printk (" block %ld read failed\n", partsect);
-                     brelse(bh);
-                     return 0;
-                   }
-                 if (partsect & 1)
-                   xrs = (struct rootsector *) &xbh->b_data[512];
-                 else
-                   xrs = (struct rootsector *) &xbh->b_data[0];
-
-                 /* ++roman: sanity check: bit 0 of flg field must be set */
-                 if (!(xrs->part[0].flg & 1)) {
-                   printk( "\nFirst sub-partition in extended partition is not valid!\n" );
-                   break;
-                 }
-
-                 add_gd_partition(hd, minor,
+               printk(" XGM<");
+               partsect = extensect = be32_to_cpu(pi->st);
+               while (1) {
+                       xrs = (struct rootsector *)read_dev_sector(bdev, partsect, &sect2);
+                       if (!xrs) {
+                               printk (" block %ld read failed\n", partsect);
+                               put_dev_sector(sect);
+                               return 0;
+                       }
+
+                       /* ++roman: sanity check: bit 0 of flg field must be set */
+                       if (!(xrs->part[0].flg & 1)) {
+                               printk( "\nFirst sub-partition in extended partition is not valid!\n" );
+                               put_dev_sector(sect2);
+                               break;
+                       }
+
+                       add_gd_partition(hd, minor,
                                   partsect + be32_to_cpu(xrs->part[0].st),
                                   be32_to_cpu(xrs->part[0].siz));
 
-                 if (!(xrs->part[1].flg & 1)) {
-                   /* end of linked partition list */
-                   brelse( xbh );
-                   break;
-                 }
-                 if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
-                   printk( "\nID of extended partition is not XGM!\n" );
-                   brelse( xbh );
-                   break;
-                 }
-
-                 partsect = be32_to_cpu(xrs->part[1].st) + extensect;
-                 brelse (xbh);
-                 minor++;
-                 if (minor >= m_lim) {
-                   printk( "\nMaximum number of partitions reached!\n" );
-                   break;
-                 }
+                       if (!(xrs->part[1].flg & 1)) {
+                               /* end of linked partition list */
+                               put_dev_sector(sect2);
+                               break;
+                       }
+                       if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
+                               printk("\nID of extended partition is not XGM!\n");
+                               put_dev_sector(sect2);
+                               break;
+                       }
+
+                       partsect = be32_to_cpu(xrs->part[1].st) + extensect;
+                       put_dev_sector(sect2);
+                       minor++;
+                       if (minor >= m_lim) {
+                               printk( "\nMaximum number of partitions reached!\n" );
+                               break;
+                       }
                }
-             printk(" >");
-           }
-         else
-           {
-             /* we don't care about other id's */
-             add_gd_partition (hd, minor, be32_to_cpu(pi->st),
-                               be32_to_cpu(pi->siz));
-           }
+               printk(" >");
        }
-    }
 #ifdef ICD_PARTS
-  if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
-  {
-    pi = &rs->icdpart[0];
-    /* sanity check: no ICD format if first partition invalid */
-    if (memcmp (pi->id, "GEM", 3) == 0 ||
-        memcmp (pi->id, "BGM", 3) == 0 ||
-        memcmp (pi->id, "LNX", 3) == 0 ||
-        memcmp (pi->id, "SWP", 3) == 0 ||
-        memcmp (pi->id, "RAW", 3) == 0 )
-    {
-      printk(" ICD<");
-      for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
-      {
-        /* accept only GEM,BGM,RAW,LNX,SWP partitions */
-        if (pi->flg & 1 && 
-            (memcmp (pi->id, "GEM", 3) == 0 ||
-             memcmp (pi->id, "BGM", 3) == 0 ||
-             memcmp (pi->id, "LNX", 3) == 0 ||
-             memcmp (pi->id, "SWP", 3) == 0 ||
-             memcmp (pi->id, "RAW", 3) == 0) )
-        {
-          part_fmt = 2;
-         add_gd_partition (hd, minor, be32_to_cpu(pi->st),
-                           be32_to_cpu(pi->siz));
-        }
-      }
-      printk(" >");
-    }
-  }
+       if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */
+               pi = &rs->icdpart[0];
+               /* sanity check: no ICD format if first partition invalid */
+               if (OK_id(pi->id)) {
+                       printk(" ICD<");
+                       for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++) {
+                               /* accept only GEM,BGM,RAW,LNX,SWP partitions */
+                               if (!((pi->flg & 1) && OK_id(pi->id)))
+                                       continue;
+                               part_fmt = 2;
+                               add_gd_partition (hd, minor,
+                                               be32_to_cpu(pi->st),
+                                               be32_to_cpu(pi->siz));
+                       }
+                       printk(" >");
+               }
+       }
 #endif
-  brelse (bh);
+       put_dev_sector(sect);
 
-  printk ("\n");
+       printk ("\n");
 
-  return 1;
+       return 1;
 }
 
index 6d19c93e561aa4af280cf1d5986b87429e391be8..6a14eb75947d6bdc9551bad18c8794eecfbd2fa6 100644 (file)
@@ -31,6 +31,6 @@ struct rootsector
   u16 checksum;                        /* checksum for bootable disks */
 } __attribute__((__packed__));
 
-int atari_partition (struct gendisk *hd, kdev_t dev,
+int atari_partition (struct gendisk *hd, struct block_device *bdev,
                     unsigned long first_sector, int first_part_minor);
 
index 6d00b601a1795f3098be602fcebcf119503fddf3..ee0ce88fed8484ab3d664d53fa92701c97b4d1e9 100644 (file)
@@ -38,7 +38,7 @@ extern int *blk_size[];
 
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
 
-static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {
+static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
 #ifdef CONFIG_ACORN_PARTITION
        acorn_partition,
 #endif
@@ -215,54 +215,12 @@ void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
 #endif
 }
 
-unsigned int get_ptable_blocksize(kdev_t dev)
-{
-       int ret = 1024;
-
-       /*
-        * See whether the low-level driver has given us a minumum blocksize.
-        * If so, check to see whether it is larger than the default of 1024.
-        */
-       if (!blksize_size[MAJOR(dev)])
-               return ret;
-
-       /*
-        * Check for certain special power of two sizes that we allow.
-        * With anything larger than 1024, we must force the blocksize up to
-        * the natural blocksize for the device so that we don't have to try
-        * and read partial sectors.  Anything smaller should be just fine.
-        */
-
-       switch (blksize_size[MAJOR(dev)][MINOR(dev)]) {
-               case 2048:
-                       ret = 2048;
-                       break;
-               case 4096:
-                       ret = 4096;
-                       break;
-               case 8192:
-                       ret = 8192;
-                       break;
-               case 1024:
-               case 512:
-               case 256:
-               case 0:
-                       /*
-                        * These are all OK.
-                        */
-                       break;
-               default:
-                       panic("Strange blocksize for partition table\n");
-       }
-
-       return ret;
-}
-
 static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
 {
        devfs_handle_t de = NULL;
        static int first_time = 1;
        unsigned long first_sector;
+       struct block_device *bdev;
        char buf[64];
        int i;
 
@@ -287,12 +245,23 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
                printk(KERN_INFO " /dev/%s:", buf + i);
        else
                printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
-       for (i = 0; check_part[i]; i++)
-               if (check_part[i](hd, dev, first_sector, first_part_minor))
+       bdev = bdget(kdev_t_to_nr(dev));
+       bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
+       for (i = 0; check_part[i]; i++) {
+               int res;
+               res = check_part[i](hd, bdev, first_sector, first_part_minor);
+               if (res) {
+                       if (res < 0 &&  warn_no_part)
+                               printk(" unable to read partition table\n");
                        goto setup_devfs;
+               }
+       }
 
        printk(" unknown partition table\n");
 setup_devfs:
+       invalidate_bdev(bdev, 1);
+       truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
+       bdput(bdev);
        i = first_part_minor - 1;
        devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
 }
@@ -428,3 +397,26 @@ void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
                blk_size[dev->major] = dev->sizes;
        }
 }
+
+unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
+{
+       struct address_space *mapping = bdev->bd_inode->i_mapping;
+       int sect = PAGE_CACHE_SIZE / 512;
+       struct page *page;
+
+       page = read_cache_page(mapping, n/sect,
+                       (filler_t *)mapping->a_ops->readpage, NULL);
+       if (!IS_ERR(page)) {
+               wait_on_page(page);
+               if (!Page_Uptodate(page))
+                       goto fail;
+               if (PageError(page))
+                       goto fail;
+               p->v = page;
+               return (unsigned char *)page_address(page) + 512 * (n % sect);
+fail:
+               page_cache_release(page);
+       }
+       p->v = NULL;
+       return NULL;
+}
index c2dde3a97edfefb432cd44a00b59a2393df11a2d..32d7940469a406aa949bcc58df22c46f74ef20d3 100644 (file)
@@ -4,9 +4,13 @@
  */
 void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
 
-/*
- * Get the default block size for this device
- */
-unsigned int get_ptable_blocksize(kdev_t dev);
+typedef struct {struct page *v;} Sector;
+
+unsigned char *read_dev_sector(struct block_device *, unsigned long, Sector *);
+
+static inline void put_dev_sector(Sector p)
+{
+       page_cache_release(p.v);
+}
 
 extern int warn_no_part;
index 8e2b6d5da229bb1eadb3e9fb3e5631178043b2da..cc6e7470eb7f0afaa3be5fb4fe0d0822590026ef 100644 (file)
@@ -42,30 +42,6 @@ static char* part_names[] = {   [ibm_partition_lnx1] = "LNX1",
                             [ibm_partition_none] = "(nonl)"
 };
 
-static int
-get_drive_geometry(int kdev,struct hd_geometry *geo) 
-{
-       struct block_device *bdev = bdget(kdev_t_to_nr(kdev));
-       int rc = blkdev_get(bdev, 0, 1, BDEV_FILE);
-        if ( rc == 0 ) {
-               rc = ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
-               blkdev_put(bdev, BDEV_FILE);
-       }
-       return rc;
-}
-
-static int
-get_drive_info(int kdev,dasd_information_t *info) 
-{
-       struct block_device *bdev = bdget(kdev_t_to_nr(kdev));
-       int rc = blkdev_get(bdev, 0, 1, BDEV_FILE);
-        if ( rc == 0 ) {
-               rc = ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)(info));
-               blkdev_put(bdev, BDEV_FILE);
-       }
-       return rc;
-}
-
 static ibm_partition_t
 get_partition_type ( char * type )
 {
@@ -89,10 +65,8 @@ two_partitions(struct gendisk *hd,
               int offset,
               int size) {
 
-        add_gd_partition( hd, minor, 0,size);
-       add_gd_partition( hd, minor + 1, 
-                          offset * (blocksize >> 9),
-                          size-offset*(blocksize>>9));
+        add_gd_partition( hd, minor, 0, size);
+       add_gd_partition( hd, minor+1, offset*blocksize, size-offset*blocksize);
 }
 
 
@@ -119,10 +93,11 @@ cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
 }
 
 int 
-ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int
-first_part_minor)
+ibm_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sector, int first_part_minor)
 {
-       struct buffer_head *bh, *buf;
+       Sector sect, sect2;
+       unsigned char *data;
        ibm_partition_t partition_type;
        char type[5] = {0,};
        char name[7] = {0,};
@@ -133,40 +108,41 @@ first_part_minor)
        format1_label_t f1;
        volume_label_t vlabel;
        dasd_information_t *info;
+       kdev_t dev = to_kdev_t(bdev->bd_dev);
 
-       if ( first_sector != 0 ) {
+       if ( first_sector != 0 )
                BUG();
-       }
+
        info = (struct dasd_information_t *)kmalloc(sizeof(dasd_information_t),
                                                    GFP_KERNEL);
        if ( info == NULL )
                return 0;
-       if (get_drive_info (dev,info)) 
+       if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)(info)))
                return 0;
        geo = (struct hd_geometry *)kmalloc(sizeof(struct hd_geometry),
                                            GFP_KERNEL);
        if ( geo == NULL )
                return 0;
-       if (get_drive_geometry (dev,geo)) 
+       if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
                return 0;
        blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
        if ( blocksize <= 0 ) {
                return 0;
        }
+       blocksize >>= 9;
        
-       set_blocksize(dev, blocksize);  /* OUCH !! */
-       if ( ( bh = bread( dev, info->label_block, blocksize) ) != NULL ) {
-               strncpy ( type,bh -> b_data + 0, 4);
-               if ((!info->FBA_layout) && (!strcmp(info->type,"ECKD"))) {
-                       
-                       strncpy ( name,bh -> b_data + 8, 6);
-               } else {
-                       strncpy ( name,bh -> b_data + 4, 6);              
-               }
-               memcpy (&vlabel, bh->b_data, sizeof(volume_label_t));
-        } else {
+       data = read_dev_sector(bdev, inode->label_block*blocksize, &sect);
+       if (!data)
                return 0;
+
+       strncpy (type, data, 4);
+       if ((!info->FBA_layout) && (!strcmp(info->type,"ECKD"))) {
+               strncpy ( name, data + 8, 6);
+       } else {
+               strncpy ( name, data + 4, 6);
        }
+       memcpy (&vlabel, data, sizeof(volume_label_t));
+
        EBCASC(type,4);
        EBCASC(name,6);
        
@@ -174,12 +150,12 @@ first_part_minor)
        printk ( "%4s/%8s:",part_names[partition_type],name);
        switch ( partition_type ) {
        case ibm_partition_cms1:
-               if (* (((long *)bh->b_data) + 13) != 0) {
+               if (* ((long *)data + 13) != 0) {
                        /* disk is reserved minidisk */
-                       long *label=(long*)bh->b_data;
-                       blocksize = label[3];
+                       long *label=(long*)data;
+                       blocksize = label[3]>>9;
                        offset = label[13];
-                       size = (label[7]-1)*(blocksize>>9)
+                       size = (label[7]-1)*blocksize
                        printk ("(MDSK)");
                } else {
                        offset = (info->label_block + 1);
@@ -199,9 +175,10 @@ first_part_minor)
                
                /* get block number and read then first format1 label */
                blk = cchhb2blk(&vlabel.vtoc, geo) + 1;
-               if ((buf = bread( dev, blk, blocksize)) != NULL) {
-                       memcpy (&f1, buf->b_data, sizeof(format1_label_t));
-                       bforget(buf);
+               data = read_dev_sector(bdev, blk * blocksize, &sect2);
+               if (data) {
+                       memcpy (&f1, data, sizeof(format1_label_t));
+                       put_dev_sector(sect2);
                }
                
                while (f1.DS1FMTID == _ascebc['1']) {
@@ -211,14 +188,14 @@ first_part_minor)
                        
                        counter++;
                        add_gd_partition(hd, MINOR(dev) + counter, 
-                                        offset * (blocksize >> 9),
-                                        psize * (blocksize >> 9));
+                                        offset * blocksize,
+                                        psize * blocksize);
                        
                        blk++;
-                       if ((buf = bread( dev, blk, blocksize)) != NULL) {
-                               memcpy (&f1, buf->b_data, 
-                                       sizeof(format1_label_t));
-                               bforget(buf);
+                       data = read_dev_sector(bdev, blk * blocksize, &sect2);
+                       if (data) {
+                               memcpy (&f1, data, sizeof(format1_label_t));
+                               put_dev_sector(sect2);
                        }
                }
                break;
@@ -228,6 +205,6 @@ first_part_minor)
        }
        
        printk ( "\n" );
-       bforget(bh);
+       put_dev_sector(sect);
        return 1;
 }
index 49ff10bc45b6a12373a46b6778d85163418c4177..08b05ed151feb57a133bb636579fcf4c7e66f21b 100644 (file)
@@ -1 +1 @@
-int ibm_partition(struct gendisk *, kdev_t, unsigned long, int);
+int ibm_partition(struct gendisk *, struct block_device *, unsigned long, int);
index 9da28781cf529d7b12244dd0a4add6b0494ce94a..9cef2a18fbd0d66ca145f85b71d6384e8981504c 100644 (file)
@@ -178,10 +178,12 @@ static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb)
  */
 static int create_data_partitions(struct gendisk *hd,
                const unsigned long first_sector, int first_part_minor,
-               const kdev_t dev, const struct vmdb *vm,
-               const struct privhead *ph, const struct ldmdisk *dk)
+               struct block_device *bdev, const struct vmdb *vm,
+               const struct privhead *ph, const struct ldmdisk *dk,
+               unsigned long base)
 {
-       struct buffer_head *bh;
+       Sector  sect;
+       unsigned char *data;
        struct vblk *vb;
        int vblk;
        int vsize;              /* VBLK size. */
@@ -192,14 +194,14 @@ static int create_data_partitions(struct gendisk *hd,
        if (!vb)
                goto no_mem;
        vsize   = vm->vblk_size;
-       if (vsize < 1 || vsize > LDM_BLOCKSIZE)
+       if (vsize < 1 || vsize > 512)
                goto err_out;
-       perbuf  = LDM_BLOCKSIZE / vsize;
-       if (perbuf < 1 || LDM_BLOCKSIZE % vsize)
+       perbuf  = 512 / vsize;
+       if (perbuf < 1 || 512 % vsize)
                goto err_out;
                                        /* 512 == VMDB size */
-       lastbuf = (vm->last_vblk_seq - (512 / vsize)) / perbuf;
-       lastofs = (vm->last_vblk_seq - (512 / vsize)) % perbuf;
+       lastbuf = vm->last_vblk_seq / perbuf - 1;
+       lastofs = vm->last_vblk_seq % perbuf;
        if (lastofs)
                lastbuf++;
        if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
@@ -207,17 +209,18 @@ static int create_data_partitions(struct gendisk *hd,
                goto err_out;
        printk(" <");
        for (buffer = 0; buffer < lastbuf; buffer++) {
-               if (!(bh = bread(dev, buffer + OFF_VBLK, LDM_BLOCKSIZE)))
+               data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
+               if (!data)
                        goto read_err;
                for (vblk = 0; vblk < perbuf; vblk++) {
                        u8 *block;
                        
                        if (lastofs && buffer == lastbuf - 1 && vblk >= lastofs)
                                break;
-                       block = bh->b_data + vsize * vblk;
-                       if (block + vsize > (u8*)bh->b_data + LDM_BLOCKSIZE)
+                       block = data + vsize * vblk;
+                       if (block + vsize > data + 512)
                                goto brelse_out;
-                       if (parse_vblk(block, LDM_BLOCKSIZE, vb) != 1)
+                       if (parse_vblk(block, vsize, vb) != 1)
                                continue;
                        if (vb->vblk_type != VBLK_PART)
                                continue;
@@ -229,7 +232,7 @@ static int create_data_partitions(struct gendisk *hd,
                                        vb->num_sectors) == 1)
                                first_part_minor++;
                }
-               brelse(bh);
+               put_dev_sector(sect);
        }
        printk(" >\n");
        err = 1;
@@ -237,7 +240,7 @@ out:
        kfree(vb);
        return err;
 brelse_out:
-       brelse(bh);
+       put_dev_sector(sect);
        goto err_out;
 no_mem:
        printk(LDM_CRIT "Not enough memory to allocate required buffers.\n");
@@ -326,10 +329,12 @@ static int get_vstr(const u8 *block, u8 *buffer, const int buflen)
  *
  * Return 1 on success and -1 on error, in which case @dk is undefined.
  */
-static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
-               const struct privhead *ph, struct ldmdisk *dk)
+static int get_disk_objid(struct block_device *bdev, const struct vmdb *vm,
+               const struct privhead *ph, struct ldmdisk *dk,
+               unsigned long base)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        u8 *disk_id;
        int vblk;
        int vsize;              /* VBLK size. */
@@ -340,21 +345,22 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
        if (!disk_id)
                goto no_mem;
        vsize   = vm->vblk_size;
-       if (vsize < 1 || vsize > LDM_BLOCKSIZE)
+       if (vsize < 1 || vsize > 512)
                goto err_out;
-       perbuf  = LDM_BLOCKSIZE / vsize;
-       if (perbuf < 1 || LDM_BLOCKSIZE % vsize)
+       perbuf  = 512 / vsize;
+       if (perbuf < 1 || 512 % vsize)
                goto err_out;
                                        /* 512 == VMDB size */
-       lastbuf = (vm->last_vblk_seq - (512 / vsize)) / perbuf;
-       lastofs = (vm->last_vblk_seq - (512 / vsize)) % perbuf;
+       lastbuf = vm->last_vblk_seq / perbuf - 1;
+       lastofs = vm->last_vblk_seq % perbuf;
        if (lastofs)
                lastbuf++;
        if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
                        ph->config_size * 512)
                goto err_out;
        for (buffer = 0; buffer < lastbuf; buffer++) {
-               if (!(bh = bread(dev, buffer + OFF_VBLK, LDM_BLOCKSIZE)))
+               data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
+               if (!data)
                        goto read_err;
                for (vblk = 0; vblk < perbuf; vblk++) {
                        int rel_objid, rel_name, delta;
@@ -362,20 +368,19 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
 
                        if (lastofs && buffer == lastbuf - 1 && vblk >= lastofs)
                                break;
-                       block = bh->b_data + vblk * vsize;
+                       block = data + vblk * vsize;
                        delta = vblk * vsize + 0x18;
-                       if (delta >= LDM_BLOCKSIZE)
+                       if (delta >= 512)
                                goto brelse_out;
                        if (block[0x13] != VBLK_DISK)
                                continue;
                        /* Calculate relative offsets. */
                        rel_objid = 1 + block[0x18];
-                       if (delta + rel_objid >= LDM_BLOCKSIZE)
+                       if (delta + rel_objid >= 512)
                                goto brelse_out;
                        rel_name  = 1 + block[0x18 + rel_objid] + rel_objid;
-                       if (delta + rel_name >= LDM_BLOCKSIZE ||
-                           delta + rel_name + block[0x18 + rel_name] >=
-                                       LDM_BLOCKSIZE)
+                       if (delta + rel_name >= 512 ||
+                           delta + rel_name + block[0x18 + rel_name] >= 512)
                                goto brelse_out;
                        err = get_vstr(block + 0x18 + rel_name, disk_id,
                                        DISK_ID_SIZE);
@@ -383,7 +388,7 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
                                goto brelse_out;
                        if (!strncmp(disk_id, ph->disk_id, DISK_ID_SIZE)) {
                                dk->obj_id = get_vnum(block + 0x18, &err);
-                               brelse(bh);
+                               put_dev_sector(sect);
                                if (err)
                                        goto out;
                                strncpy(dk->disk_id, ph->disk_id,
@@ -393,14 +398,14 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
                                goto out;
                        }
                }
-               brelse(bh);
+               put_dev_sector(sect);
        }
        err = -1;
 out:
        kfree(disk_id);
        return err;
 brelse_out:
-       brelse(bh);
+       put_dev_sector(sect);
        goto err_out;
 no_mem:
        printk(LDM_CRIT "Not enough memory to allocate required buffers.\n");
@@ -457,17 +462,19 @@ static int parse_vmdb(const u8 *buffer, struct vmdb *vm)
  *
  * Return 1 on success and -1 on error, in which case @vm is undefined.
  */
-static int validate_vmdb(const kdev_t dev, struct vmdb *vm)
+static int validate_vmdb(struct block_device *bdev, struct vmdb *vm, unsigned long base)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        int ret;
 
-       if (!(bh = bread(dev, OFF_VMDB, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, base + OFF_VMDB * 2 + 1, &sect);
+       if (!data) {
                printk(LDM_CRIT "Disk read failed in validate_vmdb.\n");
                return -1;
        }
-       ret = parse_vmdb(bh->b_data + 0x200, vm);
-       brelse(bh);
+       ret = parse_vmdb(data, vm);
+       put_dev_sector(sect);
        return ret;
 }
 
@@ -553,9 +560,12 @@ static int parse_tocblock(const u8 *buffer, struct tocblock *toc)
  *
  * Return 1 on success and -1 on error, in which case @toc1 is undefined.
  */
-static int validate_tocblocks(const kdev_t devdb, struct tocblock *toc1)
+static int validate_tocblocks(struct block_device *bdev,
+                       struct tocblock *toc1,
+                       unsigned long base)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        struct tocblock *toc2 = NULL, *toc3 = NULL, *toc4 = NULL;
        int err;
 
@@ -569,39 +579,43 @@ static int validate_tocblocks(const kdev_t devdb, struct tocblock *toc1)
        if (!toc4)
                goto no_mem;
        /* Read and parse first toc. */
-       if (!(bh = bread(devdb, OFF_TOCBLOCK1, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, base + OFF_TOCBLOCK1 * 2 + 1, &sect);
+       if (!data) {
                printk(LDM_CRIT "Disk read 1 failed in validate_tocblocks.\n");
                goto err_out;
        }
-       err = parse_tocblock(bh->b_data + 0x0200, toc1);
-       brelse(bh);
+       err = parse_tocblock(data, toc1);
+       put_dev_sector(sect);
        if (err != 1)
                goto out;
        /* Read and parse second toc. */
-       if (!(bh = bread(devdb, OFF_TOCBLOCK2, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, base + OFF_TOCBLOCK2 * 2, &sect);
+       if (!data) {
                printk(LDM_CRIT "Disk read 2 failed in validate_tocblocks.\n");
                goto err_out;
        }
-       err = parse_tocblock(bh->b_data, toc2);
-       brelse(bh);
+       err = parse_tocblock(data, toc2);
+       put_dev_sector(sect);
        if (err != 1)
                goto out;
        /* Read and parse third toc. */
-       if (!(bh = bread(devdb, OFF_TOCBLOCK3, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, base + OFF_TOCBLOCK3 * 2 + 1, &sect);
+       if (!data) {
                printk(LDM_CRIT "Disk read 3 failed in validate_tocblocks.\n");
                goto err_out;
        }
-       err = parse_tocblock(bh->b_data + 0x0200, toc3);
-       brelse(bh);
+       err = parse_tocblock(data, toc3);
+       put_dev_sector(sect);
        if (err != 1)
                goto out;
        /* Read and parse fourth toc. */
-       if (!(bh = bread(devdb, OFF_TOCBLOCK4, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, base + OFF_TOCBLOCK4 * 2, &sect);
+       if (!data) {
                printk(LDM_CRIT "Disk read 4 failed in validate_tocblocks.\n");
                goto err_out;
        }
-       err = parse_tocblock(bh->b_data, toc4);
-       brelse(bh);
+       err = parse_tocblock(data, toc4);
+       put_dev_sector(sect);
        if (err != 1)
                goto out;
        /* Compare all tocs. */
@@ -665,9 +679,12 @@ static int compare_privheads(const struct privhead *ph1,
  *
  * Return 1 on succes and -1 on error.
  */
-static int validate_privheads(const kdev_t dev, const struct privhead *ph1)
+static int validate_privheads(struct block_device *bdev,
+                             const struct privhead *ph1,
+                             unsigned long base)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        struct privhead *ph2 = NULL, *ph3 = NULL;
        int err;
 
@@ -677,20 +694,22 @@ static int validate_privheads(const kdev_t dev, const struct privhead *ph1)
        ph3 = (struct privhead*)kmalloc(sizeof(*ph3), GFP_KERNEL);
        if (!ph3)
                goto no_mem;
-       if (!(bh = bread(dev, OFF_PRIVHEAD2, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, base + OFF_PRIVHEAD2 * 2, &sect);
+       if (!data) {
                printk(LDM_CRIT "Disk read 1 failed in validate_privheads.\n");
                goto err_out;
        }
-       err = parse_privhead(bh->b_data, ph2);
-       brelse(bh);
+       err = parse_privhead(data, ph2);
+       put_dev_sector(sect);
        if (err != 1)
                goto out;
-       if (!(bh = bread(dev, OFF_PRIVHEAD3, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, base + OFF_PRIVHEAD3 * 2 + 1, &sect);
+       if (!data) {
                printk(LDM_CRIT "Disk read 2 failed in validate_privheads.\n");
                goto err_out;
        }
-       err = parse_privhead(bh->b_data + 0x0200, ph3);
-       brelse(bh);
+       err = parse_privhead(data, ph3);
+       put_dev_sector(sect);
        if (err != 1)
                goto out;
        err = compare_privheads(ph1, ph2);
@@ -807,27 +826,29 @@ static int parse_privhead(const u8 *buffer, struct privhead *ph)
  *
  * Return 1 on succes, 0 if device is not a dynamic disk and -1 on error.
  */
-static int create_db_partition(struct gendisk *hd, const kdev_t dev,
+static int create_db_partition(struct gendisk *hd, struct block_device *bdev,
                const unsigned long first_sector, const int first_part_minor,
                struct privhead *ph)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        int err;
 
-       if (!(bh = bread(dev, OFF_PRIVHEAD1, LDM_BLOCKSIZE))) {
+       data = read_dev_sector(bdev, OFF_PRIVHEAD1*2, &sect);
+       if (!data) {
                printk(LDM_CRIT __FUNCTION__ "(): Device read failed.\n");
                return -1;
        }
-       if (BE64(bh->b_data) != MAGIC_PRIVHEAD) {
+       if (BE64(data) != MAGIC_PRIVHEAD) {
                ldm_debug("Cannot find PRIVHEAD structure. Not a dynamic disk "
                                "or corrupt LDM database.\n");
                return 0;
        }
-       err = parse_privhead(bh->b_data, ph);
+       err = parse_privhead(data, ph);
        if (err == 1)
                err = create_partition(hd, first_part_minor, first_sector +
                                ph->config_start, ph->config_size);
-       brelse(bh);
+       put_dev_sector(sect);
        return err;
 }
 
@@ -842,23 +863,23 @@ static int create_db_partition(struct gendisk *hd, const kdev_t dev,
  *
  * Return 1 if @dev is a dynamic disk, 0 if not and -1 on error.
  */
-static int validate_partition_table(const kdev_t dev)
+static int validate_partition_table(struct block_device *bdev)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        struct partition *p;
        int i, nr_sfs;
 
-       if (!(bh = bread(dev, 0, LDM_BLOCKSIZE))) {
-               if (warn_no_part)
-                       printk(LDM_ERR "Unable to read partition table.\n");
+       data = read_dev_sector(bdev, 0, &sect);
+       if (!data)
                return -1;
-       }
-       if (*(u16*)(bh->b_data + 0x01FE) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+
+       if (*(u16*)(data + 0x01FE) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
                ldm_debug("No MS-DOS partition found.\n");
                goto no_msdos_partition;
        }
        nr_sfs = 0;
-       p = (struct partition*)(bh->b_data + 0x01BE);
+       p = (struct partition*)(data + 0x01BE);
        for (i = 0; i < 4; i++) {
                if (!SYS_IND(p+i) || SYS_IND(p+i) == WIN2K_EXTENDED_PARTITION)
                        continue;
@@ -871,12 +892,12 @@ static int validate_partition_table(const kdev_t dev)
        if (!nr_sfs)
                goto not_dynamic_disk;
        ldm_debug("Parsed partition table successfully.\n");
-       brelse(bh);
+       put_dev_sector(sect);
        return 1;
 not_dynamic_disk:
        ldm_debug("Found basic MS-DOS partition, not a dynamic disk.\n");
 no_msdos_partition:
-       brelse(bh);
+       put_dev_sector(sect);
        return 0;
 }
 
@@ -904,67 +925,54 @@ no_msdos_partition:
  *      0 if @dev is not a dynamic disk,
  *     -1 if an error occured.
  */
-int ldm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-               int first_part_minor)
+int ldm_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sector, int first_part_minor)
 {
-       kdev_t devdb;
        struct privhead *ph  = NULL;
        struct tocblock *toc = NULL;
        struct vmdb     *vm  = NULL;
        struct ldmdisk  *dk  = NULL;
+       unsigned long db_first;
        int err;
 
        if (!hd)
                return 0;
-       err = (int)get_ptable_blocksize(dev);
-       if (err != LDM_BLOCKSIZE) {     /* 1024 bytes */
-               ldm_debug("Expected a blocksize of %d bytes, got %d instead.\n",
-                               LDM_BLOCKSIZE, get_ptable_blocksize(dev));
-               return 0;
-       }
-       err = get_hardsect_size(dev); 
-       if (err != 512) {
-               ldm_debug("Expected a sector size of %d bytes, got %d "
-                               "instead.\n", 512, get_hardsect_size(dev));
-               return 0;
-       }
        /* Check the partition table. */
-       err = validate_partition_table(dev);
+       err = validate_partition_table(bdev);
        if (err != 1)
                return err;
        if (!(ph = (struct privhead*)kmalloc(sizeof(*ph), GFP_KERNEL)))
                goto no_mem;
        /* Create the LDM database device. */
-       err = create_db_partition(hd, dev, first_sector, first_part_minor, ph);
+       err = create_db_partition(hd, bdev, first_sector, first_part_minor, ph);
        if (err != 1)
                goto out;
-       /* For convenience, work with the LDM database device from now on. */
-       devdb = MKDEV(MAJOR(dev), first_part_minor);
+       db_first = hd->part[first_part_minor].start_sect;
        /* Check the backup privheads. */
-       err = validate_privheads(devdb, ph);
+       err = validate_privheads(bdev, ph, db_first);
        if (err != 1)
                goto out;
        /* Check the table of contents and its backups. */
        if (!(toc = (struct tocblock*)kmalloc(sizeof(*toc), GFP_KERNEL)))
                goto no_mem;
-       err = validate_tocblocks(devdb, toc);
+       err = validate_tocblocks(bdev, toc, db_first);
        if (err != 1)
                goto out;
        /* Check the vmdb. */
        if (!(vm = (struct vmdb*)kmalloc(sizeof(*vm), GFP_KERNEL)))
                goto no_mem;
-       err = validate_vmdb(devdb, vm);
+       err = validate_vmdb(bdev, vm, db_first);
        if (err != 1)
                goto out;
        /* Find the object id for @dev in the LDM database. */
        if (!(dk = (struct ldmdisk*)kmalloc(sizeof(*dk), GFP_KERNEL)))
                goto no_mem;
-       err = get_disk_objid(devdb, vm, ph, dk);
+       err = get_disk_objid(bdev, vm, ph, dk, db_first);
        if (err != 1)
                goto out;
        /* Finally, create the data partition devices. */
        err = create_data_partitions(hd, first_sector, first_part_minor +
-                       LDM_FIRST_PART_OFFSET, devdb, vm, ph, dk);
+                       LDM_FIRST_PART_OFFSET, bdev, vm, ph, dk, db_first);
        if (err == 1)
                ldm_debug("Parsed LDM database successfully.\n");
 out:
index ee7c60becb84b530df867f7cd11d416d065444be..0404543ec1b23abe530b2399272dad7117025239 100644 (file)
@@ -144,8 +144,8 @@ struct vblk {
        u64     num_sectors;
 };
 
-int ldm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-               int first_part_minor);
+int ldm_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sector, int first_part_minor);
 
 #endif /* _FS_PT_LDM_H_ */
 
index 5c46935c7288ff1e486c271ef58cc208fe068248..84baad30c812b1aa34754c01101d989ec6940dac 100644 (file)
@@ -20,7 +20,7 @@
 #include "check.h"
 #include "mac.h"
 
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
 extern void note_bootable_part(kdev_t dev, int part, int goodness);
 #endif
 
@@ -36,69 +36,54 @@ static inline void mac_fix_string(char *stg, int len)
                stg[i] = 0;
 }
 
-int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor)
+int mac_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long fsec, int first_part_minor)
 {
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        int blk, blocks_in_map;
-       int dev_bsize, dev_pos, pos;
        unsigned secsize;
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
        int found_root = 0;
        int found_root_goodness = 0;
 #endif
        struct mac_partition *part;
        struct mac_driver_desc *md;
 
-       dev_bsize = get_ptable_blocksize(dev);
-       dev_pos = 0;
        /* Get 0th block and look at the first partition map entry. */
-       if ((bh = bread(dev, 0, dev_bsize)) == 0) {
-           printk("%s: error reading partition table\n",
-                  kdevname(dev));
-           return -1;
-       }
-       md = (struct mac_driver_desc *) bh->b_data;
+       md = (struct mac_driver_desc *) read_dev_sector(bdev, 0, &sect);
+       if (!md)
+               return -1;
        if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
-               brelse(bh);
+               put_dev_sector(sect);
                return 0;
        }
        secsize = be16_to_cpu(md->block_size);
-       if (secsize >= dev_bsize) {
-               brelse(bh);
-               dev_pos = secsize;
-               if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
-                       printk("%s: error reading Mac partition table\n",
-                              kdevname(dev));
-                       return -1;
-               }
-       }
-       part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
+       put_dev_sector(sect);
+       data = read_dev_sector(bdev, secsize/512, &sect);
+       if (!data)
+               return -1;
+       part = (struct mac_partition *) (data + secsize%512);
        if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
-               brelse(bh);
+               put_dev_sector(sect);
                return 0;               /* not a MacOS disk */
        }
        printk(" [mac]");
        blocks_in_map = be32_to_cpu(part->map_count);
        for (blk = 1; blk <= blocks_in_map; ++blk) {
-               pos = blk * secsize;
-               if (pos >= dev_pos + dev_bsize) {
-                       brelse(bh);
-                       dev_pos = pos;
-                       if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
-                               printk("%s: error reading partition table\n",
-                                      kdevname(dev));
-                               return -1;
-                       }
-               }
-               part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
+               int pos = blk * secsize;
+               put_dev_sector(sect);
+               data = read_dev_sector(bdev, pos/512, &sect);
+               if (!data)
+                       return -1;
+               part = (struct mac_partition *) (data + pos%512);
                if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
                        break;
-               blocks_in_map = be32_to_cpu(part->map_count);
                add_gd_partition(hd, first_part_minor,
                        fsec + be32_to_cpu(part->start_block) * (secsize/512),
                        be32_to_cpu(part->block_count) * (secsize/512));
 
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
                /*
                 * If this is the first bootable partition, tell the
                 * setup code, in case it wants to make this the root.
@@ -139,15 +124,17 @@ int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_
                                found_root_goodness = goodness;
                        }
                }
-#endif /* CONFIG_PPC */
+#endif /* CONFIG_ALL_PPC */
 
                ++first_part_minor;
        }
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
        if (found_root_goodness)
-               note_bootable_part(dev, found_root, found_root_goodness);
+               note_bootable_part(to_kdev_t(bdev->bd_dev),
+                                       found_root, found_root_goodness);
 #endif
-       brelse(bh);
+
+       put_dev_sector(sect);
        printk("\n");
        return 1;
 }
index 1a3fd68de6e5ca34a0cf2d23d732dbfa799041cf..9d36ec64983e733d8ea4d0f861f56b9579d1a748 100644 (file)
@@ -41,4 +41,4 @@ struct mac_driver_desc {
     /* ... more stuff */
 };
 
-int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor);
+int mac_partition(struct gendisk *hd, struct block_device *bdev, unsigned long fsec, int first_part_minor);
index 52e626ab8459abf8bf65b3c292f3c3407249db25..8777f50178a9404a38206ea0aaa470ed432006b1 100644 (file)
@@ -40,8 +40,6 @@
 extern void md_autodetect_dev(kdev_t dev);
 #endif
 
-static int current_minor;
-
 /*
  * Many architectures don't like unaligned accesses, which is
  * frequently the case with the nr_sects and start_sect partition
@@ -88,7 +86,8 @@ static char __attribute__ ((unused))
 #define MSDOS_LABEL_MAGIC2     0xAA
 
 static inline int
-msdos_magic_present(unsigned char *p) {
+msdos_magic_present(unsigned char *p)
+{
        return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
 }
 
@@ -103,35 +102,38 @@ msdos_magic_present(unsigned char *p) {
  * only for the actual data partitions.
  */
 
-static void extended_partition(struct gendisk *hd, kdev_t dev)
+static void extended_partition(struct gendisk *hd, struct block_device *bdev,
+                               int minor, int *current_minor)
 {
-       struct buffer_head *bh;
        struct partition *p;
+       Sector sect;
+       unsigned char *data;
        unsigned long first_sector, first_size, this_sector, this_size;
        int mask = (1 << hd->minor_shift) - 1;
-       int sector_size = get_hardsect_size(dev) / 512;
+       int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
        int loopct = 0;         /* number of links followed
                                   without finding a data partition */
        int i;
 
-       first_sector = hd->part[MINOR(dev)].start_sect;
-       first_size = hd->part[MINOR(dev)].nr_sects;
+       first_sector = hd->part[minor].start_sect;
+       first_size = hd->part[minor].nr_sects;
        this_sector = first_sector;
 
        while (1) {
                if (++loopct > 100)
                        return;
-               if ((current_minor & mask) == 0)
+               if ((*current_minor & mask) == 0)
                        return;
-               if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+               data = read_dev_sector(bdev, this_sector, &sect);
+               if (!data)
                        return;
 
-               if (!msdos_magic_present(bh->b_data + 510))
-                       goto done;
+               if (!msdos_magic_present(data + 510))
+                       goto done; 
 
-               p = (struct partition *) (bh->b_data + 0x1be);
+               p = (struct partition *) (data + 0x1be);
 
-               this_size = hd->part[MINOR(dev)].nr_sects;
+               this_size = hd->part[minor].nr_sects;
 
                /*
                 * Usually, the first entry is the real data partition,
@@ -146,30 +148,34 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
                 * First process the data partition(s)
                 */
                for (i=0; i<4; i++, p++) {
+                       unsigned long offs, size, next;
                        if (!NR_SECTS(p) || is_extended_partition(p))
                                continue;
 
                        /* Check the 3rd and 4th entries -
                           these sometimes contain random garbage */
-                       if (i >= 2
-                               && START_SECT(p) + NR_SECTS(p) > this_size
-                               && (this_sector + START_SECT(p) < first_sector ||
-                                   this_sector + START_SECT(p) + NR_SECTS(p) >
-                                    first_sector + first_size))
-                               continue;
+                       offs = START_SECT(p)*sector_size;
+                       size = NR_SECTS(p)*sector_size;
+                       next = this_sector + offs;
+                       if (i >= 2) {
+                               if (offs + size > this_size)
+                                       continue;
+                               if (next < first_sector)
+                                       continue;
+                               if (next + size > first_sector + first_size)
+                                       continue;
+                       }
 
-                       add_gd_partition(hd, current_minor,
-                                        this_sector+START_SECT(p)*sector_size,
-                                        NR_SECTS(p)*sector_size);
+                       add_gd_partition(hd, *current_minor, next, size);
 #if CONFIG_BLK_DEV_MD
                        if (SYS_IND(p) == LINUX_RAID_PARTITION) {
-                           md_autodetect_dev(MKDEV(hd->major,current_minor));
+                           md_autodetect_dev(MKDEV(hd->major,*current_minor));
                        }
 #endif
 
-                       current_minor++;
+                       (*current_minor)++;
                        loopct = 0;
-                       if ((current_minor & mask) == 0)
+                       if ((*current_minor & mask) == 0)
                                goto done;
                }
                /*
@@ -184,61 +190,52 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
                 */
                p -= 4;
                for (i=0; i<4; i++, p++)
-                       if(NR_SECTS(p) && is_extended_partition(p))
+                       if (NR_SECTS(p) && is_extended_partition(p))
                                break;
                if (i == 4)
                        goto done;       /* nothing left to do */
 
-               hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
-               hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
                this_sector = first_sector + START_SECT(p) * sector_size;
-               dev = MKDEV(hd->major, current_minor);
-
-               /* Use bforget(), as we have changed the disk geometry */
-               bforget(bh);
+               minor = *current_minor;
+               put_dev_sector(sect);
        }
 done:
-       bforget(bh);
+       put_dev_sector(sect);
 }
 
-static inline struct buffer_head *
-get_partition_table_block(struct gendisk *hd, int minor, int blocknr) {
-       kdev_t dev = MKDEV(hd->major, minor);
-       return bread(dev, blocknr, get_ptable_blocksize(dev));
-}
-
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
 /* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
    indicates linux swap.  Be careful before believing this is Solaris. */
 
 static void
-solaris_x86_partition(struct gendisk *hd, int minor) {
-       long offset = hd->part[minor].start_sect;
+solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
+               int minor, int *current_minor)
+{
 
-       struct buffer_head *bh;
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+       long offset = hd->part[minor].start_sect;
+       Sector sect;
        struct solaris_x86_vtoc *v;
        struct solaris_x86_slice *s;
        int mask = (1 << hd->minor_shift) - 1;
        int i;
        char buf[40];
 
-       if(!(bh = get_partition_table_block(hd, minor, 0)))
+       v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
+       if (!v)
                return;
-       v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
-       if(le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
-               brelse(bh);
+       if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
+               put_dev_sector(sect);
                return;
        }
        printk(" %s: <solaris:", partition_name(hd, minor, buf));
-       if(le32_to_cpu(v->v_version) != 1) {
+       if (le32_to_cpu(v->v_version) != 1) {
                printk("  cannot handle version %d vtoc>\n",
                        le32_to_cpu(v->v_version));
-               brelse(bh);
+               put_dev_sector(sect);
                return;
        }
-       for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
-               if ((current_minor & mask) == 0)
+       for (i=0; i<SOLARIS_X86_NUMSLICE; i++) {
+               if ((*current_minor & mask) == 0)
                        break;
                s = &v->v_slice[i];
 
@@ -249,23 +246,25 @@ solaris_x86_partition(struct gendisk *hd, int minor) {
                 * one but add_gd_partition starts relative to sector
                 * zero of the disk.  Therefore, must add the offset
                 * of the current partition */
-               add_gd_partition(hd, current_minor, le32_to_cpu(s->s_start)+offset,
+               add_gd_partition(hd, *current_minor,
+                                le32_to_cpu(s->s_start)+offset,
                                 le32_to_cpu(s->s_size));
-               current_minor++;
+               (*current_minor)++;
        }
-       brelse(bh);
+       put_dev_sector(sect);
        printk(" >\n");
-}
 #endif
+}
 
 #ifdef CONFIG_BSD_DISKLABEL
 static void
-check_and_add_bsd_partition(struct gendisk *hd,
-                           struct bsd_partition *bsd_p, int minor) {
+check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
+       int minor, int *current_minor)
+{
        struct hd_struct *lin_p;
                /* check relative position of partitions.  */
        for (lin_p = hd->part + 1 + minor;
-            lin_p - hd->part - minor < current_minor; lin_p++) {
+            lin_p - hd->part - minor < *current_minor; lin_p++) {
                        /* no relationship -> try again */
                if (lin_p->start_sect + lin_p->nr_sects <= le32_to_cpu(bsd_p->p_offset) ||
                    lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size))
@@ -297,232 +296,290 @@ check_and_add_bsd_partition(struct gendisk *hd,
        } /* if the bsd partition is not currently known to linux, we end
           * up here 
           */
-       add_gd_partition(hd, current_minor, le32_to_cpu(bsd_p->p_offset),
+       add_gd_partition(hd, *current_minor, le32_to_cpu(bsd_p->p_offset),
                         le32_to_cpu(bsd_p->p_size));
-       current_minor++;
+       (*current_minor)++;
 }
 
 /* 
  * Create devices for BSD partitions listed in a disklabel, under a
  * dos-like partition. See extended_partition() for more information.
  */
-static void bsd_disklabel_partition(struct gendisk *hd, int minor, int type) {
-       struct buffer_head *bh;
+static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
+       int minor, int *current_minor, char *name, int max_partitions)
+{
+       long offset = hd->part[minor].start_sect;
+       Sector sect;
        struct bsd_disklabel *l;
        struct bsd_partition *p;
-       int max_partitions;
        int mask = (1 << hd->minor_shift) - 1;
        char buf[40];
 
-       if (!(bh = get_partition_table_block(hd, minor, 0)))
+       l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
+       if (!l)
                return;
-       l = (struct bsd_disklabel *) (bh->b_data+512);
        if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
-               brelse(bh);
+               put_dev_sector(sect);
                return;
        }
-       printk(" %s:", partition_name(hd, minor, buf));
-       printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
-              (type == NETBSD_PARTITION) ? " <netbsd:" : " <bsd:");
+       printk(" %s: <%s", partition_name(hd, minor, buf), name);
 
-       max_partitions = ((type == OPENBSD_PARTITION) ? OPENBSD_MAXPARTITIONS
-                                                     : BSD_MAXPARTITIONS);
        if (le16_to_cpu(l->d_npartitions) < max_partitions)
                max_partitions = le16_to_cpu(l->d_npartitions);
        for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
-               if ((current_minor & mask) == 0)
+               if ((*current_minor & mask) == 0)
                        break;
-
-               if (p->p_fstype != BSD_FS_UNUSED) 
-                       check_and_add_bsd_partition(hd, p, minor);
+               if (p->p_fstype == BSD_FS_UNUSED) 
+                       continue;
+               check_and_add_bsd_partition(hd, p, minor, current_minor);
        }
+       put_dev_sector(sect);
+       printk(" >\n");
+}
+#endif
 
-       /* Use bforget(), as we have changed the disk setup */
-       bforget(bh);
+static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
+       int minor, int *current_minor)
+{
+#ifdef CONFIG_BSD_DISKLABEL
+       do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
+               BSD_MAXPARTITIONS);
+#endif
+}
 
-       printk(" >\n");
+static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
+               int minor, int *current_minor)
+{
+#ifdef CONFIG_BSD_DISKLABEL
+       do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
+                       BSD_MAXPARTITIONS);
+#endif
 }
+
+static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
+               int minor, int *current_minor)
+{
+#ifdef CONFIG_BSD_DISKLABEL
+       do_bsd_partition(hd, bdev, minor, current_minor,
+                       "openbsd", OPENBSD_MAXPARTITIONS);
 #endif
+}
 
-#ifdef CONFIG_UNIXWARE_DISKLABEL
 /*
  * Create devices for Unixware partitions listed in a disklabel, under a
  * dos-like partition. See extended_partition() for more information.
  */
-static void unixware_partition(struct gendisk *hd, int minor) {
-       struct buffer_head *bh;
+static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
+               int minor, int *current_minor)
+{
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+       long offset = hd->part[minor].start_sect;
+       Sector sect;
        struct unixware_disklabel *l;
        struct unixware_slice *p;
        int mask = (1 << hd->minor_shift) - 1;
        char buf[40];
 
-       if (!(bh = get_partition_table_block(hd, minor, 14)))
+       l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
+       if (!l)
                return;
-       l = (struct unixware_disklabel *) (bh->b_data+512);
        if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
            le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
-               brelse(bh);
+               put_dev_sector(sect);
                return;
        }
        printk(" %s: <unixware:", partition_name(hd, minor, buf));
        p = &l->vtoc.v_slice[1];
        /* I omit the 0th slice as it is the same as whole disk. */
        while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
-               if ((current_minor & mask) == 0)
+               if ((*current_minor & mask) == 0)
                        break;
 
                if (p->s_label != UNIXWARE_FS_UNUSED) {
-                       add_gd_partition(hd, current_minor, START_SECT(p),
+                       add_gd_partition(hd, *current_minor, START_SECT(p),
                                         NR_SECTS(p));
-                       current_minor++;
+                       (*current_minor)++;
                }
                p++;
        }
-       /* Use bforget, as we have changed the disk setup */
-       bforget(bh);
+       put_dev_sector(sect);
        printk(" >\n");
-}
 #endif
+}
 
-#ifdef CONFIG_MINIX_SUBPARTITION
 /*
  * Minix 2.0.0/2.0.2 subpartition support.
  * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
  * Rajeev V. Pillai    <rajeevvp@yahoo.com>
  */
-static void minix_partition(struct gendisk *hd, int minor)
+static void minix_partition(struct gendisk *hd, struct block_device *bdev,
+               int minor, int *current_minor)
 {
-       struct buffer_head *bh;
+#ifdef CONFIG_MINIX_SUBPARTITION
+       long offset = hd->part[minor].start_sect;
+       Sector sect;
+       unsigned char *data;
        struct partition *p;
        int mask = (1 << hd->minor_shift) - 1;
        int i;
        char buf[40];
 
-       if (!(bh = get_partition_table_block(hd, minor, 0)))
+       data = read_dev_sector(bdev, offset, &sect);
+       if (!data)
                return;
-       bh->b_state = 0;
 
-       p = (struct partition *)(bh->b_data + 0x1be);
+       p = (struct partition *)(data + 0x1be);
 
        /* The first sector of a Minix partition can have either
         * a secondary MBR describing its subpartitions, or
         * the normal boot sector. */
-       if (msdos_magic_present (bh->b_data + 510) &&
+       if (msdos_magic_present (data + 510) &&
            SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
 
                printk(" %s: <minix:", partition_name(hd, minor, buf));
                for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
-                       if ((current_minor & mask) == 0)
+                       if ((*current_minor & mask) == 0)
                                break;
                        /* add each partition in use */
                        if (SYS_IND(p) == MINIX_PARTITION) {
-                               add_gd_partition(hd, current_minor,
+                               add_gd_partition(hd, *current_minor,
                                              START_SECT(p), NR_SECTS(p));
-                               current_minor++;
+                               (*current_minor)++;
                        }
                }
                printk(" >\n");
        }
-       brelse(bh);
-}
+       put_dev_sector(sect);
 #endif /* CONFIG_MINIX_SUBPARTITION */
-int msdos_partition(struct gendisk *hd, kdev_t dev,
-                   unsigned long first_sector, int first_part_minor) {
-       int i, minor = current_minor = first_part_minor;
-       struct buffer_head *bh;
-       struct partition *p;
-       unsigned char *data;
-       int mask = (1 << hd->minor_shift) - 1;
-       int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_BLK_DEV_IDE
-       int tested_for_xlate = 0;
+}
 
-read_mbr:
-#endif /* CONFIG_BLK_DEV_IDE */
-       if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-               if (warn_no_part) printk(" unable to read partition table\n");
-               return -1;
-       }
-       data = bh->b_data;
+static struct {
+       unsigned char id;
+       void (*parse)(struct gendisk *, struct block_device *, int, int *);
+} subtypes[] = {
+       {BSD_PARTITION, bsd_partition},
+       {NETBSD_PARTITION, netbsd_partition},
+       {OPENBSD_PARTITION, openbsd_partition},
+       {MINIX_PARTITION, minix_partition},
+       {UNIXWARE_PARTITION, unixware_partition},
+       {SOLARIS_X86_PARTITION, solaris_x86_partition},
+       {0, NULL},
+};
+/*
+ * Look for various forms of IDE disk geometry translation
+ */
+static int handle_ide_mess(struct block_device *bdev)
+{
 #ifdef CONFIG_BLK_DEV_IDE
-check_table:
-#endif /* CONFIG_BLK_DEV_IDE */
-       /* Use bforget(), because we may have changed the disk geometry */
+       Sector sect;
+       unsigned char *data;
+       kdev_t dev = to_kdev_t(bdev->bd_dev);
+       unsigned int sig;
+       int heads = 0;
+       struct partition *p;
+       int i;
+       /*
+        * The i386 partition handling programs very often
+        * make partitions end on cylinder boundaries.
+        * There is no need to do so, and Linux fdisk doesnt always
+        * do this, and Windows NT on Alpha doesnt do this either,
+        * but still, this helps to guess #heads.
+        */
+       data = read_dev_sector(bdev, 0, &sect);
+       if (!data)
+               return -1;
        if (!msdos_magic_present(data + 510)) {
-               bforget(bh);
+               put_dev_sector(sect);
                return 0;
        }
+       sig = le16_to_cpu(*(unsigned short *)(data + 2));
        p = (struct partition *) (data + 0x1be);
+       for (i = 0; i < 4; i++) {
+               struct partition *q = &p[i];
+               if (NR_SECTS(q)) {
+                       if ((q->sector & 63) == 1 &&
+                           (q->end_sector & 63) == 63)
+                               heads = q->end_head + 1;
+                       break;
+               }
+       }
+       if (SYS_IND(p) == EZD_PARTITION) {
+               /*
+                * Accesses to sector 0 must go to sector 1 instead.
+                */
+               if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
+                       goto reread;
+       } else if (SYS_IND(p) == DM6_PARTITION) {
 
-#ifdef CONFIG_BLK_DEV_IDE
-       if (!tested_for_xlate++) {      /* Do this only once per disk */
                /*
-                * Look for various forms of IDE disk geometry translation
+                * Everything on the disk is offset by 63 sectors,
+                * including a "new" MBR with its own partition table.
                 */
-               unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
-               int heads = 0;
+               if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
+                       goto reread;
+       } else if (sig <= 0x1ae &&
+                  data[sig] == 0xAA && data[sig+1] == 0x55 &&
+                  (data[sig+2] & 1)) {
+               /* DM6 signature in MBR, courtesy of OnTrack */
+               (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
+       } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
+                  SYS_IND(p) == DM6_AUX3PARTITION) {
                /*
-                * The i386 partition handling programs very often
-                * make partitions end on cylinder boundaries.
-                * There is no need to do so, and Linux fdisk doesnt always
-                * do this, and Windows NT on Alpha doesnt do this either,
-                * but still, this helps to guess #heads.
+                * DM6 on other than the first (boot) drive
                 */
-               for (i = 0; i < 4; i++) {
-                       struct partition *q = &p[i];
-                       if (NR_SECTS(q)) {
-                               if ((q->sector & 63) == 1 &&
-                                   (q->end_sector & 63) == 63)
-                                       heads = q->end_head + 1;
-                               break;
-                       }
-               }
-               if (SYS_IND(p) == EZD_PARTITION) {
-                       /*
-                        * Accesses to sector 0 must go to sector 1 instead.
-                        */
-                       if (ide_xlate_1024(dev, -1, heads, " [EZD]")) {
-                               data += 512;
-                               goto check_table;
-                       }
-               } else if (SYS_IND(p) == DM6_PARTITION) {
-
-                       /*
-                        * Everything on the disk is offset by 63 sectors,
-                        * including a "new" MBR with its own partition table.
-                        */
-                       if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) {
-                               bforget(bh);
-                               goto read_mbr;  /* start over with new MBR */
-                       }
-               } else if (sig <= 0x1ae &&
-                          data[sig] == 0xAA && data[sig+1] == 0x55 &&
-                          (data[sig+2] & 1)) {
-                       /* DM6 signature in MBR, courtesy of OnTrack */
-                       (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
-               } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
-                          SYS_IND(p) == DM6_AUX3PARTITION) {
-                       /*
-                        * DM6 on other than the first (boot) drive
-                        */
-                       (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
-               } else {
-                       (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
-               }
+               (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
+       } else {
+               (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
        }
+       put_dev_sector(sect);
+       return 1;
+
+reread:
+       put_dev_sector(sect);
+       /* Flush the cache */
+       invalidate_bdev(bdev, 1);
+       truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
 #endif /* CONFIG_BLK_DEV_IDE */
+       return 1;
+}
+int msdos_partition(struct gendisk *hd, struct block_device *bdev,
+                   unsigned long first_sector, int first_part_minor)
+{
+       int i, minor = first_part_minor;
+       Sector sect;
+       struct partition *p;
+       unsigned char *data;
+       int mask = (1 << hd->minor_shift) - 1;
+       int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
+       int current_minor = first_part_minor;
+       int err;
+
+       err = handle_ide_mess(bdev);
+       if (err <= 0)
+               return err;
+       data = read_dev_sector(bdev, 0, &sect);
+       if (!data)
+               return -1;
+       if (!msdos_magic_present(data + 510)) {
+               put_dev_sector(sect);
+               return 0;
+       }
+       p = (struct partition *) (data + 0x1be);
 
-       /* Look for partitions in two passes:
-          First find the primary partitions, and the DOS-type extended partitions.
-          On the second pass look inside *BSD and Unixware and Solaris partitions. */
+       /*
+        * Look for partitions in two passes:
+        * First find the primary and DOS-type extended partitions.
+        * On the second pass look inside *BSD, Unixware and Solaris partitions.
+        */
 
-       current_minor += 4;  /* first "extra" minor (for extended partitions) */
+       current_minor += 4;
        for (i=1 ; i<=4 ; minor++,i++,p++) {
                if (!NR_SECTS(p))
                        continue;
-               add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size,
-                                NR_SECTS(p)*sector_size);
+               add_gd_partition(hd, minor,
+                               first_sector+START_SECT(p)*sector_size,
+                               NR_SECTS(p)*sector_size);
 #if CONFIG_BLK_DEV_MD
                if (SYS_IND(p) == LINUX_RAID_PARTITION) {
                        md_autodetect_dev(MKDEV(hd->major,minor));
@@ -530,20 +587,12 @@ check_table:
 #endif
                if (is_extended_partition(p)) {
                        printk(" <");
-                       /*
-                        * If we are rereading the partition table, we need
-                        * to set the size of the partition so that we will
-                        * be able to bread the block containing the extended
-                        * partition info.
-                        */
-                       hd->sizes[minor] = hd->part[minor].nr_sects 
-                               >> (BLOCK_SIZE_BITS - 9);
-                       extended_partition(hd, MKDEV(hd->major, minor));
-                       printk(" >");
                        /* prevent someone doing mkfs or mkswap on an
                           extended partition, but leave room for LILO */
                        if (hd->part[minor].nr_sects > 2)
                                hd->part[minor].nr_sects = 2;
+                       extended_partition(hd, bdev, minor, &current_minor);
+                       printk(" >");
                }
        }
 
@@ -567,29 +616,18 @@ check_table:
        minor -= 4;
        p = (struct partition *) (0x1be + data);
        for (i=1 ; i<=4 ; minor++,i++,p++) {
+               unsigned char id = SYS_IND(p);
+               int n;
+
                if (!NR_SECTS(p))
                        continue;
-#ifdef CONFIG_BSD_DISKLABEL
-               if (SYS_IND(p) == BSD_PARTITION ||
-                   SYS_IND(p) == NETBSD_PARTITION ||
-                   SYS_IND(p) == OPENBSD_PARTITION)
-                       bsd_disklabel_partition(hd, minor, SYS_IND(p));
-#endif
-#ifdef CONFIG_MINIX_SUBPARTITION
-               if (SYS_IND(p) == MINIX_PARTITION) {
-                       minix_partition(hd, minor);
-               }
-#endif
-#ifdef CONFIG_UNIXWARE_DISKLABEL
-               if (SYS_IND(p) == UNIXWARE_PARTITION)
-                       unixware_partition(hd, minor);
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-               if(SYS_IND(p) == SOLARIS_X86_PARTITION)
-                       solaris_x86_partition(hd, minor);
-#endif
-       }
 
-       bforget(bh);
+               for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
+                       ;
+
+               if (subtypes[n].parse)
+                       subtypes[n].parse(hd, bdev, minor, &current_minor);
+       }
+       put_dev_sector(sect);
        return 1;
 }
index e24740c5e031037bcd3c4dd45e387d91873bebe2..09c8b095ad5609f06b5585011add166571e32296 100644 (file)
@@ -4,6 +4,6 @@
 
 #define MSDOS_LABEL_MAGIC              0xAA55
 
-int msdos_partition(struct gendisk *hd, kdev_t dev,
+int msdos_partition(struct gendisk *hd, struct block_device *bdev,
                    unsigned long first_sector, int first_part_minor);
 
index 52aae3bbd6bab77c8b981e5ddf7ba833292fa861..e178ca2b6543b45f065c4602c0c80ba6701eb739 100644 (file)
 #include "check.h"
 #include "osf.h"
 
-int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-                 int current_minor)
+int osf_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sector, int current_minor)
 {
        int i;
+       Sector sect;
+       unsigned char *data;
        int mask = (1 << hd->minor_shift) - 1;
-       struct buffer_head *bh;
        struct disklabel {
                u32 d_magic;
                u16 d_type,d_subtype;
@@ -56,18 +57,18 @@ int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
        } * label;
        struct d_partition * partition;
 
-       if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-               if (warn_no_part) printk("unable to read partition table\n");
+       data = read_dev_sector(bdev, 0, &sect);
+       if (!data)
                return -1;
-       }
-       label = (struct disklabel *) (bh->b_data+64);
+
+       label = (struct disklabel *) (data+64);
        partition = label->d_partitions;
        if (le32_to_cpu(label->d_magic) != DISKLABELMAGIC) {
-               brelse(bh);
+               put_dev_sector(sect);
                return 0;
        }
        if (le32_to_cpu(label->d_magic2) != DISKLABELMAGIC) {
-               brelse(bh);
+               put_dev_sector(sect);
                return 0;
        }
        for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
@@ -80,7 +81,7 @@ int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
                current_minor++;
        }
        printk("\n");
-       brelse(bh);
+       put_dev_sector(sect);
        return 1;
 }
 
index ce14150565b978d55f6c884ade5862c8db553ba8..6f02393c490b6decfc0d8dba4eb17f22024cb9f3 100644 (file)
@@ -4,6 +4,6 @@
 
 #define DISKLABELMAGIC (0x82564557UL)
 
-int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-                 int current_minor);
+int osf_partition(struct gendisk *hd, struct block_device *bdev,
+               unsigned long first_sector, int current_minor);
 
index 3806b5f31afbed271565c79bcf2f946749dc2af6..ea74ebb4b57b594fe8f2cf548569da84e6a30a4d 100644 (file)
 #include "check.h"
 #include "sgi.h"
 
-int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int current_minor)
+int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int current_minor)
 {
        int i, csum, magic;
        unsigned int *ui, start, blocks, cs;
-       struct buffer_head *bh;
+       Sector sect;
+       kdev_t dev = to_kdev_t(bdev->bd_dev);
        struct sgi_disklabel {
                int magic_mushroom;         /* Big fat spliff... */
                short root_part_num;        /* Root partition number */
@@ -43,17 +44,15 @@ int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
        } *label;
        struct sgi_partition *p;
 
-       if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
-               if (warn_no_part) printk(KERN_WARNING "Dev %s: unable to read partition table\n", kdevname(dev));
+       label = (struct sgi_disklabel *) read_dev_sector(bdev, 0, &sect);
+       if (!label)
                return -1;
-       }
-       label = (struct sgi_disklabel *) bh->b_data;
        p = &label->partitions[0];
        magic = label->magic_mushroom;
        if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
                /*printk("Dev %s SGI disklabel: bad magic %08x\n",
-                      kdevname(dev), magic);*/
-               brelse(bh);
+                      bdevname(dev), magic);*/
+               put_dev_sector(sect);
                return 0;
        }
        ui = ((unsigned int *) (label + 1)) - 1;
@@ -63,8 +62,8 @@ int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
        }
        if(csum) {
                printk(KERN_WARNING "Dev %s SGI disklabel: csum bad, label corrupted\n",
-                      kdevname(dev));
-               brelse(bh);
+                      bdevname(dev));
+               put_dev_sector(sect);
                return 0;
        }
        /* All SGI disk labels have 16 partitions, disks under Linux only
@@ -81,6 +80,6 @@ int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
                current_minor++;
        }
        printk("\n");
-       brelse(bh);
+       put_dev_sector(sect);
        return 1;
 }
index 6e4ac1ac488f0d2134c33be39b5561c74876dac7..55840d9285e57659708b4e6d92a449a5b3acfd39 100644 (file)
@@ -2,7 +2,7 @@
  *  fs/partitions/sgi.h
  */
 
-extern int sgi_partition(struct gendisk *hd, kdev_t dev,
+extern int sgi_partition(struct gendisk *hd, struct block_device *bdev,
         unsigned long first_sector, int first_part_minor);
 
 #define SGI_LABEL_MAGIC 0x0be5a941
index f48bc5cd8c5c54656ac775a7671d25c870ba0c31..bee5abb6537b8caedb923374f109c34954832000 100644 (file)
 #include "check.h"
 #include "sun.h"
 
-int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int first_part_minor)
 {
        int i, csum;
        unsigned short *ush;
-       struct buffer_head *bh;
+       Sector sect;
+       kdev_t dev = to_kdev_t(bdev->bd_dev);
        struct sun_disklabel {
                unsigned char info[128];   /* Informative text string */
                unsigned char spare[292];  /* Boot information etc. */
@@ -47,27 +48,25 @@ int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
        struct sun_partition *p;
        unsigned long spc;
 
-       if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
-               if (warn_no_part) printk(KERN_WARNING "Dev %s: unable to read partition table\n",
-                      kdevname(dev));
+       label = (struct sun_disklabel *)read_dev_sector(bdev, 0, &sect);
+       if (!label)
                return -1;
-       }
-       label = (struct sun_disklabel *) bh->b_data;
+
        p = label->partitions;
        if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
 /*             printk(KERN_INFO "Dev %s Sun disklabel: bad magic %04x\n",
-                      kdevname(dev), be16_to_cpu(label->magic)); */
-               brelse(bh);
+                      bdevname(dev), be16_to_cpu(label->magic)); */
+               put_dev_sector(sect);
                return 0;
        }
        /* Look at the checksum */
        ush = ((unsigned short *) (label+1)) - 1;
-       for(csum = 0; ush >= ((unsigned short *) label);)
+       for (csum = 0; ush >= ((unsigned short *) label);)
                csum ^= *ush--;
        if(csum) {
                printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
-                      kdevname(dev));
-               brelse(bh);
+                      bdevname(dev));
+               put_dev_sector(sect);
                return 0;
        }
        /* All Sun disks have 8 partition entries */
@@ -83,7 +82,6 @@ int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
                first_part_minor++;
        }
        printk("\n");
-       brelse(bh);
+       put_dev_sector(sect);
        return 1;
 }
-
index 3426d4aa29fcb4bb93553017da1b4d38c676d90c..ae2f9579ef8755fd00a2f113e9ad2196827943ac 100644 (file)
@@ -4,6 +4,6 @@
 
 #define SUN_LABEL_MAGIC          0xDABE
 
-int sun_partition(struct gendisk *hd, kdev_t dev,
+int sun_partition(struct gendisk *hd, struct block_device *bdev,
                  unsigned long first_sector, int first_part_minor);
 
index aa49ba517fd8daa64e8ec946065a50a301c1b518..a7e0629dd2da587cf8c5a1f2011adce1952d19eb 100644 (file)
 
 #include "check.h"
 
-int ultrix_partition(struct gendisk *hd, kdev_t dev,
+int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
                             unsigned long first_sector, int first_part_minor)
 {
        int i;
-       struct buffer_head *bh;
+       Sector sect;
+       unsigned char *data;
        struct ultrix_disklabel {
                s32     pt_magic;       /* magic no. indicating part. info exits */
                s32     pt_valid;       /* set by driver if pt is current */
@@ -31,18 +32,11 @@ int ultrix_partition(struct gendisk *hd, kdev_t dev,
 #define PT_MAGIC       0x032957        /* Partition magic number */
 #define PT_VALID       1               /* Indicates if struct is valid */
 
-#define        SBLOCK  ((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
-                  /get_ptable_blocksize(dev)))
-
-       bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
-       if (!bh) {
-               if (warn_no_part) printk (" unable to read block 0x%lx\n", SBLOCK);
+       data = read_dev_sector(bdev, (16384 - sizeof(*label))/512, &sect);
+       if (!data)
                return -1;
-       }
        
-       label = (struct ultrix_disklabel *)(bh->b_data
-                                            + get_ptable_blocksize(dev)
-                                            - sizeof(struct ultrix_disklabel));
+       label = (struct ultrix_disklabel *)(data + 512 - sizeof(*label));
 
        if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
                for (i=0; i<8; i++, first_part_minor++)
@@ -50,11 +44,11 @@ int ultrix_partition(struct gendisk *hd, kdev_t dev,
                                add_gd_partition(hd, first_part_minor, 
                                              label->pt_part[i].pi_blkoff,
                                              label->pt_part[i].pi_nblocks);
-               brelse(bh);
+               put_dev_sector(sect);
                printk ("\n");
                return 1;
        } else {
-               brelse(bh);
+               put_dev_sector(sect);
                return 0;
        }
 }
index d2259db3e9178fe2028ac6bae2efb59697322213..1572c90d90bee77e861e30e13d34c29be5f18577 100644 (file)
@@ -2,6 +2,6 @@
  *  fs/partitions/ultrix.h
  */
 
-int ultrix_partition(struct gendisk *hd, kdev_t dev,
+int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
                      unsigned long first_sector, int first_part_minor);
 
index cf9e3ffc5c670784fde99fea7e86dfe61d55fa0d..63ecf3d06cafd5e5026882d538478eca85bda613 100644 (file)
@@ -1,5 +1,30 @@
 ChangeLog for smbfs.
 
+2001-09-17 Urban Widmark <urban@teststation.com>
+
+       * proc.c: Use 4096 (was 512) as the blocksize for better write
+         performance (patch originally by Jan Kratochvil)
+       * proc.c: Skip disconnect smb, allows umount on unreachable servers.
+       * proc.c: Go back to the interruptible sleep as reconnects seem to
+         handle it now.
+       * *.c: use autogenerated and private proto.h
+
+2000-11-22 Igor Zhbanov <bsg@uniyar.ac.ru>
+
+       * proc.c: fixed date_unix2dos for dates earlier than 01/01/1980
+         and date_dos2unix for date==0 (from 2.2)
+
+2001-07-13 Rob Radez <rob@osinvestor.com>
+
+       * proc.c: make smb_errno return negative error values
+
+2001-07-09 Jochen Dolze <dolze@epcnet.de>
+
+       * inode.c: smb_statfs always returned success.
+       * proc.c, ioctl.c: Allow smbmount to signal failure to reconnect with
+         a NULL argument to SMB_IOC_NEWCONN (speeds up error detection).
+       * proc.c: Add some of the missing error codes to smb_errno
+
 2001-06-12 Urban Widmark <urban@teststation.com>
 
        * proc.c: replace the win95-flush fix with smb_seek, when needed.
index 16e8ceb15d5a574616711495cb86b5e879ae851b..93ddc0df84f233520617a6c6d34b43649bdb37e9 100644 (file)
@@ -23,3 +23,19 @@ EXTRA_CFLAGS += -DSMBFS_PARANOIA
 #EXTRA_CFLAGS += -Werror
 
 include $(TOPDIR)/Rules.make
+
+#
+# Maintainer rules
+#
+
+# getopt.c not included. It is intentionally separate
+SRC = proc.c dir.c cache.c sock.c inode.c file.c ioctl.c
+
+proto:
+       -rm -f proto.h
+       @echo >  proto2.h "/*"
+       @echo >> proto2.h " *  Autogenerated with cproto on: " `date`
+       @echo >> proto2.h " */"
+       @echo >> proto2.h ""
+       cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h
+       mv proto2.h proto.h
index 3dc17d2292e344c3d8b3a452d8bc95f506f32d46..3e98f83ab19fa77bf31266913caddca0108cc17e 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/page.h>
 
 #include "smb_debug.h"
+#include "proto.h"
 
 /*
  * Force the next attempt to use the cache to be a timeout.
index 48d716c9e3a84a37445ec19e25fed6d461d81b8d..5696c8e2fbe7cf95dddd79020971b7a8bcf6f9bb 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/smbno.h>
 
 #include "smb_debug.h"
+#include "proto.h"
 
 static int smb_readdir(struct file *, void *, filldir_t);
 static int smb_dir_open(struct inode *, struct file *);
@@ -452,8 +453,7 @@ smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
        if (!inode)
                goto out_no_inode;
 
-       if (have_id)
-       {
+       if (have_id) {
                inode->u.smbfs_i.fileid = fileid;
                inode->u.smbfs_i.access = SMB_O_RDWR;
                inode->u.smbfs_i.open = server->generation;
@@ -465,8 +465,7 @@ out:
 out_no_inode:
        error = -EACCES;
 out_close:
-       if (have_id)
-       {
+       if (have_id) {
                PARANOIA("%s/%s failed, error=%d, closing %u\n",
                         DENTRY_PATH(dentry), error, fileid);
                smb_close_fileid(dentry, fileid);
@@ -562,12 +561,10 @@ smb_rename(struct inode *old_dir, struct dentry *old_dentry,
         */
        if (old_dentry->d_inode)
                smb_close(old_dentry->d_inode);
-       if (new_dentry->d_inode)
-       {
+       if (new_dentry->d_inode) {
                smb_close(new_dentry->d_inode);
                error = smb_proc_unlink(new_dentry);
-               if (error)
-               {
+               if (error) {
                        VERBOSE("unlink %s/%s, error=%d\n",
                                DENTRY_PATH(new_dentry), error);
                        goto out;
@@ -579,8 +576,7 @@ smb_rename(struct inode *old_dir, struct dentry *old_dentry,
        smb_invalid_dir_cache(old_dir);
        smb_invalid_dir_cache(new_dir);
        error = smb_proc_mv(old_dentry, new_dentry);
-       if (!error)
-       {
+       if (!error) {
                smb_renew_times(old_dentry);
                smb_renew_times(new_dentry);
        }
index 189828846025d6d68009a232ec1309f19f7670b6..d74e32ad6bf52079b162f6a469e0fa15d99513c4 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/smb_fs.h>
 
 #include "smb_debug.h"
+#include "proto.h"
 
 static int
 smb_fsync(struct file *file, struct dentry * dentry, int datasync)
index 348e5acad771715a3eedadfbec6ec18990365957..9f5921c18fb5d11a8a5c29216f79690d30c8f9bd 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "smb_debug.h"
 #include "getopt.h"
+#include "proto.h"
 
 /* Always pick a default string */
 #ifdef CONFIG_SMB_NLS_REMOTE
@@ -259,7 +260,7 @@ smb_delete_inode(struct inode *ino)
 }
 
 /* FIXME: flags and has_arg could probably be merged. */
-struct option opts[] = {
+static struct option opts[] = {
        { "version",    1, 0, 'v' },
        { "win95",      0, SMB_MOUNT_WIN95, 1 },
        { "oldattr",    0, SMB_MOUNT_OLDATTR, 1 },
@@ -344,7 +345,6 @@ smb_put_super(struct super_block *sb)
        struct smb_sb_info *server = &(sb->u.smbfs_sb);
 
        if (server->sock_file) {
-               smb_proc_disconnect(server);
                smb_dont_catch_keepalive(server);
                fput(server->sock_file);
        }
@@ -353,23 +353,24 @@ smb_put_super(struct super_block *sb)
               kill_proc(server->conn_pid, SIGTERM, 1);
 
        smb_kfree(server->mnt);
-       smb_kfree(sb->u.smbfs_sb.temp_buf);
+       smb_kfree(server->temp_buf);
        if (server->packet)
                smb_vfree(server->packet);
 
-       if(sb->u.smbfs_sb.remote_nls) {
-               unload_nls(sb->u.smbfs_sb.remote_nls);
-               sb->u.smbfs_sb.remote_nls = NULL;
+       if (server->remote_nls) {
+               unload_nls(server->remote_nls);
+               server->remote_nls = NULL;
        }
-       if(sb->u.smbfs_sb.local_nls) {
-               unload_nls(sb->u.smbfs_sb.local_nls);
-               sb->u.smbfs_sb.local_nls = NULL;
+       if (server->local_nls) {
+               unload_nls(server->local_nls);
+               server->local_nls = NULL;
        }
 }
 
 struct super_block *
 smb_read_super(struct super_block *sb, void *raw_data, int silent)
 {
+       struct smb_sb_info *server = &sb->u.smbfs_sb;
        struct smb_mount_data_kernel *mnt;
        struct smb_mount_data *oldmnt;
        struct inode *root_inode;
@@ -389,34 +390,34 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        sb->s_magic = SMB_SUPER_MAGIC;
        sb->s_op = &smb_sops;
 
-       sb->u.smbfs_sb.mnt = NULL;
-       sb->u.smbfs_sb.sock_file = NULL;
-       init_MUTEX(&sb->u.smbfs_sb.sem);
-       init_waitqueue_head(&sb->u.smbfs_sb.wait);
-       sb->u.smbfs_sb.conn_pid = 0;
-       sb->u.smbfs_sb.state = CONN_INVALID; /* no connection yet */
-       sb->u.smbfs_sb.generation = 0;
-       sb->u.smbfs_sb.packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);
-       sb->u.smbfs_sb.packet = smb_vmalloc(sb->u.smbfs_sb.packet_size);
-       if (!sb->u.smbfs_sb.packet)
+       server->mnt = NULL;
+       server->sock_file = NULL;
+       init_MUTEX(&server->sem);
+       init_waitqueue_head(&server->wait);
+       server->conn_pid = 0;
+       server->state = CONN_INVALID; /* no connection yet */
+       server->generation = 0;
+       server->packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);
+       server->packet = smb_vmalloc(server->packet_size);
+       if (!server->packet)
                goto out_no_mem;
 
        /* Allocate the global temp buffer */
-       sb->u.smbfs_sb.temp_buf = smb_kmalloc(2*SMB_MAXPATHLEN+20, GFP_KERNEL);
-       if (!sb->u.smbfs_sb.temp_buf)
+       server->temp_buf = smb_kmalloc(2*SMB_MAXPATHLEN+20, GFP_KERNEL);
+       if (!server->temp_buf)
                goto out_no_temp;
 
        /* Setup NLS stuff */
-       sb->u.smbfs_sb.remote_nls = NULL;
-       sb->u.smbfs_sb.local_nls = NULL;
-       sb->u.smbfs_sb.name_buf = sb->u.smbfs_sb.temp_buf + SMB_MAXPATHLEN + 20;
+       server->remote_nls = NULL;
+       server->local_nls = NULL;
+       server->name_buf = server->temp_buf + SMB_MAXPATHLEN + 20;
 
        /* Allocate the mount data structure */
        /* FIXME: merge this with the other malloc and get a whole page? */
        mnt = smb_kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
        if (!mnt)
                goto out_no_mount;
-       sb->u.smbfs_sb.mnt = mnt;
+       server->mnt = mnt;
 
        memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
        strncpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
@@ -447,9 +448,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
 
                mnt->mounted_uid = current->uid;
        }
-       smb_setcodepage(&sb->u.smbfs_sb, &mnt->codepage);
-       if (!sb->u.smbfs_sb.convert)
-               PARANOIA("convert funcptr was NULL!\n");
+       smb_setcodepage(server, &mnt->codepage);
 
        /*
         * Display the enabled options
@@ -463,7 +462,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        /*
         * Keep the super block locked while we get the root inode.
         */
-       smb_init_root_dirent(&(sb->u.smbfs_sb), &root);
+       smb_init_root_dirent(server, &root);
        root_inode = smb_iget(sb, &root);
        if (!root_inode)
                goto out_no_root;
@@ -478,13 +477,13 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
 out_no_root:
        iput(root_inode);
 out_bad_option:
-       smb_kfree(sb->u.smbfs_sb.mnt);
+       smb_kfree(server->mnt);
 out_no_mount:
-       smb_kfree(sb->u.smbfs_sb.temp_buf);
+       smb_kfree(server->temp_buf);
 out_no_temp:
-       smb_vfree(sb->u.smbfs_sb.packet);
+       smb_vfree(server->packet);
 out_no_mem:
-       if (!sb->u.smbfs_sb.mnt)
+       if (!server->mnt)
                printk(KERN_ERR "smb_read_super: allocation failure\n");
        goto out_fail;
 out_wrong_data:
@@ -499,11 +498,11 @@ out_fail:
 static int
 smb_statfs(struct super_block *sb, struct statfs *buf)
 {
-       smb_proc_dskattr(sb, buf);
+       int result = smb_proc_dskattr(sb, buf);
 
        buf->f_type = SMB_SUPER_MAGIC;
        buf->f_namelen = SMB_MAXPATHLEN;
-       return 0;
+       return result;
 }
 
 int
@@ -532,8 +531,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
        if ((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~mask))
                goto out;
 
-       if ((attr->ia_valid & ATTR_SIZE) != 0)
-       {
+       if ((attr->ia_valid & ATTR_SIZE) != 0) {
                VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
                        DENTRY_PATH(dentry),
                        (long) inode->i_size, (long) attr->ia_size);
@@ -558,20 +556,17 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
        smb_get_inode_attr(inode, &fattr);
 
        changed = 0;
-       if ((attr->ia_valid & ATTR_MTIME) != 0)
-       {
+       if ((attr->ia_valid & ATTR_MTIME) != 0) {
                fattr.f_mtime = attr->ia_mtime;
                changed = 1;
        }
-       if ((attr->ia_valid & ATTR_ATIME) != 0)
-       {
+       if ((attr->ia_valid & ATTR_ATIME) != 0) {
                fattr.f_atime = attr->ia_atime;
                /* Earlier protocols don't have an access time */
                if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
                        changed = 1;
        }
-       if (changed)
-       {
+       if (changed) {
                error = smb_proc_settime(dentry, &fattr);
                if (error)
                        goto out;
@@ -582,27 +577,22 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
         * Check for mode changes ... we're extremely limited in
         * what can be set for SMB servers: just the read-only bit.
         */
-       if ((attr->ia_valid & ATTR_MODE) != 0)
-       {
+       if ((attr->ia_valid & ATTR_MODE) != 0) {
                VERBOSE("%s/%s mode change, old=%x, new=%x\n",
                        DENTRY_PATH(dentry), fattr.f_mode, attr->ia_mode);
                changed = 0;
-               if (attr->ia_mode & S_IWUSR)
-               {
-                       if (fattr.attr & aRONLY)
-                       {
+               if (attr->ia_mode & S_IWUSR) {
+                       if (fattr.attr & aRONLY) {
                                fattr.attr &= ~aRONLY;
                                changed = 1;
                        }
                } else {
-                       if (!(fattr.attr & aRONLY))
-                       {
+                       if (!(fattr.attr & aRONLY)) {
                                fattr.attr |= aRONLY;
                                changed = 1;
                        }
                }
-               if (changed)
-               {
+               if (changed) {
                        error = smb_proc_setattr(dentry, &fattr);
                        if (error)
                                goto out;
index 285c25b039aa2a231cb4603bbbf35a771c84c8d6..afc45b4f7fd9eb449329afe36889900b92c5ec88 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <asm/uaccess.h>
 
+#include "proto.h"
+
 int
 smb_ioctl(struct inode *inode, struct file *filp,
          unsigned int cmd, unsigned long arg)
@@ -37,9 +39,11 @@ smb_ioctl(struct inode *inode, struct file *filp,
                break;
 
        case SMB_IOC_NEWCONN:
-               /* require an argument == smb_conn_opt, else it is EINVAL */
-               if (!arg)
+               /* arg is smb_conn_opt, or NULL if no connection was made */
+               if (!arg) {
+                       result = smb_wakeup(server);
                        break;
+               }
 
                result = -EFAULT;
                if (!copy_from_user(&opt, (void *)arg, sizeof(opt)))
index c075b7aa497321ec0601cea53dddb30586d46774..27ec4c40a70b59b89b4c04a998f44f9f388c0645 100644 (file)
 #include <linux/smb_mount.h>
 
 #include <asm/string.h>
+#include <asm/div64.h>
 
 #include "smb_debug.h"
+#include "proto.h"
 
 
 /* Features. Undefine if they cause problems, this should perhaps be a
    config option. */
 #define SMBFS_POSIX_UNLINK 1
 
-/* Allow smb_retry to be interrupted. Not sure of the benefit ... */
-/* #define SMB_RETRY_INTR */
+/* Allow smb_retry to be interrupted. */
+#define SMB_RETRY_INTR
 
 #define SMB_VWV(packet)  ((packet) + SMB_HEADER_LEN)
 #define SMB_CMD(packet)  (*(packet+8))
@@ -43,6 +45,9 @@
 #define SMB_DIRINFO_SIZE 43
 #define SMB_STATUS_SIZE  21
 
+#define SMB_ST_BLKSIZE (PAGE_SIZE)
+#define SMB_ST_BLKSHIFT        (PAGE_SHIFT)
+
 static int
 smb_proc_setattr_ext(struct smb_sb_info *, struct inode *,
                     struct smb_fattr *);
@@ -137,8 +142,7 @@ out:
        return len;
 }
 
-static int setcodepage(struct smb_sb_info *server,
-                      struct nls_table **p, char *name)
+static int setcodepage(struct nls_table **p, char *name)
 {
        struct nls_table *nls;
 
@@ -160,16 +164,20 @@ static int setcodepage(struct smb_sb_info *server,
 /* Handles all changes to codepage settings. */
 int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp)
 {
-       int n;
+       int n = 0;
 
        smb_lock_server(server);
 
-       n = setcodepage(server, &server->local_nls, cp->local_name);
+       /* Don't load any nls_* at all, if no remote is requested */
+       if (!*cp->remote_name)
+               goto out;
+
+       n = setcodepage(&server->local_nls, cp->local_name);
        if (n != 0)
                goto out;
-       n = setcodepage(server, &server->remote_nls, cp->remote_name);
+       n = setcodepage(&server->remote_nls, cp->remote_name);
        if (n != 0)
-               setcodepage(server, &server->local_nls, NULL);
+               setcodepage(&server->local_nls, NULL);
 
 out:
        if (server->local_nls != NULL && server->remote_nls != NULL)
@@ -188,7 +196,7 @@ out:
 /*                                                                           */
 /*****************************************************************************/
 
-__u8 *
+static __u8 *
 smb_encode_smb_length(__u8 * p, __u32 len)
 {
        *p = 0;
@@ -308,7 +316,9 @@ date_dos2unix(struct smb_sb_info *server, __u16 date, __u16 time)
        int month, year;
        time_t secs;
 
-       month = ((date >> 5) & 15) - 1;
+       /* first subtract and mask after that... Otherwise, if
+          date == 0, bad things happen */
+       month = ((date >> 5) - 1) & 15;
        year = date >> 9;
        secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
            ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
@@ -327,6 +337,9 @@ date_unix2dos(struct smb_sb_info *server,
        int day, year, nl_day, month;
 
        unix_date = utc2local(server, unix_date);
+       if (unix_date < 315532800)
+               unix_date = 315532800;
+
        *time = (unix_date % 60) / 2 +
                (((unix_date / 60) % 60) << 5) +
                (((unix_date / 3600) % 24) << 11);
@@ -350,57 +363,20 @@ date_unix2dos(struct smb_sb_info *server,
 
 /* The following are taken from fs/ntfs/util.c */
 
+#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
+
 /*
  * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
  * into Unix UTC (based 1970-01-01, in seconds).
- *
- * This is very gross because
- * 1: We must do 64-bit division on a 32-bit machine
- * 2: We can't use libgcc for long long operations in the kernel
- * 3: Floating point math in the kernel would corrupt user data
  */
 static time_t
-smb_ntutc2unixutc(struct smb_sb_info *server, u64 ntutc)
+smb_ntutc2unixutc(u64 ntutc)
 {
-       const unsigned int D = 10000000;
-       unsigned int H = (unsigned int)(ntutc >> 32);
-       unsigned int L = (unsigned int)ntutc;
-       unsigned int numerator2;
-       unsigned int lowseconds;
-       unsigned int result;
-
-       /*
-        * It is best to subtract 0x019db1ded53e8000 first.
-        * Then the 1601-based date becomes a 1970-based date.
-        */
-       if (L < (unsigned)0xd53e8000) H--;
-       L -= (unsigned)0xd53e8000;
-       H -= (unsigned)0x019db1de;
-
-       /*
-        * Now divide 64-bit numbers on a 32-bit machine :-)
-        * With the subtraction already done, the result fits in 32 bits.
-        * The numerator fits in 56 bits and the denominator fits
-        * in 24 bits, so we can shift by 8 bits to make this work.
-        */
-
-       numerator2  = (H<<8) | (L>>24);
-       result      = (numerator2 / D);   /* shifted 24 right!! */
-       lowseconds  = result << 24;
-
-       numerator2  = ((numerator2-result*D)<<8) | ((L>>16)&0xff);
-       result      = (numerator2 / D);   /* shifted 16 right!! */
-       lowseconds |= result << 16;
-
-       numerator2  = ((numerator2-result*D)<<8) | ((L>>8)&0xff);
-       result      = (numerator2 / D);   /* shifted 8 right!! */
-       lowseconds |= result << 8;
-
-       numerator2  = ((numerator2-result*D)<<8) | (L&0xff);
-       result      = (numerator2 / D);   /* not shifted */
-       lowseconds |= result;
-
-       return lowseconds;
+       /* FIXME: what about the timezone difference? */
+       /* Subtract the NTFS time offset, then convert to 1s intervals. */
+       u64 t = ntutc - NTFS_TIME_OFFSET;
+       do_div(t, 10000000);
+       return (time_t)t;
 }
 
 #if 0
@@ -409,7 +385,7 @@ static u64
 smb_unixutc2ntutc(struct smb_sb_info *server, time_t t)
 {
        /* Note: timezone conversion is probably wrong. */
-       return ((utc2local(server, t) + (u64)(369*365+89)*24*3600) * 10000000);
+       return ((u64)utc2local(server, t)) * 10000000 + NTFS_TIME_OFFSET;
 }
 #endif
 
@@ -519,6 +495,9 @@ smb_get_wsize(struct smb_sb_info *server)
        return size;
 }
 
+/*
+ * Convert SMB error codes to -E... errno values.
+ */
 int
 smb_errno(struct smb_sb_info *server)
 {
@@ -529,110 +508,115 @@ smb_errno(struct smb_sb_info *server)
        VERBOSE("errcls %d  code %d  from command 0x%x\n",
                errcls, error, SMB_CMD(server->packet));
 
-       if (errcls == ERRDOS)
-               switch (error)
-               {
+       if (errcls == ERRDOS) {
+               switch (error) {
                case ERRbadfunc:
-                       return EINVAL;
+                       return -EINVAL;
                case ERRbadfile:
                case ERRbadpath:
-                       return ENOENT;
+                       return -ENOENT;
                case ERRnofids:
-                       return EMFILE;
+                       return -EMFILE;
                case ERRnoaccess:
-                       return EACCES;
+                       return -EACCES;
                case ERRbadfid:
-                       return EBADF;
+                       return -EBADF;
                case ERRbadmcb:
-                       return EREMOTEIO;
+                       return -EREMOTEIO;
                case ERRnomem:
-                       return ENOMEM;
+                       return -ENOMEM;
                case ERRbadmem:
-                       return EFAULT;
+                       return -EFAULT;
                case ERRbadenv:
                case ERRbadformat:
-                       return EREMOTEIO;
+                       return -EREMOTEIO;
                case ERRbadaccess:
-                       return EACCES;
+                       return -EACCES;
                case ERRbaddata:
-                       return E2BIG;
+                       return -E2BIG;
                case ERRbaddrive:
-                       return ENXIO;
+                       return -ENXIO;
                case ERRremcd:
-                       return EREMOTEIO;
+                       return -EREMOTEIO;
                case ERRdiffdevice:
-                       return EXDEV;
-               case ERRnofiles:        /* Why is this mapped to 0?? */
-                       return 0;
+                       return -EXDEV;
+               case ERRnofiles:
+                       return -ENOENT;
                case ERRbadshare:
-                       return ETXTBSY;
+                       return -ETXTBSY;
                case ERRlock:
-                       return EDEADLK;
+                       return -EDEADLK;
                case ERRfilexists:
-                       return EEXIST;
-               case 87:                /* should this map to 0?? */
-                       return 0;       /* Unknown error!! */
-               case 123:               /* Invalid name?? e.g. .tmp* */
-                       return ENOENT;
-               case 145:               /* Win NT 4.0: non-empty directory? */
-                       return ENOTEMPTY;
-                       /* This next error seems to occur on an mv when
-                        * the destination exists */
-               case 183:
-                       return EEXIST;
+                       return -EEXIST;
+               case ERRinvalidparam:
+                       return -EINVAL;
+               case ERRdiskfull:
+                       return -ENOSPC;
+               case ERRinvalidname:
+                       return -ENOENT;
+               case ERRdirnotempty:
+                       return -ENOTEMPTY;
+               case ERRnotlocked:
+                       return -ENOLCK;
+               case ERRexists:
+                       return -EEXIST;
                default:
                        class = "ERRDOS";
                        goto err_unknown;
-       } else if (errcls == ERRSRV)
-               switch (error)
-               {
+               }
+       } else if (errcls == ERRSRV) {
+               switch (error) {
                /* N.B. This is wrong ... EIO ? */
                case ERRerror:
-                       return ENFILE;
+                       return -ENFILE;
                case ERRbadpw:
-                       return EINVAL;
+                       return -EINVAL;
                case ERRbadtype:
-                       return EIO;
+                       return -EIO;
                case ERRaccess:
-                       return EACCES;
+                       return -EACCES;
                /*
                 * This is a fatal error, as it means the "tree ID"
                 * for this connection is no longer valid. We map
                 * to a special error code and get a new connection.
                 */
                case ERRinvnid:
-                       return EBADSLT;
+                       return -EBADSLT;
                default:
                        class = "ERRSRV";
                        goto err_unknown;
-       } else if (errcls == ERRHRD)
-               switch (error)
-               {
+               }
+       } else if (errcls == ERRHRD) {
+               switch (error) {
                case ERRnowrite:
-                       return EROFS;
+                       return -EROFS;
                case ERRbadunit:
-                       return ENODEV;
+                       return -ENODEV;
                case ERRnotready:
-                       return EUCLEAN;
+                       return -EUCLEAN;
                case ERRbadcmd:
                case ERRdata:
-                       return EIO;
+                       return -EIO;
                case ERRbadreq:
-                       return ERANGE;
+                       return -ERANGE;
                case ERRbadshare:
-                       return ETXTBSY;
+                       return -ETXTBSY;
                case ERRlock:
-                       return EDEADLK;
+                       return -EDEADLK;
                default:
                        class = "ERRHRD";
                        goto err_unknown;
-       } else if (errcls == ERRCMD)
+               }
+       } else if (errcls == ERRCMD) {
                class = "ERRCMD";
+       } else if (errcls == SUCCESS) {
+               return 0;       /* This is the only valid 0 return */
+       }
 
 err_unknown:
        printk(KERN_ERR "smb_errno: class %s, code %d from command 0x%x\n",
               class, error, SMB_CMD(server->packet));
-       return EIO;
+       return -EIO;
 }
 
 /*
@@ -749,12 +733,10 @@ smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc)
        }
 
        /*
-        * Check for server errors.  The current smb_errno() routine
-        * is squashing some error codes, but I don't think this is
-        * correct: after a server error the packet won't be valid.
+        * Check for server errors.
         */
        if (s->rcls != 0) {
-               result = -smb_errno(s);
+               result = smb_errno(s);
                if (!result)
                        printk(KERN_DEBUG "smb_request_ok: rcls=%d, err=%d mapped to 0\n",
                                s->rcls, s->err);
@@ -850,17 +832,23 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
 
 out:
        smb_unlock_server(server);
+       smb_wakeup(server);
+       return error;
 
+out_putf:
+       fput(filp);
+       goto out;
+}
+
+int
+smb_wakeup(struct smb_sb_info *server)
+{
 #ifdef SMB_RETRY_INTR
        wake_up_interruptible(&server->wait);
 #else
        wake_up(&server->wait);
 #endif
-       return error;
-
-out_putf:
-       fput(filp);
-       goto out;
+       return 0;
 }
 
 /* smb_setup_header: We completely set up the packet. You only have to
@@ -1490,7 +1478,7 @@ smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
        fattr->f_nlink = 1;
        fattr->f_uid = server->mnt->uid;
        fattr->f_gid = server->mnt->gid;
-       fattr->f_blksize = 512;
+       fattr->f_blksize = SMB_ST_BLKSIZE;
 }
 
 static void
@@ -1500,18 +1488,16 @@ smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
        if (fattr->attr & aDIR)
        {
                fattr->f_mode = server->mnt->dir_mode;
-               fattr->f_size = 512;
+               fattr->f_size = SMB_ST_BLKSIZE;
        }
        /* Check the read-only flag */
        if (fattr->attr & aRONLY)
                fattr->f_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
 
+       /* How many 512 byte blocks do we need for this file? */
        fattr->f_blocks = 0;
-       if ((fattr->f_blksize != 0) && (fattr->f_size != 0))
-       {
-               fattr->f_blocks =
-                   (fattr->f_size - 1) / fattr->f_blksize + 1;
-       }
+       if (fattr->f_size != 0)
+               fattr->f_blocks = 1 + ((fattr->f_size-1) >> 9);
        return;
 }
 
@@ -1770,9 +1756,9 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p, int level,
                if (len && qname->name[len-1] == '\0')
                        len--;
 
-               fattr->f_ctime = smb_ntutc2unixutc(server, LVAL(p, 8));
-               fattr->f_atime = smb_ntutc2unixutc(server, LVAL(p, 16));
-               fattr->f_mtime = smb_ntutc2unixutc(server, LVAL(p, 24));
+               fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 8));
+               fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 16));
+               fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 24));
                /* change time (32) */
                fattr->f_size = DVAL(p, 40);
                /* alloc size (48) */
@@ -1940,7 +1926,7 @@ smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
                 }
 
                if (server->rcls != 0) {
-                       result = -smb_errno(server);
+                       result = smb_errno(server);
                        PARANOIA("name=%s, result=%d, rcls=%d, err=%d\n",
                                 mask, result, server->rcls, server->err);
                        break;
@@ -2104,7 +2090,7 @@ retry:
        }
        if (server->rcls != 0)
        { 
-               result = -smb_errno(server);
+               result = smb_errno(server);
 #ifdef SMBFS_PARANOIA
                if (result != -ENOENT)
                        PARANOIA("error for %s, rcls=%d, err=%d\n",
@@ -2227,7 +2213,7 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
        {
                VERBOSE("for %s: result=%d, rcls=%d, err=%d\n",
                        &param[6], result, server->rcls, server->err);
-               result = -smb_errno(server);
+               result = smb_errno(server);
                goto out;
        }
        result = -ENOENT;
@@ -2490,7 +2476,7 @@ smb_proc_setattr_trans2(struct smb_sb_info *server,
        }
        result = 0;
        if (server->rcls != 0)
-               result = -smb_errno(server);
+               result = smb_errno(server);
 
 out:
        return result;
@@ -2559,6 +2545,7 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
        struct smb_sb_info *server = &(sb->u.smbfs_sb);
        int result;
        char *p;
+       long unit;
 
        smb_lock_server(server);
 
@@ -2571,23 +2558,13 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
                goto out;
        }
        p = SMB_VWV(server->packet);
-       attr->f_blocks = WVAL(p, 0);
-       attr->f_bsize  = WVAL(p, 2) * WVAL(p, 4);
-       attr->f_bavail = attr->f_bfree = WVAL(p, 6);
+       unit = (WVAL(p, 2) * WVAL(p, 4)) >> SMB_ST_BLKSHIFT;
+       attr->f_blocks = WVAL(p, 0) * unit;
+       attr->f_bsize  = SMB_ST_BLKSIZE;
+       attr->f_bavail = attr->f_bfree = WVAL(p, 6) * unit;
        result = 0;
 
 out:
        smb_unlock_server(server);
        return result;
 }
-
-int
-smb_proc_disconnect(struct smb_sb_info *server)
-{
-       int result;
-       smb_lock_server(server);
-       smb_setup_header(server, SMBtdis, 0, 0);
-       result = smb_request_ok(server, SMBtdis, 0, 0);
-       smb_unlock_server(server);
-       return result;
-}
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
new file mode 100644 (file)
index 0000000..65b1871
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Autogenerated with cproto on:  Tue Oct 2 20:40:54 CEST 2001
+ */
+
+/* proc.c */
+extern int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
+extern __u32 smb_len(__u8 *p);
+extern int smb_get_rsize(struct smb_sb_info *server);
+extern int smb_get_wsize(struct smb_sb_info *server);
+extern int smb_errno(struct smb_sb_info *server);
+extern int smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt);
+extern int smb_wakeup(struct smb_sb_info *server);
+extern __u8 *smb_setup_header(struct smb_sb_info *server, __u8 command, __u16 wct, __u16 bcc);
+extern int smb_open(struct dentry *dentry, int wish);
+extern int smb_close(struct inode *ino);
+extern int smb_close_fileid(struct dentry *dentry, __u16 fileid);
+extern int smb_proc_read(struct inode *inode, off_t offset, int count, char *data);
+extern int smb_proc_write(struct inode *inode, off_t offset, int count, const char *data);
+extern int smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid);
+extern int smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry);
+extern int smb_proc_mkdir(struct dentry *dentry);
+extern int smb_proc_rmdir(struct dentry *dentry);
+extern int smb_proc_unlink(struct dentry *dentry);
+extern int smb_proc_flush(struct smb_sb_info *server, __u16 fileid);
+extern int smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length);
+extern void smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
+extern int smb_proc_readdir(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctl);
+extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr);
+extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
+extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr);
+extern int smb_proc_dskattr(struct super_block *sb, struct statfs *attr);
+/* dir.c */
+extern struct file_operations smb_dir_operations;
+extern struct inode_operations smb_dir_inode_operations;
+extern void smb_new_dentry(struct dentry *dentry);
+extern void smb_renew_times(struct dentry *dentry);
+/* cache.c */
+extern void smb_invalid_dir_cache(struct inode *dir);
+extern void smb_invalidate_dircache_entries(struct dentry *parent);
+extern struct dentry *smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos);
+extern int smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctrl, struct qstr *qname, struct smb_fattr *entry);
+/* sock.c */
+extern int smb_valid_socket(struct inode *inode);
+extern int smb_catch_keepalive(struct smb_sb_info *server);
+extern int smb_dont_catch_keepalive(struct smb_sb_info *server);
+extern void smb_close_socket(struct smb_sb_info *server);
+extern int smb_round_length(int len);
+extern int smb_request(struct smb_sb_info *server);
+extern int smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command, int ldata, unsigned char *data, int lparam, unsigned char *param, int *lrdata, unsigned char **rdata, int *lrparam, unsigned char **rparam);
+/* inode.c */
+extern struct inode *smb_iget(struct super_block *sb, struct smb_fattr *fattr);
+extern void smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr);
+extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
+extern void smb_invalidate_inodes(struct smb_sb_info *server);
+extern int smb_revalidate_inode(struct dentry *dentry);
+extern struct super_block *smb_read_super(struct super_block *sb, void *raw_data, int silent);
+extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
+/* file.c */
+extern struct address_space_operations smb_file_aops;
+extern struct file_operations smb_file_operations;
+extern struct inode_operations smb_file_inode_operations;
+/* ioctl.c */
+extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
index 47aad9dc1cb150b2640088b2bd94f426d940c84e..46313b623c7b70a92e8575c87206ec2d0360d58e 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/uaccess.h>
 
 #include "smb_debug.h"
+#include "proto.h"
 
 
 static int
@@ -674,7 +675,7 @@ smb_request(struct smb_sb_info *server)
         */
        if (server->rcls) {
                int error = smb_errno(server);
-               if (error == EBADSLT) {
+               if (error == -EBADSLT) {
                        printk(KERN_ERR "smb_request: tree ID invalid\n");
                        result = error;
                        goto bad_conn;
@@ -866,7 +867,7 @@ smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
         */
        if (server->rcls) {
                int error = smb_errno(server);
-               if (error == EBADSLT) {
+               if (error == -EBADSLT) {
                        printk(KERN_ERR "smb_request: tree ID invalid\n");
                        result = error;
                        goto bad_conn;
index 4736ded323c647c0226be5136bb35afcb8fddb66..c4ad15b24195b4f36469d5efff870d16f1fb9989 100644 (file)
@@ -280,6 +280,7 @@ struct file_system_type *get_fs_type(const char *name)
 }
 
 static LIST_HEAD(vfsmntlist);
+static struct vfsmount *root_vfsmnt;
 
 static struct list_head *mount_hashtable;
 static int hash_mask, hash_bits;
@@ -326,6 +327,15 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
        return p;
 }
 
+static int check_mnt(struct vfsmount *mnt)
+{
+       spin_lock(&dcache_lock);
+       while (mnt->mnt_parent != mnt)
+               mnt = mnt->mnt_parent;
+       spin_unlock(&dcache_lock);
+       return mnt == root_vfsmnt;
+}
+
 static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
 {
        old_nd->dentry = mnt->mnt_mountpoint;
@@ -346,50 +356,20 @@ static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd)
        nd->dentry->d_mounted++;
 }
 
-/**
- *     add_vfsmnt - add a new mount node
- *     @nd: location of mountpoint or %NULL if we want a root node
- *     @root: root of (sub)tree to be mounted
- *     @dev_name: device name to show in /proc/mounts or %NULL (for "none").
- *
- *     This is VFS idea of mount. New node is allocated, bound to a tree
- *     we are mounting and optionally (OK, usually) registered as mounted
- *     on a given mountpoint. Returns a pointer to new node or %NULL in
- *     case of failure.
- *
- *     Potential reason for failure (aside of trivial lack of memory) is a
- *     deleted mountpoint. Caller must hold ->i_zombie on mountpoint
- *     dentry (if any).
- */
-
-static struct vfsmount *add_vfsmnt(struct dentry *root, const char *dev_name)
+static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root)
 {
-       struct vfsmount *mnt;
-       struct super_block *sb = root->d_inode->i_sb;
-       char *name;
-
-       mnt = alloc_vfsmnt();
-       if (!mnt)
-               goto out;
-
-       /* It may be NULL, but who cares? */
-       if (dev_name) {
-               name = kmalloc(strlen(dev_name)+1, GFP_KERNEL);
-               if (name) {
-                       strcpy(name, dev_name);
-                       mnt->mnt_devname = name;
+       struct list_head *next = p->mnt_mounts.next;
+       if (next == &p->mnt_mounts) {
+               while (1) {
+                       if (p == root)
+                               return NULL;
+                       next = p->mnt_child.next;
+                       if (next != &p->mnt_parent->mnt_mounts)
+                               break;
+                       p = p->mnt_parent;
                }
        }
-       mnt->mnt_sb = sb;
-       mnt->mnt_root = dget(root);
-       mnt->mnt_mountpoint = mnt->mnt_root;
-       mnt->mnt_parent = mnt;
-
-       spin_lock(&dcache_lock);
-       list_add(&mnt->mnt_list, vfsmntlist.prev);
-       spin_unlock(&dcache_lock);
-out:
-       return mnt;
+       return list_entry(next, struct vfsmount, mnt_child);
 }
 
 static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root)
@@ -447,37 +427,6 @@ fail1:
        return -ENOENT;
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-static void move_vfsmnt(struct vfsmount *mnt,
-                       struct nameidata *nd, 
-                       const char *dev_name)
-{
-       struct nameidata parent_nd;
-       char *new_devname = NULL;
-
-       if (dev_name) {
-               new_devname = kmalloc(strlen(dev_name)+1, GFP_KERNEL);
-               if (new_devname)
-                       strcpy(new_devname, dev_name);
-       }
-
-       spin_lock(&dcache_lock);
-       detach_mnt(mnt, &parent_nd);
-       attach_mnt(mnt, nd);
-
-       if (new_devname) {
-               if (mnt->mnt_devname)
-                       kfree(mnt->mnt_devname);
-               mnt->mnt_devname = new_devname;
-       }
-       spin_unlock(&dcache_lock);
-
-       /* put the old stuff */
-       if (parent_nd.mnt != mnt)
-               path_release(&parent_nd);
-}
-#endif
-
 static void kill_super(struct super_block *);
 
 void __mntput(struct vfsmount *mnt)
@@ -1189,10 +1138,52 @@ int may_umount(struct vfsmount *mnt)
        return 0;
 }
 
+void umount_tree(struct vfsmount *mnt)
+{
+       struct vfsmount *p;
+       LIST_HEAD(kill);
+
+       if (list_empty(&mnt->mnt_list))
+               return;
+
+       for (p = mnt; p; p = next_mnt(p, mnt)) {
+               list_del(&p->mnt_list);
+               list_add(&p->mnt_list, &kill);
+       }
+
+       while (!list_empty(&kill)) {
+               mnt = list_entry(kill.next, struct vfsmount, mnt_list);
+               list_del_init(&mnt->mnt_list);
+               if (mnt->mnt_parent == mnt) {
+                       spin_unlock(&dcache_lock);
+               } else {
+                       struct nameidata old_nd;
+                       detach_mnt(mnt, &old_nd);
+                       spin_unlock(&dcache_lock);
+                       path_release(&old_nd);
+               }
+               mntput(mnt);
+               spin_lock(&dcache_lock);
+       }
+}
+
 static int do_umount(struct vfsmount *mnt, int flags)
 {
        struct super_block * sb = mnt->mnt_sb;
-       struct nameidata parent_nd;
+       int retval = 0;
+
+       /*
+        * If we may have to abort operations to get out of this
+        * mount, and they will themselves hold resources we must
+        * allow the fs to do things. In the Unix tradition of
+        * 'Gee thats tricky lets do it in userspace' the umount_begin
+        * might fail to complete on the first run through as other tasks
+        * must return, and the like. Thats for the mount program to worry
+        * about for the moment.
+        */
+
+       if( (flags&MNT_FORCE) && sb->s_op->umount_begin)
+               sb->s_op->umount_begin(sb);
 
        /*
         * No sense to grab the lock for this test, but test itself looks
@@ -1204,7 +1195,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
         * /reboot - static binary that would close all descriptors and
         * call reboot(9). Then init(8) could umount root and exec /reboot.
         */
-       if (mnt == current->fs->rootmnt) {
+       if (mnt == current->fs->rootmnt && !(flags & MNT_DETACH)) {
                int retval = 0;
                /*
                 * Special case for "unmounting" root ...
@@ -1220,59 +1211,20 @@ static int do_umount(struct vfsmount *mnt, int flags)
 
        spin_lock(&dcache_lock);
 
-       if (atomic_read(&sb->s_active) > 1) {
-               if (atomic_read(&mnt->mnt_count) > 2) {
-                       spin_unlock(&dcache_lock);
-                       return -EBUSY;
-               }
-               detach_mnt(mnt, &parent_nd);
-               list_del(&mnt->mnt_list);
+       if (atomic_read(&sb->s_active) == 1) {
+               /* last instance - try to be smart */
                spin_unlock(&dcache_lock);
-               mntput(mnt);
-               if (parent_nd.mnt != mnt)
-                       path_release(&parent_nd);
-               return 0;
+               DQUOT_OFF(sb);
+               acct_auto_close(sb->s_dev);
+               spin_lock(&dcache_lock);
        }
-       spin_unlock(&dcache_lock);
-
-       /*
-        * Before checking whether the filesystem is still busy,
-        * make sure the kernel doesn't hold any quota files open
-        * on the device. If the umount fails, too bad -- there
-        * are no quotas running any more. Just turn them on again.
-        */
-       DQUOT_OFF(sb);
-       acct_auto_close(sb->s_dev);
-
-       /*
-        * If we may have to abort operations to get out of this
-        * mount, and they will themselves hold resources we must
-        * allow the fs to do things. In the Unix tradition of
-        * 'Gee thats tricky lets do it in userspace' the umount_begin
-        * might fail to complete on the first run through as other tasks
-        * must return, and the like. Thats for the mount program to worry
-        * about for the moment.
-        */
-
-       if( (flags&MNT_FORCE) && sb->s_op->umount_begin)
-               sb->s_op->umount_begin(sb);
-
-       /* Something might grab it again - redo checks */
-
-       spin_lock(&dcache_lock);
-       if (atomic_read(&mnt->mnt_count) > 2) {
-               spin_unlock(&dcache_lock);
-               return -EBUSY;
+       retval = -EBUSY;
+       if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
+               umount_tree(mnt);
+               retval = 0;
        }
-
-       /* OK, that's the point of no return */
-       detach_mnt(mnt, &parent_nd);
-       list_del(&mnt->mnt_list);
        spin_unlock(&dcache_lock);
-       mntput(mnt);
-       if (parent_nd.mnt != mnt)
-               path_release(&parent_nd);
-       return 0;
+       return retval;
 }
 
 /*
@@ -1302,6 +1254,8 @@ asmlinkage long sys_umount(char * name, int flags)
        retval = -EINVAL;
        if (nd.dentry != nd.mnt->mnt_root)
                goto dput_and_out;
+       if (!check_mnt(nd.mnt))
+               goto dput_and_out;
 
        retval = -EPERM;
        if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
@@ -1353,7 +1307,7 @@ static int mount_is_safe(struct nameidata *nd)
 static int do_loopback(struct nameidata *nd, char *old_name)
 {
        struct nameidata old_nd;
-       struct vfsmount *mnt;
+       struct vfsmount *mnt = NULL;
        int err;
 
        err = mount_is_safe(nd);
@@ -1369,12 +1323,16 @@ static int do_loopback(struct nameidata *nd, char *old_name)
                return err;
 
        down(&mount_sem);
-       err = -ENOMEM;
-       mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+       err = -EINVAL;
+       if (check_mnt(nd->mnt)) {
+               err = -ENOMEM;
+               mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+       }
        if (mnt) {
                err = graft_tree(mnt, nd);
                mntput(mnt);
        }
+
        up(&mount_sem);
        path_release(&old_nd);
        return err;
@@ -1394,6 +1352,9 @@ static int do_remount(struct nameidata *nd,int flags,int mnt_flags,char *data)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (!check_mnt(nd->mnt))
+               return -EINVAL;
+
        if (nd->dentry != nd->mnt->mnt_root)
                return -EINVAL;
 
@@ -1472,27 +1433,31 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags,
                        int mnt_flags, char *name, void *data)
 {
        struct vfsmount *mnt = do_kern_mount(type, flags, name, data);
-       int retval = PTR_ERR(mnt);
+       int err = PTR_ERR(mnt);
 
        if (IS_ERR(mnt))
                goto out;
 
-       mnt->mnt_flags = mnt_flags;
-
        down(&mount_sem);
        /* Something was mounted here while we slept */
        while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
                ;
+       err = -EINVAL;
+       if (!check_mnt(nd->mnt))
+               goto unlock;
 
        /* Refuse the same filesystem on the same mount point */
+       err = -EBUSY;
        if (nd->mnt->mnt_sb == mnt->mnt_sb && nd->mnt->mnt_root == nd->dentry)
-               retval = -EBUSY;
-       else
-               retval = graft_tree(mnt, nd);
+               goto unlock;
+
+       mnt->mnt_flags = mnt_flags;
+       err = graft_tree(mnt, nd);
+unlock:
        up(&mount_sem);
        mntput(mnt);
 out:
-       return retval;
+       return err;
 }
 
 static int copy_mount_options (const void *data, unsigned long *where)
@@ -1630,6 +1595,7 @@ out1:
 
 void __init mount_root(void)
 {
+       struct nameidata root_nd;
        struct file_system_type * fs_type;
        struct super_block * sb;
        struct vfsmount *vfsmnt;
@@ -1639,6 +1605,7 @@ void __init mount_root(void)
        void *handle;
        char path[64];
        int path_start = -1;
+       char *name = "/dev/root";
 
 #ifdef CONFIG_ROOT_NFS
        void *data;
@@ -1776,13 +1743,26 @@ mount_it:
                fs_type->name,
                (sb->s_flags & MS_RDONLY) ? " readonly" : "");
        if (path_start >= 0) {
+               name = path + path_start;
                devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
-                                 path + 5 + path_start, NULL, NULL);
-               memcpy (path + path_start, "/dev/", 5);
-               vfsmnt = add_vfsmnt(sb->s_root, path + path_start);
+                                 name + 5, NULL, NULL);
+               memcpy (name, "/dev/", 5);
        }
-       else
-               vfsmnt = add_vfsmnt(sb->s_root, "/dev/root");
+       vfsmnt = alloc_vfsmnt();
+       if (!vfsmnt)
+               panic("VFS: alloc_vfsmnt failed for root fs");
+
+       vfsmnt->mnt_devname = kmalloc(strlen(name)+1, GFP_KERNEL);
+       if (vfsmnt->mnt_devname)
+               strcpy(vfsmnt->mnt_devname, name);
+       vfsmnt->mnt_sb = sb;
+       vfsmnt->mnt_root = dget(sb->s_root);
+
+       root_nd.mnt = root_vfsmnt;
+       root_nd.dentry = root_vfsmnt->mnt_sb->s_root;
+       graft_tree(vfsmnt, &root_nd);
+       mntput(vfsmnt);
+
        /* FIXME: if something will try to umount us right now... */
        if (vfsmnt) {
                set_fs_root(current->fs, vfsmnt, sb->s_root);
@@ -1791,10 +1771,8 @@ mount_it:
                        bdput(bdev); /* sb holds a reference */
                return;
        }
-       panic("VFS: add_vfsmnt failed for root fs");
 }
 
-
 static void chroot_fs_refs(struct dentry *old_root,
                           struct vfsmount *old_rootmnt,
                           struct dentry *new_root,
@@ -1836,10 +1814,8 @@ static void chroot_fs_refs(struct dentry *old_root,
 
 asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
 {
-       struct dentry *root;
-       struct vfsmount *root_mnt;
        struct vfsmount *tmp;
-       struct nameidata new_nd, old_nd, parent_nd, root_parent;
+       struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
        char *name;
        int error;
 
@@ -1858,11 +1834,14 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
        putname(name);
        if (error)
                goto out0;
+       error = -EINVAL;
+       if (!check_mnt(new_nd.mnt))
+               goto out1;
 
        name = getname(put_old);
        error = PTR_ERR(name);
        if (IS_ERR(name))
-               goto out0;
+               goto out1;
        error = 0;
        if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd))
                error = path_walk(name, &old_nd);
@@ -1871,11 +1850,14 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
                goto out1;
 
        read_lock(&current->fs->lock);
-       root_mnt = mntget(current->fs->rootmnt);
-       root = dget(current->fs->root);
+       user_nd.mnt = mntget(current->fs->rootmnt);
+       user_nd.dentry = dget(current->fs->root);
        read_unlock(&current->fs->lock);
        down(&mount_sem);
        down(&old_nd.dentry->d_inode->i_zombie);
+       error = -EINVAL;
+       if (!check_mnt(user_nd.mnt))
+               goto out2;
        error = -ENOENT;
        if (IS_DEADDIR(new_nd.dentry->d_inode))
                goto out2;
@@ -1884,10 +1866,10 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
        if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
                goto out2;
        error = -EBUSY;
-       if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
+       if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt)
                goto out2; /* loop */
        error = -EINVAL;
-       if (root_mnt->mnt_root != root)
+       if (user_nd.mnt->mnt_root != user_nd.dentry)
                goto out2;
        if (new_nd.mnt->mnt_root != new_nd.dentry)
                goto out2; /* not a mountpoint */
@@ -1906,22 +1888,18 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
        } else if (!is_subdir(old_nd.dentry, new_nd.dentry))
                goto out3;
        detach_mnt(new_nd.mnt, &parent_nd);
-       detach_mnt(root_mnt, &root_parent);
-       attach_mnt(root_mnt, &old_nd);
-       if (root_parent.mnt != root_mnt)
-               attach_mnt(new_nd.mnt, &root_parent);
+       detach_mnt(user_nd.mnt, &root_parent);
+       attach_mnt(user_nd.mnt, &old_nd);
+       attach_mnt(new_nd.mnt, &root_parent);
        spin_unlock(&dcache_lock);
-       chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
+       chroot_fs_refs(user_nd.dentry,user_nd.mnt,new_nd.dentry,new_nd.mnt);
        error = 0;
-       if (root_parent.mnt != root_mnt)
-               path_release(&root_parent);
-       if (parent_nd.mnt != new_nd.mnt)
-               path_release(&parent_nd);
+       path_release(&root_parent);
+       path_release(&parent_nd);
 out2:
        up(&old_nd.dentry->d_inode->i_zombie);
        up(&mount_sem);
-       dput(root);
-       mntput(root_mnt);
+       path_release(&user_nd);
        path_release(&old_nd);
 out1:
        path_release(&new_nd);
@@ -1940,8 +1918,13 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
 {
        struct vfsmount *old_rootmnt;
        struct nameidata devfs_nd, nd;
+       struct nameidata parent_nd;
+       char *new_devname = kmalloc(strlen("/dev/root.old")+1, GFP_KERNEL);
        int error = 0;
 
+       if (new_devname)
+               strcpy(new_devname, "/dev/root.old");
+
        read_lock(&current->fs->lock);
        old_rootmnt = mntget(current->fs->rootmnt);
        read_unlock(&current->fs->lock);
@@ -1958,6 +1941,9 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
                } else 
                        path_release(&devfs_nd);
        }
+       spin_lock(&dcache_lock);
+       detach_mnt(old_rootmnt, &parent_nd);
+       spin_unlock(&dcache_lock);
        ROOT_DEV = new_root_dev;
        mount_root();
 #if 1
@@ -1980,25 +1966,36 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
                blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
                printk(KERN_NOTICE "Trying to unmount old root ... ");
                if (!blivet) {
-                       blivet = do_umount(old_rootmnt, 0);
+                       spin_lock(&dcache_lock);
+                       list_del(&old_rootmnt->mnt_list);
+                       spin_unlock(&dcache_lock);
+                       mntput(old_rootmnt);
                        mntput(old_rootmnt);
-                       if (!blivet) {
-                               int ioctl_err;
-
-                               ioctl_err = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
-                               if (ioctl_err)
-                                       printk("failed to release ramdisk %d...", ioctl_err);
-                               printk("okay\n");
-                               error = 0;
-                       }
+                       blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
+                       path_release(&parent_nd);
                        blkdev_put(ramdisk, BDEV_FS);
                }
-               if (blivet)
+               if (blivet) {
                        printk(KERN_ERR "error %d\n", blivet);
+               } else {
+                       printk("okay\n");
+                       error = 0;
+               }                       
+               kfree(new_devname);
                return error;
        }
-       /* FIXME: we should hold i_zombie on nd.dentry */
-       move_vfsmnt(old_rootmnt, &nd, "/dev/root.old");
+
+       spin_lock(&dcache_lock);
+       attach_mnt(old_rootmnt, &nd);
+       if (new_devname) {
+               if (old_rootmnt->mnt_devname)
+                       kfree(old_rootmnt->mnt_devname);
+               old_rootmnt->mnt_devname = new_devname;
+       }
+       spin_unlock(&dcache_lock);
+
+       /* put the old stuff */
+       path_release(&parent_nd);
        mntput(old_rootmnt);
        path_release(&nd);
        return 0;
@@ -2006,6 +2003,54 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
 
 #endif
 
+/*
+ * Absolutely minimal fake fs - only empty root directory and nothing else.
+ * In 2.5 we'll use ramfs or tmpfs, but for now it's all we need - just
+ * something to go with root vfsmount.
+ */
+static struct dentry *rootfs_lookup(struct inode *dir, struct dentry *dentry)
+{
+       d_add(dentry, NULL);
+       return NULL;
+}
+static struct file_operations rootfs_dir_operations = {
+       read:           generic_read_dir,
+       readdir:        dcache_readdir,
+};
+static struct inode_operations rootfs_dir_inode_operations = {
+       lookup:         rootfs_lookup,
+};
+static struct super_block *rootfs_read_super(struct super_block * sb, void * data, int silent)
+{
+       struct inode * inode;
+       struct dentry * root;
+       static struct super_operations s_ops = {};
+       sb->s_op = &s_ops;
+       inode = new_inode(sb);
+       if (!inode)
+               return NULL;
+       inode->i_mode = S_IFDIR|0555;
+       inode->i_uid = inode->i_gid = 0;
+       inode->i_op = &rootfs_dir_inode_operations;
+       inode->i_fop = &rootfs_dir_operations;
+       root = d_alloc_root(inode);
+       if (!root) {
+               iput(inode);
+               return NULL;
+       }
+       sb->s_root = root;
+       return sb;
+}
+static DECLARE_FSTYPE(root_fs_type, "rootfs", rootfs_read_super, FS_NOMOUNT);
+
+static void __init init_mount_tree(void)
+{
+       register_filesystem(&root_fs_type);
+       root_vfsmnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
+       if (IS_ERR(root_vfsmnt))
+               panic("can't allocate root vfsmount");
+}
+
 void __init mnt_init(unsigned long mempages)
 {
        struct list_head *d;
@@ -2061,4 +2106,5 @@ void __init mnt_init(unsigned long mempages)
                d++;
                i--;
        } while (i);
+       init_mount_tree();
 }
index 7624088c38d5ddd343bca3b79fffb2849561e5da..58b4d6179855a90e5473f0525fefebcd825a9657 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.mmu_context.h 1.15 08/16/01 23:00:17 paulus
+ * BK Id: SCCS/s.mmu_context.h 1.18 09/26/01 16:02:49 paulus
  */
 #ifdef __KERNEL__
 #ifndef __PPC_MMU_CONTEXT_H
@@ -29,7 +29,7 @@
  * of the 32-bit virtual address (the "effective segment ID") in order
  * to spread out the entries in the MMU hash table.  Note, if this
  * function is changed then arch/ppc/mm/hashtable.S will have to be
- * changed correspondly.
+ * changed to correspond.
  */
 #define CTX_TO_VSID(ctx, va)   (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
                                 & 0xffffff)
@@ -89,7 +89,7 @@ extern void set_context(mm_context_t context, pgd_t *pgd);
  * Bitmap of contexts in use.
  * The size of this bitmap is LAST_CONTEXT + 1 bits.
  */
-extern unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
+extern unsigned long context_map[];
 
 /*
  * This caches the next context number that we expect to be free.
index 9d04f9af4908f97640aa341851bfc33f2917dc6c..9d314051fb0b98276038faa514b99e26d82adecb 100644 (file)
@@ -650,6 +650,7 @@ struct quota_mount_options
  */
 
 #define MNT_FORCE      0x00000001      /* Attempt to forcibily umount */
+#define MNT_DETACH     0x00000002      /* Just detach from the tree */
 
 #include <linux/minix_fs_sb.h>
 #include <linux/ext2_fs_sb.h>
index 4e341f1fdbe9006c2fa14f6352b7252c2837dbdd..37b72807182b2baab3cf65f1686b3aaed8ab18b7 100644 (file)
@@ -74,8 +74,8 @@ void gameport_rescan(struct gameport *gameport);
 void gameport_register_port(struct gameport *gameport);
 void gameport_unregister_port(struct gameport *gameport);
 #else
-void __inline__ gameport_register_port(struct gameport *gameport) { return; }
-void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
+static void __inline__ gameport_register_port(struct gameport *gameport) { return; }
+static void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
 #endif
 
 void gameport_register_device(struct gameport_dev *dev);
index 7aea8bc88b32d15f339ddda055b5980c6c945f14..a356cb65a4acec7a10d0e01ffe03adaaee5b6759 100644 (file)
 #include <linux/types.h>
 #include <linux/major.h>
 
+enum {
 /* These three have identical behaviour; use the second one if DOS fdisk gets
    confused about extended/logical partitions starting past cylinder 1023. */
-#define DOS_EXTENDED_PARTITION 5
-#define LINUX_EXTENDED_PARTITION 0x85
-#define WIN98_EXTENDED_PARTITION 0x0f
+       DOS_EXTENDED_PARTITION = 5,
+       LINUX_EXTENDED_PARTITION = 0x85,
+       WIN98_EXTENDED_PARTITION = 0x0f,
 
-#define LINUX_SWAP_PARTITION   0x82
-#define LINUX_RAID_PARTITION   0xfd    /* autodetect RAID partition */
+       LINUX_SWAP_PARTITION = 0x82,
+       LINUX_RAID_PARTITION = 0xfd,    /* autodetect RAID partition */
 
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-#define SOLARIS_X86_PARTITION  LINUX_SWAP_PARTITION
-#endif
+       SOLARIS_X86_PARTITION = LINUX_SWAP_PARTITION,
 
-#define DM6_PARTITION          0x54    /* has DDO: use xlated geom & offset */
-#define EZD_PARTITION          0x55    /* EZ-DRIVE */
-#define DM6_AUX1PARTITION      0x51    /* no DDO:  use xlated geom */
-#define DM6_AUX3PARTITION      0x53    /* no DDO:  use xlated geom */
+       DM6_PARTITION = 0x54,   /* has DDO: use xlated geom & offset */
+       EZD_PARTITION = 0x55,   /* EZ-DRIVE */
+       DM6_AUX1PARTITION = 0x51,       /* no DDO:  use xlated geom */
+       DM6_AUX3PARTITION = 0x53,       /* no DDO:  use xlated geom */
+
+       FREEBSD_PARTITION = 0xa5,    /* FreeBSD Partition ID */
+       OPENBSD_PARTITION = 0xa6,    /* OpenBSD Partition ID */
+       NETBSD_PARTITION = 0xa9,   /* NetBSD Partition ID */
+       BSDI_PARTITION = 0xb7,    /* BSDI Partition ID */
+/* Ours is not to wonder why.. */
+       BSD_PARTITION = FREEBSD_PARTITION,
+       MINIX_PARTITION = 0x81,  /* Minix Partition ID */
+       UNIXWARE_PARTITION = 0x63,              /* Partition ID, same as */
+                                               /* GNU_HURD and SCO Unix */
+};
 
 struct partition {
        unsigned char boot_ind;         /* 0x80 - active */
@@ -117,13 +127,6 @@ struct solaris_x86_vtoc {
  * BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>
  * updated by Marc Espie <Marc.Espie@openbsd.org>
  */
-#define FREEBSD_PARTITION      0xa5    /* FreeBSD Partition ID */
-#define OPENBSD_PARTITION      0xa6    /* OpenBSD Partition ID */
-#define NETBSD_PARTITION       0xa9    /* NetBSD Partition ID */
-#define BSDI_PARTITION         0xb7    /* BSDI Partition ID */
-
-/* Ours is not to wonder why.. */
-#define BSD_PARTITION          FREEBSD_PARTITION
 
 /* check against BSD src/sys/sys/disklabel.h for consistency */
 
@@ -182,8 +185,6 @@ struct bsd_disklabel {
  * and Krzysztof G. Baranowski <kgb@knm.org.pl>
  */
 
-#define UNIXWARE_PARTITION     0x63            /* Partition ID, same as */
-                                               /* GNU_HURD and SCO Unix */
 #define UNIXWARE_DISKMAGIC     (0xCA5E600DUL)  /* The disk magic number */
 #define UNIXWARE_DISKMAGIC2    (0x600DDEEEUL)  /* The slice table magic nr */
 #define UNIXWARE_NUMSLICE      16
@@ -233,7 +234,6 @@ struct unixware_disklabel {
 #endif /* CONFIG_UNIXWARE_DISKLABEL */
 
 #ifdef CONFIG_MINIX_SUBPARTITION
-#   define MINIX_PARTITION         0x81  /* Minix Partition ID */
 #   define MINIX_NR_SUBPARTITIONS  4
 #endif /* CONFIG_MINIX_SUBPARTITION */
 
index d32bf62b8fb0c106b5340698a32e35aa25538aba..becc3a0e48c85f6eead41ab88287a87477d883b9 100644 (file)
@@ -366,10 +366,10 @@ __attribute__((section("__ksymtab"))) =                   \
 
 #define __EXPORT_SYMBOL_GPL(sym, str)                  \
 const char __kstrtab_##sym[]                           \
-__attribute__((section(".kstrtab"))) = str;            \
-const struct module_symbol __ksymtab_GPLONLY_##sym     \
+__attribute__((section(".kstrtab"))) = "GPLONLY_" str; \
+const struct module_symbol __ksymtab_##sym             \
 __attribute__((section("__ksymtab"))) =                        \
-{ (unsigned long)&sym, __kstrtab_GPLONLY_##sym }
+{ (unsigned long)&sym, __kstrtab_##sym }
 
 #if defined(MODVERSIONS) || !defined(CONFIG_MODVERSIONS)
 #define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
index 716e50ec65f90494bab1621fd15e0d99fb54ef87..2200209882ecff0b08bbaebb551fcf5c2fd4ce18 100644 (file)
@@ -161,84 +161,6 @@ smb_is_open(struct inode *i)
 }
 
 
-/* FIXME! the prototype list is probably not correct. Automate? */
-
-/* linux/fs/smbfs/file.c */
-extern struct inode_operations smb_file_inode_operations;
-extern struct file_operations smb_file_operations;
-extern struct address_space_operations smb_file_aops;
-
-/* linux/fs/smbfs/dir.c */
-extern struct inode_operations smb_dir_inode_operations;
-extern struct file_operations smb_dir_operations;
-void smb_new_dentry(struct dentry *dentry);
-void smb_renew_times(struct dentry *);
-
-/* linux/fs/smbfs/ioctl.c */
-int smb_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
-
-/* linux/fs/smbfs/inode.c */
-struct super_block *smb_read_super(struct super_block *, void *, int);
-void smb_get_inode_attr(struct inode *, struct smb_fattr *);
-void smb_set_inode_attr(struct inode *, struct smb_fattr *);
-void smb_invalidate_inodes(struct smb_sb_info *);
-int  smb_revalidate_inode(struct dentry *);
-int  smb_notify_change(struct dentry *, struct iattr *);
-struct inode *smb_iget(struct super_block *, struct smb_fattr *);
-
-/* linux/fs/smbfs/proc.c */
-int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
-__u32 smb_len(unsigned char *);
-__u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16);
-int smb_get_rsize(struct smb_sb_info *);
-int smb_get_wsize(struct smb_sb_info *);
-int smb_newconn(struct smb_sb_info *, struct smb_conn_opt *);
-int smb_errno(struct smb_sb_info *);
-int smb_close(struct inode *);
-int smb_close_fileid(struct dentry *, __u16);
-int smb_open(struct dentry *, int);
-int smb_proc_read(struct inode *, off_t, int, char *);
-int smb_proc_write(struct inode *, off_t, int, const char *);
-int smb_proc_create(struct dentry *, __u16, time_t, __u16 *);
-int smb_proc_mv(struct dentry *, struct dentry *);
-int smb_proc_mkdir(struct dentry *);
-int smb_proc_rmdir(struct dentry *);
-int smb_proc_unlink(struct dentry *);
-int smb_proc_readdir(struct file *filp, void *dirent, filldir_t filldir,
-                    struct smb_cache_control *ctl);
-int smb_proc_getattr(struct dentry *, struct smb_fattr *);
-int smb_proc_setattr(struct dentry *, struct smb_fattr *);
-int smb_proc_settime(struct dentry *, struct smb_fattr *);
-int smb_proc_dskattr(struct super_block *, struct statfs *);
-int smb_proc_disconnect(struct smb_sb_info *);
-int smb_proc_trunc(struct smb_sb_info *, __u16, __u32);
-int smb_proc_flush(struct smb_sb_info *, __u16);
-void smb_init_root_dirent(struct smb_sb_info *, struct smb_fattr *);
-
-/* linux/fs/smbfs/sock.c */
-int smb_round_length(int);
-int smb_valid_socket(struct inode *);
-void smb_close_socket(struct smb_sb_info *);
-int smb_request(struct smb_sb_info *server);
-int smb_catch_keepalive(struct smb_sb_info *server);
-int smb_dont_catch_keepalive(struct smb_sb_info *server);
-int smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
-                      int ldata, unsigned char *data,
-                      int lparam, unsigned char *param,
-                      int *lrdata, unsigned char **rdata,
-                      int *lrparam, unsigned char **rparam);
-
-/* fs/smbfs/cache.c */
-
-void smb_invalid_dir_cache(struct inode * dir);
-void smb_invalidate_dircache_entries(struct dentry *parent);
-struct dentry * smb_dget_fpos(struct dentry *dentry, struct dentry *parent, 
-                             unsigned long fpos);
-int smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-                  struct smb_cache_control *ctrl, struct qstr *qname,
-                  struct smb_fattr *entry);
-
-
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SMB_FS_H */
index 0f25e0265393d955ef4bf17e7e98bdad752df1cf..aa5ac336c8cf0859d23cdf604dffa6ba4c6e28e1 100644 (file)
 #define ERRbadshare 32          /* Share mode on file conflict with open mode */
 #define ERRlock 33              /* Lock request conflicts with existing lock */
 #define ERRfilexists 80         /* File in operation already exists */
-#define ERRundocumented1 123    /* Invalid name?? e.g. .tmp* */
+#define ERRinvalidparam 87      /* ERROR_INVALID_PARAMETER */
+#define ERRdiskfull 112         /* ERROR_DISK_FULL */
+#define ERRinvalidname 123      /* ERROR_INVALID_NAME */
+#define ERRdirnotempty 145      /* ERROR_DIR_NOT_EMPTY */
+#define ERRnotlocked 158        /* ERROR_NOT_LOCKED */
+#define ERRexists 183           /* ERROR_ALREADY_EXISTS, see also 80 */
 #define ERRbadpipe 230          /* Named pipe invalid */
 #define ERRpipebusy 231         /* All instances of pipe are busy */
 #define ERRpipeclosing 232      /* named pipe close in progress */
index 1d49bb8e265ac95e3093b39a560e4788b94f3039..059329c7759e33007b415cad102083ccddca2e95 100644 (file)
@@ -42,6 +42,7 @@
 #if (DEBUG_SPINLOCKS < 1)
 
 #define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
+#define ATOMIC_DEC_AND_LOCK
 
 /*
  * Your basic spinlocks, allowing only a single CPU anywhere
@@ -128,7 +129,7 @@ typedef struct {
 #endif /* !SMP */
 
 /* "lock on reference count zero" */
-#ifndef atomic_dec_and_lock
+#ifndef ATOMIC_DEC_AND_LOCK
 #include <asm/atomic.h>
 extern int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
 #endif
index d4c15678e4f8a458175da59da8bc8c99524bbdee..5ef5c9d5e13e9211f6d52df74bc1e96ee8fff71f 100644 (file)
@@ -94,7 +94,6 @@ extern void ppc_init(void);
 extern void sysctl_init(void);
 extern void signals_init(void);
 extern int init_pcmcia_ds(void);
-extern void net_notifier_init(void);
 
 extern void free_initmem(void);
 
index b9d574ce4eb4051c7703b54adac3fbf79d487e34..f84d1608bef55e48a0c102999d9b3f3f87fbe696 100644 (file)
@@ -26,7 +26,7 @@
  * store-conditional approach, for example.
  */
 
-#ifndef atomic_dec_and_lock
+#ifndef ATOMIC_DEC_AND_LOCK
 int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 {
        spin_lock(lock);