patch-2.4.22 linux-2.4.22/drivers/ieee1394/sbp2.c

Next file: linux-2.4.22/drivers/ieee1394/sbp2.h
Previous file: linux-2.4.22/drivers/ieee1394/raw1394.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/drivers/ieee1394/sbp2.c linux-2.4.22/drivers/ieee1394/sbp2.c
@@ -4,6 +4,8 @@
  * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com)
  * jamesg@filanet.com (JSG)
  *
+ * Copyright (C) 2003 Ben Collins <bcollins@debian.org>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -27,283 +29,17 @@
  * driver. It also registers as a SCSI lower-level driver in order to accept
  * SCSI commands for transport using SBP-2.
  *
- *
- * Driver Loading:
- *
- * Currently, the SBP-2 driver is supported only as a module. Because the 
- * Linux SCSI stack is not Plug-N-Play aware, module load order is 
- * important. Assuming the SCSI core drivers are either built into the 
- * kernel or already loaded as modules, you should load the IEEE-1394 modules 
- * in the following order:
- *
- * 	ieee1394 (e.g. insmod ieee1394)
- *	ohci1394 (e.g. insmod ohci1394)
- *	sbp2 (e.g. insmod sbp2)
- *
- * The SBP-2 driver will attempt to discover any attached SBP-2 devices when first
- * loaded, or after any IEEE-1394 bus reset (e.g. a hot-plug). It will then print 
- * out a debug message indicating if it was able to discover a SBP-2 device.
- *
- * Currently, the SBP-2 driver will catch any attached SBP-2 devices during the
- * initial scsi bus scan (when the driver is first loaded). To add or remove
- * SBP-2 devices "after" this initial scan (i.e. if you plug-in or un-plug a 
- * device after the SBP-2 driver is loaded), you must either use the scsi procfs
- * add-single-device, remove-single-device, or a shell script such as 
- * rescan-scsi-bus.sh.
- *
  * The easiest way to add/detect new SBP-2 devices is to run the shell script
- * rescan-scsi-bus.sh (or re-load the SBP-2 driver). This script may be 
- * found at:
+ * rescan-scsi-bus.sh. This script may be found at:
  * http://www.garloff.de/kurt/linux/rescan-scsi-bus.sh
  *
- * As an alternative, you may manually add/remove SBP-2 devices via the procfs with
- * add-single-device <h> <b> <t> <l> or remove-single-device <h> <b> <t> <l>, where:
- *	<h> = host (starting at zero for first SCSI adapter)
- *	<b> = bus (normally zero)
- *	<t> = target (starting at zero for first SBP-2 device)
- *	<l> = lun (normally zero)
- *
- * e.g. To manually add/detect a new SBP-2 device
- *	echo "scsi add-single-device 0 0 0 0" > /proc/scsi/scsi
- *
- * e.g. To manually remove a SBP-2 device after it's been unplugged
- *	echo "scsi remove-single-device 0 0 0 0" > /proc/scsi/scsi
- *
- * e.g. To check to see which SBP-2/SCSI devices are currently registered
- * 	cat /proc/scsi/scsi
- *
- * After scanning for new SCSI devices (above), you may access any attached 
- * SBP-2 storage devices as if they were SCSI devices (e.g. mount /dev/sda1, 
- * fdisk, mkfs, etc.).
- *
- *
- * Module Load Options:
- *
- * sbp2_max_speed 		- Force max speed allowed 
- *				  (2 = 400mb, 1 = 200mb, 0 = 100mb. default = 2)
- * sbp2_serialize_io		- Serialize all I/O coming down from the scsi drivers 
- *				  (0 = deserialized, 1 = serialized, default = 0)
- * sbp2_max_sectors, 		- Change max sectors per I/O supported (default = 255)
- * sbp2_exclusive_login		- Set to zero if you'd like to allow multiple hosts the ability
- *				  to log in at the same time. Sbp2 device must support this,
- *				  and you must know what you're doing (default = 1)
- *
- * (e.g. insmod sbp2 sbp2_serialize_io = 1)
- *
- *
- * Current Support:
- *
- * The SBP-2 driver is still in an early state, but supports a variety of devices.
- * I have read/written many gigabytes of data from/to SBP-2 drives, and have seen 
- * performance of more than 25 MBytes/s on individual drives (limit of the media 
- * transfer rate).
- *
- *
- * Following are a sampling of devices that have been tested successfully:
- *
- *	- Western Digital IEEE-1394 hard drives
- *	- Maxtor IEEE-1394 hard drives
- *	- VST (SmartDisk) IEEE-1394 hard drives and Zip drives (several flavors)
- *	- LaCie IEEE-1394 hard drives (several flavors)
- *	- QPS IEEE-1394 CD-RW/DVD drives and hard drives
- *	- BusLink IEEE-1394 hard drives
- *	- Iomega IEEE-1394 Zip/Jazz/Peerless drives
- *	- ClubMac IEEE-1394 hard drives
- *	- FirePower IEEE-1394 hard drives
- *	- EzQuest IEEE-1394 hard drives and CD-RW drives
- *	- Castlewood/ADS IEEE-1394 ORB drives
- *	- Evergreen IEEE-1394 hard drives and CD-RW drives
- *	- Addonics IEEE-1394 CD-RW drives
- *	- Bellstor IEEE-1394 hard drives and CD-RW drives
- *	- APDrives IEEE-1394 hard drives
- *	- Fujitsu IEEE-1394 MO drives
- *	- Sony IEEE-1394 CD-RW drives
- *	- Epson IEEE-1394 scanners
- *	- ADS IEEE-1394 memory stick and compact flash readers 
- *	- SBP-2 bridge-based devices (LSI, Oxford Semiconductor, Indigita bridges)
- *	- Various other standard IEEE-1394 hard drives and enclosures
- *
- *
- * Performance Issues:
- *
- *	- Make sure you are "not" running fat/fat32 on your attached SBP-2 drives. You'll
- *	  get much better performance formatting the drive ext2 (but you will lose the
- *	  ability to easily move the drive between Windows/Linux).
- *
+ * You may access any attached SBP-2 storage devices as if they were SCSI
+ * devices (e.g. mount /dev/sda1,  fdisk, mkfs, etc.).
  *
  * Current Issues:
  *
  *	- Error Handling: SCSI aborts and bus reset requests are handled somewhat
  *	  but the code needs additional debugging.
- *
- *	- Module: 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.   ;-)
- *
- *	- Hot-plugging: Interaction with the SCSI stack and support for hot-plugging could
- *	  stand some improvement.
- *
- *
- * History:
- *
- *	07/25/00 - Initial revision (JSG)
- *	08/11/00 - Following changes/bug fixes were made (JSG):
- *		   * Bug fix to SCSI procfs code (still needs to be synched with 2.4 kernel).
- *		   * Bug fix where request sense commands were actually sent on the bus.
- *		   * Changed bus reset/abort code to deal with devices that spin up quite
- *		     slowly (which result in SCSI time-outs).
- *		   * "More" properly pull information from device's config rom, for enumeration
- *		     of SBP-2 devices, and determining SBP-2 register offsets.
- *		   * Change Simplified Direct Access Device type to Direct Access Device type in
- *		     returned inquiry data, in order to make the SCSI stack happy.
- *		   * Modified driver to register with the SCSI stack "before" enumerating any attached
- *		     SBP-2 devices. This means that you'll have to use procfs scsi-add-device or 
- *		     some sort of script to discover new SBP-2 devices.
- *		   * Minor re-write of some code and other minor changes.
- *	08/28/00 - Following changes/bug fixes were made (JSG):
- *		   * Bug fixes to scatter/gather support (case of one s/g element)
- *		   * Updated direction table for scsi commands (mostly DVD commands)
- *		   * Retries when trying to detect SBP-2 devices (for slow devices)
- *		   * Slightly better error handling (previously none) when commands time-out.
- *		   * Misc. other bug fixes and code reorganization.
- *	09/13/00 - Following changes/bug fixes were made (JSG)
- *		   * Moved detection/enumeration code to a kernel thread which is woken up when IEEE-1394
- *		     bus resets occur.
- *		   * Added code to handle bus resets and hot-plugging while devices are mounted, but full
- *		     hot-plug support is not quite there yet.
- *		   * Now use speed map to determine speed and max payload sizes for ORBs
- *		   * Clean-up of code and reorganization 
- *	09/19/00 - Added better hot-plug support and other minor changes (JSG)
- *	10/15/00 - Fixes for latest 2.4.0 test kernel, minor fix for hot-plug race. (JSG)
- *	12/03/00 - Created pool of request packet structures for use in sending out sbp2 command
- *		   and agent reset requests. This removes the kmallocs/kfrees in the critical I/O paths,
- *		   and also deals with some subtle race conditions related to allocating and freeing
- *		   packets. (JSG)
- *      12/09/00 - Improved the sbp2 device detection by actually reading the root and unit 
- *		   directory (khk@khk.net)
- *	12/23/00 - Following changes/enhancements were made (JSG)
- *		   * Only do SCSI to RBC command conversion for Direct Access and Simplified
- *		     Direct Access Devices (this is pulled from the config rom root directory).
- *		     This is needed because doing the conversion for all device types broke the
- *		     Epson scanner. Still looking for a better way of determining when to convert
- *		     commands (for RBC devices). Thanks to khk for helping on this!
- *		   * Added ability to "emulate" physical dma support, for host adapters such as TILynx.
- *		   * Determine max payload and speed by also looking at the host adapter's max_rec field.
- *	01/19/01 - Added checks to sbp2 login and made the login time-out longer. Also fixed a compile 
- *		   problem for 2.4.0. (JSG)
- *	01/24/01 - Fixed problem when individual s/g elements are 64KB or larger. Needed to break
- *		   up these larger elements, since the sbp2 page table element size is only 16 bits. (JSG)
- *	01/29/01 - Minor byteswap fix for login response (used for reconnect and log out).
- *	03/07/01 - Following changes/enhancements were made (JSG)
- *		   * Changes to allow us to catch the initial scsi bus scan (for detecting sbp2
- *		     devices when first loading sbp2.o). To disable this, un-define 
- *		     SBP2_SUPPORT_INITIAL_BUS_SCAN.
- *		   * Temporary fix to deal with many sbp2 devices that do not support individual
- *		     transfers of greater than 128KB in size. 
- *		   * Mode sense conversion from 6 byte to 10 byte versions for CDRW/DVD devices. (Mark Burton)
- *		   * Define allowing support for goofy sbp2 devices that do not support mode
- *		     sense command at all, allowing them to be mounted rw (such as 1394 memory
- *		     stick and compact flash readers). Define SBP2_MODE_SENSE_WRITE_PROTECT_HACK
- *		     if you need this fix.
- *	03/29/01 - Major performance enhancements and misc. other changes. Thanks to Daniel Berlin for many of
- *		   changes and suggestions for change:
- *		   * Now use sbp2 doorbell and link commands on the fly (instead of serializing requests)
- *		   * Removed all bit fields in an attempt to run on PPC machines (still needs a little more work)
- *		   * Added large request break-up/linking support for sbp2 chipsets that do not support transfers 
- *		     greater than 128KB in size.
- *		   * Bumped up max commands per lun to two, and max total outstanding commands to eight.
- *	04/03/01 - Minor clean-up. Write orb pointer directly if no outstanding commands (saves one 1394 bus
- *		   transaction). Added module load options (bus scan, mode sense hack, max speed, serialize_io,
- *		   no_large_transfers). Better bus reset handling while I/O pending. Set serialize_io to 1 by 
- *		   default (debugging of deserialized I/O in progress).
- *	04/04/01 - Added workaround for PPC Pismo firewire chipset. See #define below. (Daniel Berlin)
- *	04/20/01 - Minor clean-up. Allocate more orb structures when running with sbp2 target chipsets with
- *		   128KB max transfer limit.
- *	06/16/01 - Converted DMA interfaces to pci_dma - Ben Collins
- *							 <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>
- *
- *      11/17/01 - Various bugfixes/cleanups:
- *                 * Remember to logout of device in sbp2_disconnect.
- *                 * If we fail to reconnect to a device after bus reset
- *                   remember to release unit directory, so the ieee1394
- *                   knows we no longer manage it.
- *                 * Unregister scsi hosts in sbp2_remove_host when a
- *                   hpsb_host goes away.
- *                 * Remove stupid hack in sbp2_remove_host.
- *                 * Switched to "manual" module initialization
- *                   (i.e. not scsi_module.c) and moved sbp2_cleanup
- *                   moved sbp2scsi_release to sbp2_module_ext.  The
- *                   release function is called once pr. registered
- *                   scsi host, but sbp2_cleanup should only be called
- *                   upon module unload.  Moved much initialization
- *                   from sbp2scsi_detect to sbp2_module_init.
- *                                 Kristian Hogsberg <hogsberg@users.sf.net>
- *	01/06/02 - Misc bug fixes/enhancements:	(JSG)
- *		   * Enable use_new_eh_code for scsi stuff.
- *		   * Do not write all ones for NULL ORB high/low fields, but
- *		     rather leave reserved areas zeroed (per SBP2 spec).
- *		   * Use newer scsi transfer direction passed down instead of our
- *		     direction table.
- *		   * Bumped login time-out to 20 seconds, as some devices are slow.
- *		   * Fixed a couple scsi unregister bugs on module unload
- *	01/13/02 - Fixed compatibility with certain SBP2 devices, such as Iomega
- *		   1394 devices (Peerless, Jazz). Also a bit of clean-up of the 
- *		   driver, thanks to H.J.Lu (hjl@lucon.org). Removed mode_sense_hack
- *		   module load option, as it's been fixed in the 2.4 scsi stack.
- *	02/10/02 - Added support for max_sectors, minor fix for inquiry command, make
- *		   up sbp2 device type from inquiry response data if not part of 
- *		   device's 1394 unit directory. (JSG)
- *	02/18/02 - Code clean-up and enhancements: (JSG)
- *		   * Finish cleaning out hacked code for dealing with broken sbp2 devices
- *		     which do not support requests of 128KB or greater. Now use 
- *		     max_sectors scsi host entry to limit transfer sizes.
- *		   * Change status fifo address from a single address to a set of addresses,
- *		     with each sbp2 device having its own status fifo address. This makes
- *		     it easier to match the status write to the sbp2 device instance.
- *		   * Minor change to use lun when logging into sbp2 devices. First step in
- *		     supporting multi-lun devices such as CD/DVD changer devices.
- *		   * Added a new module load option for setting max sectors. For use by folk
- *		     who'd like to bump up the max scsi transfer size supported.
- *		   * Enabled deserialized operation by default, allowing for better performance,
- *		     particularily when running with multiple sbp2 devices. For debugging,
- *		     you may enable serialization through use of the sbp2_serialize_io module
- *		     load option (e.g. insmod sbp2 sbp2_serialize_io=1).
- *	02/20/02 - Added a couple additional module load options. 
- *		   Needed to bump down max commands per lun because of the !%@&*^# QPS CDRW 
- *		   drive I have, which doesn't seem to get along with other sbp2 devices 
- *		   (or handle linked commands well).
- *	04/21/02 - Added some additional debug capabilities:
- *		   * Able to handle phys dma requests directly, if host controller has phys
- *		     dma disabled (e.g. insmod ohci1394 phys_dma=0). Undefine CONFIG_IEEE1394_SBP2_PHYS_DMA
- *		     if you'd like to disable sbp2 driver from registering for phys address range. 
- *		   * New packet dump debug define (CONFIG_IEEE1394_SBP2_PACKET_DUMP) which allows
- *		     dumping of all sbp2 related packets sent and received. Especially effective
- *		     when phys dma is disabled on ohci controller (e.g. insmod ohci1394 phys_dma=0).
- *		   * Added new sbp2 module load option (sbp2_exclusive_login) for allowing
- *		     non-exclusive login to sbp2 device, for special multi-host applications.
- *	04/23/02 - Fix for Sony CD-ROM drives. Only send fetch agent reset to sbp2 device if it
- *		   returns the dead bit in status. Thanks to Chandan (chandan@toad.net) for this one.
- *	04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG)
- *	06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG)   
- *	02/04/03 - Fixed a SMP deadlock (don't hold sbp2_command_lock while calling sbp2scsi_complete_command).
- *		   Also save/restore irq flags in sbp2scsi_complete_command  - Sancho Dauskardt <sda@bdit.de>
- *
- */
-
-
-/*
- * Includes
  */
 
 #include <linux/config.h>
@@ -321,6 +57,8 @@
 #include <linux/blk.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/pci.h>
+
 #include <asm/current.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -343,15 +81,15 @@
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "ieee1394_core.h"
+#include "nodemgr.h"
 #include "hosts.h"
 #include "nodemgr.h"
 #include "highlevel.h"
 #include "ieee1394_transactions.h"
-#include "ieee1394_hotplug.h"
 #include "sbp2.h"
 
 static char version[] __devinitdata =
-	"$Rev: 906 $ James Goodwin <jamesg@filanet.com>";
+	"$Rev: 1010 $ Ben Collins <bcollins@debian.org>";
 
 /*
  * Module load parameter definitions
@@ -367,7 +105,7 @@
  */
 MODULE_PARM(sbp2_max_speed,"i");
 MODULE_PARM_DESC(sbp2_max_speed, "Force max speed (3 = 800mb, 2 = 400mb default, 1 = 200mb, 0 = 100mb)");
-static int sbp2_max_speed = SPEED_MAX;
+static int sbp2_max_speed = IEEE1394_SPEED_MAX;
 
 /*
  * Set sbp2_serialize_io to 1 if you'd like only one scsi command sent
@@ -489,6 +227,13 @@
 #define SBP2_ERR(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)
 
 
+/* If you get the linux-2.4 scsi_{add,remove}_single_device patch, you can
+ * enable this define to make use of it. This provides better hotplug
+ * support. The mentioned patch is not part of the kernel proper though,
+ * because it is considered somewhat of a hack. */
+//#define SBP2_USE_SCSI_ADDREM_HACK
+
+
 /*
  * Globals
  */
@@ -502,9 +247,10 @@
 	
 static Scsi_Host_Template scsi_driver_template;
 
+const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
+
 static struct hpsb_highlevel sbp2_highlevel = {
 	.name =		SBP2_DEVICE_NAME,
-	.add_host =	sbp2_add_host,
 	.remove_host =	sbp2_remove_host,
 };
 
@@ -815,22 +561,22 @@
 /* Free our DMA's */
 static void sbp2util_free_command_dma(struct sbp2_command_info *command)
 {
-	struct sbp2scsi_host_info *hi;
+	struct hpsb_host *host;
 
-	hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel,
+	host = hpsb_get_host_bykey(&sbp2_highlevel,
 		(unsigned long)command->Current_SCpnt->device->host->hostt);
-	if (!hi) {
-		printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__);
+	if (!host) {
+		printk(KERN_ERR "%s: host == NULL\n", __FUNCTION__);
 		return;
 	}
 
 	if (command->cmd_dma) {
 		if (command->dma_type == CMD_DMA_SINGLE) {
-			pci_unmap_single(hi->host->pdev, command->cmd_dma,
+			pci_unmap_single(host->pdev, command->cmd_dma,
 					 command->dma_size, command->dma_dir);
 			SBP2_DMA_FREE("single bulk");
 		} else if (command->dma_type == CMD_DMA_PAGE) {
-			pci_unmap_page(hi->host->pdev, command->cmd_dma,
+			pci_unmap_page(host->pdev, command->cmd_dma,
 				       command->dma_size, command->dma_dir);
 			SBP2_DMA_FREE("single page");
 		} /* XXX: Check for CMD_DMA_NONE bug */
@@ -839,7 +585,7 @@
 	}
 
 	if (command->sge_buffer) {
-		pci_unmap_sg(hi->host->pdev, command->sge_buffer,
+		pci_unmap_sg(host->pdev, command->sge_buffer,
 			     command->dma_size, command->dma_dir);
 		SBP2_DMA_FREE("scatter list");
 		command->sge_buffer = NULL;
@@ -873,7 +619,7 @@
 static int sbp2scsi_detect(Scsi_Host_Template *tpnt)
 {
 	struct Scsi_Host *scsi_host;
-	struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, (unsigned long)tpnt);
+	struct hpsb_host *host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)tpnt);
 
 	SBP2_DEBUG("sbp2scsi_detect");
 
@@ -881,7 +627,7 @@
 	if (!(scsi_host = scsi_register(tpnt, 0)))
 		return 0;
 
-	scsi_set_pci_device(scsi_host, hi->host->pdev);
+	scsi_set_pci_device(scsi_host, host->pdev);
 
 	tpnt->present = 1;
 
@@ -892,81 +638,112 @@
 {
 	struct sbp2scsi_host_info *hi;
 
-	SBP2_DEBUG("sbp2_probe");
-	hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
+	SBP2_DEBUG(__FUNCTION__);
+
+	/* Don't probe UD's that have the LUN flag. We'll probe the LUN(s)
+	 * instead. */
+	if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
+		return -1;
 
-	return sbp2_start_device(hi, ud);
+	/* This will only add it if it doesn't exist */
+	hi = sbp2_add_host(ud->ne->host);
+
+	if (!hi)
+		return -1;
+
+	return sbp2_start_ud(hi, ud);
 }
 
 static void sbp2_disconnect(struct unit_directory *ud)
 {
-	struct scsi_id_instance_data *scsi_id = ud->driver_data;
+	struct scsi_id_group *scsi_group = ud->driver_data;
+	struct list_head *lh, *next;
+	struct scsi_id_instance_data *scsi_id;
 
 	SBP2_DEBUG("sbp2_disconnect");
 
-	if (scsi_id) {
-		sbp2_logout_device(scsi_id);
- 		sbp2_remove_device(scsi_id);
+	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {
+		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
+		if (scsi_id) {
+			sbp2_logout_device(scsi_id);
+ 			sbp2_remove_device(scsi_id);
+		}
 	}
+
+	kfree(scsi_group);
 }
 
 static void sbp2_update(struct unit_directory *ud)
 {
 	struct sbp2scsi_host_info *hi;
-	struct scsi_id_instance_data *scsi_id = ud->driver_data;
+	struct scsi_id_group *scsi_group = ud->driver_data;
+	struct list_head *lh, *next;
+	struct scsi_id_instance_data *scsi_id;
 	unsigned long flags;
 
 	SBP2_DEBUG("sbp2_update");
 	hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
 
-	if (sbp2_reconnect_device(scsi_id)) {
-		
-		/* 
-		 * Ok, reconnect has failed. Perhaps we didn't
-		 * reconnect fast enough. Try doing a regular login.
-		 */
-		if (sbp2_login_device(scsi_id)) {
-			/* Login failed too, just remove the device. */
-			SBP2_ERR("sbp2_reconnect_device failed!");
-			sbp2_remove_device(scsi_id);
-			hpsb_release_unit_directory(ud);
-			return;
+	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {
+		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
+
+		if (sbp2_reconnect_device(scsi_id)) {
+			/* 
+			 * Ok, reconnect has failed. Perhaps we didn't
+			 * reconnect fast enough. Try doing a regular login.
+			 */
+			if (sbp2_login_device(scsi_id)) {
+				/* Login failed too, just remove the device. */
+				SBP2_ERR("sbp2_reconnect_device failed!");
+				sbp2_remove_device(scsi_id);
+				continue;
+			}
 		}
-	}
 
-	/* Set max retries to something large on the device. */
-	sbp2_set_busy_timeout(scsi_id);
+		/* Set max retries to something large on the device. */
+		sbp2_set_busy_timeout(scsi_id);
 
-	/* Do a SBP-2 fetch agent reset. */
-	sbp2_agent_reset(scsi_id, 0);
+		/* Do a SBP-2 fetch agent reset. */
+		sbp2_agent_reset(scsi_id, 0);
 	
-	/* Get the max speed and packet size that we can use. */
-	sbp2_max_speed_and_size(scsi_id);
+		/* Get the max speed and packet size that we can use. */
+		sbp2_max_speed_and_size(scsi_id);
 
-	/* Complete any pending commands with busy (so they get
-	 * retried) and remove them from our queue
-	 */
-	spin_lock_irqsave(&hi->sbp2_command_lock, flags);
-	sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
-	spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
+		/* Complete any pending commands with busy (so they get
+		 * retried) and remove them from our queue
+		 */
+		spin_lock_irqsave(&hi->sbp2_command_lock, flags);
+		sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
+		spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
+	}
+
+	if (list_empty(&scsi_group->scsi_id_list)) {
+		hpsb_release_unit_directory(ud);
+		kfree(scsi_group);
+	}
 }
 
 /*
  * 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 struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host)
 {
 	struct sbp2scsi_host_info *hi;
 
 	SBP2_DEBUG("sbp2_add_host");
 
+	/* Check for existing hostinfo */
+	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
+	if (hi)
+		return hi;
+
 	/* Allocate some memory for our host info structure */
 	hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi));
 
 	if (hi == NULL) {
 		SBP2_ERR("out of memory in sbp2_add_host");
-		return;
+		return NULL;
 	}
 
 	/* Initialize some host stuff */
@@ -981,7 +758,7 @@
 	if (SCSI_REGISTER_HOST(&hi->sht)) {
                 SBP2_ERR("Failed to register scsi template for ieee1394 host");
 		hpsb_destroy_hostinfo(&sbp2_highlevel, host);
-                return;
+                return NULL;
         }
 
 	for (hi->scsi_host = scsi_hostlist; hi->scsi_host; hi->scsi_host = hi->scsi_host->next)
@@ -992,12 +769,12 @@
 		SBP2_ERR("Failed to register scsi host for ieee1394 host");
 		SCSI_UNREGISTER_HOST(&hi->sht);
 		hpsb_destroy_hostinfo(&sbp2_highlevel, host);
-		return;
+		return NULL;
 	}
 
 	hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
 
-	return;
+	return hi;
 }
 
 
@@ -1014,34 +791,61 @@
 
 	if (hi)
 		SCSI_UNREGISTER_HOST(&hi->sht);
-	else
-		SBP2_ERR("attempt to remove unknown host %p", host);
 }
 
+static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud)
+{
+	struct scsi_id_instance_data *scsi_id;
+	struct scsi_id_group *scsi_group;
+	struct list_head *lh, *next;
+
+	SBP2_DEBUG("sbp2_start_ud");
+
+	scsi_group = kmalloc(sizeof(*scsi_group), GFP_KERNEL);
+	if (!scsi_group) {
+		SBP2_ERR ("Could not allocate memory for scsi_group");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&scsi_group->scsi_id_list);
+	ud->driver_data = scsi_group;
+	sbp2_parse_unit_directory(scsi_group, ud);
+
+	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {
+		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
+
+		scsi_id->ne = ud->ne;
+		scsi_id->hi = hi;
+		scsi_id->speed_code = IEEE1394_SPEED_100;
+		scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
+		atomic_set(&scsi_id->sbp2_login_complete, 0);
+		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;
+
+		sbp2_start_device(scsi_id);
+	}
+
+	/* Check to see if any of our devices survived the ordeal */
+	if (list_empty(&scsi_group->scsi_id_list)) {
+		kfree(scsi_group);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+
 /*
  * 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, struct unit_directory *ud)
+static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 {
-	struct scsi_id_instance_data *scsi_id = NULL;
-	struct node_entry *ne;
+	struct sbp2scsi_host_info *hi = scsi_id->hi;
 	int i;
 
 	SBP2_DEBUG("sbp2_start_device");
-	ne = ud->ne;
-
-	/*
-	 * 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);
-	if (!scsi_id)
-		goto alloc_fail_first;
-	memset(scsi_id, 0, sizeof(struct scsi_id_instance_data));
-
-	scsi_id->hi = hi;
 
 	/* Login FIFO DMA */
 	scsi_id->login_response =
@@ -1130,7 +934,9 @@
 		}
 
 		kfree(scsi_id);
-alloc_fail_first:
+
+		list_del(&scsi_id->list);
+
 		SBP2_ERR ("Could not allocate memory for scsi_id");
 
 		return -ENOMEM;
@@ -1138,31 +944,6 @@
 	SBP2_DMA_ALLOC("consistent DMA region for login ORB");
 
 	/*
-	 * Initialize some of the fields in this structure
-	 */
-	scsi_id->ne = ne;
-	scsi_id->ud = ud;
-	scsi_id->speed_code = SPEED_100;
-	scsi_id->max_payload_size = hpsb_speedto_maxrec[SPEED_100];
-	ud->driver_data = scsi_id;
-
-	atomic_set(&scsi_id->sbp2_login_complete, 0);
-
-	/* 
-	 * 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;
-
-	/*
-	 * Make sure that we've gotten ahold of the sbp2 management agent
-	 * address. Also figure out the command set being used (SCSI or
-	 * RBC).
-	 */
-	sbp2_parse_unit_directory(scsi_id);
-
-	/*
 	 * Find an empty spot to stick our scsi id instance data. 
 	 */
 	for (i = 0; i < hi->scsi_host->max_id; i++) {
@@ -1216,6 +997,12 @@
 	 */
 	sbp2_max_speed_and_size(scsi_id);
 
+#ifdef SBP2_USE_SCSI_ADDREM_HACK
+	/* Try to hook ourselves into the SCSI subsystem */
+	if (scsi_add_single_device(hi->scsi_host, 0, scsi_id->id, 0))
+		SBP2_INFO("Unable to connect SBP-2 device into the SCSI subsystem");
+#endif
+
 	return 0;
 }
 
@@ -1286,6 +1073,8 @@
 
 	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);
 
+	list_del(&scsi_id->list);
+
 	kfree(scsi_id);
 }
 
@@ -1362,6 +1151,8 @@
 	scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
 	if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
 		scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
+		SBP2_DEBUG("sbp2_query_logins: set lun to %d",
+			   ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
 	}
 	SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
 
@@ -1379,7 +1170,7 @@
 
 	SBP2_DEBUG("sbp2_query_logins: orb byte-swapped");
 
-	sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(stuct sbp2_query_logins_orb),
+	sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb),
 			     "sbp2 query logins orb", scsi_id->query_logins_orb_dma);
 
 	memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
@@ -1474,6 +1265,8 @@
 	/* Set the lun if we were able to pull it from the device's unit directory */
 	if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
 		scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
+		SBP2_DEBUG("sbp2_query_logins: set lun to %d",
+			   ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
 	}
 	SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
 
@@ -1514,7 +1307,8 @@
 
 	atomic_set(&scsi_id->sbp2_login_complete, 0);
 
-	SBP2_DEBUG("sbp2_login_device: prepared to write");
+	SBP2_DEBUG("sbp2_login_device: prepared to write to %08x",
+		   (unsigned int)scsi_id->sbp2_management_agent_addr);
 	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 	SBP2_DEBUG("sbp2_login_device: written");
 
@@ -1625,8 +1419,14 @@
 
 	SBP2_INFO("Logged out of SBP-2 device");
 
-	return(0);
+#ifdef SBP2_USE_SCSI_ADDREM_HACK
+	/* Now that we are logged out of the SBP-2 device, lets
+	 * try to un-hook ourselves from the SCSI subsystem */
+	if (scsi_remove_single_device(hi->scsi_host, 0, scsi_id->id, 0))
+		SBP2_INFO("Unable to disconnect SBP-2 device from the SCSI subsystem");
+#endif
 
+	return 0;
 }
 
 /*
@@ -1745,50 +1545,50 @@
  * directory. Used to determine things like sbp2 management agent offset,
  * and command set used (SCSI or RBC). 
  */
-static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id)
+static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
+				      struct unit_directory *ud)
 {
-	struct unit_directory *ud;
+	struct scsi_id_instance_data *scsi_id;
+	struct list_head *lh;
+	u64 management_agent_addr;
+	u32 command_set_spec_id, command_set, unit_characteristics,
+		firmware_revision, workarounds;
 	int i;
 
 	SBP2_DEBUG("sbp2_parse_unit_directory");
 
-	/* Initialize some fields, in case an entry does not exist */
-	scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
-	scsi_id->sbp2_management_agent_addr = 0x0;
-	scsi_id->sbp2_command_set_spec_id = 0x0;
-	scsi_id->sbp2_command_set = 0x0;
-	scsi_id->sbp2_unit_characteristics = 0x0;
-	scsi_id->sbp2_firmware_revision = 0x0;
-
-	ud = scsi_id->ud;
+	management_agent_addr = 0x0;
+	command_set_spec_id = 0x0;
+	command_set = 0x0;
+	unit_characteristics = 0x0;
+	firmware_revision = 0x0;
 
 	/* Handle different fields in the unit directory, based on keys */
 	for (i = 0; i < ud->length; i++) {
 		switch (CONFIG_ROM_KEY(ud->quadlets[i])) {
 		case SBP2_CSR_OFFSET_KEY:
 			/* Save off the management agent address */
-			scsi_id->sbp2_management_agent_addr =
+			management_agent_addr =
 				CSR_REGISTER_BASE + 
 				(CONFIG_ROM_VALUE(ud->quadlets[i]) << 2);
 
 			SBP2_DEBUG("sbp2_management_agent_addr = %x",
-				   (unsigned int) scsi_id->sbp2_management_agent_addr);
+				   (unsigned int) management_agent_addr);
 			break;
 
 		case SBP2_COMMAND_SET_SPEC_ID_KEY:
 			/* Command spec organization */
-			scsi_id->sbp2_command_set_spec_id
+			command_set_spec_id
 				= CONFIG_ROM_VALUE(ud->quadlets[i]);
 			SBP2_DEBUG("sbp2_command_set_spec_id = %x",
-				   (unsigned int) scsi_id->sbp2_command_set_spec_id);
+				   (unsigned int) command_set_spec_id);
 			break;
 
 		case SBP2_COMMAND_SET_KEY:
 			/* Command set used by sbp2 device */
-			scsi_id->sbp2_command_set
-				= CONFIG_ROM_VALUE(ud->quadlets[i]);
+			command_set = CONFIG_ROM_VALUE(ud->quadlets[i]);
 			SBP2_DEBUG("sbp2_command_set = %x",
-				   (unsigned int) scsi_id->sbp2_command_set);
+				   (unsigned int) command_set);
 			break;
 
 		case SBP2_UNIT_CHARACTERISTICS_KEY:
@@ -1796,10 +1596,10 @@
 			 * Unit characterisitcs (orb related stuff
 			 * that I'm not yet paying attention to)
 			 */
-			scsi_id->sbp2_unit_characteristics
+			unit_characteristics
 				= CONFIG_ROM_VALUE(ud->quadlets[i]);
 			SBP2_DEBUG("sbp2_unit_characteristics = %x",
-				   (unsigned int) scsi_id->sbp2_unit_characteristics);
+				   (unsigned int) unit_characteristics);
 			break;
 
 		case SBP2_DEVICE_TYPE_AND_LUN_KEY:
@@ -1807,21 +1607,29 @@
 			 * Device type and lun (used for
 			 * detemining type of sbp2 device)
 			 */
+			scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
+			if (!scsi_id) {
+				SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added");
+				break;
+			}
+			memset(scsi_id, 0, sizeof(*scsi_id));
+
 			scsi_id->sbp2_device_type_and_lun
 				= CONFIG_ROM_VALUE(ud->quadlets[i]);
 			SBP2_DEBUG("sbp2_device_type_and_lun = %x",
 				   (unsigned int) scsi_id->sbp2_device_type_and_lun);
+			list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);
 			break;
 
 		case SBP2_FIRMWARE_REVISION_KEY:
 			/* Firmware revision */
-			scsi_id->sbp2_firmware_revision
+			firmware_revision
 				= CONFIG_ROM_VALUE(ud->quadlets[i]);
 			if (sbp2_force_inquiry_hack)
 				SBP2_INFO("sbp2_firmware_revision = %x",
-				   (unsigned int) scsi_id->sbp2_firmware_revision);
+				   (unsigned int) firmware_revision);
 			else	SBP2_DEBUG("sbp2_firmware_revision = %x",
-				   (unsigned int) scsi_id->sbp2_firmware_revision);
+				   (unsigned int) firmware_revision);
 			break;
 
 		default:
@@ -1831,7 +1639,7 @@
 
 	/* This is the start of our broken device checking. We try to hack
 	 * around oddities and known defects.  */
-	scsi_id->workarounds = 0x0;
+	workarounds = 0x0;
 
 	/* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a
 	 * bridge with 128KB max transfer size limitation. For sanity, we
@@ -1842,28 +1650,60 @@
 	 * host gets initialized. That way we can down-force the
 	 * sbp2_max_sectors to account for it. That is not currently
 	 * possible.  */
-	if ((scsi_id->sbp2_firmware_revision & 0xffff00) ==
+	if ((firmware_revision & 0xffff00) ==
 			SBP2_128KB_BROKEN_FIRMWARE &&
 			(sbp2_max_sectors * 512) > (128 * 1024)) {
 		SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",
-				NODE_BUS_ARGS(scsi_id->ne->nodeid));
+				NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
 		SBP2_WARN("WARNING: Current sbp2_max_sectors setting is larger than 128KB (%d sectors)!",
 				sbp2_max_sectors);
-		scsi_id->workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
+		workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
 	}
 
 	/* Check for a blacklisted set of devices that require us to force
 	 * a 36 byte host inquiry. This can be overriden as a module param
 	 * (to force all hosts).  */
 	for (i = 0; i < NUM_BROKEN_INQUIRY_DEVS; i++) {
-		if ((scsi_id->sbp2_firmware_revision & 0xffff00) ==
+		if ((firmware_revision & 0xffff00) ==
 				sbp2_broken_inquiry_list[i]) {
 			SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
-					NODE_BUS_ARGS(scsi_id->ne->nodeid));
-			scsi_id->workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
+					NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
+			workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
 			break; /* No need to continue. */
 		}
 	}
+
+	/* If this is a logical unit directory entry, process the parent
+	 * to get the common values. */
+	if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {
+		sbp2_parse_unit_directory(scsi_group, ud->parent);
+	} else {
+		/* If our list is empty, add a base scsi_id (happens in a normal
+		 * case where there is no logical_unit_number entry */
+		if (list_empty(&scsi_group->scsi_id_list)) {
+			scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
+			if (!scsi_id) {
+				SBP2_ERR("Out of memory adding scsi_id");
+				return;
+			}
+			memset(scsi_id, 0, sizeof(*scsi_id));
+
+			scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
+			list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);
+		}
+
+		/* Update the generic fields in all the LUN's */
+		list_for_each (lh, &scsi_group->scsi_id_list) {
+			scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
+
+			scsi_id->sbp2_management_agent_addr = management_agent_addr;
+			scsi_id->sbp2_command_set_spec_id = command_set_spec_id;
+			scsi_id->sbp2_command_set = command_set;
+			scsi_id->sbp2_unit_characteristics = unit_characteristics;
+			scsi_id->sbp2_firmware_revision = firmware_revision;
+			scsi_id->workarounds = workarounds;
+		}
+	}
 }
 
 /*
@@ -1894,11 +1734,12 @@
 
 	/* Payload size is the lesser of what our speed supports and what
 	 * our host supports.  */
-	scsi_id->max_payload_size = min(hpsb_speedto_maxrec[scsi_id->speed_code],
+	scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code],
 					(u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1));
 
-	SBP2_ERR("Node[" NODE_BUS_FMT "]: Max speed [%s] - Max payload [%u]",
-		 NODE_BUS_ARGS(scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code],
+	SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
+		 NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
+		 hpsb_speedto_str[scsi_id->speed_code],
 		 1 << ((u32)scsi_id->max_payload_size + 2));
 
 	return(0);
@@ -3053,28 +2894,27 @@
 			      int length, int hostno, int inout)
 {
 	Scsi_Device *scd;
-	struct Scsi_Host *host;
-	struct sbp2scsi_host_info *hi;
+	struct Scsi_Host *scsi_host;
+	struct hpsb_host *host;
 	char *pos = buffer;
 
 	/* if someone is sending us data, just throw it away */
 	if (inout)
 		return length;
 
-	for (host = scsi_hostlist; host; host = host->next)
-		if (host->host_no == hostno)
+	for (scsi_host = scsi_hostlist; scsi_host; scsi_host = scsi_host->next)
+		if (scsi_host->host_no == hostno)
 			break;
 
-	if (!host)  /* if we couldn't find it, we return an error */
+	if (!scsi_host)  /* if we couldn't find it, we return an error */
 		return -ESRCH;
 
-	hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, (unsigned long)host->hostt);
-	if (!hi) /* shouldn't happen, but... */
+	host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)scsi_host->hostt);
+	if (!host) /* shouldn't happen, but... */
 		return -ESRCH;
 
 	SPRINTF("Host scsi%d             : SBP-2 IEEE-1394 (%s)\n", hostno,
-		hi->host->driver->name);
-	SPRINTF("Driver version         : %s\n", version);
+		host->driver->name);
 
 	SPRINTF("\nModule options         :\n");
 	SPRINTF("  max_speed            : %s\n", hpsb_speedto_str[sbp2_max_speed]);
@@ -3082,9 +2922,9 @@
 	SPRINTF("  serialize_io         : %s\n", sbp2_serialize_io ? "yes" : "no");
 	SPRINTF("  exclusive_login      : %s\n", sbp2_exclusive_login ? "yes" : "no");
 
-	SPRINTF("\nAttached devices       : %s\n", host->host_queue ? "" : "none");
+	SPRINTF("\nAttached devices       : %s\n", scsi_host->host_queue ? "" : "none");
 
-	for (scd = host->host_queue; scd; scd = scd->next) {
+	for (scd = scsi_host->host_queue; scd; scd = scd->next) {
 		int i;
 
 		SPRINTF("  [Channel: %02d, Id: %02d, Lun: %02d]  ", scd->channel,
@@ -3117,7 +2957,7 @@
 }
 
 
-MODULE_AUTHOR("James Goodwin <jamesg@filanet.com>");
+MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
 MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
 MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
 MODULE_LICENSE("GPL");
@@ -3149,6 +2989,8 @@
 {
 	SBP2_DEBUG("sbp2_module_init");
 
+	printk(KERN_INFO "sbp2: %s\n", version);
+
 	/* Module load debug option to force one command at a time (serializing I/O) */
 	if (sbp2_serialize_io) {
 		SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)