diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt
--- a/Documentation/scsi/aic7xxx.txt
+++ b/Documentation/scsi/aic7xxx.txt
@@ -1,5 +1,5 @@
 ====================================================================
-=    Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.2.28   =
+=    Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0      =
 =                            README for                            =
 =                     The Linux Operating System                   =
 ====================================================================
@@ -131,6 +131,10 @@ The following information is available i
       SCSI "stub" effects.
 
 2. Version History
+   7.0	  (4th August, 2005)
+	- Updated driver to use SCSI transport class infrastructure
+	- Upported sequencer and core fixes from last adaptec released
+	  version of the driver.
    6.2.36 (June 3rd, 2003)
         - Correct code that disables PCI parity error checking.
         - Correct and simplify handling of the ignore wide residue
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -373,13 +373,11 @@ Summary:
    scsi_activate_tcq - turn on tag command queueing
    scsi_add_device - creates new scsi device (lu) instance
    scsi_add_host - perform sysfs registration and SCSI bus scan.
-   scsi_add_timer - (re-)start timer on a SCSI command.
    scsi_adjust_queue_depth - change the queue depth on a SCSI device
    scsi_assign_lock - replace default host_lock with given lock
    scsi_bios_ptable - return copy of block device's partition table
    scsi_block_requests - prevent further commands being queued to given host
    scsi_deactivate_tcq - turn off tag command queueing
-   scsi_delete_timer - cancel timer on a SCSI command.
    scsi_host_alloc - return a new scsi_host instance whose refcount==1
    scsi_host_get - increments Scsi_Host instance's refcount
    scsi_host_put - decrements Scsi_Host instance's refcount (free if 0)
@@ -458,27 +456,6 @@ int scsi_add_host(struct Scsi_Host *shos
 
 
 /**
- * scsi_add_timer - (re-)start timer on a SCSI command.
- * @scmd:    pointer to scsi command instance
- * @timeout: duration of timeout in "jiffies"
- * @complete: pointer to function to call if timeout expires
- *
- *      Returns nothing
- *
- *      Might block: no
- *
- *      Notes: Each scsi command has its own timer, and as it is added
- *      to the queue, we set up the timer. When the command completes, 
- *      we cancel the timer. An LLD can use this function to change
- *      the existing timeout value.
- *
- *      Defined in: drivers/scsi/scsi_error.c
- **/
-void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, 
-                    void (*complete)(struct scsi_cmnd *))
-
-
-/**
  * scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device
  * @sdev:       pointer to SCSI device to change queue depth on
  * @tagged:     0 - no tagged queuing
@@ -566,24 +543,6 @@ void scsi_deactivate_tcq(struct scsi_dev
 
 
 /**
- * scsi_delete_timer - cancel timer on a SCSI command.
- * @scmd:    pointer to scsi command instance
- *
- *      Returns 1 if able to cancel timer else 0 (i.e. too late or already
- *      cancelled).
- *
- *      Might block: no [may in the future if it invokes del_timer_sync()]
- *
- *      Notes: All commands issued by upper levels already have a timeout
- *      associated with them. An LLD can use this function to cancel the
- *      timer.
- *
- *      Defined in: drivers/scsi/scsi_error.c
- **/
-int scsi_delete_timer(struct scsi_cmnd *scmd)
-
-
-/**
  * scsi_host_alloc - create a scsi host adapter instance and perform basic
  *                   initialization.
  * @sht:        pointer to scsi host template
diff --git a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -824,6 +824,13 @@ L:	emu10k1-devel@lists.sourceforge.net
 W:	http://sourceforge.net/projects/emu10k1/
 S:	Maintained
 
+EMULEX LPFC FC SCSI DRIVER
+P:      James Smart
+M:      james.smart@emulex.com
+L:      linux-scsi@vger.kernel.org
+W:      http://sourceforge.net/projects/lpfcxxxx
+S:      Supported
+
 EPSON 1355 FRAMEBUFFER DRIVER
 P:	Christopher Hoover
 M:	ch@murgatroid.com, ch@hpl.hp.com
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -22,11 +22,26 @@
 /* This is a private structure used to tie the classdev and the
  * container .. it should never be visible outside this file */
 struct internal_container {
-	struct list_head node;
+	struct klist_node node;
 	struct attribute_container *cont;
 	struct class_device classdev;
 };
 
+static void internal_container_klist_get(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_put(&ic->classdev);
+}
+
+
 /**
  * attribute_container_classdev_to_container - given a classdev, return the container
  *
@@ -57,7 +72,8 @@ int
 attribute_container_register(struct attribute_container *cont)
 {
 	INIT_LIST_HEAD(&cont->node);
-	INIT_LIST_HEAD(&cont->containers);
+	klist_init(&cont->containers,internal_container_klist_get,
+		   internal_container_klist_put);
 		
 	down(&attribute_container_mutex);
 	list_add_tail(&cont->node, &attribute_container_list);
@@ -77,11 +93,13 @@ attribute_container_unregister(struct at
 {
 	int retval = -EBUSY;
 	down(&attribute_container_mutex);
-	if (!list_empty(&cont->containers))
+	spin_lock(&cont->containers.k_lock);
+	if (!list_empty(&cont->containers.k_list))
 		goto out;
 	retval = 0;
 	list_del(&cont->node);
  out:
+	spin_unlock(&cont->containers.k_lock);
 	up(&attribute_container_mutex);
 	return retval;
 		
@@ -140,7 +158,6 @@ attribute_container_add_device(struct de
 			continue;
 		}
 		memset(ic, 0, sizeof(struct internal_container));
-		INIT_LIST_HEAD(&ic->node);
 		ic->cont = cont;
 		class_device_initialize(&ic->classdev);
 		ic->classdev.dev = get_device(dev);
@@ -151,11 +168,22 @@ attribute_container_add_device(struct de
 			fn(cont, dev, &ic->classdev);
 		else
 			attribute_container_add_class_device(&ic->classdev);
-		list_add_tail(&ic->node, &cont->containers);
+		klist_add_tail(&ic->node, &cont->containers);
 	}
 	up(&attribute_container_mutex);
 }
 
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+	for (klist_iter_init(head, iter); (pos = ({ \
+		struct klist_node *n = klist_next(iter); \
+		n ? container_of(n, typeof(*pos), member) : \
+			({ klist_iter_exit(iter) ; NULL; }); \
+	}) ) != NULL; )
+			
+
 /**
  * attribute_container_remove_device - make device eligible for removal.
  *
@@ -182,17 +210,19 @@ attribute_container_remove_device(struct
 
 	down(&attribute_container_mutex);
 	list_for_each_entry(cont, &attribute_container_list, node) {
-		struct internal_container *ic, *tmp;
+		struct internal_container *ic;
+		struct klist_iter iter;
 
 		if (attribute_container_no_classdevs(cont))
 			continue;
 
 		if (!cont->match(cont, dev))
 			continue;
-		list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
 			if (dev != ic->classdev.dev)
 				continue;
-			list_del(&ic->node);
+			klist_del(&ic->node);
 			if (fn)
 				fn(cont, dev, &ic->classdev);
 			else {
@@ -225,12 +255,18 @@ attribute_container_device_trigger(struc
 
 	down(&attribute_container_mutex);
 	list_for_each_entry(cont, &attribute_container_list, node) {
-		struct internal_container *ic, *tmp;
+		struct internal_container *ic;
+		struct klist_iter iter;
 
 		if (!cont->match(cont, dev))
 			continue;
 
-		list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+		if (attribute_container_no_classdevs(cont)) {
+			fn(cont, dev, NULL);
+			continue;
+		}
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
 			if (dev == ic->classdev.dev)
 				fn(cont, dev, &ic->classdev);
 		}
@@ -368,6 +404,36 @@ attribute_container_class_device_del(str
 }
 EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
 
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont:	the container
+ * @dev:	the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+				      struct device *dev)
+{
+	struct class_device *cdev = NULL;
+	struct internal_container *ic;
+	struct klist_iter iter;
+
+	klist_for_each_entry(ic, &cont->containers, node, &iter) {
+		if (ic->classdev.dev == dev) {
+			cdev = &ic->classdev;
+			/* FIXME: must exit iterator then break */
+			klist_iter_exit(&iter);
+			break;
+		}
+	}
+
+	return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
 int __init
 attribute_container_init(void)
 {
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -7,7 +7,7 @@
  * This file is licensed under GPLv2
  *
  * The basic idea here is to allow any "device controller" (which
- * would most often be a Host Bus Adapter" to use the services of one
+ * would most often be a Host Bus Adapter to use the services of one
  * or more tranport classes for performing transport specific
  * services.  Transport specific services are things that the generic
  * command layer doesn't want to know about (speed settings, line
@@ -64,7 +64,9 @@ void transport_class_unregister(struct t
 }
 EXPORT_SYMBOL_GPL(transport_class_unregister);
 
-static int anon_transport_dummy_function(struct device *dev)
+static int anon_transport_dummy_function(struct transport_container *tc,
+					 struct device *dev,
+					 struct class_device *cdev)
 {
 	/* do nothing */
 	return 0;
@@ -115,9 +117,10 @@ static int transport_setup_classdev(stru
 				    struct class_device *classdev)
 {
 	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
 
 	if (tclass->setup)
-		tclass->setup(dev);
+		tclass->setup(tcont, dev, classdev);
 
 	return 0;
 }
@@ -178,12 +181,14 @@ void transport_add_device(struct device 
 EXPORT_SYMBOL_GPL(transport_add_device);
 
 static int transport_configure(struct attribute_container *cont,
-			       struct device *dev)
+			       struct device *dev,
+			       struct class_device *cdev)
 {
 	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
 
 	if (tclass->configure)
-		tclass->configure(dev);
+		tclass->configure(tcont, dev, cdev);
 
 	return 0;
 }
@@ -202,7 +207,7 @@ static int transport_configure(struct at
  */
 void transport_configure_device(struct device *dev)
 {
-	attribute_container_trigger(dev, transport_configure);
+	attribute_container_device_trigger(dev, transport_configure);
 }
 EXPORT_SYMBOL_GPL(transport_configure_device);
 
@@ -215,7 +220,7 @@ static int transport_remove_classdev(str
 	struct transport_class *tclass = class_to_transport_class(cont->class);
 
 	if (tclass->remove)
-		tclass->remove(dev);
+		tclass->remove(tcont, dev, classdev);
 
 	if (tclass->remove != anon_transport_dummy_function) {
 		if (tcont->statistics)
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -284,6 +284,7 @@ static inline void rq_init(request_queue
 	rq->special = NULL;
 	rq->data_len = 0;
 	rq->data = NULL;
+	rq->nr_phys_segments = 0;
 	rq->sense = NULL;
 	rq->end_io = NULL;
 	rq->end_io_data = NULL;
@@ -2115,7 +2116,7 @@ EXPORT_SYMBOL(blk_insert_request);
 /**
  * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage
  * @q:		request queue where request should be inserted
- * @rw:		READ or WRITE data
+ * @rq:		request structure to fill
  * @ubuf:	the user buffer
  * @len:	length of user data
  *
@@ -2132,21 +2133,19 @@ EXPORT_SYMBOL(blk_insert_request);
  *    original bio must be passed back in to blk_rq_unmap_user() for proper
  *    unmapping.
  */
-struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
-				unsigned int len)
+int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
+		    unsigned int len)
 {
 	unsigned long uaddr;
-	struct request *rq;
 	struct bio *bio;
+	int reading;
 
 	if (len > (q->max_sectors << 9))
-		return ERR_PTR(-EINVAL);
-	if ((!len && ubuf) || (len && !ubuf))
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
+	if (!len || !ubuf)
+		return -EINVAL;
 
-	rq = blk_get_request(q, rw, __GFP_WAIT);
-	if (!rq)
-		return ERR_PTR(-ENOMEM);
+	reading = rq_data_dir(rq) == READ;
 
 	/*
 	 * if alignment requirement is satisfied, map in user pages for
@@ -2154,9 +2153,9 @@ struct request *blk_rq_map_user(request_
 	 */
 	uaddr = (unsigned long) ubuf;
 	if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
-		bio = bio_map_user(q, NULL, uaddr, len, rw == READ);
+		bio = bio_map_user(q, NULL, uaddr, len, reading);
 	else
-		bio = bio_copy_user(q, uaddr, len, rw == READ);
+		bio = bio_copy_user(q, uaddr, len, reading);
 
 	if (!IS_ERR(bio)) {
 		rq->bio = rq->biotail = bio;
@@ -2164,28 +2163,70 @@ struct request *blk_rq_map_user(request_
 
 		rq->buffer = rq->data = NULL;
 		rq->data_len = len;
-		return rq;
+		return 0;
 	}
 
 	/*
 	 * bio is the err-ptr
 	 */
-	blk_put_request(rq);
-	return (struct request *) bio;
+	return PTR_ERR(bio);
 }
 
 EXPORT_SYMBOL(blk_rq_map_user);
 
 /**
+ * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage
+ * @q:		request queue where request should be inserted
+ * @rq:		request to map data to
+ * @iov:	pointer to the iovec
+ * @iov_count:	number of elements in the iovec
+ *
+ * Description:
+ *    Data will be mapped directly for zero copy io, if possible. Otherwise
+ *    a kernel bounce buffer is used.
+ *
+ *    A matching blk_rq_unmap_user() must be issued at the end of io, while
+ *    still in process context.
+ *
+ *    Note: The mapped bio may need to be bounced through blk_queue_bounce()
+ *    before being submitted to the device, as pages mapped may be out of
+ *    reach. It's the callers responsibility to make sure this happens. The
+ *    original bio must be passed back in to blk_rq_unmap_user() for proper
+ *    unmapping.
+ */
+int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
+			struct sg_iovec *iov, int iov_count)
+{
+	struct bio *bio;
+
+	if (!iov || iov_count <= 0)
+		return -EINVAL;
+
+	/* we don't allow misaligned data like bio_map_user() does.  If the
+	 * user is using sg, they're expected to know the alignment constraints
+	 * and respect them accordingly */
+	bio = bio_map_user_iov(q, NULL, iov, iov_count, rq_data_dir(rq)== READ);
+	if (IS_ERR(bio))
+		return PTR_ERR(bio);
+
+	rq->bio = rq->biotail = bio;
+	blk_rq_bio_prep(q, rq, bio);
+	rq->buffer = rq->data = NULL;
+	rq->data_len = bio->bi_size;
+	return 0;
+}
+
+EXPORT_SYMBOL(blk_rq_map_user_iov);
+
+/**
  * blk_rq_unmap_user - unmap a request with user data
- * @rq:		request to be unmapped
- * @bio:	bio for the request
+ * @bio:	bio to be unmapped
  * @ulen:	length of user buffer
  *
  * Description:
- *    Unmap a request previously mapped by blk_rq_map_user().
+ *    Unmap a bio previously mapped by blk_rq_map_user().
  */
-int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
+int blk_rq_unmap_user(struct bio *bio, unsigned int ulen)
 {
 	int ret = 0;
 
@@ -2196,31 +2237,89 @@ int blk_rq_unmap_user(struct request *rq
 			ret = bio_uncopy_user(bio);
 	}
 
-	blk_put_request(rq);
-	return ret;
+	return 0;
 }
 
 EXPORT_SYMBOL(blk_rq_unmap_user);
 
 /**
+ * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage
+ * @q:		request queue where request should be inserted
+ * @rq:		request to fill
+ * @kbuf:	the kernel buffer
+ * @len:	length of user data
+ * @gfp_mask:	memory allocation flags
+ */
+int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
+		    unsigned int len, unsigned int gfp_mask)
+{
+	struct bio *bio;
+
+	if (len > (q->max_sectors << 9))
+		return -EINVAL;
+	if (!len || !kbuf)
+		return -EINVAL;
+
+	bio = bio_map_kern(q, kbuf, len, gfp_mask);
+	if (IS_ERR(bio))
+		return PTR_ERR(bio);
+
+	if (rq_data_dir(rq) == WRITE)
+		bio->bi_rw |= (1 << BIO_RW);
+
+	rq->bio = rq->biotail = bio;
+	blk_rq_bio_prep(q, rq, bio);
+
+	rq->buffer = rq->data = NULL;
+	rq->data_len = len;
+	return 0;
+}
+
+EXPORT_SYMBOL(blk_rq_map_kern);
+
+/**
+ * blk_execute_rq_nowait - insert a request into queue for execution
+ * @q:		queue to insert the request in
+ * @bd_disk:	matching gendisk
+ * @rq:		request to insert
+ * @at_head:    insert request at head or tail of queue
+ * @done:	I/O completion handler
+ *
+ * Description:
+ *    Insert a fully prepared request at the back of the io scheduler queue
+ *    for execution.  Don't wait for completion.
+ */
+void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
+			   struct request *rq, int at_head,
+			   void (*done)(struct request *))
+{
+	int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+
+	rq->rq_disk = bd_disk;
+	rq->flags |= REQ_NOMERGE;
+	rq->end_io = done;
+	elv_add_request(q, rq, where, 1);
+	generic_unplug_device(q);
+}
+
+/**
  * blk_execute_rq - insert a request into queue for execution
  * @q:		queue to insert the request in
  * @bd_disk:	matching gendisk
  * @rq:		request to insert
+ * @at_head:    insert request at head or tail of queue
  *
  * Description:
  *    Insert a fully prepared request at the back of the io scheduler queue
- *    for execution.
+ *    for execution and wait for completion.
  */
 int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
-		   struct request *rq)
+		   struct request *rq, int at_head)
 {
 	DECLARE_COMPLETION(wait);
 	char sense[SCSI_SENSE_BUFFERSIZE];
 	int err = 0;
 
-	rq->rq_disk = bd_disk;
-
 	/*
 	 * we need an extra reference to the request, so we can look at
 	 * it after io completion
@@ -2233,11 +2332,8 @@ int blk_execute_rq(request_queue_t *q, s
 		rq->sense_len = 0;
 	}
 
-	rq->flags |= REQ_NOMERGE;
 	rq->waiting = &wait;
-	rq->end_io = blk_end_sync_rq;
-	elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
-	generic_unplug_device(q);
+	blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
 	wait_for_completion(&wait);
 	rq->waiting = NULL;
 
@@ -2277,6 +2373,44 @@ int blkdev_issue_flush(struct block_devi
 
 EXPORT_SYMBOL(blkdev_issue_flush);
 
+/**
+ * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
+ * @q:		device queue
+ * @disk:	gendisk
+ * @error_sector:	error offset
+ *
+ * Description:
+ *    Devices understanding the SCSI command set, can use this function as
+ *    a helper for issuing a cache flush. Note: driver is required to store
+ *    the error offset (in case of error flushing) in ->sector of struct
+ *    request.
+ */
+int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
+	int ret;
+
+	rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+	rq->sector = 0;
+	memset(rq->cmd, 0, sizeof(rq->cmd));
+	rq->cmd[0] = 0x35;
+	rq->cmd_len = 12;
+	rq->data = NULL;
+	rq->data_len = 0;
+	rq->timeout = 60 * HZ;
+
+	ret = blk_execute_rq(q, disk, rq, 0);
+
+	if (ret && error_sector)
+		*error_sector = rq->sector;
+
+	blk_put_request(rq);
+	return ret;
+}
+
+EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
+
 static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
 	int rw = rq_data_dir(rq);
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -216,7 +216,7 @@ static int sg_io(struct file *file, requ
 		struct gendisk *bd_disk, struct sg_io_hdr *hdr)
 {
 	unsigned long start_time;
-	int reading, writing;
+	int writing = 0, ret = 0;
 	struct request *rq;
 	struct bio *bio;
 	char sense[SCSI_SENSE_BUFFERSIZE];
@@ -231,38 +231,48 @@ static int sg_io(struct file *file, requ
 	if (verify_command(file, cmd))
 		return -EPERM;
 
-	/*
-	 * we'll do that later
-	 */
-	if (hdr->iovec_count)
-		return -EOPNOTSUPP;
-
 	if (hdr->dxfer_len > (q->max_sectors << 9))
 		return -EIO;
 
-	reading = writing = 0;
-	if (hdr->dxfer_len) {
+	if (hdr->dxfer_len)
 		switch (hdr->dxfer_direction) {
 		default:
 			return -EINVAL;
 		case SG_DXFER_TO_FROM_DEV:
-			reading = 1;
-			/* fall through */
 		case SG_DXFER_TO_DEV:
 			writing = 1;
 			break;
 		case SG_DXFER_FROM_DEV:
-			reading = 1;
 			break;
 		}
 
-		rq = blk_rq_map_user(q, writing ? WRITE : READ, hdr->dxferp,
-				     hdr->dxfer_len);
+	rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
+	if (!rq)
+		return -ENOMEM;
+
+	if (hdr->iovec_count) {
+		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+		struct sg_iovec *iov;
+
+		iov = kmalloc(size, GFP_KERNEL);
+		if (!iov) {
+			ret = -ENOMEM;
+			goto out;
+		}
 
-		if (IS_ERR(rq))
-			return PTR_ERR(rq);
-	} else
-		rq = blk_get_request(q, READ, __GFP_WAIT);
+		if (copy_from_user(iov, hdr->dxferp, size)) {
+			kfree(iov);
+			ret = -EFAULT;
+			goto out;
+		}
+
+		ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
+		kfree(iov);
+	} else if (hdr->dxfer_len)
+		ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
+
+	if (ret)
+		goto out;
 
 	/*
 	 * fill in request structure
@@ -298,7 +308,7 @@ static int sg_io(struct file *file, requ
 	 * (if he doesn't check that is his problem).
 	 * N.B. a non-zero SCSI status is _not_ necessarily an error.
 	 */
-	blk_execute_rq(q, bd_disk, rq);
+	blk_execute_rq(q, bd_disk, rq, 0);
 
 	/* write to all output members */
 	hdr->status = 0xff & rq->errors;
@@ -320,12 +330,14 @@ static int sg_io(struct file *file, requ
 			hdr->sb_len_wr = len;
 	}
 
-	if (blk_rq_unmap_user(rq, bio, hdr->dxfer_len))
-		return -EFAULT;
+	if (blk_rq_unmap_user(bio, hdr->dxfer_len))
+		ret = -EFAULT;
 
 	/* may not have succeeded, but output values written to control
 	 * structure (struct sg_io_hdr).  */
-	return 0;
+out:
+	blk_put_request(rq);
+	return ret;
 }
 
 #define OMAX_SB_LEN 16          /* For backward compatibility */
@@ -408,7 +420,7 @@ static int sg_scsi_ioctl(struct file *fi
 	rq->data_len = bytes;
 	rq->flags |= REQ_BLOCK_PC;
 
-	blk_execute_rq(q, bd_disk, rq);
+	blk_execute_rq(q, bd_disk, rq, 0);
 	err = rq->errors & 0xff;	/* only 8 bit SCSI status */
 	if (err) {
 		if (rq->sense_len && rq->sense) {
@@ -561,7 +573,7 @@ int scsi_cmd_ioctl(struct file *file, st
 			rq->cmd[0] = GPCMD_START_STOP_UNIT;
 			rq->cmd[4] = 0x02 + (close != 0);
 			rq->cmd_len = 6;
-			err = blk_execute_rq(q, bd_disk, rq);
+			err = blk_execute_rq(q, bd_disk, rq, 0);
 			blk_put_request(rq);
 			break;
 		default:
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2097,6 +2097,10 @@ static int cdrom_read_cdda_bpc(struct cd
 	if (!q)
 		return -ENXIO;
 
+	rq = blk_get_request(q, READ, GFP_KERNEL);
+	if (!rq)
+		return -ENOMEM;
+
 	cdi->last_sense = 0;
 
 	while (nframes) {
@@ -2108,9 +2112,9 @@ static int cdrom_read_cdda_bpc(struct cd
 
 		len = nr * CD_FRAMESIZE_RAW;
 
-		rq = blk_rq_map_user(q, READ, ubuf, len);
-		if (IS_ERR(rq))
-			return PTR_ERR(rq);
+		ret = blk_rq_map_user(q, rq, ubuf, len);
+		if (ret)
+			break;
 
 		memset(rq->cmd, 0, sizeof(rq->cmd));
 		rq->cmd[0] = GPCMD_READ_CD;
@@ -2132,13 +2136,13 @@ static int cdrom_read_cdda_bpc(struct cd
 		if (rq->bio)
 			blk_queue_bounce(q, &rq->bio);
 
-		if (blk_execute_rq(q, cdi->disk, rq)) {
+		if (blk_execute_rq(q, cdi->disk, rq, 0)) {
 			struct request_sense *s = rq->sense;
 			ret = -EIO;
 			cdi->last_sense = s->sense_key;
 		}
 
-		if (blk_rq_unmap_user(rq, bio, len))
+		if (blk_rq_unmap_user(bio, len))
 			ret = -EFAULT;
 
 		if (ret)
@@ -2149,6 +2153,7 @@ static int cdrom_read_cdda_bpc(struct cd
 		ubuf += len;
 	}
 
+	blk_put_request(rq);
 	return ret;
 }
 
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -754,7 +754,7 @@ static int idedisk_issue_flush(request_q
 
 	idedisk_prepare_flush(q, rq);
 
-	ret = blk_execute_rq(q, disk, rq);
+	ret = blk_execute_rq(q, disk, rq, 0);
 
 	/*
 	 * if we failed and caller wants error offset, get it
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.07
+ *    mpi.h Version:  01.05.08
  *
  *  Version History
  *  ---------------
@@ -71,6 +71,9 @@
  *  03-11-05  01.05.07  Removed function codes for SCSI IO 32 and
  *                      TargetAssistExtended requests.
  *                      Removed EEDP IOCStatus codes.
+ *  06-24-05  01.05.08  Added function codes for SCSI IO 32 and
+ *                      TargetAssistExtended requests.
+ *                      Added EEDP IOCStatus codes.
  *  --------------------------------------------------------------------------
  */
 
@@ -101,7 +104,7 @@
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x09)
+#define MPI_HEADER_VERSION_UNIT             (0x0A)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
@@ -292,10 +295,13 @@
 #define MPI_FUNCTION_DIAG_BUFFER_POST               (0x1D)
 #define MPI_FUNCTION_DIAG_RELEASE                   (0x1E)
 
+#define MPI_FUNCTION_SCSI_IO_32                     (0x1F)
+
 #define MPI_FUNCTION_LAN_SEND                       (0x20)
 #define MPI_FUNCTION_LAN_RECEIVE                    (0x21)
 #define MPI_FUNCTION_LAN_RESET                      (0x22)
 
+#define MPI_FUNCTION_TARGET_ASSIST_EXTENDED         (0x23)
 #define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST       (0x24)
 #define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST       (0x25)
 
@@ -681,6 +687,15 @@ typedef struct _MSG_DEFAULT_REPLY
 #define MPI_IOCSTATUS_SCSI_EXT_TERMINATED       (0x004C)
 
 /****************************************************************************/
+/*  For use by SCSI Initiator and SCSI Target end-to-end data protection    */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_EEDP_GUARD_ERROR          (0x004D)
+#define MPI_IOCSTATUS_EEDP_REF_TAG_ERROR        (0x004E)
+#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR        (0x004F)
+
+
+/****************************************************************************/
 /*  SCSI Target values                                                      */
 /****************************************************************************/
 
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.08
+ *    mpi_cnfg.h Version:  01.05.09
  *
  *  Version History
  *  ---------------
@@ -232,6 +232,23 @@
  *                      New physical mapping mode in SAS IO Unit Page 2.
  *                      Added CONFIG_PAGE_SAS_ENCLOSURE_0.
  *                      Added Slot and Enclosure fields to SAS Device Page 0.
+ *  06-24-05  01.05.09  Added EEDP defines to IOC Page 1.
+ *                      Added more RAID type defines to IOC Page 2.
+ *                      Added Port Enable Delay settings to BIOS Page 1.
+ *                      Added Bad Block Table Full define to RAID Volume Page 0.
+ *                      Added Previous State defines to RAID Physical Disk
+ *                      Page 0.
+ *                      Added Max Sata Targets define for DiscoveryStatus field
+ *                      of SAS IO Unit Page 0.
+ *                      Added Device Self Test to Control Flags of SAS IO Unit
+ *                      Page 1.
+ *                      Added Direct Attach Starting Slot Number define for SAS
+ *                      IO Unit Page 2.
+ *                      Added new fields in SAS Device Page 2 for enclosure
+ *                      mapping.
+ *                      Added OwnerDevHandle and Flags field to SAS PHY Page 0.
+ *                      Added IOC GPIO Flags define to SAS Enclosure Page 0.
+ *                      Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
  *  --------------------------------------------------------------------------
  */
 
@@ -477,6 +494,7 @@ typedef struct _MSG_CONFIG_REPLY
 #define MPI_MANUFACTPAGE_DEVICEID_FC929X            (0x0626)
 #define MPI_MANUFACTPAGE_DEVICEID_FC939X            (0x0642)
 #define MPI_MANUFACTPAGE_DEVICEID_FC949X            (0x0640)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949ES           (0x0646)
 /* SCSI */
 #define MPI_MANUFACTPAGE_DEVID_53C1030              (0x0030)
 #define MPI_MANUFACTPAGE_DEVID_53C1030ZC            (0x0031)
@@ -769,9 +787,13 @@ typedef struct _CONFIG_PAGE_IOC_1
 } CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
   IOCPage1_t, MPI_POINTER pIOCPage1_t;
 
-#define MPI_IOCPAGE1_PAGEVERSION                        (0x02)
+#define MPI_IOCPAGE1_PAGEVERSION                        (0x03)
 
 /* defines for the Flags field */
+#define MPI_IOCPAGE1_EEDP_MODE_MASK                     (0x07000000)
+#define MPI_IOCPAGE1_EEDP_MODE_OFF                      (0x00000000)
+#define MPI_IOCPAGE1_EEDP_MODE_T10                      (0x01000000)
+#define MPI_IOCPAGE1_EEDP_MODE_LSI_1                    (0x02000000)
 #define MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE    (0x00000010)
 #define MPI_IOCPAGE1_REPLY_COALESCING                   (0x00000001)
 
@@ -795,6 +817,11 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_V
 #define MPI_RAID_VOL_TYPE_IS                        (0x00)
 #define MPI_RAID_VOL_TYPE_IME                       (0x01)
 #define MPI_RAID_VOL_TYPE_IM                        (0x02)
+#define MPI_RAID_VOL_TYPE_RAID_5                    (0x03)
+#define MPI_RAID_VOL_TYPE_RAID_6                    (0x04)
+#define MPI_RAID_VOL_TYPE_RAID_10                   (0x05)
+#define MPI_RAID_VOL_TYPE_RAID_50                   (0x06)
+#define MPI_RAID_VOL_TYPE_UNKNOWN                   (0xFF)
 
 /* IOC Page 2 Volume Flags values */
 
@@ -820,13 +847,17 @@ typedef struct _CONFIG_PAGE_IOC_2
 } CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
   IOCPage2_t, MPI_POINTER pIOCPage2_t;
 
-#define MPI_IOCPAGE2_PAGEVERSION                        (0x02)
+#define MPI_IOCPAGE2_PAGEVERSION                        (0x03)
 
 /* IOC Page 2 Capabilities flags */
 
 #define MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT               (0x00000001)
 #define MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT              (0x00000002)
 #define MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT               (0x00000004)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT           (0x00000008)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT           (0x00000010)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT          (0x00000020)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT          (0x00000040)
 #define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT              (0x20000000)
 #define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT            (0x40000000)
 #define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT    (0x80000000)
@@ -945,7 +976,7 @@ typedef struct _CONFIG_PAGE_BIOS_1
 } CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
   BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
 
-#define MPI_BIOSPAGE1_PAGEVERSION                       (0x01)
+#define MPI_BIOSPAGE1_PAGEVERSION                       (0x02)
 
 /* values for the BiosOptions field */
 #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE                (0x00000400)
@@ -954,6 +985,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
 #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS              (0x00000001)
 
 /* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY     (0x00F00000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY    (20)
 #define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE       (0x00030000)
 #define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT        (0x00000000)
 #define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT           (0x00010000)
@@ -1167,6 +1200,7 @@ typedef struct _CONFIG_PAGE_BIOS_2
 #define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER              (0x03)
 #define MPI_BIOSPAGE2_FORM_FC_WWN                       (0x04)
 #define MPI_BIOSPAGE2_FORM_SAS_WWN                      (0x05)
+#define MPI_BIOSPAGE2_FORM_ENCLOSURE_SLOT               (0x06)
 
 
 /****************************************************************************
@@ -1957,11 +1991,11 @@ typedef struct _RAID_VOL0_STATUS
   RaidVol0Status_t, MPI_POINTER pRaidVol0Status_t;
 
 /* RAID Volume Page 0 VolumeStatus defines */
-
 #define MPI_RAIDVOL0_STATUS_FLAG_ENABLED                (0x01)
 #define MPI_RAIDVOL0_STATUS_FLAG_QUIESCED               (0x02)
 #define MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS     (0x04)
 #define MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE        (0x08)
+#define MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL   (0x10)
 
 #define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL               (0x00)
 #define MPI_RAIDVOL0_STATUS_STATE_DEGRADED              (0x01)
@@ -2025,7 +2059,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0
 } CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
   RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
 
-#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x04)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x05)
 
 /* values for RAID Volume Page 0 InactiveStatus field */
 #define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE               (0x00)
@@ -2104,6 +2138,8 @@ typedef struct _RAID_PHYS_DISK0_STATUS
 #define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC           (0x01)
 #define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED              (0x02)
 #define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME       (0x04)
+#define MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS      (0x00)
+#define MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS  (0x08)
 
 #define MPI_PHYSDISK0_STATUS_ONLINE                     (0x00)
 #define MPI_PHYSDISK0_STATUS_MISSING                    (0x01)
@@ -2132,7 +2168,7 @@ typedef struct _CONFIG_PAGE_RAID_PHYS_DI
 } CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0,
   RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t;
 
-#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION           (0x01)
+#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION           (0x02)
 
 
 typedef struct _RAID_PHYS_DISK1_PATH
@@ -2263,7 +2299,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
 } CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
   SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
 
-#define MPI_SASIOUNITPAGE0_PAGEVERSION      (0x02)
+#define MPI_SASIOUNITPAGE0_PAGEVERSION      (0x03)
 
 /* values for SAS IO Unit Page 0 PortFlags */
 #define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS    (0x08)
@@ -2299,6 +2335,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
 #define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK                 (0x00000200)
 #define MPI_SAS_IOUNIT0_DS_TABLE_LINK                       (0x00000400)
 #define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
+#define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS                 (0x00001000)
 
 
 typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
@@ -2336,6 +2373,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
 #define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x04)
 
 /* values for SAS IO Unit Page 1 ControlFlags */
+#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST        (0x8000)
 #define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX            (0x4000)
 #define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX            (0x2000)
 #define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE        (0x1000)
@@ -2345,9 +2383,8 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
 #define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT       (9)
 #define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH        (0x00)
 #define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT         (0x01)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT        (0x10)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT        (0x02)
 
-#define MPI_SAS_IOUNIT1_CONTROL_AUTO_PORT_SAME_SAS_ADDR (0x0100)
 #define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
 #define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED     (0x0040)
 #define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED       (0x0020)
@@ -2390,7 +2427,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
 } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
   SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
 
-#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x03)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x04)
 
 /* values for SAS IO Unit Page 2 Status field */
 #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2406,6 +2443,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
 #define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP       (0x02)
 
 #define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT         (0x10)
+#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT              (0x20)
 
 
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3
@@ -2584,11 +2622,19 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2
 {
     CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
     U64                                 PhysicalIdentifier;     /* 08h */
-    U32                                 Reserved1;              /* 10h */
+    U32                                 EnclosureMapping;       /* 10h */
 } CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2,
   SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t;
 
-#define MPI_SASDEVICE2_PAGEVERSION          (0x00)
+#define MPI_SASDEVICE2_PAGEVERSION          (0x01)
+
+/* defines for SAS Device Page 2 EnclosureMapping field */
+#define MPI_SASDEVICE2_ENC_MAP_MASK_MISSING_COUNT       (0x0000000F)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_MISSING_COUNT      (0)
+#define MPI_SASDEVICE2_ENC_MAP_MASK_NUM_SLOTS           (0x000007F0)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_NUM_SLOTS          (4)
+#define MPI_SASDEVICE2_ENC_MAP_MASK_START_INDEX         (0x001FF800)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_START_INDEX        (11)
 
 
 /****************************************************************************
@@ -2598,7 +2644,8 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2
 typedef struct _CONFIG_PAGE_SAS_PHY_0
 {
     CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
-    U32                                 Reserved1;              /* 08h */
+    U16                                 OwnerDevHandle;         /* 08h */
+    U16                                 Reserved1;              /* 0Ah */
     U64                                 SASAddress;             /* 0Ch */
     U16                                 AttachedDevHandle;      /* 14h */
     U8                                  AttachedPhyIdentifier;  /* 16h */
@@ -2607,12 +2654,12 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
     U8                                  ProgrammedLinkRate;     /* 20h */
     U8                                  HwLinkRate;             /* 21h */
     U8                                  ChangeCount;            /* 22h */
-    U8                                  Reserved3;              /* 23h */
+    U8                                  Flags;                  /* 23h */
     U32                                 PhyInfo;                /* 24h */
 } CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
   SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
 
-#define MPI_SASPHY0_PAGEVERSION             (0x00)
+#define MPI_SASPHY0_PAGEVERSION             (0x01)
 
 /* values for SAS PHY Page 0 ProgrammedLinkRate field */
 #define MPI_SAS_PHY0_PRATE_MAX_RATE_MASK                        (0xF0)
@@ -2632,6 +2679,9 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
 #define MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5                        (0x08)
 #define MPI_SAS_PHY0_HWRATE_MIN_RATE_3_0                        (0x09)
 
+/* values for SAS PHY Page 0 Flags field */
+#define MPI_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC              (0x01)
+
 /* values for SAS PHY Page 0 PhyInfo field */
 #define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE                   (0x00004000)
 #define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR                 (0x00002000)
@@ -2690,7 +2740,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSUR
 } CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0,
   SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t;
 
-#define MPI_SASENCLOSURE0_PAGEVERSION       (0x00)
+#define MPI_SASENCLOSURE0_PAGEVERSION       (0x01)
 
 /* values for SAS Enclosure Page 0 Flags field */
 #define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID       (0x0020)
@@ -2702,6 +2752,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSUR
 #define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO          (0x0002)
 #define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO          (0x0003)
 #define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE      (0x0004)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO           (0x0005)
 
 
 /****************************************************************************
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,17 +6,17 @@
  Copyright (c) 2000-2005 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.05.09
+ Header Set Release Version:    01.05.10
  Header Set Release Date:       03-11-05
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.05.07            01.05.06
- mpi_ioc.h              01.05.08            01.05.07
- mpi_cnfg.h             01.05.08            01.05.07
- mpi_init.h             01.05.04            01.05.03
- mpi_targ.h             01.05.04            01.05.03
+ mpi.h                  01.05.08            01.05.07
+ mpi_ioc.h              01.05.09            01.05.08
+ mpi_cnfg.h             01.05.09            01.05.08
+ mpi_init.h             01.05.05            01.05.04
+ mpi_targ.h             01.05.05            01.05.04
  mpi_fc.h               01.05.01            01.05.01
  mpi_lan.h              01.05.01            01.05.01
  mpi_raid.h             01.05.02            01.05.02
@@ -24,7 +24,7 @@
  mpi_inb.h              01.05.01            01.05.01
  mpi_sas.h              01.05.01            01.05.01
  mpi_type.h             01.05.01            01.05.01
- mpi_history.txt        01.05.09            01.05.08
+ mpi_history.txt        01.05.09            01.05.09
 
 
  *  Date      Version   Description
@@ -88,6 +88,9 @@ mpi.h
  *  03-11-05  01.05.07  Removed function codes for SCSI IO 32 and
  *                      TargetAssistExtended requests.
  *                      Removed EEDP IOCStatus codes.
+ *  06-24-05  01.05.08  Added function codes for SCSI IO 32 and
+ *                      TargetAssistExtended requests.
+ *                      Added EEDP IOCStatus codes.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -159,6 +162,8 @@ mpi_ioc.h
  *                      Reply and IOC Init Request.
  *  03-11-05  01.05.08  Added family code for 1068E family.
  *                      Removed IOCFacts Reply EEDP Capability bit.
+ *  06-24-05  01.05.09  Added 5 new IOCFacts Reply IOCCapabilities bits.
+ *                      Added Max SATA Targets to SAS Discovery Error event.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -380,6 +385,23 @@ mpi_cnfg.h
  *                      New physical mapping mode in SAS IO Unit Page 2.
  *                      Added CONFIG_PAGE_SAS_ENCLOSURE_0.
  *                      Added Slot and Enclosure fields to SAS Device Page 0.
+ *  06-24-05  01.05.09  Added EEDP defines to IOC Page 1.
+ *                      Added more RAID type defines to IOC Page 2.
+ *                      Added Port Enable Delay settings to BIOS Page 1.
+ *                      Added Bad Block Table Full define to RAID Volume Page 0.
+ *                      Added Previous State defines to RAID Physical Disk
+ *                      Page 0.
+ *                      Added Max Sata Targets define for DiscoveryStatus field
+ *                      of SAS IO Unit Page 0.
+ *                      Added Device Self Test to Control Flags of SAS IO Unit
+ *                      Page 1.
+ *                      Added Direct Attach Starting Slot Number define for SAS
+ *                      IO Unit Page 2.
+ *                      Added new fields in SAS Device Page 2 for enclosure
+ *                      mapping.
+ *                      Added OwnerDevHandle and Flags field to SAS PHY Page 0.
+ *                      Added IOC GPIO Flags define to SAS Enclosure Page 0.
+ *                      Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -418,6 +440,8 @@ mpi_init.h
  *                      Modified SCSI Enclosure Processor Request and Reply to
  *                      support Enclosure/Slot addressing rather than WWID
  *                      addressing.
+ *  06-24-05  01.05.05  Added SCSI IO 32 structures and defines.
+ *                      Added four new defines for SEP SlotStatus.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -461,6 +485,7 @@ mpi_targ.h
  *  10-05-04  01.05.02  MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
  *  02-22-05  01.05.03  Changed a comment.
  *  03-11-05  01.05.04  Removed TargetAssistExtended Request.
+ *  06-24-05  01.05.05  Added TargetAssistExtended structures and defines.
  *  --------------------------------------------------------------------------
 
 mpi_fc.h
@@ -571,20 +596,20 @@ mpi_type.h
 
 mpi_history.txt         Parts list history
 
-Filename    01.05.09
-----------  --------
-mpi.h       01.05.07
-mpi_ioc.h   01.05.08
-mpi_cnfg.h  01.05.08
-mpi_init.h  01.05.04
-mpi_targ.h  01.05.04
-mpi_fc.h    01.05.01
-mpi_lan.h   01.05.01
-mpi_raid.h  01.05.02
-mpi_tool.h  01.05.03
-mpi_inb.h   01.05.01
-mpi_sas.h   01.05.01
-mpi_type.h  01.05.01
+Filename    01.05.10  01.05.09
+----------  --------  --------
+mpi.h       01.05.08  01.05.07
+mpi_ioc.h   01.05.09  01.05.08
+mpi_cnfg.h  01.05.09  01.05.08
+mpi_init.h  01.05.05  01.05.04
+mpi_targ.h  01.05.05  01.05.04
+mpi_fc.h    01.05.01  01.05.01
+mpi_lan.h   01.05.01  01.05.01
+mpi_raid.h  01.05.02  01.05.02
+mpi_tool.h  01.05.03  01.05.03
+mpi_inb.h   01.05.01  01.05.01
+mpi_sas.h   01.05.01  01.05.01
+mpi_type.h  01.05.01  01.05.01
 
 Filename    01.05.08   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
 ----------  --------   --------   --------   --------   --------   --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -6,7 +6,7 @@
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.04
+ *    mpi_init.h Version:  01.05.05
  *
  *  Version History
  *  ---------------
@@ -48,6 +48,8 @@
  *                      Modified SCSI Enclosure Processor Request and Reply to
  *                      support Enclosure/Slot addressing rather than WWID
  *                      addressing.
+ *  06-24-05  01.05.05  Added SCSI IO 32 structures and defines.
+ *                      Added four new defines for SEP SlotStatus.
  *  --------------------------------------------------------------------------
  */
 
@@ -203,6 +205,197 @@ typedef struct _MSG_SCSI_IO_REPLY
 
 
 /****************************************************************************/
+/*  SCSI IO 32 messages and associated structures                           */
+/****************************************************************************/
+
+typedef struct
+{
+    U8                      CDB[20];                    /* 00h */
+    U32                     PrimaryReferenceTag;        /* 14h */
+    U16                     PrimaryApplicationTag;      /* 18h */
+    U16                     PrimaryApplicationTagMask;  /* 1Ah */
+    U32                     TransferLength;             /* 1Ch */
+} MPI_SCSI_IO32_CDB_EEDP32, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP32,
+  MpiScsiIo32CdbEedp32_t, MPI_POINTER pMpiScsiIo32CdbEedp32_t;
+
+typedef struct
+{
+    U8                      CDB[16];                    /* 00h */
+    U32                     DataLength;                 /* 10h */
+    U32                     PrimaryReferenceTag;        /* 14h */
+    U16                     PrimaryApplicationTag;      /* 18h */
+    U16                     PrimaryApplicationTagMask;  /* 1Ah */
+    U32                     TransferLength;             /* 1Ch */
+} MPI_SCSI_IO32_CDB_EEDP16, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP16,
+  MpiScsiIo32CdbEedp16_t, MPI_POINTER pMpiScsiIo32CdbEedp16_t;
+
+typedef union
+{
+    U8                       CDB32[32];
+    MPI_SCSI_IO32_CDB_EEDP32 EEDP32;
+    MPI_SCSI_IO32_CDB_EEDP16 EEDP16;
+    SGE_SIMPLE_UNION         SGE;
+} MPI_SCSI_IO32_CDB_UNION, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_UNION,
+  MpiScsiIo32Cdb_t, MPI_POINTER pMpiScsiIo32Cdb_t;
+
+typedef struct
+{
+    U8                      TargetID;           /* 00h */
+    U8                      Bus;                /* 01h */
+    U16                     Reserved1;          /* 02h */
+    U32                     Reserved2;          /* 04h */
+} MPI_SCSI_IO32_BUS_TARGET_ID_FORM, MPI_POINTER PTR_MPI_SCSI_IO32_BUS_TARGET_ID_FORM,
+  MpiScsiIo32BusTargetIdForm_t, MPI_POINTER pMpiScsiIo32BusTargetIdForm_t;
+
+typedef union
+{
+    MPI_SCSI_IO32_BUS_TARGET_ID_FORM    SCSIID;
+    U64                                 WWID;
+} MPI_SCSI_IO32_ADDRESS, MPI_POINTER PTR_MPI_SCSI_IO32_ADDRESS,
+  MpiScsiIo32Address_t, MPI_POINTER pMpiScsiIo32Address_t;
+
+typedef struct _MSG_SCSI_IO32_REQUEST
+{
+    U8                          Port;                           /* 00h */
+    U8                          Reserved1;                      /* 01h */
+    U8                          ChainOffset;                    /* 02h */
+    U8                          Function;                       /* 03h */
+    U8                          CDBLength;                      /* 04h */
+    U8                          SenseBufferLength;              /* 05h */
+    U8                          Flags;                          /* 06h */
+    U8                          MsgFlags;                       /* 07h */
+    U32                         MsgContext;                     /* 08h */
+    U8                          LUN[8];                         /* 0Ch */
+    U32                         Control;                        /* 14h */
+    MPI_SCSI_IO32_CDB_UNION     CDB;                            /* 18h */
+    U32                         DataLength;                     /* 38h */
+    U32                         BidirectionalDataLength;        /* 3Ch */
+    U32                         SecondaryReferenceTag;          /* 40h */
+    U16                         SecondaryApplicationTag;        /* 44h */
+    U16                         Reserved2;                      /* 46h */
+    U16                         EEDPFlags;                      /* 48h */
+    U16                         ApplicationTagTranslationMask;  /* 4Ah */
+    U32                         EEDPBlockSize;                  /* 4Ch */
+    MPI_SCSI_IO32_ADDRESS       DeviceAddress;                  /* 50h */
+    U8                          SGLOffset0;                     /* 58h */
+    U8                          SGLOffset1;                     /* 59h */
+    U8                          SGLOffset2;                     /* 5Ah */
+    U8                          SGLOffset3;                     /* 5Bh */
+    U32                         Reserved3;                      /* 5Ch */
+    U32                         Reserved4;                      /* 60h */
+    U32                         SenseBufferLowAddr;             /* 64h */
+    SGE_IO_UNION                SGL;                            /* 68h */
+} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST,
+  SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t;
+
+/* SCSI IO 32 MsgFlags bits */
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH                (0x01)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32             (0x00)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64             (0x01)
+
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION             (0x02)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST             (0x00)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_IOC              (0x02)
+
+#define MPI_SCSIIO32_MSGFLGS_CMD_DETERMINES_DATA_DIR    (0x04)
+#define MPI_SCSIIO32_MSGFLGS_SGL_OFFSETS_CHAINS         (0x08)
+#define MPI_SCSIIO32_MSGFLGS_MULTICAST                  (0x10)
+#define MPI_SCSIIO32_MSGFLGS_BIDIRECTIONAL              (0x20)
+#define MPI_SCSIIO32_MSGFLGS_LARGE_CDB                  (0x40)
+
+/* SCSI IO 32 Flags bits */
+#define MPI_SCSIIO32_FLAGS_FORM_MASK                    (0x03)
+#define MPI_SCSIIO32_FLAGS_FORM_SCSIID                  (0x00)
+#define MPI_SCSIIO32_FLAGS_FORM_WWID                    (0x01)
+
+/* SCSI IO 32 LUN fields */
+#define MPI_SCSIIO32_LUN_FIRST_LEVEL_ADDRESSING     (0x0000FFFF)
+#define MPI_SCSIIO32_LUN_SECOND_LEVEL_ADDRESSING    (0xFFFF0000)
+#define MPI_SCSIIO32_LUN_THIRD_LEVEL_ADDRESSING     (0x0000FFFF)
+#define MPI_SCSIIO32_LUN_FOURTH_LEVEL_ADDRESSING    (0xFFFF0000)
+#define MPI_SCSIIO32_LUN_LEVEL_1_WORD               (0xFF00)
+#define MPI_SCSIIO32_LUN_LEVEL_1_DWORD              (0x0000FF00)
+
+/* SCSI IO 32 Control bits */
+#define MPI_SCSIIO32_CONTROL_DATADIRECTION_MASK     (0x03000000)
+#define MPI_SCSIIO32_CONTROL_NODATATRANSFER         (0x00000000)
+#define MPI_SCSIIO32_CONTROL_WRITE                  (0x01000000)
+#define MPI_SCSIIO32_CONTROL_READ                   (0x02000000)
+#define MPI_SCSIIO32_CONTROL_BIDIRECTIONAL          (0x03000000)
+
+#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_MASK         (0xFC000000)
+#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_SHIFT        (26)
+
+#define MPI_SCSIIO32_CONTROL_TASKATTRIBUTE_MASK     (0x00000700)
+#define MPI_SCSIIO32_CONTROL_SIMPLEQ                (0x00000000)
+#define MPI_SCSIIO32_CONTROL_HEADOFQ                (0x00000100)
+#define MPI_SCSIIO32_CONTROL_ORDEREDQ               (0x00000200)
+#define MPI_SCSIIO32_CONTROL_ACAQ                   (0x00000400)
+#define MPI_SCSIIO32_CONTROL_UNTAGGED               (0x00000500)
+#define MPI_SCSIIO32_CONTROL_NO_DISCONNECT          (0x00000700)
+
+#define MPI_SCSIIO32_CONTROL_TASKMANAGE_MASK        (0x00FF0000)
+#define MPI_SCSIIO32_CONTROL_OBSOLETE               (0x00800000)
+#define MPI_SCSIIO32_CONTROL_CLEAR_ACA_RSV          (0x00400000)
+#define MPI_SCSIIO32_CONTROL_TARGET_RESET           (0x00200000)
+#define MPI_SCSIIO32_CONTROL_LUN_RESET_RSV          (0x00100000)
+#define MPI_SCSIIO32_CONTROL_RESERVED               (0x00080000)
+#define MPI_SCSIIO32_CONTROL_CLR_TASK_SET_RSV       (0x00040000)
+#define MPI_SCSIIO32_CONTROL_ABORT_TASK_SET         (0x00020000)
+#define MPI_SCSIIO32_CONTROL_RESERVED2              (0x00010000)
+
+/* SCSI IO 32 EEDPFlags */
+#define MPI_SCSIIO32_EEDPFLAGS_MASK_OP              (0x0007)
+#define MPI_SCSIIO32_EEDPFLAGS_NOOP_OP              (0x0000)
+#define MPI_SCSIIO32_EEDPFLAGS_CHK_OP               (0x0001)
+#define MPI_SCSIIO32_EEDPFLAGS_STRIP_OP             (0x0002)
+#define MPI_SCSIIO32_EEDPFLAGS_CHKRM_OP             (0x0003)
+#define MPI_SCSIIO32_EEDPFLAGS_INSERT_OP            (0x0004)
+#define MPI_SCSIIO32_EEDPFLAGS_REPLACE_OP           (0x0006)
+#define MPI_SCSIIO32_EEDPFLAGS_CHKREGEN_OP          (0x0007)
+
+#define MPI_SCSIIO32_EEDPFLAGS_PASS_REF_TAG         (0x0008)
+#define MPI_SCSIIO32_EEDPFLAGS_8_9THS_MODE          (0x0010)
+
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_MASK         (0x0700)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD        (0x0100)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG       (0x0200)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG       (0x0400)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_SHIFT        (8)
+
+#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_APPTAG       (0x1000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_APPTAG       (0x2000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_REFTAG       (0x4000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG       (0x8000)
+
+
+/* SCSIIO32 IO reply structure */
+typedef struct _MSG_SCSIIO32_IO_REPLY
+{
+    U8                      Port;                       /* 00h */
+    U8                      Reserved1;                  /* 01h */
+    U8                      MsgLength;                  /* 02h */
+    U8                      Function;                   /* 03h */
+    U8                      CDBLength;                  /* 04h */
+    U8                      SenseBufferLength;          /* 05h */
+    U8                      Flags;                      /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U8                      SCSIStatus;                 /* 0Ch */
+    U8                      SCSIState;                  /* 0Dh */
+    U16                     IOCStatus;                  /* 0Eh */
+    U32                     IOCLogInfo;                 /* 10h */
+    U32                     TransferCount;              /* 14h */
+    U32                     SenseCount;                 /* 18h */
+    U32                     ResponseInfo;               /* 1Ch */
+    U16                     TaskTag;                    /* 20h */
+    U16                     Reserved2;                  /* 22h */
+    U32                     BidirectionalTransferCount; /* 24h */
+} MSG_SCSIIO32_IO_REPLY, MPI_POINTER PTR_MSG_SCSIIO32_IO_REPLY,
+  SCSIIO32Reply_t, MPI_POINTER pSCSIIO32Reply_t;
+
+
+/****************************************************************************/
 /*  SCSI Task Management messages                                           */
 /****************************************************************************/
 
@@ -310,10 +503,14 @@ typedef struct _MSG_SEP_REQUEST
 #define MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED             (0x00000080)
 #define MPI_SEP_REQ_SLOTSTATUS_HOT_SPARE                (0x00000100)
 #define MPI_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED          (0x00000200)
+#define MPI_SEP_REQ_SLOTSTATUS_REQ_CONSISTENCY_CHECK    (0x00001000)
+#define MPI_SEP_REQ_SLOTSTATUS_DISABLE                  (0x00002000)
+#define MPI_SEP_REQ_SLOTSTATUS_REQ_RESERVED_DEVICE      (0x00004000)
 #define MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST         (0x00020000)
 #define MPI_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE           (0x00040000)
 #define MPI_SEP_REQ_SLOTSTATUS_REQUEST_INSERT           (0x00080000)
 #define MPI_SEP_REQ_SLOTSTATUS_DO_NOT_MOVE              (0x00400000)
+#define MPI_SEP_REQ_SLOTSTATUS_ACTIVE                   (0x00800000)
 #define MPI_SEP_REQ_SLOTSTATUS_B_ENABLE_BYPASS          (0x04000000)
 #define MPI_SEP_REQ_SLOTSTATUS_A_ENABLE_BYPASS          (0x08000000)
 #define MPI_SEP_REQ_SLOTSTATUS_DEV_OFF                  (0x10000000)
@@ -352,11 +549,15 @@ typedef struct _MSG_SEP_REPLY
 #define MPI_SEP_REPLY_SLOTSTATUS_UNCONFIGURED           (0x00000080)
 #define MPI_SEP_REPLY_SLOTSTATUS_HOT_SPARE              (0x00000100)
 #define MPI_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED        (0x00000200)
+#define MPI_SEP_REPLY_SLOTSTATUS_CONSISTENCY_CHECK      (0x00001000)
+#define MPI_SEP_REPLY_SLOTSTATUS_DISABLE                (0x00002000)
+#define MPI_SEP_REPLY_SLOTSTATUS_RESERVED_DEVICE        (0x00004000)
 #define MPI_SEP_REPLY_SLOTSTATUS_REPORT                 (0x00010000)
 #define MPI_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST       (0x00020000)
 #define MPI_SEP_REPLY_SLOTSTATUS_REMOVE_READY           (0x00040000)
 #define MPI_SEP_REPLY_SLOTSTATUS_INSERT_READY           (0x00080000)
 #define MPI_SEP_REPLY_SLOTSTATUS_DO_NOT_REMOVE          (0x00400000)
+#define MPI_SEP_REPLY_SLOTSTATUS_ACTIVE                 (0x00800000)
 #define MPI_SEP_REPLY_SLOTSTATUS_B_BYPASS_ENABLED       (0x01000000)
 #define MPI_SEP_REPLY_SLOTSTATUS_A_BYPASS_ENABLED       (0x02000000)
 #define MPI_SEP_REPLY_SLOTSTATUS_B_ENABLE_BYPASS        (0x04000000)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -6,7 +6,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.08
+ *    mpi_ioc.h Version:  01.05.09
  *
  *  Version History
  *  ---------------
@@ -81,6 +81,8 @@
  *                      Reply and IOC Init Request.
  *  03-11-05  01.05.08  Added family code for 1068E family.
  *                      Removed IOCFacts Reply EEDP Capability bit.
+ *  06-24-05  01.05.09  Added 5 new IOCFacts Reply IOCCapabilities bits.
+ *                      Added Max SATA Targets to SAS Discovery Error event.
  *  --------------------------------------------------------------------------
  */
 
@@ -261,7 +263,11 @@ typedef struct _MSG_IOC_FACTS_REPLY
 #define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER       (0x00000008)
 #define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER         (0x00000010)
 #define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER         (0x00000020)
-
+#define MPI_IOCFACTS_CAPABILITY_EEDP                    (0x00000040)
+#define MPI_IOCFACTS_CAPABILITY_BIDIRECTIONAL           (0x00000080)
+#define MPI_IOCFACTS_CAPABILITY_MULTICAST               (0x00000100)
+#define MPI_IOCFACTS_CAPABILITY_SCSIIO32                (0x00000200)
+#define MPI_IOCFACTS_CAPABILITY_NO_SCSIIO16             (0x00000400)
 
 
 /*****************************************************************************
@@ -677,6 +683,7 @@ typedef struct _EVENT_DATA_DISCOVERY_ERR
 #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE          (0x00000200)
 #define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE              (0x00000400)
 #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS                (0x00000800)
+#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS            (0x00001000)
 
 
 /*****************************************************************************
diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h
--- a/drivers/message/fusion/lsi/mpi_targ.h
+++ b/drivers/message/fusion/lsi/mpi_targ.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Target mode messages and structures
  *  Creation Date:  June 22, 2000
  *
- *    mpi_targ.h Version:  01.05.04
+ *    mpi_targ.h Version:  01.05.05
  *
  *  Version History
  *  ---------------
@@ -53,6 +53,7 @@
  *  10-05-04  01.05.02  MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
  *  02-22-05  01.05.03  Changed a comment.
  *  03-11-05  01.05.04  Removed TargetAssistExtended Request.
+ *  06-24-05  01.05.05  Added TargetAssistExtended structures and defines.
  *  --------------------------------------------------------------------------
  */
 
@@ -371,6 +372,77 @@ typedef struct _MSG_TARGET_ERROR_REPLY
 
 
 /****************************************************************************/
+/* Target Assist Extended Request                                           */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_ASSIST_EXT_REQUEST
+{
+    U8                      StatusCode;                     /* 00h */
+    U8                      TargetAssistFlags;              /* 01h */
+    U8                      ChainOffset;                    /* 02h */
+    U8                      Function;                       /* 03h */
+    U16                     QueueTag;                       /* 04h */
+    U8                      Reserved1;                      /* 06h */
+    U8                      MsgFlags;                       /* 07h */
+    U32                     MsgContext;                     /* 08h */
+    U32                     ReplyWord;                      /* 0Ch */
+    U8                      LUN[8];                         /* 10h */
+    U32                     RelativeOffset;                 /* 18h */
+    U32                     Reserved2;                      /* 1Ch */
+    U32                     Reserved3;                      /* 20h */
+    U32                     PrimaryReferenceTag;            /* 24h */
+    U16                     PrimaryApplicationTag;          /* 28h */
+    U16                     PrimaryApplicationTagMask;      /* 2Ah */
+    U32                     Reserved4;                      /* 2Ch */
+    U32                     DataLength;                     /* 30h */
+    U32                     BidirectionalDataLength;        /* 34h */
+    U32                     SecondaryReferenceTag;          /* 38h */
+    U16                     SecondaryApplicationTag;        /* 3Ch */
+    U16                     Reserved5;                      /* 3Eh */
+    U16                     EEDPFlags;                      /* 40h */
+    U16                     ApplicationTagTranslationMask;  /* 42h */
+    U32                     EEDPBlockSize;                  /* 44h */
+    U8                      SGLOffset0;                     /* 48h */
+    U8                      SGLOffset1;                     /* 49h */
+    U8                      SGLOffset2;                     /* 4Ah */
+    U8                      SGLOffset3;                     /* 4Bh */
+    U32                     Reserved6;                      /* 4Ch */
+    SGE_IO_UNION            SGL[1];                         /* 50h */
+} MSG_TARGET_ASSIST_EXT_REQUEST, MPI_POINTER PTR_MSG_TARGET_ASSIST_EXT_REQUEST,
+  TargetAssistExtRequest_t, MPI_POINTER pTargetAssistExtRequest_t;
+
+/* see the defines after MSG_TARGET_ASSIST_REQUEST for TargetAssistFlags */
+
+/* defines for the MsgFlags field */
+#define TARGET_ASSIST_EXT_MSGFLAGS_BIDIRECTIONAL        (0x20)
+#define TARGET_ASSIST_EXT_MSGFLAGS_MULTICAST            (0x10)
+#define TARGET_ASSIST_EXT_MSGFLAGS_SGL_OFFSET_CHAINS    (0x08)
+
+/* defines for the EEDPFlags field */
+#define TARGET_ASSIST_EXT_EEDP_MASK_OP          (0x0007)
+#define TARGET_ASSIST_EXT_EEDP_NOOP_OP          (0x0000)
+#define TARGET_ASSIST_EXT_EEDP_CHK_OP           (0x0001)
+#define TARGET_ASSIST_EXT_EEDP_STRIP_OP         (0x0002)
+#define TARGET_ASSIST_EXT_EEDP_CHKRM_OP         (0x0003)
+#define TARGET_ASSIST_EXT_EEDP_INSERT_OP        (0x0004)
+#define TARGET_ASSIST_EXT_EEDP_REPLACE_OP       (0x0006)
+#define TARGET_ASSIST_EXT_EEDP_CHKREGEN_OP      (0x0007)
+
+#define TARGET_ASSIST_EXT_EEDP_PASS_REF_TAG     (0x0008)
+
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_MASK     (0x0700)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_GUARD    (0x0100)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_APPTAG   (0x0200)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_REFTAG   (0x0400)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_SHIFT    (8)
+
+#define TARGET_ASSIST_EXT_EEDP_INC_SEC_APPTAG   (0x1000)
+#define TARGET_ASSIST_EXT_EEDP_INC_PRI_APPTAG   (0x2000)
+#define TARGET_ASSIST_EXT_EEDP_INC_SEC_REFTAG   (0x4000)
+#define TARGET_ASSIST_EXT_EEDP_INC_PRI_REFTAG   (0x8000)
+
+
+/****************************************************************************/
 /* Target Status Send Request                                               */
 /****************************************************************************/
 
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -218,8 +218,7 @@ pci_enable_io_access(struct pci_dev *pde
  *	(also referred to as a IO Controller or IOC).
  *	This routine must clear the interrupt from the adapter and does
  *	so by reading the reply FIFO.  Multiple replies may be processed
- *	per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
- *	which is currently set to 32 in mptbase.h.
+ *	per single call to this routine.
  *
  *	This routine handles register-level access of the adapter but
  *	dispatches (calls) a protocol-specific callback routine to handle
@@ -279,11 +278,11 @@ mpt_interrupt(int irq, void *bus_id, str
 			cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
 			mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 
-			dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n",
-					ioc->name, mr, req_idx));
+			dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
+					ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
 			DBG_DUMP_REPLY_FRAME(mr)
 
-			/*  Check/log IOC log info
+			 /*  Check/log IOC log info
 			 */
 			ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
 			if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
@@ -345,7 +344,7 @@ mpt_interrupt(int irq, void *bus_id, str
 			if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
 				|| (mf < ioc->req_frames)) ) {
 				printk(MYIOC_s_WARN_FMT
-					"mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
+					"mpt_interrupt: Invalid mf (%p)!\n", ioc->name, (void *)mf);
 				cb_idx = 0;
 				pa = 0;
 				freeme = 0;
@@ -399,7 +398,7 @@ mpt_interrupt(int irq, void *bus_id, str
  *	@mf: Pointer to original MPT request frame
  *	@reply: Pointer to MPT reply frame (NULL if TurboReply)
  *
-	*	Returns 1 indicating original alloc'd request frame ptr
+ *	Returns 1 indicating original alloc'd request frame ptr
  *	should be freed, or 0 if it shouldn't.
  */
 static int
@@ -408,28 +407,17 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
 	int freereq = 1;
 	u8 func;
 
-	dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
-
-	if ((mf == NULL) ||
-	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
-		printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
-				ioc->name, (void *)mf);
-		return 1;
-	}
-
-	if (reply == NULL) {
-		dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
-				ioc->name));
-		return 1;
-	}
+	dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
 
+#if defined(MPT_DEBUG_MSG_FRAME)
 	if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
 		dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
 		DBG_DUMP_REQUEST_FRAME_HDR(mf)
 	}
+#endif
 
 	func = reply->u.hdr.Function;
-	dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
+	dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
 			ioc->name, func));
 
 	if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
@@ -448,8 +436,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
 		 *	Hmmm...  It seems that EventNotificationReply is an exception
 		 *	to the rule of one reply per request.
 		 */
-		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
+		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
 			freereq = 0;
+			devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
+				ioc->name, pEvReply));
+		} else {
+			devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
+				ioc->name, pEvReply));
+		}
 
 #ifdef CONFIG_PROC_FS
 //		LogEvent(ioc, pEvReply);
@@ -491,10 +485,21 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
 
 				pCfg->status = status;
 				if (status == MPI_IOCSTATUS_SUCCESS) {
-					pCfg->hdr->PageVersion = pReply->Header.PageVersion;
-					pCfg->hdr->PageLength = pReply->Header.PageLength;
-					pCfg->hdr->PageNumber = pReply->Header.PageNumber;
-					pCfg->hdr->PageType = pReply->Header.PageType;
+					if ((pReply->Header.PageType &
+					    MPI_CONFIG_PAGETYPE_MASK) ==
+					    MPI_CONFIG_PAGETYPE_EXTENDED) {
+						pCfg->cfghdr.ehdr->ExtPageLength =
+						    le16_to_cpu(pReply->ExtPageLength);
+						pCfg->cfghdr.ehdr->ExtPageType =
+						    pReply->ExtPageType;
+					}
+					pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
+
+					/* If this is a regular header, save PageLength. */
+					/* LMP Do this better so not using a reserved field! */
+					pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
+					pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
+					pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
 				}
 			}
 
@@ -705,7 +710,7 @@ mpt_device_driver_deregister(int cb_idx)
 		if (dd_cbfunc->remove)
 			dd_cbfunc->remove(ioc->pcidev);
 	}
-	
+
 	MptDeviceDriverHandlers[cb_idx] = NULL;
 }
 
@@ -818,7 +823,7 @@ mpt_put_msg_frame(int handle, MPT_ADAPTE
 	}
 #endif
 
-	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];  
+	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
 	dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
 	CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
 }
@@ -920,7 +925,7 @@ mpt_send_handshake_request(int handle, M
 
 	/* Make sure there are no doorbells */
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-	
+
 	CHIPREG_WRITE32(&ioc->chip->Doorbell,
 			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
 			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
@@ -935,14 +940,14 @@ mpt_send_handshake_request(int handle, M
 		return -5;
 
 	dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
-			ioc->name, ii));
+		ioc->name, ii));
 
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
 	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
 		return -2;
 	}
-		
+
 	/* Send request via doorbell handshake */
 	req_as_bytes = (u8 *) req;
 	for (ii = 0; ii < reqBytes/4; ii++) {
@@ -988,9 +993,9 @@ mpt_verify_adapter(int iocid, MPT_ADAPTE
 		if (ioc->id == iocid) {
 			*iocpp =ioc;
 			return iocid;
-		} 
+		}
 	}
-	
+
 	*iocpp = NULL;
 	return -1;
 }
@@ -1032,9 +1037,9 @@ mpt_attach(struct pci_dev *pdev, const s
 
 	if (pci_enable_device(pdev))
 		return r;
-	
+
 	dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
-	
+
 	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
 		dprintk((KERN_INFO MYNAM
 			": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
@@ -1059,7 +1064,7 @@ mpt_attach(struct pci_dev *pdev, const s
 	ioc->alloc_total = sizeof(MPT_ADAPTER);
 	ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;		/* avoid div by zero! */
 	ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
-	
+
 	ioc->pcidev = pdev;
 	ioc->diagPending = 0;
 	spin_lock_init(&ioc->diagLock);
@@ -1088,7 +1093,7 @@ mpt_attach(struct pci_dev *pdev, const s
 	/* Find lookup slot. */
 	INIT_LIST_HEAD(&ioc->list);
 	ioc->id = mpt_ids++;
-	
+
 	mem_phys = msize = 0;
 	port = psize = 0;
 	for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
@@ -1143,7 +1148,7 @@ mpt_attach(struct pci_dev *pdev, const s
 		ioc->prod_name = "LSIFC909";
 		ioc->bus_type = FC;
 	}
-	if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
 		ioc->prod_name = "LSIFC929";
 		ioc->bus_type = FC;
 	}
@@ -1322,7 +1327,7 @@ mpt_detach(struct pci_dev *pdev)
 	remove_proc_entry(pname, NULL);
 	sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
 	remove_proc_entry(pname, NULL);
-	
+
 	/* call per device driver remove entry point */
 	for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
 		if(MptDeviceDriverHandlers[ii] &&
@@ -1330,7 +1335,7 @@ mpt_detach(struct pci_dev *pdev)
 			MptDeviceDriverHandlers[ii]->remove(pdev);
 		}
 	}
-	
+
 	/* Disable interrupts! */
 	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
 
@@ -1403,7 +1408,7 @@ mpt_resume(struct pci_dev *pdev)
 	u32 device_state = pdev->current_state;
 	int recovery_state;
 	int ii;
-	
+
 	printk(MYIOC_s_INFO_FMT
 	"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
 		ioc->name, pdev, pci_name(pdev), device_state);
@@ -1534,7 +1539,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 		if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
 			break;
 	}
-	
+
 
 	if (ii == 5) {
 		dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
@@ -1542,7 +1547,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 	} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 		MptDisplayIocCapabilities(ioc);
 	}
-	
+
 	if (alt_ioc_ready) {
 		if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
 			dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
@@ -1613,7 +1618,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 
 	if (reset_alt_ioc_active && ioc->alt_ioc) {
 		/* (re)Enable alt-IOC! (reply interrupt) */
-		dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
+		dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
 				ioc->alt_ioc->name));
 		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
 		ioc->alt_ioc->active = 1;
@@ -1670,7 +1675,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 
 			/* Find IM volumes
 			 */
-			if (ioc->facts.MsgVersion >= 0x0102)
+			if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
 				mpt_findImVolumes(ioc);
 
 			/* Check, and possibly reset, the coalescing value
@@ -1700,7 +1705,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 			}
 
 			if (alt_ioc_ready && MptResetHandlers[ii]) {
-				dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
+				drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
 						ioc->name, ioc->alt_ioc->name, ii));
 				rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
 				handlers++;
@@ -1733,8 +1738,8 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc,
 
 	dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
 	    " searching for devfn match on %x or %x\n",
-		ioc->name, pci_name(pdev), pdev->devfn,
-		func-1, func+1));
+		ioc->name, pci_name(pdev), pdev->bus->number,
+		pdev->devfn, func-1, func+1));
 
 	peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
 	if (!peer) {
@@ -1861,36 +1866,39 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 static void
 mpt_adapter_dispose(MPT_ADAPTER *ioc)
 {
-	if (ioc != NULL) {
-		int sz_first, sz_last;
+	int sz_first, sz_last;
 
-		sz_first = ioc->alloc_total;
+	if (ioc == NULL)
+		return;
 
-		mpt_adapter_disable(ioc);
+	sz_first = ioc->alloc_total;
 
-		if (ioc->pci_irq != -1) {
-			free_irq(ioc->pci_irq, ioc);
-			ioc->pci_irq = -1;
-		}
+	mpt_adapter_disable(ioc);
+
+	if (ioc->pci_irq != -1) {
+		free_irq(ioc->pci_irq, ioc);
+		ioc->pci_irq = -1;
+	}
 
-		if (ioc->memmap != NULL)
-			iounmap(ioc->memmap);
+	if (ioc->memmap != NULL) {
+		iounmap(ioc->memmap);
+		ioc->memmap = NULL;
+	}
 
 #if defined(CONFIG_MTRR) && 0
-		if (ioc->mtrr_reg > 0) {
-			mtrr_del(ioc->mtrr_reg, 0, 0);
-			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
-		}
+	if (ioc->mtrr_reg > 0) {
+		mtrr_del(ioc->mtrr_reg, 0, 0);
+		dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
+	}
 #endif
 
-		/*  Zap the adapter lookup ptr!  */
-		list_del(&ioc->list);
+	/*  Zap the adapter lookup ptr!  */
+	list_del(&ioc->list);
 
-		sz_last = ioc->alloc_total;
-		dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
-				ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
-		kfree(ioc);
-	}
+	sz_last = ioc->alloc_total;
+	dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+			ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+	kfree(ioc);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1977,7 +1985,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
 	}
 
 	/* Is it already READY? */
-	if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) 
+	if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
 		return 0;
 
 	/*
@@ -1995,7 +2003,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
 	 *	Hmmm...  Did it get left operational?
 	 */
 	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
-		dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
+		dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
 				ioc->name));
 
 		/* Check WhoInit.
@@ -2004,8 +2012,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
 		 * Else, fall through to KickStart case
 		 */
 		whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
-		dprintk((KERN_WARNING MYNAM
-			": whoinit 0x%x\n statefault %d force %d\n",
+		dinitprintk((KERN_INFO MYNAM
+			": whoinit 0x%x statefault %d force %d\n",
 			whoinit, statefault, force));
 		if (whoinit == MPI_WHOINIT_PCI_PEER)
 			return -4;
@@ -2140,8 +2148,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
 	get_facts.Function = MPI_FUNCTION_IOC_FACTS;
 	/* Assert: All other get_facts fields are zero! */
 
-	dinitprintk((MYIOC_s_INFO_FMT 
-	    "Sending get IocFacts request req_sz=%d reply_sz=%d\n", 
+	dinitprintk((MYIOC_s_INFO_FMT
+	    "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
 	    ioc->name, req_sz, reply_sz));
 
 	/* No non-zero fields in the get_facts request are greater than
@@ -2174,7 +2182,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
 		facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
 		facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
 		facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
-		status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
+		status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
 		/* CHECKME! IOCStatus, IOCLogInfo */
 
 		facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
@@ -2221,7 +2229,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
 		if ( sz & 0x02 )
 			sz += 2;
 		facts->FWImageSize = sz;
-		
+
 		if (!facts->RequestFrameSize) {
 			/*  Something is wrong!  */
 			printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
@@ -2240,7 +2248,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
 		ioc->NBShiftFactor  = shiftFactor;
 		dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
 					ioc->name, vv, shiftFactor, r));
-    
+
 		if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 			/*
 			 * Set values for this IOC's request & reply frame sizes,
@@ -2261,7 +2269,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
 				return r;
 		}
 	} else {
-		printk(MYIOC_s_ERR_FMT 
+		printk(MYIOC_s_ERR_FMT
 		     "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
 		     ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
 		     RequestFrameSize)/sizeof(u32)));
@@ -2413,9 +2421,11 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
 
 	dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
 			ioc->name, &ioc_init));
-	
-	if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
+
+	if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
+		printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
 		return r;
+	}
 
 	/* YIKES!  SUPER IMPORTANT!!!
 	 *  Poll IocState until _OPERATIONAL while IOC is doing
@@ -2440,7 +2450,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
 		state = mpt_GetIocState(ioc, 1);
 		count++;
 	}
-	dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+	dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
 			ioc->name, count));
 
 	return r;
@@ -2529,7 +2539,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
 	int sz;
 
 	sz = ioc->facts.FWImageSize;
-	dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+	dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
 		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
 	pci_free_consistent(ioc->pcidev, sz,
 			ioc->cached_fw, ioc->cached_fw_dma);
@@ -2573,9 +2583,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 
 	mpt_alloc_fw_memory(ioc, sz);
 
-	dinitprintk((KERN_WARNING MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+	dinitprintk((KERN_INFO MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
 		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
-	
+
 	if (ioc->cached_fw == NULL) {
 		/* Major Failure.
 		 */
@@ -2605,14 +2615,14 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 	mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
 
 	sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-	dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n",
+	dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
 			prequest, sgeoffset));
 	DBG_DUMP_FW_REQUEST_FRAME(prequest)
 
 	ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
 				reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
 
-	dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii));
+	dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
 
 	cmdStatus = -EFAULT;
 	if (ii == 0) {
@@ -2627,10 +2637,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 				cmdStatus = 0;
 		}
 	}
-	dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
+	dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
 			ioc->name, cmdStatus));
 
-	
+
 	if (cmdStatus) {
 
 		ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
@@ -2761,8 +2771,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int s
 		fwSize = (pExtImage->ImageSize + 3) >> 2;
 		ptrFw = (u32 *)pExtImage;
 
-		ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n",
-						ioc->name, fwSize*4, ptrFw, load_addr));
+		ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
+						ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
 
 		while (fwSize--) {
@@ -2845,9 +2855,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int s
  *			  0 else
  *
  *	Returns:
- *		 1 - hard reset, READY	
- *		 0 - no reset due to History bit, READY	
- *		-1 - no reset due to History bit but not READY	
+ *		 1 - hard reset, READY
+ *		 0 - no reset due to History bit, READY
+ *		-1 - no reset due to History bit but not READY
  *		     OR reset but failed to come READY
  *		-2 - no reset, could not enter DIAG mode
  *		-3 - reset but bad FW bit
@@ -2990,7 +3000,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
 		 *
 		 */
 		CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
-		mdelay (1);
+		mdelay(1);
 
 		/*
 		 * Now hit the reset bit in the Diagnostic register
@@ -3170,7 +3180,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_
 	u32 state;
 	int cntdn, count;
 
-	drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
+	drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
 			ioc->name, reset_type));
 	CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
 	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
@@ -3374,6 +3384,9 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
 		ioc->reply_frames = (MPT_FRAME_HDR *) mem;
 		ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
 
+		dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
+	 		ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
+
 		alloc_dma += reply_sz;
 		mem += reply_sz;
 
@@ -3382,7 +3395,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
 		ioc->req_frames = (MPT_FRAME_HDR *) mem;
 		ioc->req_frames_dma = alloc_dma;
 
-		dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n",
+		dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
 			 	ioc->name, mem, (void *)(ulong)alloc_dma));
 
 		ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
@@ -3408,7 +3421,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
 		ioc->ChainBuffer = mem;
 		ioc->ChainBufferDMA = alloc_dma;
 
-		dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n",
+		dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
 			ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
 
 		/* Initialize the free chain Q.
@@ -3513,7 +3526,7 @@ out_fail:
  */
 static int
 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
-				int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
+		int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
 {
 	MPIDefaultReply_t *mptReply;
 	int failcnt = 0;
@@ -3588,7 +3601,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER
 		 */
 		if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
 			failcnt++;
-		
+
 		dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
 				ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
 
@@ -3747,7 +3760,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
 	}
 
 	dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
-			ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), 
+			ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
 			failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
 	/*
@@ -3819,7 +3832,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
 	hdr.PageLength = 0;
 	hdr.PageNumber = 0;
 	hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
-	cfg.hdr = &hdr;
+	cfg.cfghdr.hdr = &hdr;
 	cfg.physAddr = -1;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
 	cfg.dir = 0;
@@ -3863,7 +3876,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
 	hdr.PageLength = 0;
 	hdr.PageNumber = 1;
 	hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
-	cfg.hdr = &hdr;
+	cfg.cfghdr.hdr = &hdr;
 	cfg.physAddr = -1;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
 	cfg.dir = 0;
@@ -3930,7 +3943,7 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int por
 	hdr.PageLength = 0;
 	hdr.PageNumber = 0;
 	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
-	cfg.hdr = &hdr;
+	cfg.cfghdr.hdr = &hdr;
 	cfg.physAddr = -1;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
 	cfg.dir = 0;
@@ -4012,7 +4025,7 @@ GetIoUnitPage2(MPT_ADAPTER *ioc)
 	hdr.PageLength = 0;
 	hdr.PageNumber = 2;
 	hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
-	cfg.hdr = &hdr;
+	cfg.cfghdr.hdr = &hdr;
 	cfg.physAddr = -1;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
 	cfg.dir = 0;
@@ -4102,7 +4115,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
 	header.PageLength = 0;
 	header.PageNumber = 0;
 	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
-	cfg.hdr = &header;
+	cfg.cfghdr.hdr = &header;
 	cfg.physAddr = -1;
 	cfg.pageAddr = portnum;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4122,6 +4135,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
 				ioc->spi_data.minSyncFactor = MPT_ASYNC;
 				ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
 				rc = 1;
+				ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
+					ioc->name, ioc->spi_data.minSyncFactor));
 			} else {
 				/* Save the Port Page 0 data
 				 */
@@ -4131,7 +4146,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
 
 				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
 					ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
-					dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+					ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
 						ioc->name, pPP0->Capabilities));
 				}
 				ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
@@ -4140,6 +4155,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
 					ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
 					data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
 					ioc->spi_data.minSyncFactor = (u8) (data >> 8);
+					ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
+						ioc->name, ioc->spi_data.minSyncFactor));
 				} else {
 					ioc->spi_data.maxSyncOffset = 0;
 					ioc->spi_data.minSyncFactor = MPT_ASYNC;
@@ -4152,8 +4169,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
 				if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
 					(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE))  {
 
-				if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
+					if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
 						ioc->spi_data.minSyncFactor = MPT_ULTRA;
+						ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
+							ioc->name, ioc->spi_data.minSyncFactor));
+					}
 				}
 			}
 			if (pbuf) {
@@ -4168,7 +4188,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
 	header.PageLength = 0;
 	header.PageNumber = 2;
 	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
-	cfg.hdr = &header;
+	cfg.cfghdr.hdr = &header;
 	cfg.physAddr = -1;
 	cfg.pageAddr = portnum;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4236,7 +4256,7 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
 	header.PageLength = 0;
 	header.PageNumber = 1;
 	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-	cfg.hdr = &header;
+	cfg.cfghdr.hdr = &header;
 	cfg.physAddr = -1;
 	cfg.pageAddr = portnum;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4245,8 +4265,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
 	if (mpt_config(ioc, &cfg) != 0)
 		 return -EFAULT;
 
-	ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
-	ioc->spi_data.sdp1length = cfg.hdr->PageLength;
+	ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
+	ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
 
 	header.PageVersion = 0;
 	header.PageLength = 0;
@@ -4255,8 +4275,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
 	if (mpt_config(ioc, &cfg) != 0)
 		 return -EFAULT;
 
-	ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
-	ioc->spi_data.sdp0length = cfg.hdr->PageLength;
+	ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
+	ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
 
 	dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
 			ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
@@ -4298,7 +4318,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
 	header.PageLength = 0;
 	header.PageNumber = 2;
 	header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-	cfg.hdr = &header;
+	cfg.cfghdr.hdr = &header;
 	cfg.physAddr = -1;
 	cfg.pageAddr = 0;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4394,7 +4414,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
 	header.PageLength = 0;
 	header.PageNumber = 3;
 	header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-	cfg.hdr = &header;
+	cfg.cfghdr.hdr = &header;
 	cfg.physAddr = -1;
 	cfg.pageAddr = 0;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4446,7 +4466,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
 	header.PageLength = 0;
 	header.PageNumber = 4;
 	header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-	cfg.hdr = &header;
+	cfg.cfghdr.hdr = &header;
 	cfg.physAddr = -1;
 	cfg.pageAddr = 0;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4498,7 +4518,7 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
 	header.PageLength = 0;
 	header.PageNumber = 1;
 	header.PageType = MPI_CONFIG_PAGETYPE_IOC;
-	cfg.hdr = &header;
+	cfg.cfghdr.hdr = &header;
 	cfg.physAddr = -1;
 	cfg.pageAddr = 0;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4580,13 +4600,13 @@ SendEventNotification(MPT_ADAPTER *ioc, 
 
 	evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
 	if (evnp == NULL) {
-		dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
+		devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
 				ioc->name));
 		return 0;
 	}
 	memset(evnp, 0, sizeof(*evnp));
 
-	dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
+	devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
 
 	evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
 	evnp->ChainOffset = 0;
@@ -4610,8 +4630,10 @@ SendEventAck(MPT_ADAPTER *ioc, EventNoti
 	EventAck_t	*pAck;
 
 	if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
-		printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
-				ioc->name);
+		printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
+			"request frame for Event=%x EventContext=%x EventData=%x!\n",
+			ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
+			le32_to_cpu(evnp->Data[0]));
 		return -1;
 	}
 	memset(pAck, 0, sizeof(*pAck));
@@ -4647,10 +4669,11 @@ int
 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
 {
 	Config_t	*pReq;
+	ConfigExtendedPageHeader_t  *pExtHdr = NULL;
 	MPT_FRAME_HDR	*mf;
 	unsigned long	 flags;
 	int		 ii, rc;
-	u32		 flagsLength;
+	int		 flagsLength;
 	int		 in_isr;
 
 	/*	Prevent calling wait_event() (below), if caller happens
@@ -4675,16 +4698,30 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
 	pReq->Reserved = 0;
 	pReq->ChainOffset = 0;
 	pReq->Function = MPI_FUNCTION_CONFIG;
+
+	/* Assume page type is not extended and clear "reserved" fields. */
 	pReq->ExtPageLength = 0;
 	pReq->ExtPageType = 0;
 	pReq->MsgFlags = 0;
+
 	for (ii=0; ii < 8; ii++)
 		pReq->Reserved2[ii] = 0;
 
-	pReq->Header.PageVersion = pCfg->hdr->PageVersion;
-	pReq->Header.PageLength = pCfg->hdr->PageLength;
-	pReq->Header.PageNumber = pCfg->hdr->PageNumber;
-	pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+	pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
+	pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
+	pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
+	pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+
+	if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+		pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
+		pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
+		pReq->ExtPageType = pExtHdr->ExtPageType;
+		pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+
+		/* Page Length must be treated as a reserved field for the extended header. */
+		pReq->Header.PageLength = 0;
+	}
+
 	pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
 
 	/* Add a SGE to the config request.
@@ -4694,12 +4731,20 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
 	else
 		flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
 
-	flagsLength |= pCfg->hdr->PageLength * 4;
+	if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+		flagsLength |= pExtHdr->ExtPageLength * 4;
 
-	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
+		dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+			ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
+	}
+	else {
+		flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
+
+		dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+			ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+	}
 
-	dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
-		ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
 
 	/* Append pCfg pointer to end of mf
 	 */
@@ -4789,8 +4834,8 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARM
 	pReq->Reserved3 = 0;
 	pReq->NumAddressBytes = 0x01;
 	pReq->Reserved4 = 0;
-	pReq->DataLength = 0x04;
-	pdev = (struct pci_dev *) ioc->pcidev;
+	pReq->DataLength = cpu_to_le16(0x04);
+	pdev = ioc->pcidev;
 	if (pdev->devfn & 1)
 		pReq->DeviceAddr = 0xB2;
 	else
@@ -5504,6 +5549,8 @@ ProcessEventNotification(MPT_ADAPTER *io
 	 *  If needed, send (a single) EventAck.
 	 */
 	if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
+		devtprintk((MYIOC_s_WARN_FMT
+			"EventAck required\n",ioc->name));
 		if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
 			devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
 					ioc->name, ii));
@@ -5584,7 +5631,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 lo
 	case 0x00080000:
 		desc = "Outbound DMA Overrun";
 		break;
-	
+
 	case 0x00090000:
 		desc = "Task Management";
 		break;
@@ -5600,7 +5647,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 lo
 	case 0x000C0000:
 		desc = "Untagged Table Size";
 		break;
-	
+
 	}
 
 	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
@@ -5692,7 +5739,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io
 		break;
 
 	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
-		/* This error is checked in scsi_io_done(). Skip. 
+		/* This error is checked in scsi_io_done(). Skip.
 		desc = "SCSI Data Underrun";
 		*/
 		break;
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -915,7 +915,10 @@ struct scsi_cmnd;
 typedef struct _x_config_parms {
 	struct list_head	 linkage;	/* linked list */
 	struct timer_list	 timer;		/* timer function for this request  */
-	ConfigPageHeader_t	*hdr;
+	union {
+		ConfigExtendedPageHeader_t	*ehdr;
+		ConfigPageHeader_t	*hdr;
+	} cfghdr;
 	dma_addr_t		 physAddr;
 	int			 wait_done;	/* wait for this request */
 	u32			 pageAddr;	/* properly formatted */
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -242,7 +242,7 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME
 		/* Set the command status to GOOD if IOC Status is GOOD
 		 * OR if SCSI I/O cmd and data underrun or recovered error.
 		 */
-		iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
+		iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
 		if (iocStatus  == MPI_IOCSTATUS_SUCCESS)
 			ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
 
@@ -2324,7 +2324,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
 	hdr.PageLength = 0;
 	hdr.PageNumber = 0;
 	hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
-	cfg.hdr = &hdr;
+	cfg.cfghdr.hdr = &hdr;
 	cfg.physAddr = -1;
 	cfg.pageAddr = 0;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -2333,7 +2333,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
 
 	strncpy(karg.serial_number, " ", 24);
 	if (mpt_config(ioc, &cfg) == 0) {
-		if (cfg.hdr->PageLength > 0) {
+		if (cfg.cfghdr.hdr->PageLength > 0) {
 			/* Issue the second config page request */
 			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 
@@ -2479,7 +2479,7 @@ mptctl_hp_targetinfo(unsigned long arg)
 		hdr.PageNumber = 0;
 		hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
 
-		cfg.hdr = &hdr;
+		cfg.cfghdr.hdr = &hdr;
 		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 		cfg.dir = 0;
 		cfg.timeout = 0;
@@ -2527,15 +2527,15 @@ mptctl_hp_targetinfo(unsigned long arg)
 	hdr.PageNumber = 3;
 	hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
 
-	cfg.hdr = &hdr;
+	cfg.cfghdr.hdr = &hdr;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
 	cfg.dir = 0;
 	cfg.timeout = 0;
 	cfg.physAddr = -1;
-	if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) {
+	if ((mpt_config(ioc, &cfg) == 0) && (cfg.cfghdr.hdr->PageLength > 0)) {
 		/* Issue the second config page request */
 		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-		data_sz = (int) cfg.hdr->PageLength * 4;
+		data_sz = (int) cfg.cfghdr.hdr->PageLength * 4;
 		pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent(
 							ioc->pcidev, data_sz, &page_dma);
 		if (pg3_alloc) {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -281,12 +281,12 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER 
 		offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
 		chain_idx = offset / ioc->req_sz;
 		rc = SUCCESS;
-		dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
-			ioc->name, *retIndex, chainBuf));
+		dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
+			ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
 	} else {
 		rc = FAILED;
 		chain_idx = MPT_HOST_NO_CHAIN;
-		dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
+		dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
 			ioc->name));
 	}
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
@@ -432,7 +432,7 @@ nextSGEset:
 			 */
 			pReq->ChainOffset = 0;
 			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
-			dsgprintk((MYIOC_s_ERR_FMT 
+			dsgprintk((MYIOC_s_INFO_FMT
 			    "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
 			ioc->RequestNB[req_idx] = RequestNB;
 		}
@@ -491,11 +491,12 @@ nextSGEset:
 		/* NOTE: psge points to the beginning of the chain element
 		 * in current buffer. Get a chain buffer.
 		 */
-		dsgprintk((MYIOC_s_INFO_FMT 
-		    "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
-		    ioc->name, pReq->CDB[0], SCpnt));
-		if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)
+		if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
+			dfailprintk((MYIOC_s_INFO_FMT
+			    "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
+ 			    ioc->name, pReq->CDB[0], SCpnt));
 			return FAILED;
+		}
 
 		/* Update the tracking arrays.
 		 * If chainSge == NULL, update ReqToChain, else ChainToChain
@@ -577,14 +578,20 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 		return 1;
 	}
 
-	dmfprintk((MYIOC_s_INFO_FMT
-		"ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
-		ioc->name, mf, mr, sc, req_idx));
-
 	sc->result = DID_OK << 16;		/* Set default reply as OK */
 	pScsiReq = (SCSIIORequest_t *) mf;
 	pScsiReply = (SCSIIOReply_t *) mr;
 
+	if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
+		dmfprintk((MYIOC_s_INFO_FMT
+			"ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
+			ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
+	}else{
+		dmfprintk((MYIOC_s_INFO_FMT
+			"ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
+			ioc->name, mf, mr, sc, req_idx));
+	}
+
 	if (pScsiReply == NULL) {
 		/* special context reply handling */
 		;
@@ -658,8 +665,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 				/* Sufficient data transfer occurred */
 				sc->result = (DID_OK << 16) | scsi_status;
 			} else if ( xfer_cnt == 0 ) {
-				/* A CRC Error causes this condition; retry */ 
-				sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | 
+				/* A CRC Error causes this condition; retry */
+				sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
 					(CHECK_CONDITION << 1);
 				sc->sense_buffer[0] = 0x70;
 				sc->sense_buffer[2] = NO_SENSE;
@@ -668,7 +675,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 			} else {
 				sc->result = DID_SOFT_ERROR << 16;
 			}
-			dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+			dreplyprintk((KERN_NOTICE
+			    "RESIDUAL_MISMATCH: result=%x on id=%d\n",
+			    sc->result, sc->device->id));
 			break;
 
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
@@ -796,7 +805,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 	return 1;
 }
 
-
 /*
  *	mptscsih_flush_running_cmds - For each command found, search
  *		Scsi_Host instance taskQ and reply to OS.
@@ -1017,7 +1025,7 @@ mptscsih_remove(struct pci_dev *pdev)
 	scsi_host_put(host);
 
 	mpt_detach(pdev);
-	
+
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1072,7 +1080,7 @@ mptscsih_resume(struct pci_dev *pdev)
 	MPT_SCSI_HOST		*hd;
 
 	mpt_resume(pdev);
-	
+
 	if(!host)
 		return 0;
 
@@ -1214,8 +1222,8 @@ mptscsih_proc_info(struct Scsi_Host *hos
 	int size = 0;
 
 	if (func) {
-		/* 
-		 * write is not supported 
+		/*
+		 * write is not supported
 		 */
 	} else {
 		if (start)
@@ -1535,17 +1543,17 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
 	 */
 	if (mptscsih_tm_pending_wait(hd) == FAILED) {
 		if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
-			dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
+			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
 			   "Timed out waiting for last TM (%d) to complete! \n",
 			   hd->ioc->name, hd->tmPending));
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
-			dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
+			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
 			   "Timed out waiting for last TM (%d) to complete! \n",
 			   hd->ioc->name, hd->tmPending));
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
-			dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
+			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
 			   "Timed out waiting for last TM (%d) to complete! \n",
 			   hd->ioc->name, hd->tmPending));
 			if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
@@ -1631,8 +1639,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd
 	if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
 		dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
 				hd->ioc->name));
-		//return FAILED;
-		return -999;
+		return FAILED;
 	}
 	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
 			hd->ioc->name, mf));
@@ -1661,9 +1668,8 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd
 
 	pScsiTm->TaskMsgContext = ctx2abort;
 
-	dtmprintk((MYIOC_s_INFO_FMT
-		"IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
-		hd->ioc->name, ctx2abort, type));
+	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+			hd->ioc->name, ctx2abort, type));
 
 	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
 
@@ -1902,13 +1908,13 @@ mptscsih_host_reset(struct scsi_cmnd *SC
 
 	/*  If we can't locate the host to reset, then we failed. */
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-		dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+		dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
 			     "Can't locate host! (sc=%p)\n",
 			     SCpnt ) );
 		return FAILED;
 	}
 
-	printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
+	printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
 	       hd->ioc->name, SCpnt);
 
 	/*  If our attempts to reset the host failed, then return a failed
@@ -1924,7 +1930,7 @@ mptscsih_host_reset(struct scsi_cmnd *SC
 		hd->tmState = TM_STATE_NONE;
 	}
 
-	dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+	dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
 		     "Status = %s\n",
 		     (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
 
@@ -1951,8 +1957,8 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST *
 		if (hd->tmState == TM_STATE_NONE) {
 			hd->tmState = TM_STATE_IN_PROGRESS;
 			hd->tmPending = 1;
-			status = SUCCESS;
 			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+			status = SUCCESS;
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -1980,7 +1986,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI
 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
 		if(hd->tmPending == 0) {
 			status = SUCCESS;
-			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ 			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -2318,10 +2324,10 @@ mptscsih_slave_configure(struct scsi_dev
 	if (pTarget == NULL) {
 		/* Driver doesn't know about this device.
 		 * Kernel may generate a "Dummy Lun 0" which
-		 * may become a real Lun if a 
+		 * may become a real Lun if a
 		 * "scsi add-single-device" command is executed
-		 * while the driver is active (hot-plug a 
-		 * device).  LSI Raid controllers need 
+		 * while the driver is active (hot-plug a
+		 * device).  LSI Raid controllers need
 		 * queue_depth set to DEV_HIGH for this reason.
 		 */
 		scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
@@ -2691,7 +2697,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
 	 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
 	 * (i.e. The targer is capable of supporting the specified peripheral device type
 	 * on this logical unit; however, the physical device is not currently connected
-	 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not 
+	 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
 	 * capable of supporting a physical device on this logical unit). This is to work
 	 * around a bug in th emid-layer in some distributions in which the mid-layer will
 	 * continue to try to communicate to the LUN and evntually create a dummy LUN.
@@ -3194,8 +3200,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, in
 		/* Get a MF for this command.
 		 */
 		if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
-			dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
-						ioc->name));
+			dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
+				ioc->name));
 			return -EAGAIN;
 		}
 
@@ -3289,7 +3295,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd
 	/* Get a MF for this command.
 	 */
 	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
-		dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+		dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
 					ioc->name));
 		return -EAGAIN;
 	}
@@ -3447,7 +3453,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
 				 * some type of error occurred.
 				 */
 				MpiRaidActionReply_t	*pr = (MpiRaidActionReply_t *)mr;
-				if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
+				if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
 					completionCode = MPT_SCANDV_GOOD;
 				else
 					completionCode = MPT_SCANDV_SOME_ERROR;
@@ -3955,7 +3961,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
 				header1.PageLength = ioc->spi_data.sdp1length;
 				header1.PageNumber = 1;
 				header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-				cfg.hdr = &header1;
+				cfg.cfghdr.hdr = &header1;
 				cfg.physAddr = cfg1_dma_addr;
 				cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 				cfg.dir = 1;
@@ -3996,9 +4002,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
 			dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
 				"offset=0 negoFlags=%x request=%x config=%x\n",
 				id, flags, requested, configuration));
-			pcfg1Data->RequestedParameters = le32_to_cpu(requested);
+			pcfg1Data->RequestedParameters = cpu_to_le32(requested);
 			pcfg1Data->Reserved = 0;
-			pcfg1Data->Configuration = le32_to_cpu(configuration);
+			pcfg1Data->Configuration = cpu_to_le32(configuration);
 			cfg.pageAddr = (bus<<8) | id;
 			mpt_config(hd->ioc, &cfg);
 		}
@@ -4353,7 +4359,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 	/* Prep cfg structure
 	 */
 	cfg.pageAddr = (bus<<8) | id;
-	cfg.hdr = NULL;
+	cfg.cfghdr.hdr = NULL;
 
 	/* Prep SDP0 header
 	 */
@@ -4399,7 +4405,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 	pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
 	cfg1_dma_addr = dvbuf_dma + sz;
 
-	/* Skip this ID? Set cfg.hdr to force config page write
+	/* Skip this ID? Set cfg.cfghdr.hdr to force config page write
 	 */
 	{
 		ScsiCfgData *pspi_data = &hd->ioc->spi_data;
@@ -4417,7 +4423,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 
 				dv.cmd = MPT_SET_MAX;
 				mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-				cfg.hdr = &header1;
+				cfg.cfghdr.hdr = &header1;
 
 				/* Save the final negotiated settings to
 				 * SCSI device page 1.
@@ -4483,7 +4489,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 		dv.cmd = MPT_SET_MIN;
 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
 
-		cfg.hdr = &header1;
+		cfg.cfghdr.hdr = &header1;
 		cfg.physAddr = cfg1_dma_addr;
 		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 		cfg.dir = 1;
@@ -4596,8 +4602,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 				if ((pbuf1[56] & 0x02) == 0) {
 					pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
 					hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
-					ddvprintk((MYIOC_s_NOTE_FMT 
-					    "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", 
+					ddvprintk((MYIOC_s_NOTE_FMT
+					    "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
 					    ioc->name, id, pbuf1[56]));
 				}
 			}
@@ -4637,7 +4643,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 					u32 sdp0_info;
 					u32 sdp0_nego;
 
-					cfg.hdr = &header0;
+					cfg.cfghdr.hdr = &header0;
 					cfg.physAddr = cfg0_dma_addr;
 					cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 					cfg.dir = 0;
@@ -4673,7 +4679,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 						if (!firstPass)
 							doFallback = 1;
 					} else {
-						ddvprintk((MYIOC_s_NOTE_FMT 
+						ddvprintk((MYIOC_s_NOTE_FMT
 						    "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
 						hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
 						mptscsih_initTarget(hd,
@@ -4689,8 +4695,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 
 			} else if (rc == MPT_SCANDV_ISSUE_SENSE)
 				doFallback = 1;	/* set fallback flag */
-			else if ((rc == MPT_SCANDV_DID_RESET) || 
-				 (rc == MPT_SCANDV_SENSE) || 
+			else if ((rc == MPT_SCANDV_DID_RESET) ||
+				 (rc == MPT_SCANDV_SENSE) ||
 				 (rc == MPT_SCANDV_FALLBACK))
 				doFallback = 1;	/* set fallback flag */
 			else
@@ -4722,7 +4728,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 	 * 4) release
 	 * 5) update nego parms to target struct
 	 */
-	cfg.hdr = &header1;
+	cfg.cfghdr.hdr = &header1;
 	cfg.physAddr = cfg1_dma_addr;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 	cfg.dir = 1;
@@ -5121,12 +5127,12 @@ target_done:
 
 	/* Set if cfg1_dma_addr contents is valid
 	 */
-	if ((cfg.hdr != NULL) && (retcode == 0)){
+	if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
 		/* If disk, not U320, disable QAS
 		 */
 		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
 			hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
-			ddvprintk((MYIOC_s_NOTE_FMT 
+			ddvprintk((MYIOC_s_NOTE_FMT
 			    "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
 		}
 
@@ -5137,7 +5143,7 @@ target_done:
 		 * skip save of the final negotiated settings to
 		 * SCSI device page 1.
 		 *
-		cfg.hdr = &header1;
+		cfg.cfghdr.hdr = &header1;
 		cfg.physAddr = cfg1_dma_addr;
 		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 		cfg.dir = 1;
@@ -5248,7 +5254,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
 		/* Update tmax values with those from Device Page 0.*/
 		pPage0 = (SCSIDevicePage0_t *) pPage;
 		if (pPage0) {
-			val = cpu_to_le32(pPage0->NegotiatedParameters);
+			val = le32_to_cpu(pPage0->NegotiatedParameters);
 			dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
 			dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
 			dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
@@ -5276,12 +5282,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
 				dv->now.offset, &val, &configuration, dv->now.flags);
 			dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
 				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
-			pPage1->RequestedParameters = le32_to_cpu(val);
+			pPage1->RequestedParameters = cpu_to_le32(val);
 			pPage1->Reserved = 0;
-			pPage1->Configuration = le32_to_cpu(configuration);
+			pPage1->Configuration = cpu_to_le32(configuration);
 		}
 
-		ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
+		ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
 				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
 		break;
 
@@ -5301,9 +5307,9 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
 				offset, &val, &configuration, negoFlags);
 			dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
 				id, width, factor, offset, negoFlags, val, configuration));
-			pPage1->RequestedParameters = le32_to_cpu(val);
+			pPage1->RequestedParameters = cpu_to_le32(val);
 			pPage1->Reserved = 0;
-			pPage1->Configuration = le32_to_cpu(configuration);
+			pPage1->Configuration = cpu_to_le32(configuration);
 		}
 		ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
 				id, width, factor, offset, val, configuration, negoFlags));
@@ -5377,12 +5383,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
 		if (pPage1) {
 			mptscsih_setDevicePage1Flags (width, factor, offset, &val,
 						&configuration, dv->now.flags);
-			dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
+			dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
 			     id, width, offset, factor, dv->now.flags, val, configuration));
 
-			pPage1->RequestedParameters = le32_to_cpu(val);
+			pPage1->RequestedParameters = cpu_to_le32(val);
 			pPage1->Reserved = 0;
-			pPage1->Configuration = le32_to_cpu(configuration);
+			pPage1->Configuration = cpu_to_le32(configuration);
 		}
 
 		ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -162,15 +162,15 @@ mptspi_probe(struct pci_dev *pdev, const
 	u8			*mem;
 	int			error=0;
 	int			r;
-	
+
 	if ((r = mpt_attach(pdev,id)) != 0)
 		return r;
-	
+
 	ioc = pci_get_drvdata(pdev);
 	ioc->DoneCtx = mptspiDoneCtx;
 	ioc->TaskCtx = mptspiTaskCtx;
 	ioc->InternalCtx = mptspiInternalCtx;
-	
+
 	/*  Added sanity check on readiness of the MPT adapter.
 	 */
 	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1499,22 +1499,43 @@ static int tw_scsiop_inquiry(TW_Device_E
 	return 0;
 } /* End tw_scsiop_inquiry() */
 
+static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
+				 void *data, unsigned int len)
+{
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+	void *buf;
+	unsigned int transfer_len;
+
+	if (cmd->use_sg) {
+		struct scatterlist *sg =
+			(struct scatterlist *)cmd->request_buffer;
+		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+		transfer_len = min(sg->length, len);
+	} else {
+		buf = cmd->request_buffer;
+		transfer_len = min(cmd->request_bufflen, len);
+	}
+
+	memcpy(buf, data, transfer_len);
+	
+	if (cmd->use_sg) {
+		struct scatterlist *sg;
+
+		sg = (struct scatterlist *)cmd->request_buffer;
+		kunmap_atomic(buf - sg->offset, KM_IRQ0);
+	}
+}
+
 /* This function is called by the isr to complete an inquiry command */
 static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
 {
 	unsigned char *is_unit_present;
-	unsigned char *request_buffer;
+	unsigned char request_buffer[36];
 	TW_Param *param;
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
 
-	/* Fill request buffer */
-	if (tw_dev->srb[request_id]->request_buffer == NULL) {
-		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n");
-		return 1;
-	}
-	request_buffer = tw_dev->srb[request_id]->request_buffer;
-	memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
+	memset(request_buffer, 0, sizeof(request_buffer));
 	request_buffer[0] = TYPE_DISK; /* Peripheral device type */
 	request_buffer[1] = 0;	       /* Device type modifier */
 	request_buffer[2] = 0;	       /* No ansi/iso compliance */
@@ -1522,6 +1543,8 @@ static int tw_scsiop_inquiry_complete(TW
 	memcpy(&request_buffer[8], "3ware   ", 8);	 /* Vendor ID */
 	sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id);
 	memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3);
+	tw_transfer_internal(tw_dev, request_id, request_buffer,
+			     sizeof(request_buffer));
 
 	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
 	if (param == NULL) {
@@ -1612,7 +1635,7 @@ static int tw_scsiop_mode_sense_complete
 {
 	TW_Param *param;
 	unsigned char *flags;
-	unsigned char *request_buffer;
+	unsigned char request_buffer[8];
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");
 
@@ -1622,8 +1645,7 @@ static int tw_scsiop_mode_sense_complete
 		return 1;
 	}
 	flags = (char *)&(param->data[0]);
-	request_buffer = tw_dev->srb[request_id]->buffer;
-	memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
+	memset(request_buffer, 0, sizeof(request_buffer));
 
 	request_buffer[0] = 0xf;        /* mode data length */
 	request_buffer[1] = 0;          /* default medium type */
@@ -1635,6 +1657,8 @@ static int tw_scsiop_mode_sense_complete
 		request_buffer[6] = 0x4;        /* WCE on */
 	else
 		request_buffer[6] = 0x0;        /* WCE off */
+	tw_transfer_internal(tw_dev, request_id, request_buffer,
+			     sizeof(request_buffer));
 
 	return 0;
 } /* End tw_scsiop_mode_sense_complete() */
@@ -1701,17 +1725,12 @@ static int tw_scsiop_read_capacity_compl
 {
 	unsigned char *param_data;
 	u32 capacity;
-	char *buff;
+	char buff[8];
 	TW_Param *param;
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
 
-	buff = tw_dev->srb[request_id]->request_buffer;
-	if (buff == NULL) {
-		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
-		return 1;
-	}
-	memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+	memset(buff, 0, sizeof(buff));
 	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
 	if (param == NULL) {
 		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
@@ -1739,6 +1758,8 @@ static int tw_scsiop_read_capacity_compl
 	buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
 	buff[7] = TW_BLOCK_SIZE & 0xff;
 
+	tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff));
+
 	return 0;
 } /* End tw_scsiop_read_capacity_complete() */
 
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1,5 +1,11 @@
 menu "SCSI device support"
 
+config RAID_ATTRS
+	tristate "RAID Transport Class"
+	default n
+	---help---
+	  Provides RAID
+
 config SCSI
 	tristate "SCSI device support"
 	---help---
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -22,6 +22,8 @@ subdir-$(CONFIG_PCMCIA)		+= pcmcia
 
 obj-$(CONFIG_SCSI)		+= scsi_mod.o
 
+obj-$(CONFIG_RAID_ATTRS)	+= raid_class.o
+
 # --- NOTE ORDERING HERE ---
 # For kernel non-modular link, transport attributes need to
 # be initialised before drivers
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -133,6 +133,7 @@ struct inquiry_data {
  
 static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
 static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
 static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
 #ifdef AAC_DETAILED_STATUS_INFO
 static char *aac_get_status_string(u32 status);
@@ -348,6 +349,27 @@ static void aac_io_done(struct scsi_cmnd
 	spin_unlock_irqrestore(host->host_lock, cpu_flags);
 }
 
+static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
+{
+	void *buf;
+	unsigned int transfer_len;
+	struct scatterlist *sg = scsicmd->request_buffer;
+
+	if (scsicmd->use_sg) {
+		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+		transfer_len = min(sg->length, len + offset);
+	} else {
+		buf = scsicmd->request_buffer;
+		transfer_len = min(scsicmd->request_bufflen, len + offset);
+	}
+
+	memcpy(buf + offset, data, transfer_len - offset);
+
+	if (scsicmd->use_sg) 
+		kunmap_atomic(buf - sg->offset, KM_IRQ0);
+
+}
+
 static void get_container_name_callback(void *context, struct fib * fibptr)
 {
 	struct aac_get_name_resp * get_name_reply;
@@ -363,18 +385,22 @@ static void get_container_name_callback(
 	/* Failure is irrelevant, using default value instead */
 	if ((le32_to_cpu(get_name_reply->status) == CT_OK)
 	 && (get_name_reply->data[0] != '\0')) {
-		int    count;
-		char * dp;
-		char * sp = get_name_reply->data;
+		char *sp = get_name_reply->data;
 		sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';
 		while (*sp == ' ')
 			++sp;
-		count = sizeof(((struct inquiry_data *)NULL)->inqd_pid);
-		dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid;
-		if (*sp) do {
-			*dp++ = (*sp) ? *sp++ : ' ';
-		} while (--count > 0);
+		if (*sp) {
+			char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
+			int count = sizeof(d);
+			char *dp = d;
+			do {
+				*dp++ = (*sp) ? *sp++ : ' ';
+			} while (--count > 0);
+			aac_internal_transfer(scsicmd, d, 
+			  offsetof(struct inquiry_data, inqd_pid), sizeof(d));
+		}
 	}
+
 	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 
 	fib_complete(fibptr);
@@ -777,34 +803,36 @@ int aac_get_adapter_info(struct aac_dev*
 	/* 
 	 * 57 scatter gather elements 
 	 */
-	dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
-		sizeof(struct aac_fibhdr) -
-		sizeof(struct aac_write) + sizeof(struct sgmap)) /
-			sizeof(struct sgmap);
-	if (dev->dac_support) {
-		/* 
-		 * 38 scatter gather elements 
-		 */
-		dev->scsi_host_ptr->sg_tablesize =
-			(dev->max_fib_size -
+	if (!(dev->raw_io_interface)) {
+		dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
 			sizeof(struct aac_fibhdr) -
-			sizeof(struct aac_write64) +
-			sizeof(struct sgmap64)) /
-				sizeof(struct sgmap64);
-	}
-	dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
-	if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
-		/*
-		 * Worst case size that could cause sg overflow when
-		 * we break up SG elements that are larger than 64KB.
-		 * Would be nice if we could tell the SCSI layer what
-		 * the maximum SG element size can be. Worst case is
-		 * (sg_tablesize-1) 4KB elements with one 64KB
-		 * element.
-		 *	32bit -> 468 or 238KB	64bit -> 424 or 212KB
-		 */
-		dev->scsi_host_ptr->max_sectors =
-		  (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+			sizeof(struct aac_write) + sizeof(struct sgmap)) /
+				sizeof(struct sgmap);
+		if (dev->dac_support) {
+			/* 
+			 * 38 scatter gather elements 
+			 */
+			dev->scsi_host_ptr->sg_tablesize =
+				(dev->max_fib_size -
+				sizeof(struct aac_fibhdr) -
+				sizeof(struct aac_write64) +
+				sizeof(struct sgmap64)) /
+					sizeof(struct sgmap64);
+		}
+		dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+		if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+			/*
+			 * Worst case size that could cause sg overflow when
+			 * we break up SG elements that are larger than 64KB.
+			 * Would be nice if we could tell the SCSI layer what
+			 * the maximum SG element size can be. Worst case is
+			 * (sg_tablesize-1) 4KB elements with one 64KB
+			 * element.
+			 *	32bit -> 468 or 238KB	64bit -> 424 or 212KB
+			 */
+			dev->scsi_host_ptr->max_sectors =
+			  (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+		}
 	}
 
 	fib_complete(fibptr);
@@ -814,12 +842,11 @@ int aac_get_adapter_info(struct aac_dev*
 }
 
 
-static void read_callback(void *context, struct fib * fibptr)
+static void io_callback(void *context, struct fib * fibptr)
 {
 	struct aac_dev *dev;
 	struct aac_read_reply *readreply;
 	struct scsi_cmnd *scsicmd;
-	u32 lba;
 	u32 cid;
 
 	scsicmd = (struct scsi_cmnd *) context;
@@ -827,8 +854,7 @@ static void read_callback(void *context,
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
 
-	lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
-	dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+	dprintk((KERN_DEBUG "io_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3], jiffies));
 
 	if (fibptr == NULL)
 		BUG();
@@ -847,7 +873,7 @@ static void read_callback(void *context,
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 	else {
 #ifdef AAC_DETAILED_STATUS_INFO
-		printk(KERN_WARNING "read_callback: io failed, status = %d\n",
+		printk(KERN_WARNING "io_callback: io failed, status = %d\n",
 		  le32_to_cpu(readreply->status));
 #endif
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
@@ -867,53 +893,6 @@ static void read_callback(void *context,
 	aac_io_done(scsicmd);
 }
 
-static void write_callback(void *context, struct fib * fibptr)
-{
-	struct aac_dev *dev;
-	struct aac_write_reply *writereply;
-	struct scsi_cmnd *scsicmd;
-	u32 lba;
-	u32 cid;
-
-	scsicmd = (struct scsi_cmnd *) context;
-	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-	cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
-
-	lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
-	dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
-	if (fibptr == NULL)
-		BUG();
-
-	if(scsicmd->use_sg)
-		pci_unmap_sg(dev->pdev, 
-			(struct scatterlist *)scsicmd->buffer,
-			scsicmd->use_sg,
-			scsicmd->sc_data_direction);
-	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
-				 scsicmd->request_bufflen,
-				 scsicmd->sc_data_direction);
-
-	writereply = (struct aac_write_reply *) fib_data(fibptr);
-	if (le32_to_cpu(writereply->status) == ST_OK)
-		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
-	else {
-		printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status);
-		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-				    HARDWARE_ERROR,
-				    SENCODE_INTERNAL_TARGET_FAILURE,
-				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-				    0, 0);
-		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, 
-				sizeof(struct sense_data));
-	}
-
-	fib_complete(fibptr);
-	fib_free(fibptr);
-	aac_io_done(scsicmd);
-}
-
 static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 {
 	u32 lba;
@@ -954,7 +933,32 @@ static int aac_read(struct scsi_cmnd * s
 
 	fib_init(cmd_fibcontext);
 
-	if (dev->dac_support == 1) {
+	if (dev->raw_io_interface) {
+		struct aac_raw_io *readcmd;
+		readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+		readcmd->block[0] = cpu_to_le32(lba);
+		readcmd->block[1] = 0;
+		readcmd->count = cpu_to_le32(count<<9);
+		readcmd->cid = cpu_to_le16(cid);
+		readcmd->flags = cpu_to_le16(1);
+		readcmd->bpTotal = 0;
+		readcmd->bpComplete = 0;
+		
+		aac_build_sgraw(scsicmd, &readcmd->sg);
+		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
+		if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+			BUG();
+		/*
+		 *	Now send the Fib to the adapter
+		 */
+		status = fib_send(ContainerRawIo,
+			  cmd_fibcontext, 
+			  fibsize, 
+			  FsaNormal, 
+			  0, 1, 
+			  (fib_callback) io_callback, 
+			  (void *) scsicmd);
+	} else if (dev->dac_support == 1) {
 		struct aac_read64 *readcmd;
 		readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
 		readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -968,7 +972,7 @@ static int aac_read(struct scsi_cmnd * s
 		fibsize = sizeof(struct aac_read64) + 
 			((le32_to_cpu(readcmd->sg.count) - 1) * 
 			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+		BUG_ON (fibsize > (dev->max_fib_size - 
 					sizeof(struct aac_fibhdr)));
 		/*
 		 *	Now send the Fib to the adapter
@@ -978,7 +982,7 @@ static int aac_read(struct scsi_cmnd * s
 			  fibsize, 
 			  FsaNormal, 
 			  0, 1, 
-			  (fib_callback) read_callback, 
+			  (fib_callback) io_callback, 
 			  (void *) scsicmd);
 	} else {
 		struct aac_read *readcmd;
@@ -1002,7 +1006,7 @@ static int aac_read(struct scsi_cmnd * s
 			  fibsize, 
 			  FsaNormal, 
 			  0, 1, 
-			  (fib_callback) read_callback, 
+			  (fib_callback) io_callback, 
 			  (void *) scsicmd);
 	}
 
@@ -1061,7 +1065,32 @@ static int aac_write(struct scsi_cmnd * 
 	}
 	fib_init(cmd_fibcontext);
 
-	if(dev->dac_support == 1) {
+	if (dev->raw_io_interface) {
+		struct aac_raw_io *writecmd;
+		writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+		writecmd->block[0] = cpu_to_le32(lba);
+		writecmd->block[1] = 0;
+		writecmd->count = cpu_to_le32(count<<9);
+		writecmd->cid = cpu_to_le16(cid);
+		writecmd->flags = 0; 
+		writecmd->bpTotal = 0;
+		writecmd->bpComplete = 0;
+		
+		aac_build_sgraw(scsicmd, &writecmd->sg);
+		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
+		if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+			BUG();
+		/*
+		 *	Now send the Fib to the adapter
+		 */
+		status = fib_send(ContainerRawIo,
+			  cmd_fibcontext, 
+			  fibsize, 
+			  FsaNormal, 
+			  0, 1, 
+			  (fib_callback) io_callback, 
+			  (void *) scsicmd);
+	} else if (dev->dac_support == 1) {
 		struct aac_write64 *writecmd;
 		writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
 		writecmd->command = cpu_to_le32(VM_CtHostWrite64);
@@ -1085,7 +1114,7 @@ static int aac_write(struct scsi_cmnd * 
 			  fibsize, 
 			  FsaNormal, 
 			  0, 1, 
-			  (fib_callback) write_callback, 
+			  (fib_callback) io_callback, 
 			  (void *) scsicmd);
 	} else {
 		struct aac_write *writecmd;
@@ -1111,7 +1140,7 @@ static int aac_write(struct scsi_cmnd * 
 			  fibsize, 
 			  FsaNormal, 
 			  0, 1, 
-			  (fib_callback) write_callback, 
+			  (fib_callback) io_callback, 
 			  (void *) scsicmd);
 	}
 
@@ -1340,44 +1369,45 @@ int aac_scsi_cmd(struct scsi_cmnd * scsi
 	switch (scsicmd->cmnd[0]) {
 	case INQUIRY:
 	{
-		struct inquiry_data *inq_data_ptr;
+		struct inquiry_data inq_data;
 
 		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
-		inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;
-		memset(inq_data_ptr, 0, sizeof (struct inquiry_data));
+		memset(&inq_data, 0, sizeof (struct inquiry_data));
 
-		inq_data_ptr->inqd_ver = 2;	/* claim compliance to SCSI-2 */
-		inq_data_ptr->inqd_dtq = 0x80;	/* set RMB bit to one indicating that the medium is removable */
-		inq_data_ptr->inqd_rdf = 2;	/* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
-		inq_data_ptr->inqd_len = 31;
+		inq_data.inqd_ver = 2;	/* claim compliance to SCSI-2 */
+		inq_data.inqd_dtq = 0x80;	/* set RMB bit to one indicating that the medium is removable */
+		inq_data.inqd_rdf = 2;	/* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
+		inq_data.inqd_len = 31;
 		/*Format for "pad2" is  RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
-		inq_data_ptr->inqd_pad2= 0x32 ;	 /*WBus16|Sync|CmdQue */
+		inq_data.inqd_pad2= 0x32 ;	 /*WBus16|Sync|CmdQue */
 		/*
 		 *	Set the Vendor, Product, and Revision Level
 		 *	see: <vendor>.c i.e. aac.c
 		 */
 		if (scsicmd->device->id == host->this_id) {
-			setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *)));
-			inq_data_ptr->inqd_pdt = INQD_PDT_PROC;	/* Processor device */
+			setinqstr(cardtype, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
+			inq_data.inqd_pdt = INQD_PDT_PROC;	/* Processor device */
+			aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
 			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 			scsicmd->scsi_done(scsicmd);
 			return 0;
 		}
-		setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type);
-		inq_data_ptr->inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */
+		setinqstr(cardtype, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
+		inq_data.inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */
+		aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
 		return aac_get_container_name(scsicmd, cid);
 	}
 	case READ_CAPACITY:
 	{
 		u32 capacity;
-		char *cp;
+		char cp[8];
 
 		dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
 		if (fsa_dev_ptr[cid].size <= 0x100000000LL)
 			capacity = fsa_dev_ptr[cid].size - 1;
 		else
 			capacity = (u32)-1;
-		cp = scsicmd->request_buffer;
+
 		cp[0] = (capacity >> 24) & 0xff;
 		cp[1] = (capacity >> 16) & 0xff;
 		cp[2] = (capacity >> 8) & 0xff;
@@ -1386,6 +1416,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsi
 		cp[5] = 0;
 		cp[6] = 2;
 		cp[7] = 0;
+		aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
 
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 		scsicmd->scsi_done(scsicmd);
@@ -1395,15 +1426,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsi
 
 	case MODE_SENSE:
 	{
-		char *mode_buf;
+		char mode_buf[4];
 
 		dprintk((KERN_DEBUG "MODE SENSE command.\n"));
-		mode_buf = scsicmd->request_buffer;
 		mode_buf[0] = 3;	/* Mode data length */
 		mode_buf[1] = 0;	/* Medium type - default */
 		mode_buf[2] = 0;	/* Device-specific param, bit 8: 0/1 = write enabled/protected */
 		mode_buf[3] = 0;	/* Block descriptor length */
 
+		aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 		scsicmd->scsi_done(scsicmd);
 
@@ -1411,10 +1442,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsi
 	}
 	case MODE_SENSE_10:
 	{
-		char *mode_buf;
+		char mode_buf[8];
 
 		dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
-		mode_buf = scsicmd->request_buffer;
 		mode_buf[0] = 0;	/* Mode data length (MSB) */
 		mode_buf[1] = 6;	/* Mode data length (LSB) */
 		mode_buf[2] = 0;	/* Medium type - default */
@@ -1423,6 +1453,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsi
 		mode_buf[5] = 0;	/* reserved */
 		mode_buf[6] = 0;	/* Block descriptor length (MSB) */
 		mode_buf[7] = 0;	/* Block descriptor length (LSB) */
+		aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
 
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 		scsicmd->scsi_done(scsicmd);
@@ -1894,7 +1925,7 @@ static int aac_send_srb_fib(struct scsi_
 	srbcmd->id   = cpu_to_le32(scsicmd->device->id);
 	srbcmd->lun      = cpu_to_le32(scsicmd->device->lun);
 	srbcmd->flags    = cpu_to_le32(flag);
-	timeout = (scsicmd->timeout-jiffies)/HZ;
+	timeout = scsicmd->timeout_per_command/HZ;
 	if(timeout == 0){
 		timeout = 1;
 	}
@@ -2077,6 +2108,76 @@ static unsigned long aac_build_sg64(stru
 	return byte_count;
 }
 
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
+{
+	struct Scsi_Host *host = scsicmd->device->host;
+	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+	unsigned long byte_count = 0;
+
+	// Get rid of old data
+	psg->count = 0;
+	psg->sg[0].next = 0;
+	psg->sg[0].prev = 0;
+	psg->sg[0].addr[0] = 0;
+	psg->sg[0].addr[1] = 0;
+	psg->sg[0].count = 0;
+	psg->sg[0].flags = 0;
+	if (scsicmd->use_sg) {
+		struct scatterlist *sg;
+		int i;
+		int sg_count;
+		sg = (struct scatterlist *) scsicmd->request_buffer;
+
+		sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
+			scsicmd->sc_data_direction);
+
+		for (i = 0; i < sg_count; i++) {
+			int count = sg_dma_len(sg);
+			u64 addr = sg_dma_address(sg);
+			psg->sg[i].next = 0;
+			psg->sg[i].prev = 0;
+			psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
+			psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+			psg->sg[i].count = cpu_to_le32(count);
+			psg->sg[i].flags = 0;
+			byte_count += count;
+			sg++;
+		}
+		psg->count = cpu_to_le32(sg_count);
+		/* hba wants the size to be exact */
+		if(byte_count > scsicmd->request_bufflen){
+			u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+				(byte_count - scsicmd->request_bufflen);
+			psg->sg[i-1].count = cpu_to_le32(temp);
+			byte_count = scsicmd->request_bufflen;
+		}
+		/* Check for command underflow */
+		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
+			printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+					byte_count, scsicmd->underflow);
+		}
+	}
+	else if(scsicmd->request_bufflen) {
+		int count;
+		u64 addr;
+		scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
+				scsicmd->request_buffer,
+				scsicmd->request_bufflen,
+				scsicmd->sc_data_direction);
+		addr = scsicmd->SCp.dma_handle;
+		count = scsicmd->request_bufflen;
+		psg->count = cpu_to_le32(1);
+		psg->sg[0].next = 0;
+		psg->sg[0].prev = 0;
+		psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
+		psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+		psg->sg[0].count = cpu_to_le32(count);
+		psg->sg[0].flags = 0;
+		byte_count = scsicmd->request_bufflen;
+	}
+	return byte_count;
+}
+
 #ifdef AAC_DETAILED_STATUS_INFO
 
 struct aac_srb_status_info {
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -110,6 +110,22 @@ struct user_sgentry64 {
 	u32	count;	/* Length. */
 };
 
+struct sgentryraw {
+	__le32		next;	/* reserved for F/W use */
+	__le32		prev;	/* reserved for F/W use */
+	__le32		addr[2];
+	__le32		count;
+	__le32		flags;	/* reserved for F/W use */
+};
+
+struct user_sgentryraw {
+	u32		next;	/* reserved for F/W use */
+	u32		prev;	/* reserved for F/W use */
+	u32		addr[2];
+	u32		count;
+	u32		flags;	/* reserved for F/W use */
+};
+
 /*
  *	SGMAP
  *
@@ -137,6 +153,16 @@ struct user_sgmap64 {
 	struct user_sgentry64 sg[1];
 };
 
+struct sgmapraw {
+	__le32		  count;
+	struct sgentryraw sg[1];
+};
+
+struct user_sgmapraw {
+	u32		  count;
+	struct user_sgentryraw sg[1];
+};
+
 struct creation_info
 {
 	u8 		buildnum;		/* e.g., 588 */
@@ -351,6 +377,7 @@ struct hw_fib {
  */
 #define		ContainerCommand		500
 #define		ContainerCommand64		501
+#define		ContainerRawIo			502
 /*
  *	Cluster Commands
  */
@@ -456,6 +483,7 @@ struct adapter_ops
 {
 	void (*adapter_interrupt)(struct aac_dev *dev);
 	void (*adapter_notify)(struct aac_dev *dev, u32 event);
+	void (*adapter_disable_int)(struct aac_dev *dev);
 	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
 	int  (*adapter_check_health)(struct aac_dev *dev);
 };
@@ -981,6 +1009,9 @@ struct aac_dev
 	u8			nondasd_support; 
 	u8			dac_support;
 	u8			raid_scsi_mode;
+	/* macro side-effects BEWARE */
+#	define			raw_io_interface \
+	  init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
 	u8			printf_enabled;
 };
 
@@ -990,6 +1021,9 @@ struct aac_dev
 #define aac_adapter_notify(dev, event) \
 	(dev)->a_ops.adapter_notify(dev, event)
 
+#define aac_adapter_disable_int(dev) \
+	(dev)->a_ops.adapter_disable_int(dev)
+
 #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
 	(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
 
@@ -1156,6 +1190,17 @@ struct aac_write_reply
 	__le32		committed;
 };
 
+struct aac_raw_io
+{
+	__le32		block[2];
+	__le32		count;
+	__le16		cid;
+	__le16		flags;		/* 00 W, 01 R */
+	__le16		bpTotal;	/* reserved for F/W use */
+	__le16		bpComplete;	/* reserved for F/W use */
+	struct sgmapraw	sg;
+};
+
 #define CT_FLUSH_CACHE 129
 struct aac_synchronize {
 	__le32		command;	/* VM_ContainerConfig */
@@ -1196,7 +1241,7 @@ struct aac_srb
 };
 
 /*
- * This and assocated data structs are used by the 
+ * This and associated data structs are used by the
  * ioctl caller and are in cpu order.
  */
 struct user_aac_srb
@@ -1508,11 +1553,12 @@ struct fib_ioctl
 
 struct revision
 {
-	u32 compat;
-	u32 version;
-	u32 build;
+	__le32 compat;
+	__le32 version;
+	__le32 build;
 };
 	
+
 /*
  * 	Ugly - non Linux like ioctl coding for back compat.
  */
@@ -1733,3 +1779,4 @@ int aac_get_adapter_info(struct aac_dev*
 int aac_send_shutdown(struct aac_dev *dev);
 extern int numacb;
 extern int acbsize;
+extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -287,7 +287,6 @@ return_fib:
 		kfree(fib->hw_fib);
 		kfree(fib);
 		status = 0;
-		fibctx->jiffies = jiffies/HZ;
 	} else {
 		spin_unlock_irqrestore(&dev->fib_lock, flags);
 		if (f.wait) {
@@ -302,6 +301,7 @@ return_fib:
 			status = -EAGAIN;
 		}	
 	}
+	fibctx->jiffies = jiffies/HZ;
 	return status;
 }
 
@@ -405,10 +405,20 @@ static int close_getadapter_fib(struct a
 static int check_revision(struct aac_dev *dev, void __user *arg)
 {
 	struct revision response;
+	char *driver_version = aac_driver_version;
+	u32 version;
 
-	response.compat = 1;
-	response.version = le32_to_cpu(dev->adapter_info.kernelrev);
-	response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
+	response.compat = cpu_to_le32(1);
+	version = (simple_strtol(driver_version, 
+				&driver_version, 10) << 24) | 0x00000400;
+	version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;
+	version += simple_strtol(driver_version + 1, NULL, 10);
+	response.version = cpu_to_le32(version);
+#	if (defined(AAC_DRIVER_BUILD))
+		response.build = cpu_to_le32(AAC_DRIVER_BUILD);
+#	else
+		response.build = cpu_to_le32(9999);
+#	endif
 
 	if (copy_to_user(arg, &response, sizeof(response)))
 		return -EFAULT;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -44,7 +44,9 @@
 
 #include "aacraid.h"
 
-struct aac_common aac_config;
+struct aac_common aac_config = {
+	.irq_mod = 1
+};
 
 static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
 {
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -254,6 +254,7 @@ static void fib_dealloc(struct fib * fib
 static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify)
 {
 	struct aac_queue * q;
+	unsigned long idx;
 
 	/*
 	 *	All of the queues wrap when they reach the end, so we check
@@ -263,10 +264,23 @@ static int aac_get_entry (struct aac_dev
 	 */
 
 	q = &dev->queues->queue[qid];
-	
-	*index = le32_to_cpu(*(q->headers.producer));
-	if ((*index - 2) == le32_to_cpu(*(q->headers.consumer)))
+
+	idx = *index = le32_to_cpu(*(q->headers.producer));
+	/* Interrupt Moderation, only interrupt for first two entries */
+	if (idx != le32_to_cpu(*(q->headers.consumer))) {
+		if (--idx == 0) {
+			if (qid == AdapHighCmdQueue)
+				idx = ADAP_HIGH_CMD_ENTRIES;
+			else if (qid == AdapNormCmdQueue)
+				idx = ADAP_NORM_CMD_ENTRIES;
+			else if (qid == AdapHighRespQueue) 
+	        		idx = ADAP_HIGH_RESP_ENTRIES;
+			else if (qid == AdapNormRespQueue) 
+				idx = ADAP_NORM_RESP_ENTRIES;
+		}
+		if (idx != le32_to_cpu(*(q->headers.consumer)))
 			*nonotify = 1; 
+	}
 
 	if (qid == AdapHighCmdQueue) {
 	        if (*index >= ADAP_HIGH_CMD_ENTRIES)
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -27,8 +27,11 @@
  * Abstract: Linux Driver entry module for Adaptec RAID Array Controller
  */
 
-#define AAC_DRIVER_VERSION		"1.1.2-lk2"
-#define AAC_DRIVER_BUILD_DATE		__DATE__
+#define AAC_DRIVER_VERSION		"1.1-4"
+#ifndef AAC_DRIVER_BRANCH
+#define AAC_DRIVER_BRANCH		""
+#endif
+#define AAC_DRIVER_BUILD_DATE		__DATE__ " " __TIME__
 #define AAC_DRIVERNAME			"aacraid"
 
 #include <linux/compat.h>
@@ -58,16 +61,24 @@
 
 #include "aacraid.h"
 
+#ifdef AAC_DRIVER_BUILD
+#define _str(x) #x
+#define str(x) _str(x)
+#define AAC_DRIVER_FULL_VERSION	AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH
+#else
+#define AAC_DRIVER_FULL_VERSION	AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE
+#endif
 
 MODULE_AUTHOR("Red Hat Inc and Adaptec");
 MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
 		   "Adaptec Advanced Raid Products, "
 		   "and HP NetRAID-4M SCSI driver");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(AAC_DRIVER_VERSION);
+MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
 
 static LIST_HEAD(aac_devices);
 static int aac_cfg_major = -1;
+char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
 
 /*
  * Because of the way Linux names scsi devices, the order in this table has
@@ -109,36 +120,39 @@ static struct pci_device_id aac_pci_tbl[
 	{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */
 	{ 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */
 	{ 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */
-	{ 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 32 }, /* Themisto Jupiter Platform */
-	{ 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 32 }, /* Themisto Jupiter Platform */
-	{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 33 }, /* Callisto Jupiter Platform */
-	{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 34 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
-	{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 35 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
-	{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 36 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
-	{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 37 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
-	{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 38 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
-	{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 39 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
-	{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 40 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
-	{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 41 }, /* AAR-2610SA PCI SATA 6ch */
-	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 42 }, /* ASR-2240S (SabreExpress) */
-	{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 43 }, /* ASR-4005SAS */
-	{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 44 }, /* IBM 8i (AvonPark) */
-	{ 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 44 }, /* IBM 8i (AvonPark Lite) */
-	{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 45 }, /* ASR-4000SAS (BlackBird) */
-	{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 46 }, /* ASR-4800SAS (Marauder-X) */
-	{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 47 }, /* ASR-4805SAS (Marauder-E) */
-	{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 48 }, /* ASR-4810SAS (Hurricane */
-
-	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 49 }, /* Perc 320/DC*/
-	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 50 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 51 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 52 }, /* Dell PERC2/QC */
-	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 53 }, /* HP NetRAID-4M */
-
-	{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 54 }, /* Dell Catchall */
-	{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 55 }, /* Legend Catchall */
-	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 56 }, /* Adaptec Catch All */
-	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 57 }, /* Adaptec Rocket Catch All */
+	{ 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */
+	{ 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 33 }, /* Themisto Jupiter Platform */
+	{ 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 33 }, /* Themisto Jupiter Platform */
+	{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 34 }, /* Callisto Jupiter Platform */
+	{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 35 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
+	{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 36 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
+	{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 37 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
+	{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 38 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+	{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 39 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+	{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 40 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+	{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
+	{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */
+	{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005SAS */
+	{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */
+	{ 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */
+	{ 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */
+	{ 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */
+	{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
+	{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
+	{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
+	{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */
+
+	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
+	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 54 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 55 }, /* Dell PERC2/QC */
+	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 56 }, /* HP NetRAID-4M */
+
+	{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 57 }, /* Dell Catchall */
+	{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */
+	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
+	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -180,8 +194,9 @@ static struct aac_driver_ident aac_drive
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9047MA       ", 1 }, /* ICP9047MA (Lancer) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9087MA       ", 1 }, /* ICP9087MA (Lancer) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP5085AU       ", 1 }, /* ICP5085AU (Hurricane) */
-	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9085LI       ", 1 }, /* ICP9085LI (Marauder-X) */
-	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP5085BR       ", 1 }, /* ICP5085BR (Marauder-E) */
+	{ aac_rx_init, "aacraid",  "ICP     ", "ICP9085LI       ", 1 }, /* ICP9085LI (Marauder-X) */
+	{ aac_rx_init, "aacraid",  "ICP     ", "ICP5085BR       ", 1 }, /* ICP5085BR (Marauder-E) */
+	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9067MA       ", 1 }, /* ICP9067MA (Intruder-6) */
 	{ NULL        , "aacraid",  "ADAPTEC ", "Themisto        ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */
 	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "Callisto        ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020SA       ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
@@ -195,10 +210,12 @@ static struct aac_driver_ident aac_drive
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2240S       ", 1 }, /* ASR-2240S (SabreExpress) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4005SAS     ", 1 }, /* ASR-4005SAS */
 	{ aac_rx_init, "ServeRAID","IBM     ", "ServeRAID 8i    ", 1 }, /* IBM 8i (AvonPark) */
+	{ aac_rkt_init, "ServeRAID","IBM     ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */
+	{ aac_rkt_init, "ServeRAID","IBM     ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4000SAS     ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4800SAS     ", 1 }, /* ASR-4800SAS (Marauder-X) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4805SAS     ", 1 }, /* ASR-4805SAS (Marauder-E) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4810SAS     ", 1 }, /* ASR-4810SAS (Hurricane) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-4810SAS     ", 1 }, /* ASR-4810SAS (Hurricane) */
 
 	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
 	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
@@ -839,11 +856,12 @@ static int __devinit aac_probe_one(struc
 
 	return 0;
 
-out_deinit:
+ out_deinit:
 	kill_proc(aac->thread_pid, SIGKILL, 0);
 	wait_for_completion(&aac->aif_completion);
 
 	aac_send_shutdown(aac);
+	aac_adapter_disable_int(aac);
 	fib_map_free(aac);
 	pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
 	kfree(aac->queues);
@@ -860,6 +878,13 @@ out_deinit:
 	return error;
 }
 
+static void aac_shutdown(struct pci_dev *dev)
+{
+	struct Scsi_Host *shost = pci_get_drvdata(dev);
+	struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+	aac_send_shutdown(aac);
+}
+
 static void __devexit aac_remove_one(struct pci_dev *pdev)
 {
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -871,6 +896,7 @@ static void __devexit aac_remove_one(str
 	wait_for_completion(&aac->aif_completion);
 
 	aac_send_shutdown(aac);
+	aac_adapter_disable_int(aac);
 	fib_map_free(aac);
 	pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
 			aac->comm_phys);
@@ -891,14 +917,15 @@ static struct pci_driver aac_pci_driver 
 	.id_table	= aac_pci_tbl,
 	.probe		= aac_probe_one,
 	.remove		= __devexit_p(aac_remove_one),
+	.shutdown 	= aac_shutdown,
 };
 
 static int __init aac_init(void)
 {
 	int error;
 	
-	printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n",
-			AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE);
+	printk(KERN_INFO "Adaptec %s driver (%s)\n",
+	  AAC_DRIVERNAME, aac_driver_version);
 
 	error = pci_module_init(&aac_pci_driver);
 	if (error)
@@ -909,6 +936,7 @@ static int __init aac_init(void)
 		printk(KERN_WARNING
 		       "aacraid: unable to register \"aac\" device.\n");
 	}
+
 	return 0;
 }
 
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rkt_intr(int irq,
 }
 
 /**
+ *	aac_rkt_disable_interrupt	-	Disable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_rkt_disable_interrupt(struct aac_dev *dev)
+{
+	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
+}
+
+/**
  *	rkt_sync_cmd	-	send a command and wait
  *	@dev: Adapter
  *	@command: Command to execute
@@ -412,10 +422,19 @@ int aac_rkt_init(struct aac_dev *dev)
 	 *	Fill in the function dispatch table.
 	 */
 	dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
+	dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
 	dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_rkt_check_health;
 
+	/*
+	 *	First clear out all interrupts.  Then enable the one's that we
+	 *	can handle.
+	 */
+	rkt_writeb(dev, MUnit.OIMR, 0xff);
+	rkt_writel(dev, MUnit.ODR, 0xffffffff);
+	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+
 	if (aac_init_adapter(dev) == NULL)
 		goto error_irq;
 	/*
@@ -438,6 +457,7 @@ error_kfree:
 	kfree(dev->queues);
 
 error_irq:
+	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
 	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
 
 error_iounmap:
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rx_intr(int irq, 
 }
 
 /**
+ *	aac_rx_disable_interrupt	-	Disable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_rx_disable_interrupt(struct aac_dev *dev)
+{
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
+}
+
+/**
  *	rx_sync_cmd	-	send a command and wait
  *	@dev: Adapter
  *	@command: Command to execute
@@ -412,10 +422,19 @@ int aac_rx_init(struct aac_dev *dev)
 	 *	Fill in the function dispatch table.
 	 */
 	dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
+	dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
 	dev->a_ops.adapter_notify = aac_rx_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_rx_check_health;
 
+	/*
+	 *	First clear out all interrupts.  Then enable the one's that we
+	 *	can handle.
+	 */
+	rx_writeb(dev, MUnit.OIMR, 0xff);
+	rx_writel(dev, MUnit.ODR, 0xffffffff);
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+
 	if (aac_init_adapter(dev) == NULL)
 		goto error_irq;
 	/*
@@ -438,6 +457,7 @@ error_kfree:
 	kfree(dev->queues);
 
 error_irq:
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
 	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
 
 error_iounmap:
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -82,6 +82,16 @@ static irqreturn_t aac_sa_intr(int irq, 
 }
 
 /**
+ *	aac_sa_disable_interrupt	-	disable interrupt
+ *	@dev: Which adapter to enable.
+ */
+
+static void aac_sa_disable_interrupt (struct aac_dev *dev)
+{
+	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+}
+
+/**
  *	aac_sa_notify_adapter		-	handle adapter notification
  *	@dev:	Adapter that notification is for
  *	@event:	Event to notidy
@@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *d
  
 static void aac_sa_interrupt_adapter (struct aac_dev *dev)
 {
-	u32 ret;
 	sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
-			&ret, NULL, NULL, NULL, NULL);
+			NULL, NULL, NULL, NULL, NULL);
 }
 
 /**
@@ -352,10 +361,18 @@ int aac_sa_init(struct aac_dev *dev)
 	 */
 
 	dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
+	dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
 	dev->a_ops.adapter_notify = aac_sa_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_sa_check_health;
 
+	/*
+	 *	First clear out all interrupts.  Then enable the one's that 
+	 *	we can handle.
+	 */
+	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | 
+				DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
 
 	if(aac_init_adapter(dev) == NULL)
 		goto error_irq;
@@ -381,6 +398,7 @@ error_kfree:
 	kfree(dev->queues);
 
 error_irq:
+	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
 	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
 
 error_iounmap:
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -9200,8 +9200,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
         (unsigned) s->serial_number, s->retries, s->allowed);
 
     printk(
-" timeout_per_command %d, timeout_total %d, timeout %d\n",
-        s->timeout_per_command, s->timeout_total, s->timeout);
+" timeout_per_command %d\n",
+        s->timeout_per_command);
 
     printk(
 " scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -5,6 +5,7 @@
 config SCSI_AIC79XX
 	tristate "Adaptec AIC79xx U320 support"
 	depends on PCI && SCSI
+	select SCSI_SPI_ATTRS
 	help
 	This driver supports all of Adaptec's Ultra 320 PCI-X
 	based SCSI controllers.
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id)
 int
 aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
 {
-	u_long	l;
 	int	error;
 	int	have_seeprom;
 	u_int	hostconf;
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1247,9 +1247,6 @@ struct ahd_softc {
 	uint16_t		  user_tagenable;/* Tagged Queuing allowed */
 };
 
-TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
-extern struct ahd_softc_tailq ahd_tailq;
-
 /*************************** IO Cell Configuration ****************************/
 #define	AHD_PRECOMP_SLEW_INDEX						\
     (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
@@ -1374,8 +1371,6 @@ void			 ahd_enable_coalescing(struct ahd
 void			 ahd_pause_and_flushwork(struct ahd_softc *ahd);
 int			 ahd_suspend(struct ahd_softc *ahd); 
 int			 ahd_resume(struct ahd_softc *ahd);
-void			 ahd_softc_insert(struct ahd_softc *);
-struct ahd_softc	*ahd_find_softc(struct ahd_softc *ahd);
 void			 ahd_set_unit(struct ahd_softc *, int);
 void			 ahd_set_name(struct ahd_softc *, char *);
 struct scb		*ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
@@ -1524,7 +1519,6 @@ void			ahd_print_scb(struct scb *scb);
 void			ahd_print_devinfo(struct ahd_softc *ahd,
 					  struct ahd_devinfo *devinfo);
 void			ahd_dump_sglist(struct scb *scb);
-void			ahd_dump_all_cards_state(void);
 void			ahd_dump_card_state(struct ahd_softc *ahd);
 int			ahd_print_register(ahd_reg_parse_entry_t *table,
 					   u_int num_entries,
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -52,8 +52,6 @@
 #include <dev/aic7xxx/aicasm/aicasm_insformat.h>
 #endif
 
-/******************************** Globals *************************************/
-struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
 
 /***************************** Lookup Tables **********************************/
 char *ahd_chip_names[] =
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd)
 }
 
 void
-ahd_softc_insert(struct ahd_softc *ahd)
-{
-	struct ahd_softc *list_ahd;
-
-#if AHD_PCI_CONFIG > 0
-	/*
-	 * Second Function PCI devices need to inherit some
-	 * settings from function 0.
-	 */
-	if ((ahd->features & AHD_MULTI_FUNC) != 0) {
-		TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
-			ahd_dev_softc_t list_pci;
-			ahd_dev_softc_t pci;
-
-			list_pci = list_ahd->dev_softc;
-			pci = ahd->dev_softc;
-			if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
-			 && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
-				struct ahd_softc *master;
-				struct ahd_softc *slave;
-
-				if (ahd_get_pci_function(list_pci) == 0) {
-					master = list_ahd;
-					slave = ahd;
-				} else {
-					master = ahd;
-					slave = list_ahd;
-				}
-				slave->flags &= ~AHD_BIOS_ENABLED; 
-				slave->flags |=
-				    master->flags & AHD_BIOS_ENABLED;
-				break;
-			}
-		}
-	}
-#endif
-
-	/*
-	 * Insertion sort into our list of softcs.
-	 */
-	list_ahd = TAILQ_FIRST(&ahd_tailq);
-	while (list_ahd != NULL
-	    && ahd_softc_comp(ahd, list_ahd) <= 0)
-		list_ahd = TAILQ_NEXT(list_ahd, links);
-	if (list_ahd != NULL)
-		TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
-	else
-		TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
-	ahd->init_level++;
-}
-
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahd_softc *
-ahd_find_softc(struct ahd_softc *ahd)
-{
-	struct ahd_softc *list_ahd;
-
-	TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
-		if (list_ahd == ahd)
-			return (ahd);
-	}
-	return (NULL);
-}
-
-void
 ahd_set_unit(struct ahd_softc *ahd, int unit)
 {
 	ahd->unit = unit;
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd,
 static void
 ahd_reset_poll(void *arg)
 {
-	struct	ahd_softc *ahd;
+	struct	ahd_softc *ahd = arg;
 	u_int	scsiseq1;
-	u_long	l;
 	u_long	s;
 	
-	ahd_list_lock(&l);
-	ahd = ahd_find_softc((struct ahd_softc *)arg);
-	if (ahd == NULL) {
-		printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
-		ahd_list_unlock(&l);
-		return;
-	}
 	ahd_lock(ahd, &s);
 	ahd_pause(ahd);
 	ahd_update_modes(ahd);
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
 				ahd_reset_poll, ahd);
 		ahd_unpause(ahd);
 		ahd_unlock(ahd, &s);
-		ahd_list_unlock(&l);
 		return;
 	}
 
@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
 	ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
 	ahd_unlock(ahd, &s);
 	ahd_release_simq(ahd);
-	ahd_list_unlock(&l);
 }
 
 /**************************** Statistics Processing ***************************/
 static void
 ahd_stat_timer(void *arg)
 {
-	struct	ahd_softc *ahd;
-	u_long	l;
+	struct	ahd_softc *ahd = arg;
 	u_long	s;
 	int	enint_coal;
 	
-	ahd_list_lock(&l);
-	ahd = ahd_find_softc((struct ahd_softc *)arg);
-	if (ahd == NULL) {
-		printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
-		ahd_list_unlock(&l);
-		return;
-	}
 	ahd_lock(ahd, &s);
 
 	enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
 	ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
 			ahd_stat_timer, ahd);
 	ahd_unlock(ahd, &s);
-	ahd_list_unlock(&l);
 }
 
 /****************************** Status Processing *****************************/
@@ -8745,16 +8656,6 @@ sized:
 	return (last_probe);
 }
 
-void
-ahd_dump_all_cards_state(void)
-{
-	struct ahd_softc *list_ahd;
-
-	TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
-		ahd_dump_card_state(list_ahd);
-	}
-}
-
 int
 ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
 		   const char *name, u_int address, u_int value,
@@ -9039,7 +8940,6 @@ ahd_dump_card_state(struct ahd_softc *ah
 		ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
 	}
 	printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
-	ahd_platform_dump_card_state(ahd);
 	ahd_restore_modes(ahd, saved_modes);
 	if (paused == 0)
 		ahd_unpause(ahd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -46,32 +46,14 @@
 #include "aic79xx_inline.h"
 #include <scsi/scsicam.h>
 
-/*
- * Include aiclib.c as part of our
- * "module dependencies are hard" work around.
- */
-#include "aiclib.c"
+static struct scsi_transport_template *ahd_linux_transport_template = NULL;
 
 #include <linux/init.h>		/* __setup */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "sd.h"			/* For geometry detection */
-#endif
-
 #include <linux/mm.h>		/* For fetching system memory size */
+#include <linux/blkdev.h>		/* For block_size() */
 #include <linux/delay.h>	/* For ssleep/msleep */
 
 /*
- * Lock protecting manipulation of the ahd softc list.
- */
-spinlock_t ahd_list_spinlock;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* For dynamic sglist size calculation. */
-u_int ahd_linux_nseg;
-#endif
-
-/*
  * Bucket size for counting good commands in between bad ones.
  */
 #define AHD_LINUX_ERR_THRESH	1000
@@ -188,71 +170,6 @@ static adapter_tag_info_t aic79xx_tag_in
 };
 
 /*
- * By default, read streaming is disabled.  In theory,
- * read streaming should enhance performance, but early
- * U320 drive firmware actually performs slower with
- * read streaming enabled.
- */
-#ifdef CONFIG_AIC79XX_ENABLE_RD_STRM
-#define AIC79XX_CONFIGED_RD_STRM 0xFFFF
-#else
-#define AIC79XX_CONFIGED_RD_STRM 0
-#endif
-
-static uint16_t aic79xx_rd_strm_info[] =
-{
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM,
-	AIC79XX_CONFIGED_RD_STRM
-};
-
-/*
- * DV option:
- *
- * positive value = DV Enabled
- * zero		  = DV Disabled
- * negative value = DV Default for adapter type/seeprom
- */
-#ifdef CONFIG_AIC79XX_DV_SETTING
-#define AIC79XX_CONFIGED_DV CONFIG_AIC79XX_DV_SETTING
-#else
-#define AIC79XX_CONFIGED_DV -1
-#endif
-
-static int8_t aic79xx_dv_settings[] =
-{
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV,
-	AIC79XX_CONFIGED_DV
-};
-
-/*
  * The I/O cell on the chip is very configurable in respect to its analog
  * characteristics.  Set the defaults here; they can be overriden with
  * the proper insmod parameters.
@@ -375,13 +292,6 @@ static uint32_t aic79xx_pci_parity = ~0;
 uint32_t aic79xx_allow_memio = ~0;
 
 /*
- * aic79xx_detect() has been run, so register all device arrivals
- * immediately with the system rather than deferring to the sorted
- * attachment performed by aic79xx_detect().
- */
-int aic79xx_detect_complete;
-
-/*
  * So that we can set how long each device is given as a selection timeout.
  * The table of values goes like this:
  *   0 - 256ms
@@ -412,7 +322,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gib
 MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(AIC79XX_DRIVER_VERSION);
-module_param(aic79xx, charp, 0);
+module_param(aic79xx, charp, 0444);
 MODULE_PARM_DESC(aic79xx,
 "period delimited, options string.\n"
 "	verbose			Enable verbose/diagnostic logging\n"
@@ -427,8 +337,6 @@ MODULE_PARM_DESC(aic79xx,
 "	reverse_scan		Sort PCI devices highest Bus/Slot to lowest\n"
 "	tag_info:<tag_str>	Set per-target tag depth\n"
 "	global_tag_depth:<int>	Global tag depth for all targets on all buses\n"
-"	rd_strm:<rd_strm_masks> Set per-target read streaming setting.\n"
-"	dv:<dv_settings>	Set per-controller Domain Validation Setting.\n"
 "	slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
 "	precomp:<pcomp_list>	Set the signal precompensation (0-7).\n"
 "	amplitude:<int>		Set the signal amplitude (0-7).\n"
@@ -441,249 +349,35 @@ MODULE_PARM_DESC(aic79xx,
 "		Shorten the selection timeout to 128ms\n"
 "\n"
 "	options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
-"\n"
-"	Sample /etc/modprobe.conf line:\n"
-"		Change Read Streaming for Controller's 2 and 3\n"
-"\n"
-"	options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
+"\n");
 
 static void ahd_linux_handle_scsi_status(struct ahd_softc *,
-					 struct ahd_linux_device *,
+					 struct scsi_device *,
 					 struct scb *);
 static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
-					 Scsi_Cmnd *cmd);
-static void ahd_linux_filter_inquiry(struct ahd_softc *ahd,
-				     struct ahd_devinfo *devinfo);
-static void ahd_linux_dev_timed_unfreeze(u_long arg);
+					 struct scsi_cmnd *cmd);
 static void ahd_linux_sem_timeout(u_long arg);
+static int  ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
 static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
-static void ahd_linux_size_nseg(void);
-static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd);
-static void ahd_linux_start_dv(struct ahd_softc *ahd);
-static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
-static int  ahd_linux_dv_thread(void *data);
-static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd);
-static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target);
-static void ahd_linux_dv_transition(struct ahd_softc *ahd,
-				    struct scsi_cmnd *cmd,
-				    struct ahd_devinfo *devinfo,
-				    struct ahd_linux_target *targ);
-static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd,
-				  struct scsi_cmnd *cmd,
-				  struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_inq(struct ahd_softc *ahd,
-			     struct scsi_cmnd *cmd,
-			     struct ahd_devinfo *devinfo,
-			     struct ahd_linux_target *targ,
-			     u_int request_length);
-static void ahd_linux_dv_tur(struct ahd_softc *ahd,
-			     struct scsi_cmnd *cmd,
-			     struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_rebd(struct ahd_softc *ahd,
-			      struct scsi_cmnd *cmd,
-			      struct ahd_devinfo *devinfo,
-			      struct ahd_linux_target *targ);
-static void ahd_linux_dv_web(struct ahd_softc *ahd,
-			     struct scsi_cmnd *cmd,
-			     struct ahd_devinfo *devinfo,
-			     struct ahd_linux_target *targ);
-static void ahd_linux_dv_reb(struct ahd_softc *ahd,
-			     struct scsi_cmnd *cmd,
-			     struct ahd_devinfo *devinfo,
-			     struct ahd_linux_target *targ);
-static void ahd_linux_dv_su(struct ahd_softc *ahd,
-			    struct scsi_cmnd *cmd,
-			    struct ahd_devinfo *devinfo,
-			    struct ahd_linux_target *targ);
-static int ahd_linux_fallback(struct ahd_softc *ahd,
-			      struct ahd_devinfo *devinfo);
-static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
-					  struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_complete(Scsi_Cmnd *cmd);
-static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ);
 static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
 				     struct ahd_devinfo *devinfo);
-static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd);
-static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd);
-static void ahd_linux_device_queue_depth(struct ahd_softc *ahd,
-					 struct ahd_linux_device *dev);
-static struct ahd_linux_target*	ahd_linux_alloc_target(struct ahd_softc*,
-						       u_int, u_int);
-static void			ahd_linux_free_target(struct ahd_softc*,
-						      struct ahd_linux_target*);
-static struct ahd_linux_device*	ahd_linux_alloc_device(struct ahd_softc*,
-						       struct ahd_linux_target*,
-						       u_int);
-static void			ahd_linux_free_device(struct ahd_softc*,
-						      struct ahd_linux_device*);
-static void ahd_linux_run_device_queue(struct ahd_softc*,
-				       struct ahd_linux_device*);
+static void ahd_linux_device_queue_depth(struct scsi_device *);
+static int ahd_linux_run_command(struct ahd_softc*,
+				 struct ahd_linux_device *,
+				 struct scsi_cmnd *);
 static void ahd_linux_setup_tag_info_global(char *p);
-static aic_option_callback_t ahd_linux_setup_tag_info;
-static aic_option_callback_t ahd_linux_setup_rd_strm_info;
-static aic_option_callback_t ahd_linux_setup_dv;
-static aic_option_callback_t ahd_linux_setup_iocell_info;
-static int ahd_linux_next_unit(void);
-static void ahd_runq_tasklet(unsigned long data);
-static int aic79xx_setup(char *c);
-
-/****************************** Inlines ***************************************/
-static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
-static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
-static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
-static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
-static __inline struct ahd_linux_device*
-		     ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
-					  u_int target, u_int lun, int alloc);
-static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
-static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
-						  struct ahd_linux_device *dev);
-static __inline struct ahd_linux_device *
-		     ahd_linux_next_device_to_run(struct ahd_softc *ahd);
-static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd);
-static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
-
-static __inline void
-ahd_schedule_completeq(struct ahd_softc *ahd)
-{
-	if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
-		ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
-		ahd->platform_data->completeq_timer.expires = jiffies;
-		add_timer(&ahd->platform_data->completeq_timer);
-	}
-}
-
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahd_schedule_runq(struct ahd_softc *ahd)
-{
-	tasklet_schedule(&ahd->platform_data->runq_tasklet);
-}
-
-static __inline
-void ahd_setup_runq_tasklet(struct ahd_softc *ahd)
-{
-	tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,
-		     (unsigned long)ahd);
-}
-
-static __inline void
-ahd_teardown_runq_tasklet(struct ahd_softc *ahd)
-{
-	tasklet_kill(&ahd->platform_data->runq_tasklet);
-}
-
-static __inline struct ahd_linux_device*
-ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
-		     u_int lun, int alloc)
-{
-	struct ahd_linux_target *targ;
-	struct ahd_linux_device *dev;
-	u_int target_offset;
-
-	target_offset = target;
-	if (channel != 0)
-		target_offset += 8;
-	targ = ahd->platform_data->targets[target_offset];
-	if (targ == NULL) {
-		if (alloc != 0) {
-			targ = ahd_linux_alloc_target(ahd, channel, target);
-			if (targ == NULL)
-				return (NULL);
-		} else
-			return (NULL);
-	}
-	dev = targ->devices[lun];
-	if (dev == NULL && alloc != 0)
-		dev = ahd_linux_alloc_device(ahd, targ, lun);
-	return (dev);
-}
-
-#define AHD_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahd_cmd *
-ahd_linux_run_complete_queue(struct ahd_softc *ahd)
-{	
-	struct	ahd_cmd *acmd;
-	u_long	done_flags;
-	int	with_errors;
-
-	with_errors = 0;
-	ahd_done_lock(ahd, &done_flags);
-	while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) {
-		Scsi_Cmnd *cmd;
-
-		if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) {
-			/*
-			 * Linux uses stack recursion to requeue
-			 * commands that need to be retried.  Avoid
-			 * blowing out the stack by "spoon feeding"
-			 * commands that completed with error back
-			 * the operating system in case they are going
-			 * to be retried. "ick"
-			 */
-			ahd_schedule_completeq(ahd);
-			break;
-		}
-		TAILQ_REMOVE(&ahd->platform_data->completeq,
-			     acmd, acmd_links.tqe);
-		cmd = &acmd_scsi_cmd(acmd);
-		cmd->host_scribble = NULL;
-		if (ahd_cmd_get_transaction_status(cmd) != DID_OK
-		 || (cmd->result & 0xFF) != SCSI_STATUS_OK)
-			with_errors++;
-
-		cmd->scsi_done(cmd);
-	}
-	ahd_done_unlock(ahd, &done_flags);
-	return (acmd);
-}
-
-static __inline void
-ahd_linux_check_device_queue(struct ahd_softc *ahd,
-			     struct ahd_linux_device *dev)
-{
-	if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0
-	 && dev->active == 0) {
-		dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY;
-		dev->qfrozen--;
-	}
-
-	if (TAILQ_FIRST(&dev->busyq) == NULL
-	 || dev->openings == 0 || dev->qfrozen != 0)
-		return;
-
-	ahd_linux_run_device_queue(ahd, dev);
-}
+static int  aic79xx_setup(char *c);
 
-static __inline struct ahd_linux_device *
-ahd_linux_next_device_to_run(struct ahd_softc *ahd)
-{
-	
-	if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0
-	 || (ahd->platform_data->qfrozen != 0
-	  && AHD_DV_SIMQ_FROZEN(ahd) == 0))
-		return (NULL);
-	return (TAILQ_FIRST(&ahd->platform_data->device_runq));
-}
+static int ahd_linux_unit;
 
-static __inline void
-ahd_linux_run_device_queues(struct ahd_softc *ahd)
-{
-	struct ahd_linux_device *dev;
 
-	while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
-		TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
-		dev->flags &= ~AHD_DEV_ON_RUN_LIST;
-		ahd_linux_check_device_queue(ahd, dev);
-	}
-}
+/****************************** Inlines ***************************************/
+static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
 
 static __inline void
 ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
 {
-	Scsi_Cmnd *cmd;
+	struct scsi_cmnd *cmd;
 	int direction;
 
 	cmd = scb->io_ctx;
@@ -705,197 +399,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ah
 #define BUILD_SCSIID(ahd, cmd)						\
 	((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)
 
-/************************  Host template entry points *************************/
-static int	   ahd_linux_detect(Scsi_Host_Template *);
-static const char *ahd_linux_info(struct Scsi_Host *);
-static int	   ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int	   ahd_linux_slave_alloc(Scsi_Device *);
-static int	   ahd_linux_slave_configure(Scsi_Device *);
-static void	   ahd_linux_slave_destroy(Scsi_Device *);
-#if defined(__i386__)
-static int	   ahd_linux_biosparam(struct scsi_device*,
-				       struct block_device*, sector_t, int[]);
-#endif
-#else
-static int	   ahd_linux_release(struct Scsi_Host *);
-static void	   ahd_linux_select_queue_depth(struct Scsi_Host *host,
-						Scsi_Device *scsi_devs);
-#if defined(__i386__)
-static int	   ahd_linux_biosparam(Disk *, kdev_t, int[]);
-#endif
-#endif
-static int	   ahd_linux_bus_reset(Scsi_Cmnd *);
-static int	   ahd_linux_dev_reset(Scsi_Cmnd *);
-static int	   ahd_linux_abort(Scsi_Cmnd *);
-
-/*
- * Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg).
- *
- * In pre-2.5.X...
- * The midlayer allocates an S/G array dynamically when a command is issued
- * using SCSI malloc.  This array, which is in an OS dependent format that
- * must later be copied to our private S/G list, is sized to house just the
- * number of segments needed for the current transfer.  Since the code that
- * sizes the SCSI malloc pool does not take into consideration fragmentation
- * of the pool, executing transactions numbering just a fraction of our
- * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will
- * quickly depleat the SCSI malloc pool of usable space.  Unfortunately, the
- * mid-layer does not properly handle this scsi malloc failures for the S/G
- * array and the result can be a lockup of the I/O subsystem.  We try to size
- * our S/G list so that it satisfies our drivers allocation requirements in
- * addition to avoiding fragmentation of the SCSI malloc pool.
- */
-static void
-ahd_linux_size_nseg(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	u_int cur_size;
-	u_int best_size;
-
-	/*
-	 * The SCSI allocator rounds to the nearest 512 bytes
-	 * an cannot allocate across a page boundary.  Our algorithm
-	 * is to start at 1K of scsi malloc space per-command and
-	 * loop through all factors of the PAGE_SIZE and pick the best.
-	 */
-	best_size = 0;
-	for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
-		u_int nseg;
-
-		nseg = cur_size / sizeof(struct scatterlist);
-		if (nseg < AHD_LINUX_MIN_NSEG)
-			continue;
-
-		if (best_size == 0) {
-			best_size = cur_size;
-			ahd_linux_nseg = nseg;
-		} else {
-			u_int best_rem;
-			u_int cur_rem;
-
-			/*
-			 * Compare the traits of the current "best_size"
-			 * with the current size to determine if the
-			 * current size is a better size.
-			 */
-			best_rem = best_size % sizeof(struct scatterlist);
-			cur_rem = cur_size % sizeof(struct scatterlist);
-			if (cur_rem < best_rem) {
-				best_size = cur_size;
-				ahd_linux_nseg = nseg;
-			}
-		}
-	}
-#endif
-}
-
-/*
- * Try to detect an Adaptec 79XX controller.
- */
-static int
-ahd_linux_detect(Scsi_Host_Template *template)
-{
-	struct	ahd_softc *ahd;
-	int     found;
-	int	error = 0;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	/*
-	 * It is a bug that the upper layer takes
-	 * this lock just prior to calling us.
-	 */
-	spin_unlock_irq(&io_request_lock);
-#endif
-
-	/*
-	 * Sanity checking of Linux SCSI data structures so
-	 * that some of our hacks^H^H^H^H^Hassumptions aren't
-	 * violated.
-	 */
-	if (offsetof(struct ahd_cmd_internal, end)
-	  > offsetof(struct scsi_cmnd, host_scribble)) {
-		printf("ahd_linux_detect: SCSI data structures changed.\n");
-		printf("ahd_linux_detect: Unable to attach\n");
-		return (0);
-	}
-	/*
-	 * Determine an appropriate size for our Scatter Gatther lists.
-	 */
-	ahd_linux_size_nseg();
-#ifdef MODULE
-	/*
-	 * If we've been passed any parameters, process them now.
-	 */
-	if (aic79xx)
-		aic79xx_setup(aic79xx);
-#endif
-
-	template->proc_name = "aic79xx";
-
-	/*
-	 * Initialize our softc list lock prior to
-	 * probing for any adapters.
-	 */
-	ahd_list_lockinit();
-
-#ifdef CONFIG_PCI
-	error = ahd_linux_pci_init();
-	if (error)
-		return error;
-#endif
-
-	/*
-	 * Register with the SCSI layer all
-	 * controllers we've found.
-	 */
-	found = 0;
-	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-
-		if (ahd_linux_register_host(ahd, template) == 0)
-			found++;
-	}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	spin_lock_irq(&io_request_lock);
-#endif
-	aic79xx_detect_complete++;
-	return 0;
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * Free the passed in Scsi_Host memory structures prior to unloading the
- * module.
- */
-static int
-ahd_linux_release(struct Scsi_Host * host)
-{
-	struct ahd_softc *ahd;
-	u_long l;
-
-	ahd_list_lock(&l);
-	if (host != NULL) {
-
-		/*
-		 * We should be able to just perform
-		 * the free directly, but check our
-		 * list for extra sanity.
-		 */
-		ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata);
-		if (ahd != NULL) {
-			u_long s;
-
-			ahd_lock(ahd, &s);
-			ahd_intr_enable(ahd, FALSE);
-			ahd_unlock(ahd, &s);
-			ahd_free(ahd);
-		}
-	}
-	ahd_list_unlock(&l);
-	return (0);
-}
-#endif
-
 /*
  * Return a string describing the driver.
  */
@@ -928,220 +431,177 @@ ahd_linux_info(struct Scsi_Host *host)
  * Queue an SCB to the controller.
  */
 static int
-ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
+ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 {
 	struct	 ahd_softc *ahd;
-	struct	 ahd_linux_device *dev;
-	u_long	 flags;
+	struct	 ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
 
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
 
 	/*
-	 * Save the callback on completion function.
-	 */
-	cmd->scsi_done = scsi_done;
-
-	ahd_midlayer_entrypoint_lock(ahd, &flags);
-
-	/*
 	 * Close the race of a command that was in the process of
 	 * being queued to us just as our simq was frozen.  Let
 	 * DV commands through so long as we are only frozen to
 	 * perform DV.
 	 */
-	if (ahd->platform_data->qfrozen != 0
-	 && AHD_DV_CMD(cmd) == 0) {
+	if (ahd->platform_data->qfrozen != 0) {
+		printf("%s: queue frozen\n", ahd_name(ahd));
 
-		ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
-		ahd_linux_queue_cmd_complete(ahd, cmd);
-		ahd_schedule_completeq(ahd);
-		ahd_midlayer_entrypoint_unlock(ahd, &flags);
-		return (0);
-	}
-	dev = ahd_linux_get_device(ahd, cmd->device->channel,
-				   cmd->device->id, cmd->device->lun,
-				   /*alloc*/TRUE);
-	if (dev == NULL) {
-		ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
-		ahd_linux_queue_cmd_complete(ahd, cmd);
-		ahd_schedule_completeq(ahd);
-		ahd_midlayer_entrypoint_unlock(ahd, &flags);
-		printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
-		       ahd_name(ahd));
-		return (0);
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
-	if (cmd->cmd_len > MAX_CDB_LEN)
-		return (-EINVAL);
+
+	/*
+	 * Save the callback on completion function.
+	 */
+	cmd->scsi_done = scsi_done;
+
 	cmd->result = CAM_REQ_INPROG << 16;
-	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe);
-	if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
-		TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
-		dev->flags |= AHD_DEV_ON_RUN_LIST;
-		ahd_linux_run_device_queues(ahd);
-	}
-	ahd_midlayer_entrypoint_unlock(ahd, &flags);
-	return (0);
+
+	return ahd_linux_run_command(ahd, dev, cmd);
+}
+
+static inline struct scsi_target **
+ahd_linux_target_in_softc(struct scsi_target *starget)
+{
+	struct	ahd_softc *ahd =
+		*((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
+	unsigned int target_offset;
+
+	target_offset = starget->id;
+	if (starget->channel != 0)
+		target_offset += 8;
+
+	return &ahd->platform_data->starget[target_offset];
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static int
-ahd_linux_slave_alloc(Scsi_Device *device)
+ahd_linux_target_alloc(struct scsi_target *starget)
 {
-	struct	ahd_softc *ahd;
+	struct	ahd_softc *ahd =
+		*((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
+	unsigned long flags;
+	struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
+	struct ahd_linux_target *targ = scsi_transport_target_data(starget);
+	struct ahd_devinfo devinfo;
+	struct ahd_initiator_tinfo *tinfo;
+	struct ahd_tmode_tstate *tstate;
+	char channel = starget->channel + 'A';
 
-	ahd = *((struct ahd_softc **)device->host->hostdata);
-	if (bootverbose)
-		printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id);
-	return (0);
+	ahd_lock(ahd, &flags);
+
+	BUG_ON(*ahd_targp != NULL);
+
+	*ahd_targp = starget;
+	memset(targ, 0, sizeof(*targ));
+
+	tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
+				    starget->id, &tstate);
+	ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
+			    CAM_LUN_WILDCARD, channel,
+			    ROLE_INITIATOR);
+	spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */
+	if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
+		spi_max_offset(starget) = MAX_OFFSET_PACED_BUG;
+	else
+		spi_max_offset(starget) = MAX_OFFSET_PACED;
+	spi_max_width(starget) = ahd->features & AHD_WIDE;
+
+	ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
+			 AHD_TRANS_GOAL, /*paused*/FALSE);
+	ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+		      AHD_TRANS_GOAL, /*paused*/FALSE);
+	ahd_unlock(ahd, &flags);
+
+	return 0;
+}
+
+static void
+ahd_linux_target_destroy(struct scsi_target *starget)
+{
+	struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
+
+	*ahd_targp = NULL;
 }
 
 static int
-ahd_linux_slave_configure(Scsi_Device *device)
+ahd_linux_slave_alloc(struct scsi_device *sdev)
 {
-	struct	ahd_softc *ahd;
-	struct	ahd_linux_device *dev;
-	u_long	flags;
+	struct	ahd_softc *ahd =
+		*((struct ahd_softc **)sdev->host->hostdata);
+	struct scsi_target *starget = sdev->sdev_target;
+	struct ahd_linux_target *targ = scsi_transport_target_data(starget);
+	struct ahd_linux_device *dev;
 
-	ahd = *((struct ahd_softc **)device->host->hostdata);
 	if (bootverbose)
-		printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id);
-	ahd_midlayer_entrypoint_lock(ahd, &flags);
+		printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
+
+	BUG_ON(targ->sdev[sdev->lun] != NULL);
+
+	dev = scsi_transport_device_data(sdev);
+	memset(dev, 0, sizeof(*dev));
+
 	/*
-	 * Since Linux has attached to the device, configure
-	 * it so we don't free and allocate the device
-	 * structure on every command.
+	 * We start out life using untagged
+	 * transactions of which we allow one.
 	 */
-	dev = ahd_linux_get_device(ahd, device->channel,
-				   device->id, device->lun,
-				   /*alloc*/TRUE);
-	if (dev != NULL) {
-		dev->flags &= ~AHD_DEV_UNCONFIGURED;
-		dev->flags |= AHD_DEV_SLAVE_CONFIGURED;
-		dev->scsi_device = device;
-		ahd_linux_device_queue_depth(ahd, dev);
-	}
-	ahd_midlayer_entrypoint_unlock(ahd, &flags);
+	dev->openings = 1;
+
+	/*
+	 * Set maxtags to 0.  This will be changed if we
+	 * later determine that we are dealing with
+	 * a tagged queuing capable device.
+	 */
+	dev->maxtags = 0;
+	
+	targ->sdev[sdev->lun] = sdev;
+
 	return (0);
 }
 
-static void
-ahd_linux_slave_destroy(Scsi_Device *device)
+static int
+ahd_linux_slave_configure(struct scsi_device *sdev)
 {
 	struct	ahd_softc *ahd;
-	struct	ahd_linux_device *dev;
-	u_long	flags;
 
-	ahd = *((struct ahd_softc **)device->host->hostdata);
+	ahd = *((struct ahd_softc **)sdev->host->hostdata);
 	if (bootverbose)
-		printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id);
-	ahd_midlayer_entrypoint_lock(ahd, &flags);
-	dev = ahd_linux_get_device(ahd, device->channel,
-				   device->id, device->lun,
-					   /*alloc*/FALSE);
+		printf("%s: Slave Configure %d\n", ahd_name(ahd), sdev->id);
 
-	/*
-	 * Filter out "silly" deletions of real devices by only
-	 * deleting devices that have had slave_configure()
-	 * called on them.  All other devices that have not
-	 * been configured will automatically be deleted by
-	 * the refcounting process.
-	 */
-	if (dev != NULL
-	 && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) {
-		dev->flags |= AHD_DEV_UNCONFIGURED;
-		if (TAILQ_EMPTY(&dev->busyq)
-		 && dev->active == 0
-		 && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
-			ahd_linux_free_device(ahd, dev);
-	}
-	ahd_midlayer_entrypoint_unlock(ahd, &flags);
+	ahd_linux_device_queue_depth(sdev);
+
+	/* Initial Domain Validation */
+	if (!spi_initial_dv(sdev->sdev_target))
+		spi_dv_device(sdev);
+
+	return 0;
 }
-#else
-/*
- * Sets the queue depth for each SCSI device hanging
- * off the input host adapter.
- */
+
 static void
-ahd_linux_select_queue_depth(struct Scsi_Host * host,
-			     Scsi_Device * scsi_devs)
+ahd_linux_slave_destroy(struct scsi_device *sdev)
 {
-	Scsi_Device *device;
-	Scsi_Device *ldev;
 	struct	ahd_softc *ahd;
-	u_long	flags;
+	struct	ahd_linux_device *dev = scsi_transport_device_data(sdev);
+	struct  ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
 
-	ahd = *((struct ahd_softc **)host->hostdata);
-	ahd_lock(ahd, &flags);
-	for (device = scsi_devs; device != NULL; device = device->next) {
+	ahd = *((struct ahd_softc **)sdev->host->hostdata);
+	if (bootverbose)
+		printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id);
 
-		/*
-		 * Watch out for duplicate devices.  This works around
-		 * some quirks in how the SCSI scanning code does its
-		 * device management.
-		 */
-		for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
-			if (ldev->host == device->host
-			 && ldev->channel == device->channel
-			 && ldev->id == device->id
-			 && ldev->lun == device->lun)
-				break;
-		}
-		/* Skip duplicate. */
-		if (ldev != device)
-			continue;
+	BUG_ON(dev->active);
 
-		if (device->host == host) {
-			struct	 ahd_linux_device *dev;
+	targ->sdev[sdev->lun] = NULL;
 
-			/*
-			 * Since Linux has attached to the device, configure
-			 * it so we don't free and allocate the device
-			 * structure on every command.
-			 */
-			dev = ahd_linux_get_device(ahd, device->channel,
-						   device->id, device->lun,
-						   /*alloc*/TRUE);
-			if (dev != NULL) {
-				dev->flags &= ~AHD_DEV_UNCONFIGURED;
-				dev->scsi_device = device;
-				ahd_linux_device_queue_depth(ahd, dev);
-				device->queue_depth = dev->openings
-						    + dev->active;
-				if ((dev->flags & (AHD_DEV_Q_BASIC
-						| AHD_DEV_Q_TAGGED)) == 0) {
-					/*
-					 * We allow the OS to queue 2 untagged
-					 * transactions to us at any time even
-					 * though we can only execute them
-					 * serially on the controller/device.
-					 * This should remove some latency.
-					 */
-					device->queue_depth = 2;
-				}
-			}
-		}
-	}
-	ahd_unlock(ahd, &flags);
 }
-#endif
 
 #if defined(__i386__)
 /*
  * Return the disk geometry for the given SCSI device.
  */
 static int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		    sector_t capacity, int geom[])
 {
 	uint8_t *bh;
-#else
-ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
-{
-	struct	scsi_device *sdev = disk->device;
-	u_long	capacity = disk->capacity;
-	struct	buffer_head *bh;
-#endif
 	int	 heads;
 	int	 sectors;
 	int	 cylinders;
@@ -1151,22 +611,11 @@ ahd_linux_biosparam(Disk *disk, kdev_t d
 
 	ahd = *((struct ahd_softc **)sdev->host->hostdata);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	bh = scsi_bios_ptable(bdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
-	bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
-#else
-	bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);
-#endif
-
 	if (bh) {
 		ret = scsi_partsize(bh, capacity,
 				    &geom[2], &geom[0], &geom[1]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 		kfree(bh);
-#else
-		brelse(bh);
-#endif
 		if (ret != -1)
 			return (ret);
 	}
@@ -1194,2581 +643,727 @@ ahd_linux_biosparam(Disk *disk, kdev_t d
  * Abort the current SCSI command(s).
  */
 static int
-ahd_linux_abort(Scsi_Cmnd *cmd)
+ahd_linux_abort(struct scsi_cmnd *cmd)
+{
+	int error;
+
+	error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT);
+	if (error != 0)
+		printf("aic79xx_abort returns 0x%x\n", error);
+	return error;
+}
+
+/*
+ * Attempt to send a target reset message to the device that timed out.
+ */
+static int
+ahd_linux_dev_reset(struct scsi_cmnd *cmd)
+{
+	int error;
+
+	error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
+	if (error != 0)
+		printf("aic79xx_dev_reset returns 0x%x\n", error);
+	return error;
+}
+
+/*
+ * Reset the SCSI bus.
+ */
+static int
+ahd_linux_bus_reset(struct scsi_cmnd *cmd)
 {
 	struct ahd_softc *ahd;
-	struct ahd_cmd *acmd;
-	struct ahd_cmd *list_acmd;
-	struct ahd_linux_device *dev;
-	struct scb *pending_scb;
 	u_long s;
-	u_int  saved_scbptr;
-	u_int  active_scbptr;
-	u_int  last_phase;
-	u_int  cdb_byte;
-	int    retval;
-	int    was_paused;
-	int    paused;
-	int    wait;
-	int    disconnected;
-	ahd_mode_state saved_modes;
+	int    found;
 
-	pending_scb = NULL;
-	paused = FALSE;
-	wait = FALSE;
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
-	acmd = (struct ahd_cmd *)cmd;
-
-	printf("%s:%d:%d:%d: Attempting to abort cmd %p:",
-	       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-	       cmd->device->lun, cmd);
-	for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
-		printf(" 0x%x", cmd->cmnd[cdb_byte]);
-	printf("\n");
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
+		printf("%s: Bus reset called for cmd %p\n",
+		       ahd_name(ahd), cmd);
+#endif
+	ahd_lock(ahd, &s);
+	found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
+				  /*initiate reset*/TRUE);
+	ahd_unlock(ahd, &s);
 
-	/*
-	 * In all versions of Linux, we have to work around
-	 * a major flaw in how the mid-layer is locked down
-	 * if we are to sleep successfully in our error handler
-	 * while allowing our interrupt handler to run.  Since
-	 * the midlayer acquires either the io_request_lock or
-	 * our lock prior to calling us, we must use the
-	 * spin_unlock_irq() method for unlocking our lock.
-	 * This will force interrupts to be enabled on the
-	 * current CPU.  Since the EH thread should not have
-	 * been running with CPU interrupts disabled other than
-	 * by acquiring either the io_request_lock or our own
-	 * lock, this *should* be safe.
-	 */
-	ahd_midlayer_entrypoint_lock(ahd, &s);
+	if (bootverbose)
+		printf("%s: SCSI bus reset delivered. "
+		       "%d SCBs aborted.\n", ahd_name(ahd), found);
 
-	/*
-	 * First determine if we currently own this command.
-	 * Start by searching the device queue.  If not found
-	 * there, check the pending_scb list.  If not found
-	 * at all, and the system wanted us to just abort the
-	 * command, return success.
-	 */
-	dev = ahd_linux_get_device(ahd, cmd->device->channel,
-				   cmd->device->id, cmd->device->lun,
-				   /*alloc*/FALSE);
+	return (SUCCESS);
+}
 
-	if (dev == NULL) {
-		/*
-		 * No target device for this command exists,
-		 * so we must not still own the command.
-		 */
-		printf("%s:%d:%d:%d: Is not an active device\n",
-		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-		       cmd->device->lun);
-		retval = SUCCESS;
-		goto no_cmd;
-	}
+struct scsi_host_template aic79xx_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "aic79xx",
+	.proc_name		= "aic79xx",
+	.proc_info		= ahd_linux_proc_info,
+	.info			= ahd_linux_info,
+	.queuecommand		= ahd_linux_queue,
+	.eh_abort_handler	= ahd_linux_abort,
+	.eh_device_reset_handler = ahd_linux_dev_reset,
+	.eh_bus_reset_handler	= ahd_linux_bus_reset,
+#if defined(__i386__)
+	.bios_param		= ahd_linux_biosparam,
+#endif
+	.can_queue		= AHD_MAX_QUEUE,
+	.this_id		= -1,
+	.cmd_per_lun		= 2,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.slave_alloc		= ahd_linux_slave_alloc,
+	.slave_configure	= ahd_linux_slave_configure,
+	.slave_destroy		= ahd_linux_slave_destroy,
+	.target_alloc		= ahd_linux_target_alloc,
+	.target_destroy		= ahd_linux_target_destroy,
+};
 
-	TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {
-		if (list_acmd == acmd)
-			break;
-	}
+/******************************** Bus DMA *************************************/
+int
+ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
+		   bus_size_t alignment, bus_size_t boundary,
+		   dma_addr_t lowaddr, dma_addr_t highaddr,
+		   bus_dma_filter_t *filter, void *filterarg,
+		   bus_size_t maxsize, int nsegments,
+		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
+{
+	bus_dma_tag_t dmat;
 
-	if (list_acmd != NULL) {
-		printf("%s:%d:%d:%d: Command found on device queue\n",
-		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-		       cmd->device->lun);
-		TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
-		cmd->result = DID_ABORT << 16;
-		ahd_linux_queue_cmd_complete(ahd, cmd);
-		retval = SUCCESS;
-		goto done;
-	}
+	dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
+	if (dmat == NULL)
+		return (ENOMEM);
 
 	/*
-	 * See if we can find a matching cmd in the pending list.
+	 * Linux is very simplistic about DMA memory.  For now don't
+	 * maintain all specification information.  Once Linux supplies
+	 * better facilities for doing these operations, or the
+	 * needs of this particular driver change, we might need to do
+	 * more here.
 	 */
-	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
-		if (pending_scb->io_ctx == cmd)
-			break;
-	}
+	dmat->alignment = alignment;
+	dmat->boundary = boundary;
+	dmat->maxsize = maxsize;
+	*ret_tag = dmat;
+	return (0);
+}
 
-	if (pending_scb == NULL) {
-		printf("%s:%d:%d:%d: Command not found\n",
-		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-		       cmd->device->lun);
-		goto no_cmd;
-	}
+void
+ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat)
+{
+	free(dmat, M_DEVBUF);
+}
 
-	if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
-		/*
-		 * We can't queue two recovery actions using the same SCB
-		 */
-		retval = FAILED;
-		goto  done;
-	}
+int
+ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
+		 int flags, bus_dmamap_t *mapp)
+{
+	*vaddr = pci_alloc_consistent(ahd->dev_softc,
+				      dmat->maxsize, mapp);
+	if (*vaddr == NULL)
+		return (ENOMEM);
+	return(0);
+}
+
+void
+ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
+		void* vaddr, bus_dmamap_t map)
+{
+	pci_free_consistent(ahd->dev_softc, dmat->maxsize,
+			    vaddr, map);
+}
 
+int
+ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
+		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
+		void *cb_arg, int flags)
+{
 	/*
-	 * Ensure that the card doesn't do anything
-	 * behind our back.  Also make sure that we
-	 * didn't "just" miss an interrupt that would
-	 * affect this cmd.
+	 * Assume for now that this will only be used during
+	 * initialization and not for per-transaction buffer mapping.
 	 */
-	was_paused = ahd_is_paused(ahd);
-	ahd_pause_and_flushwork(ahd);
-	paused = TRUE;
-
-	if ((pending_scb->flags & SCB_ACTIVE) == 0) {
-		printf("%s:%d:%d:%d: Command already completed\n",
-		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-		       cmd->device->lun);
-		goto no_cmd;
-	}
+	bus_dma_segment_t stack_sg;
 
-	printf("%s: At time of recovery, card was %spaused\n",
-	       ahd_name(ahd), was_paused ? "" : "not ");
-	ahd_dump_card_state(ahd);
+	stack_sg.ds_addr = map;
+	stack_sg.ds_len = dmat->maxsize;
+	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
+	return (0);
+}
 
-	disconnected = TRUE;
-	if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A',
-			       cmd->device->lun, SCB_GET_TAG(pending_scb),
-			       ROLE_INITIATOR, CAM_REQ_ABORTED,
-			       SEARCH_COMPLETE) > 0) {
-		printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
-		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-				cmd->device->lun);
-		retval = SUCCESS;
-		goto done;
-	}
+void
+ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+}
 
-	saved_modes = ahd_save_modes(ahd);
-	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-	last_phase = ahd_inb(ahd, LASTPHASE);
-	saved_scbptr = ahd_get_scbptr(ahd);
-	active_scbptr = saved_scbptr;
-	if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
-		struct scb *bus_scb;
+int
+ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+	/* Nothing to do */
+	return (0);
+}
 
-		bus_scb = ahd_lookup_scb(ahd, active_scbptr);
-		if (bus_scb == pending_scb)
-			disconnected = FALSE;
-	}
+/********************* Platform Dependent Functions ***************************/
+/*
+ * Compare "left hand" softc with "right hand" softc, returning:
+ * < 0 - lahd has a lower priority than rahd
+ *   0 - Softcs are equal
+ * > 0 - lahd has a higher priority than rahd
+ */
+int
+ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
+{
+	int	value;
 
 	/*
-	 * At this point, pending_scb is the scb associated with the
-	 * passed in command.  That command is currently active on the
-	 * bus or is in the disconnected state.
+	 * Under Linux, cards are ordered as follows:
+	 *	1) PCI devices that are marked as the boot controller.
+	 *	2) PCI devices with BIOS enabled sorted by bus/slot/func.
+	 *	3) All remaining PCI devices sorted by bus/slot/func.
 	 */
-	if (last_phase != P_BUSFREE
-	 && SCB_GET_TAG(pending_scb) == active_scbptr) {
-
-		/*
-		 * We're active on the bus, so assert ATN
-		 * and hope that the target responds.
-		 */
-		pending_scb = ahd_lookup_scb(ahd, active_scbptr);
-		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
-		ahd_outb(ahd, MSG_OUT, HOST_MSG);
-		ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
-		printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
-		       ahd_name(ahd), cmd->device->channel,
-		       cmd->device->id, cmd->device->lun);
-		wait = TRUE;
-	} else if (disconnected) {
-
-		/*
-		 * Actually re-queue this SCB in an attempt
-		 * to select the device before it reconnects.
-		 */
-		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
-		ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
-		pending_scb->hscb->cdb_len = 0;
-		pending_scb->hscb->task_attribute = 0;
-		pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
-
-		if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
-			/*
-			 * Mark the SCB has having an outstanding
-			 * task management function.  Should the command
-			 * complete normally before the task management
-			 * function can be sent, the host will be notified
-			 * to abort our requeued SCB.
-			 */
-			ahd_outb(ahd, SCB_TASK_MANAGEMENT,
-				 pending_scb->hscb->task_management);
-		} else {
-			/*
-			 * If non-packetized, set the MK_MESSAGE control
-			 * bit indicating that we desire to send a message.
-			 * We also set the disconnected flag since there is
-			 * no guarantee that our SCB control byte matches
-			 * the version on the card.  We don't want the
-			 * sequencer to abort the command thinking an
-			 * unsolicited reselection occurred.
-			 */
-			pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
-
-			/*
-			 * The sequencer will never re-reference the
-			 * in-core SCB.  To make sure we are notified
-			 * during reslection, set the MK_MESSAGE flag in
-			 * the card's copy of the SCB.
-			 */
-			ahd_outb(ahd, SCB_CONTROL,
-				 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
-		}
-
-		/*
-		 * Clear out any entries in the QINFIFO first
-		 * so we are the next SCB for this target
-		 * to run.
-		 */
-		ahd_search_qinfifo(ahd, cmd->device->id,
-				   cmd->device->channel + 'A', cmd->device->lun,
-				   SCB_LIST_NULL, ROLE_INITIATOR,
-				   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
-		ahd_qinfifo_requeue_tail(ahd, pending_scb);
-		ahd_set_scbptr(ahd, saved_scbptr);
-		ahd_print_path(ahd, pending_scb);
-		printf("Device is disconnected, re-queuing SCB\n");
-		wait = TRUE;
-	} else {
-		printf("%s:%d:%d:%d: Unable to deliver message\n",
-		       ahd_name(ahd), cmd->device->channel,
-		       cmd->device->id, cmd->device->lun);
-		retval = FAILED;
-		goto done;
-	}
-
-no_cmd:
-	/*
-	 * Our assumption is that if we don't have the command, no
-	 * recovery action was required, so we return success.  Again,
-	 * the semantics of the mid-layer recovery engine are not
-	 * well defined, so this may change in time.
-	 */
-	retval = SUCCESS;
-done:
-	if (paused)
-		ahd_unpause(ahd);
-	if (wait) {
-		struct timer_list timer;
-		int ret;
-
-		pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
-		spin_unlock_irq(&ahd->platform_data->spin_lock);
-		init_timer(&timer);
-		timer.data = (u_long)pending_scb;
-		timer.expires = jiffies + (5 * HZ);
-		timer.function = ahd_linux_sem_timeout;
-		add_timer(&timer);
-		printf("Recovery code sleeping\n");
-		down(&ahd->platform_data->eh_sem);
-		printf("Recovery code awake\n");
-        	ret = del_timer_sync(&timer);
-		if (ret == 0) {
-			printf("Timer Expired\n");
-			retval = FAILED;
-		}
-		spin_lock_irq(&ahd->platform_data->spin_lock);
-	}
-	ahd_schedule_runq(ahd);
-	ahd_linux_run_complete_queue(ahd);
-	ahd_midlayer_entrypoint_unlock(ahd, &s);
-	return (retval);
-}
-
-
-static void
-ahd_linux_dev_reset_complete(Scsi_Cmnd *cmd)
-{
-	free(cmd, M_DEVBUF);
-}
-
-/*
- * Attempt to send a target reset message to the device that timed out.
- */
-static int
-ahd_linux_dev_reset(Scsi_Cmnd *cmd)
-{
-	struct	ahd_softc *ahd;
-	struct	scsi_cmnd *recovery_cmd;
-	struct	ahd_linux_device *dev;
-	struct	ahd_initiator_tinfo *tinfo;
-	struct	ahd_tmode_tstate *tstate;
-	struct	scb *scb;
-	struct	hardware_scb *hscb;
-	u_long	s;
-	struct	timer_list timer;
-	int	retval;
-
-	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
-	recovery_cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
-	if (!recovery_cmd)
-		return (FAILED);
-	memset(recovery_cmd, 0, sizeof(struct scsi_cmnd));
-	recovery_cmd->device = cmd->device;
-	recovery_cmd->scsi_done = ahd_linux_dev_reset_complete;
-#ifdef AHD_DEBUG
-	if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
-		printf("%s:%d:%d:%d: Device reset called for cmd %p\n",
-		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-		       cmd->device->lun, cmd);
-#endif
-	ahd_lock(ahd, &s);
-
-	dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id,
-				   cmd->device->lun, /*alloc*/FALSE);
-	if (dev == NULL) {
-		ahd_unlock(ahd, &s);
-		kfree(recovery_cmd);
-		return (FAILED);
-	}
-	if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) {
-		ahd_unlock(ahd, &s);
-		kfree(recovery_cmd);
-		return (FAILED);
-	}
-	tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
-				    cmd->device->id, &tstate);
-	recovery_cmd->result = CAM_REQ_INPROG << 16;
-	recovery_cmd->host_scribble = (char *)scb;
-	scb->io_ctx = recovery_cmd;
-	scb->platform_data->dev = dev;
-	scb->sg_count = 0;
-	ahd_set_residual(scb, 0);
-	ahd_set_sense_residual(scb, 0);
-	hscb = scb->hscb;
-	hscb->control = 0;
-	hscb->scsiid = BUILD_SCSIID(ahd, cmd);
-	hscb->lun = cmd->device->lun;
-	hscb->cdb_len = 0;
-	hscb->task_management = SIU_TASKMGMT_LUN_RESET;
-	scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE;
-	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
-		scb->flags |= SCB_PACKETIZED;
-	} else {
-		hscb->control |= MK_MESSAGE;
-	}
-	dev->openings--;
-	dev->active++;
-	dev->commands_issued++;
-	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
-	ahd_queue_scb(ahd, scb);
-
-	scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
-	ahd_unlock(ahd, &s);
-	init_timer(&timer);
-	timer.data = (u_long)scb;
-	timer.expires = jiffies + (5 * HZ);
-	timer.function = ahd_linux_sem_timeout;
-	add_timer(&timer);
-	printf("Recovery code sleeping\n");
-	down(&ahd->platform_data->eh_sem);
-	printf("Recovery code awake\n");
-	retval = SUCCESS;
-	if (del_timer_sync(&timer) == 0) {
-		printf("Timer Expired\n");
-		retval = FAILED;
-	}
-	ahd_lock(ahd, &s);
-	ahd_schedule_runq(ahd);
-	ahd_linux_run_complete_queue(ahd);
-	ahd_unlock(ahd, &s);
-	printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
-	return (retval);
-}
-
-/*
- * Reset the SCSI bus.
- */
-static int
-ahd_linux_bus_reset(Scsi_Cmnd *cmd)
-{
-	struct ahd_softc *ahd;
-	u_long s;
-	int    found;
-
-	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
-#ifdef AHD_DEBUG
-	if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
-		printf("%s: Bus reset called for cmd %p\n",
-		       ahd_name(ahd), cmd);
-#endif
-	ahd_lock(ahd, &s);
-	found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
-				  /*initiate reset*/TRUE);
-	ahd_linux_run_complete_queue(ahd);
-	ahd_unlock(ahd, &s);
-
-	if (bootverbose)
-		printf("%s: SCSI bus reset delivered. "
-		       "%d SCBs aborted.\n", ahd_name(ahd), found);
-
-	return (SUCCESS);
-}
-
-Scsi_Host_Template aic79xx_driver_template = {
-	.module			= THIS_MODULE,
-	.name			= "aic79xx",
-	.proc_info		= ahd_linux_proc_info,
-	.info			= ahd_linux_info,
-	.queuecommand		= ahd_linux_queue,
-	.eh_abort_handler	= ahd_linux_abort,
-	.eh_device_reset_handler = ahd_linux_dev_reset,
-	.eh_bus_reset_handler	= ahd_linux_bus_reset,
-#if defined(__i386__)
-	.bios_param		= ahd_linux_biosparam,
-#endif
-	.can_queue		= AHD_MAX_QUEUE,
-	.this_id		= -1,
-	.cmd_per_lun		= 2,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.slave_alloc		= ahd_linux_slave_alloc,
-	.slave_configure	= ahd_linux_slave_configure,
-	.slave_destroy		= ahd_linux_slave_destroy,
-};
-
-/**************************** Tasklet Handler *********************************/
-
-/*
- * In 2.4.X and above, this routine is called from a tasklet,
- * so we must re-acquire our lock prior to executing this code.
- * In all prior kernels, ahd_schedule_runq() calls this routine
- * directly and ahd_schedule_runq() is called with our lock held.
- */
-static void
-ahd_runq_tasklet(unsigned long data)
-{
-	struct ahd_softc* ahd;
-	struct ahd_linux_device *dev;
-	u_long flags;
-
-	ahd = (struct ahd_softc *)data;
-	ahd_lock(ahd, &flags);
-	while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
-	
-		TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
-		dev->flags &= ~AHD_DEV_ON_RUN_LIST;
-		ahd_linux_check_device_queue(ahd, dev);
-		/* Yeild to our interrupt handler */
-		ahd_unlock(ahd, &flags);
-		ahd_lock(ahd, &flags);
-	}
-	ahd_unlock(ahd, &flags);
-}
-
-/******************************** Bus DMA *************************************/
-int
-ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
-		   bus_size_t alignment, bus_size_t boundary,
-		   dma_addr_t lowaddr, dma_addr_t highaddr,
-		   bus_dma_filter_t *filter, void *filterarg,
-		   bus_size_t maxsize, int nsegments,
-		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
-{
-	bus_dma_tag_t dmat;
-
-	dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
-	if (dmat == NULL)
-		return (ENOMEM);
-
-	/*
-	 * Linux is very simplistic about DMA memory.  For now don't
-	 * maintain all specification information.  Once Linux supplies
-	 * better facilities for doing these operations, or the
-	 * needs of this particular driver change, we might need to do
-	 * more here.
-	 */
-	dmat->alignment = alignment;
-	dmat->boundary = boundary;
-	dmat->maxsize = maxsize;
-	*ret_tag = dmat;
-	return (0);
-}
-
-void
-ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat)
-{
-	free(dmat, M_DEVBUF);
-}
-
-int
-ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
-		 int flags, bus_dmamap_t *mapp)
-{
-	bus_dmamap_t map;
-
-	map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
-	if (map == NULL)
-		return (ENOMEM);
-	/*
-	 * Although we can dma data above 4GB, our
-	 * "consistent" memory is below 4GB for
-	 * space efficiency reasons (only need a 4byte
-	 * address).  For this reason, we have to reset
-	 * our dma mask when doing allocations.
-	 */
-	if (ahd->dev_softc != NULL)
-		if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) {
-			printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
-			kfree(map);
-			return (ENODEV);
-		}
-	*vaddr = pci_alloc_consistent(ahd->dev_softc,
-				      dmat->maxsize, &map->bus_addr);
-	if (ahd->dev_softc != NULL)
-		if (pci_set_dma_mask(ahd->dev_softc,
-				     ahd->platform_data->hw_dma_mask)) {
-			printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
-			kfree(map);
-			return (ENODEV);
-		}
-	if (*vaddr == NULL)
-		return (ENOMEM);
-	*mapp = map;
-	return(0);
-}
-
-void
-ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
-		void* vaddr, bus_dmamap_t map)
-{
-	pci_free_consistent(ahd->dev_softc, dmat->maxsize,
-			    vaddr, map->bus_addr);
-}
-
-int
-ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
-		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
-		void *cb_arg, int flags)
-{
-	/*
-	 * Assume for now that this will only be used during
-	 * initialization and not for per-transaction buffer mapping.
-	 */
-	bus_dma_segment_t stack_sg;
-
-	stack_sg.ds_addr = map->bus_addr;
-	stack_sg.ds_len = dmat->maxsize;
-	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
-	return (0);
-}
-
-void
-ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
-{
-	/*
-	 * The map may is NULL in our < 2.3.X implementation.
-	 */
-	if (map != NULL)
-		free(map, M_DEVBUF);
-}
-
-int
-ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
-{
-	/* Nothing to do */
-	return (0);
-}
-
-/********************* Platform Dependent Functions ***************************/
-/*
- * Compare "left hand" softc with "right hand" softc, returning:
- * < 0 - lahd has a lower priority than rahd
- *   0 - Softcs are equal
- * > 0 - lahd has a higher priority than rahd
- */
-int
-ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
-{
-	int	value;
-
-	/*
-	 * Under Linux, cards are ordered as follows:
-	 *	1) PCI devices that are marked as the boot controller.
-	 *	2) PCI devices with BIOS enabled sorted by bus/slot/func.
-	 *	3) All remaining PCI devices sorted by bus/slot/func.
-	 */
-#if 0
-	value = (lahd->flags & AHD_BOOT_CHANNEL)
-	      - (rahd->flags & AHD_BOOT_CHANNEL);
-	if (value != 0)
-		/* Controllers set for boot have a *higher* priority */
-		return (value);
-#endif
-
-	value = (lahd->flags & AHD_BIOS_ENABLED)
-	      - (rahd->flags & AHD_BIOS_ENABLED);
-	if (value != 0)
-		/* Controllers with BIOS enabled have a *higher* priority */
-		return (value);
-
-	/* Still equal.  Sort by bus/slot/func. */
-	if (aic79xx_reverse_scan != 0)
-		value = ahd_get_pci_bus(lahd->dev_softc)
-		      - ahd_get_pci_bus(rahd->dev_softc);
-	else
-		value = ahd_get_pci_bus(rahd->dev_softc)
-		      - ahd_get_pci_bus(lahd->dev_softc);
-	if (value != 0)
-		return (value);
-	if (aic79xx_reverse_scan != 0)
-		value = ahd_get_pci_slot(lahd->dev_softc)
-		      - ahd_get_pci_slot(rahd->dev_softc);
-	else
-		value = ahd_get_pci_slot(rahd->dev_softc)
-		      - ahd_get_pci_slot(lahd->dev_softc);
-	if (value != 0)
-		return (value);
-
-	value = rahd->channel - lahd->channel;
-	return (value);
-}
-
-static void
-ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
-{
-
-	if ((instance >= 0) && (targ >= 0)
-	 && (instance < NUM_ELEMENTS(aic79xx_tag_info))
-	 && (targ < AHD_NUM_TARGETS)) {
-		aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
-		if (bootverbose)
-			printf("tag_info[%d:%d] = %d\n", instance, targ, value);
-	}
-}
-
-static void
-ahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value)
-{
-	if ((instance >= 0)
-	 && (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) {
-		aic79xx_rd_strm_info[instance] = value & 0xFFFF;
-		if (bootverbose)
-			printf("rd_strm[%d] = 0x%x\n", instance, value);
-	}
-}
-
-static void
-ahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
-{
-	if ((instance >= 0)
-	 && (instance < NUM_ELEMENTS(aic79xx_dv_settings))) {
-		aic79xx_dv_settings[instance] = value;
-		if (bootverbose)
-			printf("dv[%d] = %d\n", instance, value);
-	}
-}
-
-static void
-ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
-{
-
-	if ((instance >= 0)
-	 && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) {
-		uint8_t *iocell_info;
-
-		iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];
-		iocell_info[index] = value & 0xFFFF;
-		if (bootverbose)
-			printf("iocell[%d:%ld] = %d\n", instance, index, value);
-	}
-}
-
-static void
-ahd_linux_setup_tag_info_global(char *p)
-{
-	int tags, i, j;
-
-	tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
-	printf("Setting Global Tags= %d\n", tags);
-
-	for (i = 0; i < NUM_ELEMENTS(aic79xx_tag_info); i++) {
-		for (j = 0; j < AHD_NUM_TARGETS; j++) {
-			aic79xx_tag_info[i].tag_commands[j] = tags;
-		}
-	}
-}
-
-/*
- * Handle Linux boot parameters. This routine allows for assigning a value
- * to a parameter with a ':' between the parameter and the value.
- * ie. aic79xx=stpwlev:1,extended
- */
-static int
-aic79xx_setup(char *s)
-{
-	int	i, n;
-	char   *p;
-	char   *end;
-
-	static struct {
-		const char *name;
-		uint32_t *flag;
-	} options[] = {
-		{ "extended", &aic79xx_extended },
-		{ "no_reset", &aic79xx_no_reset },
-		{ "verbose", &aic79xx_verbose },
-		{ "allow_memio", &aic79xx_allow_memio},
-#ifdef AHD_DEBUG
-		{ "debug", &ahd_debug },
-#endif
-		{ "reverse_scan", &aic79xx_reverse_scan },
-		{ "periodic_otag", &aic79xx_periodic_otag },
-		{ "pci_parity", &aic79xx_pci_parity },
-		{ "seltime", &aic79xx_seltime },
-		{ "tag_info", NULL },
-		{ "global_tag_depth", NULL},
-		{ "rd_strm", NULL },
-		{ "dv", NULL },
-		{ "slewrate", NULL },
-		{ "precomp", NULL },
-		{ "amplitude", NULL },
-	};
-
-	end = strchr(s, '\0');
-
-	/*
-	 * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS
-	 * will never be 0 in this case.
-	 */      
-	n = 0;  
-
-	while ((p = strsep(&s, ",.")) != NULL) {
-		if (*p == '\0')
-			continue;
-		for (i = 0; i < NUM_ELEMENTS(options); i++) {
-
-			n = strlen(options[i].name);
-			if (strncmp(options[i].name, p, n) == 0)
-				break;
-		}
-		if (i == NUM_ELEMENTS(options))
-			continue;
-
-		if (strncmp(p, "global_tag_depth", n) == 0) {
-			ahd_linux_setup_tag_info_global(p + n);
-		} else if (strncmp(p, "tag_info", n) == 0) {
-			s = aic_parse_brace_option("tag_info", p + n, end,
-			    2, ahd_linux_setup_tag_info, 0);
-		} else if (strncmp(p, "rd_strm", n) == 0) {
-			s = aic_parse_brace_option("rd_strm", p + n, end,
-			    1, ahd_linux_setup_rd_strm_info, 0);
-		} else if (strncmp(p, "dv", n) == 0) {
-			s = aic_parse_brace_option("dv", p + n, end, 1,
-			    ahd_linux_setup_dv, 0);
-		} else if (strncmp(p, "slewrate", n) == 0) {
-			s = aic_parse_brace_option("slewrate",
-			    p + n, end, 1, ahd_linux_setup_iocell_info,
-			    AIC79XX_SLEWRATE_INDEX);
-		} else if (strncmp(p, "precomp", n) == 0) {
-			s = aic_parse_brace_option("precomp",
-			    p + n, end, 1, ahd_linux_setup_iocell_info,
-			    AIC79XX_PRECOMP_INDEX);
-		} else if (strncmp(p, "amplitude", n) == 0) {
-			s = aic_parse_brace_option("amplitude",
-			    p + n, end, 1, ahd_linux_setup_iocell_info,
-			    AIC79XX_AMPLITUDE_INDEX);
-		} else if (p[n] == ':') {
-			*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
-		} else if (!strncmp(p, "verbose", n)) {
-			*(options[i].flag) = 1;
-		} else {
-			*(options[i].flag) ^= 0xFFFFFFFF;
-		}
-	}
-	return 1;
-}
-
-__setup("aic79xx=", aic79xx_setup);
-
-uint32_t aic79xx_verbose;
-
-int
-ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
-{
-	char	buf[80];
-	struct	Scsi_Host *host;
-	char	*new_name;
-	u_long	s;
-	u_long	target;
-
-	template->name = ahd->description;
-	host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
-	if (host == NULL)
-		return (ENOMEM);
-
-	*((struct ahd_softc **)host->hostdata) = ahd;
-	ahd_lock(ahd, &s);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	scsi_assign_lock(host, &ahd->platform_data->spin_lock);
-#elif AHD_SCSI_HAS_HOST_LOCK != 0
-	host->lock = &ahd->platform_data->spin_lock;
-#endif
-	ahd->platform_data->host = host;
-	host->can_queue = AHD_MAX_QUEUE;
-	host->cmd_per_lun = 2;
-	host->sg_tablesize = AHD_NSEG;
-	host->this_id = ahd->our_id;
-	host->irq = ahd->platform_data->irq;
-	host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
-	host->max_lun = AHD_NUM_LUNS;
-	host->max_channel = 0;
-	host->sg_tablesize = AHD_NSEG;
-	ahd_set_unit(ahd, ahd_linux_next_unit());
-	sprintf(buf, "scsi%d", host->host_no);
-	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
-	if (new_name != NULL) {
-		strcpy(new_name, buf);
-		ahd_set_name(ahd, new_name);
-	}
-	host->unique_id = ahd->unit;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	scsi_set_pci_device(host, ahd->dev_softc);
-#endif
-	ahd_linux_setup_user_rd_strm_settings(ahd);
-	ahd_linux_initialize_scsi_bus(ahd);
-	ahd_unlock(ahd, &s);
-	ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0);
-	ahd_lock(ahd, &s);
-	if (ahd->platform_data->dv_pid < 0) {
-		printf("%s: Failed to create DV thread, error= %d\n",
-		       ahd_name(ahd), ahd->platform_data->dv_pid);
-		return (-ahd->platform_data->dv_pid);
-	}
-	/*
-	 * Initially allocate *all* of our linux target objects
-	 * so that the DV thread will scan them all in parallel
-	 * just after driver initialization.  Any device that
-	 * does not exist will have its target object destroyed
-	 * by the selection timeout handler.  In the case of a
-	 * device that appears after the initial DV scan, async
-	 * negotiation will occur for the first command, and DV
-	 * will comence should that first command be successful.
-	 */
-	for (target = 0; target < host->max_id; target++) {
-
-		/*
-		 * Skip our own ID.  Some Compaq/HP storage devices
-		 * have enclosure management devices that respond to
-		 * single bit selection (i.e. selecting ourselves).
-		 * It is expected that either an external application
-		 * or a modified kernel will be used to probe this
-		 * ID if it is appropriate.  To accommodate these
-		 * installations, ahc_linux_alloc_target() will allocate
-		 * for our ID if asked to do so.
-		 */
-		if (target == ahd->our_id) 
-			continue;
-
-		ahd_linux_alloc_target(ahd, 0, target);
-	}
-	ahd_intr_enable(ahd, TRUE);
-	ahd_linux_start_dv(ahd);
-	ahd_unlock(ahd, &s);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
-	scsi_scan_host(host);
-#endif
-	return (0);
-}
-
-uint64_t
-ahd_linux_get_memsize(void)
-{
-	struct sysinfo si;
-
-	si_meminfo(&si);
-	return ((uint64_t)si.totalram << PAGE_SHIFT);
-}
-
-/*
- * Find the smallest available unit number to use
- * for a new device.  We don't just use a static
- * count to handle the "repeated hot-(un)plug"
- * scenario.
- */
-static int
-ahd_linux_next_unit(void)
-{
-	struct ahd_softc *ahd;
-	int unit;
-
-	unit = 0;
-retry:
-	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-		if (ahd->unit == unit) {
-			unit++;
-			goto retry;
-		}
-	}
-	return (unit);
-}
-
-/*
- * Place the SCSI bus into a known state by either resetting it,
- * or forcing transfer negotiations on the next command to any
- * target.
- */
-static void
-ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
-{
-	u_int target_id;
-	u_int numtarg;
-
-	target_id = 0;
-	numtarg = 0;
-
-	if (aic79xx_no_reset != 0)
-		ahd->flags &= ~AHD_RESET_BUS_A;
-
-	if ((ahd->flags & AHD_RESET_BUS_A) != 0)
-		ahd_reset_channel(ahd, 'A', /*initiate_reset*/TRUE);
-	else
-		numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
-
-	/*
-	 * Force negotiation to async for all targets that
-	 * will not see an initial bus reset.
-	 */
-	for (; target_id < numtarg; target_id++) {
-		struct ahd_devinfo devinfo;
-		struct ahd_initiator_tinfo *tinfo;
-		struct ahd_tmode_tstate *tstate;
-
-		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
-					    target_id, &tstate);
-		ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
-				    CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
-		ahd_update_neg_request(ahd, &devinfo, tstate,
-				       tinfo, AHD_NEG_ALWAYS);
-	}
-	/* Give the bus some time to recover */
-	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
-		ahd_freeze_simq(ahd);
-		init_timer(&ahd->platform_data->reset_timer);
-		ahd->platform_data->reset_timer.data = (u_long)ahd;
-		ahd->platform_data->reset_timer.expires =
-		    jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
-		ahd->platform_data->reset_timer.function =
-		    (ahd_linux_callback_t *)ahd_release_simq;
-		add_timer(&ahd->platform_data->reset_timer);
-	}
-}
-
-int
-ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
-{
-	ahd->platform_data =
-	    malloc(sizeof(struct ahd_platform_data), M_DEVBUF, M_NOWAIT);
-	if (ahd->platform_data == NULL)
-		return (ENOMEM);
-	memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
-	TAILQ_INIT(&ahd->platform_data->completeq);
-	TAILQ_INIT(&ahd->platform_data->device_runq);
-	ahd->platform_data->irq = AHD_LINUX_NOIRQ;
-	ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;
-	ahd_lockinit(ahd);
-	ahd_done_lockinit(ahd);
-	init_timer(&ahd->platform_data->completeq_timer);
-	ahd->platform_data->completeq_timer.data = (u_long)ahd;
-	ahd->platform_data->completeq_timer.function =
-	    (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue;
-	init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
-	init_MUTEX_LOCKED(&ahd->platform_data->dv_sem);
-	init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem);
-	ahd_setup_runq_tasklet(ahd);
-	ahd->seltime = (aic79xx_seltime & 0x3) << 4;
-	return (0);
-}
-
-void
-ahd_platform_free(struct ahd_softc *ahd)
-{
-	struct ahd_linux_target *targ;
-	struct ahd_linux_device *dev;
-	int i, j;
-
-	if (ahd->platform_data != NULL) {
-		del_timer_sync(&ahd->platform_data->completeq_timer);
-		ahd_linux_kill_dv_thread(ahd);
-		ahd_teardown_runq_tasklet(ahd);
-		if (ahd->platform_data->host != NULL) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-			scsi_remove_host(ahd->platform_data->host);
-#endif
-			scsi_host_put(ahd->platform_data->host);
-		}
-
-		/* destroy all of the device and target objects */
-		for (i = 0; i < AHD_NUM_TARGETS; i++) {
-			targ = ahd->platform_data->targets[i];
-			if (targ != NULL) {
-				/* Keep target around through the loop. */
-				targ->refcount++;
-				for (j = 0; j < AHD_NUM_LUNS; j++) {
-
-					if (targ->devices[j] == NULL)
-						continue;
-					dev = targ->devices[j];
-					ahd_linux_free_device(ahd, dev);
-				}
-				/*
-				 * Forcibly free the target now that
-				 * all devices are gone.
-				 */
-				ahd_linux_free_target(ahd, targ);
-			}
-		}
-
-		if (ahd->platform_data->irq != AHD_LINUX_NOIRQ)
-			free_irq(ahd->platform_data->irq, ahd);
-		if (ahd->tags[0] == BUS_SPACE_PIO
-		 && ahd->bshs[0].ioport != 0)
-			release_region(ahd->bshs[0].ioport, 256);
-		if (ahd->tags[1] == BUS_SPACE_PIO
-		 && ahd->bshs[1].ioport != 0)
-			release_region(ahd->bshs[1].ioport, 256);
-		if (ahd->tags[0] == BUS_SPACE_MEMIO
-		 && ahd->bshs[0].maddr != NULL) {
-			iounmap(ahd->bshs[0].maddr);
-			release_mem_region(ahd->platform_data->mem_busaddr,
-					   0x1000);
-		}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-    		/*
-		 * In 2.4 we detach from the scsi midlayer before the PCI
-		 * layer invokes our remove callback.  No per-instance
-		 * detach is provided, so we must reach inside the PCI
-		 * subsystem's internals and detach our driver manually.
-		 */
-		if (ahd->dev_softc != NULL)
-			ahd->dev_softc->driver = NULL;
-#endif
-		free(ahd->platform_data, M_DEVBUF);
-	}
-}
-
-void
-ahd_platform_init(struct ahd_softc *ahd)
-{
-	/*
-	 * Lookup and commit any modified IO Cell options.
-	 */
-	if (ahd->unit < NUM_ELEMENTS(aic79xx_iocell_info)) {
-		struct ahd_linux_iocell_opts *iocell_opts;
-
-		iocell_opts = &aic79xx_iocell_info[ahd->unit];
-		if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
-			AHD_SET_PRECOMP(ahd, iocell_opts->precomp);
-		if (iocell_opts->slewrate != AIC79XX_DEFAULT_SLEWRATE)
-			AHD_SET_SLEWRATE(ahd, iocell_opts->slewrate);
-		if (iocell_opts->amplitude != AIC79XX_DEFAULT_AMPLITUDE)
-			AHD_SET_AMPLITUDE(ahd, iocell_opts->amplitude);
-	}
-
-}
-
-void
-ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
-{
-	ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
-				SCB_GET_CHANNEL(ahd, scb),
-				SCB_GET_LUN(scb), SCB_LIST_NULL,
-				ROLE_UNKNOWN, CAM_REQUEUE_REQ);
-}
-
-void
-ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
-		      ahd_queue_alg alg)
-{
-	struct ahd_linux_device *dev;
-	int was_queuing;
-	int now_queuing;
-
-	dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',
-				   devinfo->target,
-				   devinfo->lun, /*alloc*/FALSE);
-	if (dev == NULL)
-		return;
-	was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
-	switch (alg) {
-	default:
-	case AHD_QUEUE_NONE:
-		now_queuing = 0;
-		break; 
-	case AHD_QUEUE_BASIC:
-		now_queuing = AHD_DEV_Q_BASIC;
-		break;
-	case AHD_QUEUE_TAGGED:
-		now_queuing = AHD_DEV_Q_TAGGED;
-		break;
-	}
-	if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0
-	 && (was_queuing != now_queuing)
-	 && (dev->active != 0)) {
-		dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY;
-		dev->qfrozen++;
-	}
-
-	dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);
-	if (now_queuing) {
-		u_int usertags;
-
-		usertags = ahd_linux_user_tagdepth(ahd, devinfo);
-		if (!was_queuing) {
-			/*
-			 * Start out agressively and allow our
-			 * dynamic queue depth algorithm to take
-			 * care of the rest.
-			 */
-			dev->maxtags = usertags;
-			dev->openings = dev->maxtags - dev->active;
-		}
-		if (dev->maxtags == 0) {
-			/*
-			 * Queueing is disabled by the user.
-			 */
-			dev->openings = 1;
-		} else if (alg == AHD_QUEUE_TAGGED) {
-			dev->flags |= AHD_DEV_Q_TAGGED;
-			if (aic79xx_periodic_otag != 0)
-				dev->flags |= AHD_DEV_PERIODIC_OTAG;
-		} else
-			dev->flags |= AHD_DEV_Q_BASIC;
-	} else {
-		/* We can only have one opening. */
-		dev->maxtags = 0;
-		dev->openings =  1 - dev->active;
-	}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	if (dev->scsi_device != NULL) {
-		switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
-		case AHD_DEV_Q_BASIC:
-			scsi_adjust_queue_depth(dev->scsi_device,
-						MSG_SIMPLE_TASK,
-						dev->openings + dev->active);
-			break;
-		case AHD_DEV_Q_TAGGED:
-			scsi_adjust_queue_depth(dev->scsi_device,
-						MSG_ORDERED_TASK,
-						dev->openings + dev->active);
-			break;
-		default:
-			/*
-			 * We allow the OS to queue 2 untagged transactions to
-			 * us at any time even though we can only execute them
-			 * serially on the controller/device.  This should
-			 * remove some latency.
-			 */
-			scsi_adjust_queue_depth(dev->scsi_device,
-						/*NON-TAGGED*/0,
-						/*queue depth*/2);
-			break;
-		}
-	}
-#endif
-}
-
-int
-ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
-			int lun, u_int tag, role_t role, uint32_t status)
-{
-	int targ;
-	int maxtarg;
-	int maxlun;
-	int clun;
-	int count;
-
-	if (tag != SCB_LIST_NULL)
-		return (0);
-
-	targ = 0;
-	if (target != CAM_TARGET_WILDCARD) {
-		targ = target;
-		maxtarg = targ + 1;
-	} else {
-		maxtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
-	}
-	clun = 0;
-	if (lun != CAM_LUN_WILDCARD) {
-		clun = lun;
-		maxlun = clun + 1;
-	} else {
-		maxlun = AHD_NUM_LUNS;
-	}
-
-	count = 0;
-	for (; targ < maxtarg; targ++) {
-
-		for (; clun < maxlun; clun++) {
-			struct ahd_linux_device *dev;
-			struct ahd_busyq *busyq;
-			struct ahd_cmd *acmd;
-
-			dev = ahd_linux_get_device(ahd, /*chan*/0, targ,
-						   clun, /*alloc*/FALSE);
-			if (dev == NULL)
-				continue;
-
-			busyq = &dev->busyq;
-			while ((acmd = TAILQ_FIRST(busyq)) != NULL) {
-				Scsi_Cmnd *cmd;
-
-				cmd = &acmd_scsi_cmd(acmd);
-				TAILQ_REMOVE(busyq, acmd,
-					     acmd_links.tqe);
-				count++;
-				cmd->result = status << 16;
-				ahd_linux_queue_cmd_complete(ahd, cmd);
-			}
-		}
-	}
-
-	return (count);
-}
-
-static void
-ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd)
-{
-	u_long flags;
-
-	ahd_lock(ahd, &flags);
-	del_timer(&ahd->platform_data->completeq_timer);
-	ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER;
-	ahd_linux_run_complete_queue(ahd);
-	ahd_unlock(ahd, &flags);
-}
-
-static void
-ahd_linux_start_dv(struct ahd_softc *ahd)
-{
-
-	/*
-	 * Freeze the simq and signal ahd_linux_queue to not let any
-	 * more commands through
-	 */
-	if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) {
-#ifdef AHD_DEBUG
-		if (ahd_debug & AHD_SHOW_DV)
-			printf("%s: Starting DV\n", ahd_name(ahd));
-#endif
-
-		ahd->platform_data->flags |= AHD_DV_ACTIVE;
-		ahd_freeze_simq(ahd);
-
-		/* Wake up the DV kthread */
-		up(&ahd->platform_data->dv_sem);
-	}
-}
-
-static int
-ahd_linux_dv_thread(void *data)
-{
-	struct	ahd_softc *ahd;
-	int	target;
-	u_long	s;
-
-	ahd = (struct ahd_softc *)data;
-
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV)
-		printf("In DV Thread\n");
-#endif
-
-	/*
-	 * Complete thread creation.
-	 */
-	lock_kernel();
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
-	/*
-	 * Don't care about any signals.
-	 */
-	siginitsetinv(&current->blocked, 0);
-
-	daemonize();
-	sprintf(current->comm, "ahd_dv_%d", ahd->unit);
-#else
-	daemonize("ahd_dv_%d", ahd->unit);
-	current->flags |= PF_NOFREEZE;
-#endif
-	unlock_kernel();
-
-	while (1) {
-		/*
-		 * Use down_interruptible() rather than down() to
-		 * avoid inclusion in the load average.
-		 */
-		down_interruptible(&ahd->platform_data->dv_sem);
-
-		/* Check to see if we've been signaled to exit */
-		ahd_lock(ahd, &s);
-		if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) {
-			ahd_unlock(ahd, &s);
-			break;
-		}
-		ahd_unlock(ahd, &s);
-
-#ifdef AHD_DEBUG
-		if (ahd_debug & AHD_SHOW_DV)
-			printf("%s: Beginning Domain Validation\n",
-			       ahd_name(ahd));
+#if 0
+	value = (lahd->flags & AHD_BOOT_CHANNEL)
+	      - (rahd->flags & AHD_BOOT_CHANNEL);
+	if (value != 0)
+		/* Controllers set for boot have a *higher* priority */
+		return (value);
 #endif
 
-		/*
-		 * Wait for any pending commands to drain before proceeding.
-		 */
-		ahd_lock(ahd, &s);
-		while (LIST_FIRST(&ahd->pending_scbs) != NULL) {
-			ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY;
-			ahd_unlock(ahd, &s);
-			down_interruptible(&ahd->platform_data->dv_sem);
-			ahd_lock(ahd, &s);
-		}
-
-		/*
-		 * Wait for the SIMQ to be released so that DV is the
-		 * only reason the queue is frozen.
-		 */
-		while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
-			ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
-			ahd_unlock(ahd, &s);
-			down_interruptible(&ahd->platform_data->dv_sem);
-			ahd_lock(ahd, &s);
-		}
-		ahd_unlock(ahd, &s);
-
-		for (target = 0; target < AHD_NUM_TARGETS; target++)
-			ahd_linux_dv_target(ahd, target);
-
-		ahd_lock(ahd, &s);
-		ahd->platform_data->flags &= ~AHD_DV_ACTIVE;
-		ahd_unlock(ahd, &s);
-
-		/*
-		 * Release the SIMQ so that normal commands are
-		 * allowed to continue on the bus.
-		 */
-		ahd_release_simq(ahd);
-	}
-	up(&ahd->platform_data->eh_sem);
-	return (0);
-}
-
-static void
-ahd_linux_kill_dv_thread(struct ahd_softc *ahd)
-{
-	u_long s;
-
-	ahd_lock(ahd, &s);
-	if (ahd->platform_data->dv_pid != 0) {
-		ahd->platform_data->flags |= AHD_DV_SHUTDOWN;
-		ahd_unlock(ahd, &s);
-		up(&ahd->platform_data->dv_sem);
-
-		/*
-		 * Use the eh_sem as an indicator that the
-		 * dv thread is exiting.  Note that the dv
-		 * thread must still return after performing
-		 * the up on our semaphore before it has
-		 * completely exited this module.  Unfortunately,
-		 * there seems to be no easy way to wait for the
-		 * exit of a thread for which you are not the
-		 * parent (dv threads are parented by init).
-		 * Cross your fingers...
-		 */
-		down(&ahd->platform_data->eh_sem);
-
-		/*
-		 * Mark the dv thread as already dead.  This
-		 * avoids attempting to kill it a second time.
-		 * This is necessary because we must kill the
-		 * DV thread before calling ahd_free() in the
-		 * module shutdown case to avoid bogus locking
-		 * in the SCSI mid-layer, but we ahd_free() is
-		 * called without killing the DV thread in the
-		 * instance detach case, so ahd_platform_free()
-		 * calls us again to verify that the DV thread
-		 * is dead.
-		 */
-		ahd->platform_data->dv_pid = 0;
-	} else {
-		ahd_unlock(ahd, &s);
-	}
-}
-
-#define AHD_LINUX_DV_INQ_SHORT_LEN	36
-#define AHD_LINUX_DV_INQ_LEN		256
-#define AHD_LINUX_DV_TIMEOUT		(HZ / 4)
-
-#define AHD_SET_DV_STATE(ahd, targ, newstate) \
-	ahd_set_dv_state(ahd, targ, newstate, __LINE__)
-
-static __inline void
-ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ,
-		 ahd_dv_state newstate, u_int line)
-{
-	ahd_dv_state oldstate;
-
-	oldstate = targ->dv_state;
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV)
-		printf("%s:%d: Going from state %d to state %d\n",
-		       ahd_name(ahd), line, oldstate, newstate);
-#endif
+	value = (lahd->flags & AHD_BIOS_ENABLED)
+	      - (rahd->flags & AHD_BIOS_ENABLED);
+	if (value != 0)
+		/* Controllers with BIOS enabled have a *higher* priority */
+		return (value);
 
-	if (oldstate == newstate)
-		targ->dv_state_retry++;
+	/* Still equal.  Sort by bus/slot/func. */
+	if (aic79xx_reverse_scan != 0)
+		value = ahd_get_pci_bus(lahd->dev_softc)
+		      - ahd_get_pci_bus(rahd->dev_softc);
+	else
+		value = ahd_get_pci_bus(rahd->dev_softc)
+		      - ahd_get_pci_bus(lahd->dev_softc);
+	if (value != 0)
+		return (value);
+	if (aic79xx_reverse_scan != 0)
+		value = ahd_get_pci_slot(lahd->dev_softc)
+		      - ahd_get_pci_slot(rahd->dev_softc);
 	else
-		targ->dv_state_retry = 0;
-	targ->dv_state = newstate;
+		value = ahd_get_pci_slot(rahd->dev_softc)
+		      - ahd_get_pci_slot(lahd->dev_softc);
+	if (value != 0)
+		return (value);
+
+	value = rahd->channel - lahd->channel;
+	return (value);
 }
 
 static void
-ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
+ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
 {
-	struct	 ahd_devinfo devinfo;
-	struct	 ahd_linux_target *targ;
-	struct	 scsi_cmnd *cmd;
-	struct	 scsi_device *scsi_dev;
-	struct	 scsi_sense_data *sense;
-	uint8_t *buffer;
-	u_long	 s;
-	u_int	 timeout;
-	int	 echo_size;
-
-	sense = NULL;
-	buffer = NULL;
-	echo_size = 0;
-	ahd_lock(ahd, &s);
-	targ = ahd->platform_data->targets[target_offset];
-	if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) {
-		ahd_unlock(ahd, &s);
-		return;
-	}
-	ahd_compile_devinfo(&devinfo, ahd->our_id, targ->target, /*lun*/0,
-			    targ->channel + 'A', ROLE_INITIATOR);
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, &devinfo);
-		printf("Performing DV\n");
-	}
-#endif
-
-	ahd_unlock(ahd, &s);
-
-	cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
-	scsi_dev = malloc(sizeof(struct scsi_device), M_DEVBUF, M_WAITOK);
-	scsi_dev->host = ahd->platform_data->host;
-	scsi_dev->id = devinfo.target;
-	scsi_dev->lun = devinfo.lun;
-	scsi_dev->channel = devinfo.channel - 'A';
-	ahd->platform_data->dv_scsi_dev = scsi_dev;
-
-	AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC);
-
-	while (targ->dv_state != AHD_DV_STATE_EXIT) {
-		timeout = AHD_LINUX_DV_TIMEOUT;
-		switch (targ->dv_state) {
-		case AHD_DV_STATE_INQ_SHORT_ASYNC:
-		case AHD_DV_STATE_INQ_ASYNC:
-		case AHD_DV_STATE_INQ_ASYNC_VERIFY:
-			/*
-			 * Set things to async narrow to reduce the
-			 * chance that the INQ will fail.
-			 */
-			ahd_lock(ahd, &s);
-			ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
-					 AHD_TRANS_GOAL, /*paused*/FALSE);
-			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
-				      AHD_TRANS_GOAL, /*paused*/FALSE);
-			ahd_unlock(ahd, &s);
-			timeout = 10 * HZ;
-			targ->flags &= ~AHD_INQ_VALID;
-			/* FALLTHROUGH */
-		case AHD_DV_STATE_INQ_VERIFY:
-		{
-			u_int inq_len;
-
-			if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC)
-				inq_len = AHD_LINUX_DV_INQ_SHORT_LEN;
-			else
-				inq_len = targ->inq_data->additional_length + 5;
-			ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len);
-			break;
-		}
-		case AHD_DV_STATE_TUR:
-		case AHD_DV_STATE_BUSY:
-			timeout = 5 * HZ;
-			ahd_linux_dv_tur(ahd, cmd, &devinfo);
-			break;
-		case AHD_DV_STATE_REBD:
-			ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ);
-			break;
-		case AHD_DV_STATE_WEB:
-			ahd_linux_dv_web(ahd, cmd, &devinfo, targ);
-			break;
-
-		case AHD_DV_STATE_REB:
-			ahd_linux_dv_reb(ahd, cmd, &devinfo, targ);
-			break;
-
-		case AHD_DV_STATE_SU:
-			ahd_linux_dv_su(ahd, cmd, &devinfo, targ);
-			timeout = 50 * HZ;
-			break;
-
-		default:
-			ahd_print_devinfo(ahd, &devinfo);
-			printf("Unknown DV state %d\n", targ->dv_state);
-			goto out;
-		}
 
-		/* Queue the command and wait for it to complete */
-		/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
-		init_timer(&cmd->eh_timeout);
-#ifdef AHD_DEBUG
-		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
-			/*
-			 * All of the printfs during negotiation
-			 * really slow down the negotiation.
-			 * Add a bit of time just to be safe.
-			 */
-			timeout += HZ;
-#endif
-		scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout);
-		/*
-		 * In 2.5.X, it is assumed that all calls from the
-		 * "midlayer" (which we are emulating) will have the
-		 * ahd host lock held.  For other kernels, the
-		 * io_request_lock must be held.
-		 */
-#if AHD_SCSI_HAS_HOST_LOCK != 0
-		ahd_lock(ahd, &s);
-#else
-		spin_lock_irqsave(&io_request_lock, s);
-#endif
-		ahd_linux_queue(cmd, ahd_linux_dv_complete);
-#if AHD_SCSI_HAS_HOST_LOCK != 0
-		ahd_unlock(ahd, &s);
-#else
-		spin_unlock_irqrestore(&io_request_lock, s);
-#endif
-		down_interruptible(&ahd->platform_data->dv_cmd_sem);
-		/*
-		 * Wait for the SIMQ to be released so that DV is the
-		 * only reason the queue is frozen.
-		 */
-		ahd_lock(ahd, &s);
-		while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
-			ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
-			ahd_unlock(ahd, &s);
-			down_interruptible(&ahd->platform_data->dv_sem);
-			ahd_lock(ahd, &s);
-		}
-		ahd_unlock(ahd, &s);
-
-		ahd_linux_dv_transition(ahd, cmd, &devinfo, targ);
-	}
-
-out:
-	if ((targ->flags & AHD_INQ_VALID) != 0
-	 && ahd_linux_get_device(ahd, devinfo.channel - 'A',
-				 devinfo.target, devinfo.lun,
-				 /*alloc*/FALSE) == NULL) {
-		/*
-		 * The DV state machine failed to configure this device.  
-		 * This is normal if DV is disabled.  Since we have inquiry
-		 * data, filter it and use the "optimistic" negotiation
-		 * parameters found in the inquiry string.
-		 */
-		ahd_linux_filter_inquiry(ahd, &devinfo);
-		if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) {
-			ahd_print_devinfo(ahd, &devinfo);
-			printf("DV failed to configure device.  "
-			       "Please file a bug report against "
-			       "this driver.\n");
-		}
-	}
-
-	if (cmd != NULL)
-		free(cmd, M_DEVBUF);
+	if ((instance >= 0)
+	 && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) {
+		uint8_t *iocell_info;
 
-	if (ahd->platform_data->dv_scsi_dev != NULL) {
-		free(ahd->platform_data->dv_scsi_dev, M_DEVBUF);
-		ahd->platform_data->dv_scsi_dev = NULL;
+		iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];
+		iocell_info[index] = value & 0xFFFF;
+		if (bootverbose)
+			printf("iocell[%d:%ld] = %d\n", instance, index, value);
 	}
-
-	ahd_lock(ahd, &s);
-	if (targ->dv_buffer != NULL) {
-		free(targ->dv_buffer, M_DEVBUF);
-		targ->dv_buffer = NULL;
-	}
-	if (targ->dv_buffer1 != NULL) {
-		free(targ->dv_buffer1, M_DEVBUF);
-		targ->dv_buffer1 = NULL;
-	}
-	targ->flags &= ~AHD_DV_REQUIRED;
-	if (targ->refcount == 0)
-		ahd_linux_free_target(ahd, targ);
-	ahd_unlock(ahd, &s);
 }
 
-static __inline int
-ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+static void
+ahd_linux_setup_tag_info_global(char *p)
 {
-	u_long s;
-	int retval;
+	int tags, i, j;
 
-	ahd_lock(ahd, &s);
-	retval = ahd_linux_fallback(ahd, devinfo);
-	ahd_unlock(ahd, &s);
+	tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
+	printf("Setting Global Tags= %d\n", tags);
 
-	return (retval);
+	for (i = 0; i < NUM_ELEMENTS(aic79xx_tag_info); i++) {
+		for (j = 0; j < AHD_NUM_TARGETS; j++) {
+			aic79xx_tag_info[i].tag_commands[j] = tags;
+		}
+	}
 }
 
 static void
-ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-			struct ahd_devinfo *devinfo,
-			struct ahd_linux_target *targ)
-{
-	u_int32_t status;
-
-	status = aic_error_action(cmd, targ->inq_data,
-				  ahd_cmd_get_transaction_status(cmd),
-				  ahd_cmd_get_scsi_status(cmd));
+ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
+{
 
-	
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Entering ahd_linux_dv_transition, state= %d, "
-		       "status= 0x%x, cmd->result= 0x%x\n", targ->dv_state,
-		       status, cmd->result);
+	if ((instance >= 0) && (targ >= 0)
+	 && (instance < NUM_ELEMENTS(aic79xx_tag_info))
+	 && (targ < AHD_NUM_TARGETS)) {
+		aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
+		if (bootverbose)
+			printf("tag_info[%d:%d] = %d\n", instance, targ, value);
 	}
-#endif
-
-	switch (targ->dv_state) {
-	case AHD_DV_STATE_INQ_SHORT_ASYNC:
-	case AHD_DV_STATE_INQ_ASYNC:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-		{
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
-			break;
-		}
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		case SS_TUR:
-		case SS_RETRY:
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ)
-				targ->dv_state_retry--;
-			if ((status & SS_ERRMASK) == EBUSY)
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
-			if (targ->dv_state_retry < 10)
-				break;
-			/* FALLTHROUGH */
-		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				ahd_print_devinfo(ahd, devinfo);
-				printf("Failed DV inquiry, skipping\n");
-			}
-#endif
-			break;
-		}
-		break;
-	case AHD_DV_STATE_INQ_ASYNC_VERIFY:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-		{
-			u_int xportflags;
-			u_int spi3data;
-
-			if (memcmp(targ->inq_data, targ->dv_buffer,
-				   AHD_LINUX_DV_INQ_LEN) != 0) {
-				/*
-				 * Inquiry data must have changed.
-				 * Try from the top again.
-				 */
-				AHD_SET_DV_STATE(ahd, targ,
-						 AHD_DV_STATE_INQ_SHORT_ASYNC);
-				break;
-			}
-
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
-			targ->flags |= AHD_INQ_VALID;
-			if (ahd_linux_user_dv_setting(ahd) == 0)
-				break;
-
-			xportflags = targ->inq_data->flags;
-			if ((xportflags & (SID_Sync|SID_WBus16)) == 0)
-				break;
-
-			spi3data = targ->inq_data->spi3data;
-			switch (spi3data & SID_SPI_CLOCK_DT_ST) {
-			default:
-			case SID_SPI_CLOCK_ST:
-				/* Assume only basic DV is supported. */
-				targ->flags |= AHD_BASIC_DV;
-				break;
-			case SID_SPI_CLOCK_DT:
-			case SID_SPI_CLOCK_DT_ST:
-				targ->flags |= AHD_ENHANCED_DV;
-				break;
-			}
-			break;
-		}
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		case SS_TUR:
-		case SS_RETRY:
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ)
-				targ->dv_state_retry--;
-
-			if ((status & SS_ERRMASK) == EBUSY)
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
-			if (targ->dv_state_retry < 10)
-				break;
-			/* FALLTHROUGH */
-		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				ahd_print_devinfo(ahd, devinfo);
-				printf("Failed DV inquiry, skipping\n");
-			}
-#endif
-			break;
-		}
-		break;
-	case AHD_DV_STATE_INQ_VERIFY:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-		{
-
-			if (memcmp(targ->inq_data, targ->dv_buffer,
-				   AHD_LINUX_DV_INQ_LEN) == 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-				break;
-			}
-
-#ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				int i;
-
-				ahd_print_devinfo(ahd, devinfo);
-				printf("Inquiry buffer mismatch:");
-				for (i = 0; i < AHD_LINUX_DV_INQ_LEN; i++) {
-					if ((i & 0xF) == 0)
-						printf("\n        ");
-					printf("0x%x:0x0%x ",
-					       ((uint8_t *)targ->inq_data)[i], 
-					       targ->dv_buffer[i]);
-				}
-				printf("\n");
-			}
-#endif
-
-			if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-				break;
-			}
-			/*
-			 * Do not count "falling back"
-			 * against our retries.
-			 */
-			targ->dv_state_retry = 0;
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			break;
-		}
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		case SS_TUR:
-		case SS_RETRY:
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ) {
-				targ->dv_state_retry--;
-			} else if ((status & SSQ_FALLBACK) != 0) {
-				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
-					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
-					break;
-				}
-				/*
-				 * Do not count "falling back"
-				 * against our retries.
-				 */
-				targ->dv_state_retry = 0;
-			} else if ((status & SS_ERRMASK) == EBUSY)
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
-			if (targ->dv_state_retry < 10)
-				break;
-			/* FALLTHROUGH */
-		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				ahd_print_devinfo(ahd, devinfo);
-				printf("Failed DV inquiry, skipping\n");
-			}
-#endif
-			break;
-		}
-		break;
+}
 
-	case AHD_DV_STATE_TUR:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-			if ((targ->flags & AHD_BASIC_DV) != 0) {
-				ahd_linux_filter_inquiry(ahd, devinfo);
-				AHD_SET_DV_STATE(ahd, targ,
-						 AHD_DV_STATE_INQ_VERIFY);
-			} else if ((targ->flags & AHD_ENHANCED_DV) != 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD);
+static char *
+ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
+		       void (*callback)(u_long, int, int, int32_t),
+		       u_long callback_arg)
+{
+	char	*tok_end;
+	char	*tok_end2;
+	int      i;
+	int      instance;
+	int	 targ;
+	int	 done;
+	char	 tok_list[] = {'.', ',', '{', '}', '\0'};
+
+	/* All options use a ':' name/arg separator */
+	if (*opt_arg != ':')
+		return (opt_arg);
+	opt_arg++;
+	instance = -1;
+	targ = -1;
+	done = FALSE;
+	/*
+	 * Restore separator that may be in
+	 * the middle of our option argument.
+	 */
+	tok_end = strchr(opt_arg, '\0');
+	if (tok_end < end)
+		*tok_end = ',';
+	while (!done) {
+		switch (*opt_arg) {
+		case '{':
+			if (instance == -1) {
+				instance = 0;
 			} else {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-			}
-			break;
-		case SS_RETRY:
-		case SS_TUR:
-			if ((status & SS_ERRMASK) == EBUSY) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
-				break;
-			}
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ) {
-				targ->dv_state_retry--;
-			} else if ((status & SSQ_FALLBACK) != 0) {
-				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
-					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
-					break;
-				}
-				/*
-				 * Do not count "falling back"
-				 * against our retries.
-				 */
-				targ->dv_state_retry = 0;
-			}
-			if (targ->dv_state_retry >= 10) {
-#ifdef AHD_DEBUG
-				if (ahd_debug & AHD_SHOW_DV) {
-					ahd_print_devinfo(ahd, devinfo);
-					printf("DV TUR reties exhausted\n");
+				if (depth > 1) {
+					if (targ == -1)
+						targ = 0;
+				} else {
+					printf("Malformed Option %s\n",
+					       opt_name);
+					done = TRUE;
 				}
-#endif
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-				break;
 			}
-			if (status & SSQ_DELAY)
-				ssleep(1);
-
+			opt_arg++;
 			break;
-		case SS_START:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU);
+		case '}':
+			if (targ != -1)
+				targ = -1;
+			else if (instance != -1)
+				instance = -1;
+			opt_arg++;
+			break;
+		case ',':
+		case '.':
+			if (instance == -1)
+				done = TRUE;
+			else if (targ >= 0)
+				targ++;
+			else if (instance >= 0)
+				instance++;
+			opt_arg++;
 			break;
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+		case '\0':
+			done = TRUE;
 			break;
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			tok_end = end;
+			for (i = 0; tok_list[i]; i++) {
+				tok_end2 = strchr(opt_arg, tok_list[i]);
+				if ((tok_end2) && (tok_end2 < tok_end))
+					tok_end = tok_end2;
+			}
+			callback(callback_arg, instance, targ,
+				 simple_strtol(opt_arg, NULL, 0));
+			opt_arg = tok_end;
 			break;
 		}
-		break;
+	}
+	return (opt_arg);
+}
 
-	case AHD_DV_STATE_REBD:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-		{
-			uint32_t echo_size;
-
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
-			echo_size = scsi_3btoul(&targ->dv_buffer[1]);
-			echo_size &= 0x1FFF;
-#ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				ahd_print_devinfo(ahd, devinfo);
-				printf("Echo buffer size= %d\n", echo_size);
-			}
-#endif
-			if (echo_size == 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-				break;
-			}
+/*
+ * Handle Linux boot parameters. This routine allows for assigning a value
+ * to a parameter with a ':' between the parameter and the value.
+ * ie. aic79xx=stpwlev:1,extended
+ */
+static int
+aic79xx_setup(char *s)
+{
+	int	i, n;
+	char   *p;
+	char   *end;
 
-			/* Generate the buffer pattern */
-			targ->dv_echo_size = echo_size;
-			ahd_linux_generate_dv_pattern(targ);
-			/*
-			 * Setup initial negotiation values.
-			 */
-			ahd_linux_filter_inquiry(ahd, devinfo);
-			break;
-		}
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		case SS_RETRY:
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ)
-				targ->dv_state_retry--;
-			if (targ->dv_state_retry <= 10)
-				break;
+	static struct {
+		const char *name;
+		uint32_t *flag;
+	} options[] = {
+		{ "extended", &aic79xx_extended },
+		{ "no_reset", &aic79xx_no_reset },
+		{ "verbose", &aic79xx_verbose },
+		{ "allow_memio", &aic79xx_allow_memio},
 #ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				ahd_print_devinfo(ahd, devinfo);
-				printf("DV REBD reties exhausted\n");
-			}
+		{ "debug", &ahd_debug },
 #endif
-			/* FALLTHROUGH */
-		case SS_FATAL:
-		default:
-			/*
-			 * Setup initial negotiation values
-			 * and try level 1 DV.
-			 */
-			ahd_linux_filter_inquiry(ahd, devinfo);
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY);
-			targ->dv_echo_size = 0;
-			break;
-		}
-		break;
+		{ "reverse_scan", &aic79xx_reverse_scan },
+		{ "periodic_otag", &aic79xx_periodic_otag },
+		{ "pci_parity", &aic79xx_pci_parity },
+		{ "seltime", &aic79xx_seltime },
+		{ "tag_info", NULL },
+		{ "global_tag_depth", NULL},
+		{ "slewrate", NULL },
+		{ "precomp", NULL },
+		{ "amplitude", NULL },
+	};
 
-	case AHD_DV_STATE_WEB:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB);
-			break;
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		case SS_RETRY:
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ) {
-				targ->dv_state_retry--;
-			} else if ((status & SSQ_FALLBACK) != 0) {
-				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
-					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
-					break;
-				}
-				/*
-				 * Do not count "falling back"
-				 * against our retries.
-				 */
-				targ->dv_state_retry = 0;
-			}
-			if (targ->dv_state_retry <= 10)
-				break;
-			/* FALLTHROUGH */
-#ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				ahd_print_devinfo(ahd, devinfo);
-				printf("DV WEB reties exhausted\n");
-			}
-#endif
-		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-			break;
-		}
-		break;
+	end = strchr(s, '\0');
 
-	case AHD_DV_STATE_REB:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-			if (memcmp(targ->dv_buffer, targ->dv_buffer1,
-				   targ->dv_echo_size) != 0) {
-				if (ahd_linux_dv_fallback(ahd, devinfo) != 0)
-					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
-				else
-					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_WEB);
-				break;
-			}
-			
-			if (targ->dv_buffer != NULL) {
-				free(targ->dv_buffer, M_DEVBUF);
-				targ->dv_buffer = NULL;
-			}
-			if (targ->dv_buffer1 != NULL) {
-				free(targ->dv_buffer1, M_DEVBUF);
-				targ->dv_buffer1 = NULL;
-			}
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-			break;
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		case SS_RETRY:
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ) {
-				targ->dv_state_retry--;
-			} else if ((status & SSQ_FALLBACK) != 0) {
-				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
-					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
-					break;
-				}
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
-			}
-			if (targ->dv_state_retry <= 10) {
-				if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
-					msleep(ahd->our_id*1000/10);
-				break;
-			}
-#ifdef AHD_DEBUG
-			if (ahd_debug & AHD_SHOW_DV) {
-				ahd_print_devinfo(ahd, devinfo);
-				printf("DV REB reties exhausted\n");
-			}
-#endif
-			/* FALLTHROUGH */
-		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-			break;
-		}
-		break;
+	/*
+	 * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS
+	 * will never be 0 in this case.
+	 */      
+	n = 0;  
 
-	case AHD_DV_STATE_SU:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-			break;
-		}
-		break;
+	while ((p = strsep(&s, ",.")) != NULL) {
+		if (*p == '\0')
+			continue;
+		for (i = 0; i < NUM_ELEMENTS(options); i++) {
 
-	case AHD_DV_STATE_BUSY:
-		switch (status & SS_MASK) {
-		case SS_NOP:
-		case SS_INQ_REFRESH:
-			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
-			break;
-		case SS_TUR:
-		case SS_RETRY:
-			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
-			 == CAM_REQUEUE_REQ) {
-				targ->dv_state_retry--;
-			} else if (targ->dv_state_retry < 60) {
-				if ((status & SSQ_DELAY) != 0)
-					ssleep(1);
-			} else {
-#ifdef AHD_DEBUG
-				if (ahd_debug & AHD_SHOW_DV) {
-					ahd_print_devinfo(ahd, devinfo);
-					printf("DV BUSY reties exhausted\n");
-				}
-#endif
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-			}
-			break;
-		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-			break;
+			n = strlen(options[i].name);
+			if (strncmp(options[i].name, p, n) == 0)
+				break;
 		}
-		break;
+		if (i == NUM_ELEMENTS(options))
+			continue;
 
-	default:
-		printf("%s: Invalid DV completion state %d\n", ahd_name(ahd),
-		       targ->dv_state);
-		AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-		break;
+		if (strncmp(p, "global_tag_depth", n) == 0) {
+			ahd_linux_setup_tag_info_global(p + n);
+		} else if (strncmp(p, "tag_info", n) == 0) {
+			s = ahd_parse_brace_option("tag_info", p + n, end,
+			    2, ahd_linux_setup_tag_info, 0);
+		} else if (strncmp(p, "slewrate", n) == 0) {
+			s = ahd_parse_brace_option("slewrate",
+			    p + n, end, 1, ahd_linux_setup_iocell_info,
+			    AIC79XX_SLEWRATE_INDEX);
+		} else if (strncmp(p, "precomp", n) == 0) {
+			s = ahd_parse_brace_option("precomp",
+			    p + n, end, 1, ahd_linux_setup_iocell_info,
+			    AIC79XX_PRECOMP_INDEX);
+		} else if (strncmp(p, "amplitude", n) == 0) {
+			s = ahd_parse_brace_option("amplitude",
+			    p + n, end, 1, ahd_linux_setup_iocell_info,
+			    AIC79XX_AMPLITUDE_INDEX);
+		} else if (p[n] == ':') {
+			*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
+		} else if (!strncmp(p, "verbose", n)) {
+			*(options[i].flag) = 1;
+		} else {
+			*(options[i].flag) ^= 0xFFFFFFFF;
+		}
 	}
+	return 1;
 }
 
-static void
-ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		      struct ahd_devinfo *devinfo)
-{
-	memset(cmd, 0, sizeof(struct scsi_cmnd));
-	cmd->device = ahd->platform_data->dv_scsi_dev;
-	cmd->scsi_done = ahd_linux_dv_complete;
-}
-
-/*
- * Synthesize an inquiry command.  On the return trip, it'll be
- * sniffed and the device transfer settings set for us.
- */
-static void
-ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ,
-		 u_int request_length)
-{
+__setup("aic79xx=", aic79xx_setup);
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Sending INQ\n");
-	}
-#endif
-	if (targ->inq_data == NULL)
-		targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN,
-					M_DEVBUF, M_WAITOK);
-	if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) {
-		if (targ->dv_buffer != NULL)
-			free(targ->dv_buffer, M_DEVBUF);
-		targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN,
-					 M_DEVBUF, M_WAITOK);
-	}
-
-	ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
-	cmd->sc_data_direction = DMA_FROM_DEVICE;
-	cmd->cmd_len = 6;
-	cmd->cmnd[0] = INQUIRY;
-	cmd->cmnd[4] = request_length;
-	cmd->request_bufflen = request_length;
-	if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC)
-		cmd->request_buffer = targ->dv_buffer;
-	else
-		cmd->request_buffer = targ->inq_data;
-	memset(cmd->request_buffer, 0, AHD_LINUX_DV_INQ_LEN);
-}
+uint32_t aic79xx_verbose;
 
-static void
-ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo)
+int
+ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template)
 {
+	char	buf[80];
+	struct	Scsi_Host *host;
+	char	*new_name;
+	u_long	s;
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Sending TUR\n");
-	}
-#endif
-	/* Do a TUR to clear out any non-fatal transitional state */
-	ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
-	cmd->sc_data_direction = DMA_NONE;
-	cmd->cmd_len = 6;
-	cmd->cmnd[0] = TEST_UNIT_READY;
-}
+	template->name = ahd->description;
+	host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
+	if (host == NULL)
+		return (ENOMEM);
 
-#define AHD_REBD_LEN 4
+	*((struct ahd_softc **)host->hostdata) = ahd;
+	ahd_lock(ahd, &s);
+	scsi_assign_lock(host, &ahd->platform_data->spin_lock);
+	ahd->platform_data->host = host;
+	host->can_queue = AHD_MAX_QUEUE;
+	host->cmd_per_lun = 2;
+	host->sg_tablesize = AHD_NSEG;
+	host->this_id = ahd->our_id;
+	host->irq = ahd->platform_data->irq;
+	host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
+	host->max_lun = AHD_NUM_LUNS;
+	host->max_channel = 0;
+	host->sg_tablesize = AHD_NSEG;
+	ahd_set_unit(ahd, ahd_linux_unit++);
+	sprintf(buf, "scsi%d", host->host_no);
+	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
+	if (new_name != NULL) {
+		strcpy(new_name, buf);
+		ahd_set_name(ahd, new_name);
+	}
+	host->unique_id = ahd->unit;
+	ahd_linux_initialize_scsi_bus(ahd);
+	ahd_intr_enable(ahd, TRUE);
+	ahd_unlock(ahd, &s);
 
-static void
-ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
+	host->transportt = ahd_linux_transport_template;
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Sending REBD\n");
-	}
-#endif
-	if (targ->dv_buffer != NULL)
-		free(targ->dv_buffer, M_DEVBUF);
-	targ->dv_buffer = malloc(AHD_REBD_LEN, M_DEVBUF, M_WAITOK);
-	ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
-	cmd->sc_data_direction = DMA_FROM_DEVICE;
-	cmd->cmd_len = 10;
-	cmd->cmnd[0] = READ_BUFFER;
-	cmd->cmnd[1] = 0x0b;
-	scsi_ulto3b(AHD_REBD_LEN, &cmd->cmnd[6]);
-	cmd->request_bufflen = AHD_REBD_LEN;
-	cmd->underflow = cmd->request_bufflen;
-	cmd->request_buffer = targ->dv_buffer;
+	scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
+	scsi_scan_host(host);
+	return (0);
 }
 
-static void
-ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
+uint64_t
+ahd_linux_get_memsize(void)
 {
+	struct sysinfo si;
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Sending WEB\n");
-	}
-#endif
-	ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
-	cmd->sc_data_direction = DMA_TO_DEVICE;
-	cmd->cmd_len = 10;
-	cmd->cmnd[0] = WRITE_BUFFER;
-	cmd->cmnd[1] = 0x0a;
-	scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
-	cmd->request_bufflen = targ->dv_echo_size;
-	cmd->underflow = cmd->request_bufflen;
-	cmd->request_buffer = targ->dv_buffer;
+	si_meminfo(&si);
+	return ((uint64_t)si.totalram << PAGE_SHIFT);
 }
 
+/*
+ * Place the SCSI bus into a known state by either resetting it,
+ * or forcing transfer negotiations on the next command to any
+ * target.
+ */
 static void
-ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
+ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
 {
+	u_int target_id;
+	u_int numtarg;
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Sending REB\n");
-	}
-#endif
-	ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
-	cmd->sc_data_direction = DMA_FROM_DEVICE;
-	cmd->cmd_len = 10;
-	cmd->cmnd[0] = READ_BUFFER;
-	cmd->cmnd[1] = 0x0a;
-	scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
-	cmd->request_bufflen = targ->dv_echo_size;
-	cmd->underflow = cmd->request_bufflen;
-	cmd->request_buffer = targ->dv_buffer1;
-}
+	target_id = 0;
+	numtarg = 0;
 
-static void
-ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		struct ahd_devinfo *devinfo,
-		struct ahd_linux_target *targ)
-{
-	u_int le;
+	if (aic79xx_no_reset != 0)
+		ahd->flags &= ~AHD_RESET_BUS_A;
 
-	le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0;
+	if ((ahd->flags & AHD_RESET_BUS_A) != 0)
+		ahd_reset_channel(ahd, 'A', /*initiate_reset*/TRUE);
+	else
+		numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Sending SU\n");
+	/*
+	 * Force negotiation to async for all targets that
+	 * will not see an initial bus reset.
+	 */
+	for (; target_id < numtarg; target_id++) {
+		struct ahd_devinfo devinfo;
+		struct ahd_initiator_tinfo *tinfo;
+		struct ahd_tmode_tstate *tstate;
+
+		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
+					    target_id, &tstate);
+		ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
+				    CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
+		ahd_update_neg_request(ahd, &devinfo, tstate,
+				       tinfo, AHD_NEG_ALWAYS);
+	}
+	/* Give the bus some time to recover */
+	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
+		ahd_freeze_simq(ahd);
+		init_timer(&ahd->platform_data->reset_timer);
+		ahd->platform_data->reset_timer.data = (u_long)ahd;
+		ahd->platform_data->reset_timer.expires =
+		    jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
+		ahd->platform_data->reset_timer.function =
+		    (ahd_linux_callback_t *)ahd_release_simq;
+		add_timer(&ahd->platform_data->reset_timer);
 	}
-#endif
-	ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
-	cmd->sc_data_direction = DMA_NONE;
-	cmd->cmd_len = 6;
-	cmd->cmnd[0] = START_STOP_UNIT;
-	cmd->cmnd[4] = le | SSS_START;
 }
 
-static int
-ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+int
+ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
 {
-	struct	ahd_linux_target *targ;
-	struct	ahd_initiator_tinfo *tinfo;
-	struct	ahd_transinfo *goal;
-	struct	ahd_tmode_tstate *tstate;
-	u_int	width;
-	u_int	period;
-	u_int	offset;
-	u_int	ppr_options;
-	u_int	cur_speed;
-	u_int	wide_speed;
-	u_int	narrow_speed;
-	u_int	fallback_speed;
+	ahd->platform_data =
+	    malloc(sizeof(struct ahd_platform_data), M_DEVBUF, M_NOWAIT);
+	if (ahd->platform_data == NULL)
+		return (ENOMEM);
+	memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
+	ahd->platform_data->irq = AHD_LINUX_NOIRQ;
+	ahd_lockinit(ahd);
+	init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
+	ahd->seltime = (aic79xx_seltime & 0x3) << 4;
+	return (0);
+}
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		ahd_print_devinfo(ahd, devinfo);
-		printf("Trying to fallback\n");
-	}
-#endif
-	targ = ahd->platform_data->targets[devinfo->target_offset];
-	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
-				    devinfo->our_scsiid,
-				    devinfo->target, &tstate);
-	goal = &tinfo->goal;
-	width = goal->width;
-	period = goal->period;
-	offset = goal->offset;
-	ppr_options = goal->ppr_options;
-	if (offset == 0)
-		period = AHD_ASYNC_XFER_PERIOD;
-	if (targ->dv_next_narrow_period == 0)
-		targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2);
-	if (targ->dv_next_wide_period == 0)
-		targ->dv_next_wide_period = period;
-	if (targ->dv_max_width == 0)
-		targ->dv_max_width = width;
-	if (targ->dv_max_ppr_options == 0)
-		targ->dv_max_ppr_options = ppr_options;
-	if (targ->dv_last_ppr_options == 0)
-		targ->dv_last_ppr_options = ppr_options;
-
-	cur_speed = aic_calc_speed(width, period, offset, AHD_SYNCRATE_MIN);
-	wide_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_16_BIT,
-					  targ->dv_next_wide_period,
-					  MAX_OFFSET, AHD_SYNCRATE_MIN);
-	narrow_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_8_BIT,
-					    targ->dv_next_narrow_period,
-					    MAX_OFFSET, AHD_SYNCRATE_MIN);
-	fallback_speed = aic_calc_speed(width, period+1, offset,
-					      AHD_SYNCRATE_MIN);
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
-		       "fallback_speed= %d\n", cur_speed, wide_speed,
-		       narrow_speed, fallback_speed);
-	}
-#endif
+void
+ahd_platform_free(struct ahd_softc *ahd)
+{
+	struct scsi_target *starget;
+	int i, j;
 
-	if (cur_speed > 160000) {
-		/*
-		 * Paced/DT/IU_REQ only transfer speeds.  All we
-		 * can do is fallback in terms of syncrate.
-		 */
-		period++;
-	} else if (cur_speed > 80000) {
-		if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
-			/*
-			 * Try without IU_REQ as it may be confusing
-			 * an expander.
-			 */
-			ppr_options &= ~MSG_EXT_PPR_IU_REQ;
-		} else {
-			/*
-			 * Paced/DT only transfer speeds.  All we
-			 * can do is fallback in terms of syncrate.
-			 */
-			period++;
-			ppr_options = targ->dv_max_ppr_options;
+	if (ahd->platform_data != NULL) {
+		if (ahd->platform_data->host != NULL) {
+			scsi_remove_host(ahd->platform_data->host);
+			scsi_host_put(ahd->platform_data->host);
 		}
-	} else if (cur_speed > 3300) {
-
-		/*
-		 * In this range we the following
-		 * options ordered from highest to
-		 * lowest desireability:
-		 *
-		 * o Wide/DT
-		 * o Wide/non-DT
-		 * o Narrow at a potentally higher sync rate.
-		 *
-		 * All modes are tested with and without IU_REQ
-		 * set since using IUs may confuse an expander.
-		 */
-		if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
 
-			ppr_options &= ~MSG_EXT_PPR_IU_REQ;
-		} else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
-			/*
-			 * Try going non-DT.
-			 */
-			ppr_options = targ->dv_max_ppr_options;
-			ppr_options &= ~MSG_EXT_PPR_DT_REQ;
-		} else if (targ->dv_last_ppr_options != 0) {
-			/*
-			 * Try without QAS or any other PPR options.
-			 * We may need a non-PPR message to work with
-			 * an expander.  We look at the "last PPR options"
-			 * so we will perform this fallback even if the
-			 * target responded to our PPR negotiation with
-			 * no option bits set.
-			 */
-			ppr_options = 0;
-		} else if (width == MSG_EXT_WDTR_BUS_16_BIT) {
-			/*
-			 * If the next narrow speed is greater than
-			 * the next wide speed, fallback to narrow.
-			 * Otherwise fallback to the next DT/Wide setting.
-			 * The narrow async speed will always be smaller
-			 * than the wide async speed, so handle this case
-			 * specifically.
-			 */
-			ppr_options = targ->dv_max_ppr_options;
-			if (narrow_speed > fallback_speed
-			 || period >= AHD_ASYNC_XFER_PERIOD) {
-				targ->dv_next_wide_period = period+1;
-				width = MSG_EXT_WDTR_BUS_8_BIT;
-				period = targ->dv_next_narrow_period;
-			} else {
-				period++;
+		/* destroy all of the device and target objects */
+		for (i = 0; i < AHD_NUM_TARGETS; i++) {
+			starget = ahd->platform_data->starget[i];
+			if (starget != NULL) {
+				for (j = 0; j < AHD_NUM_LUNS; j++) {
+					struct ahd_linux_target *targ =
+						scsi_transport_target_data(starget);
+					if (targ->sdev[j] == NULL)
+						continue;
+					targ->sdev[j] = NULL;
+				}
+				ahd->platform_data->starget[i] = NULL;
 			}
-		} else if ((ahd->features & AHD_WIDE) != 0
-			&& targ->dv_max_width != 0
-			&& wide_speed >= fallback_speed
-			&& (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD
-			 || period >= AHD_ASYNC_XFER_PERIOD)) {
-
-			/*
-			 * We are narrow.  Try falling back
-			 * to the next wide speed with 
-			 * all supported ppr options set.
-			 */
-			targ->dv_next_narrow_period = period+1;
-			width = MSG_EXT_WDTR_BUS_16_BIT;
-			period = targ->dv_next_wide_period;
-			ppr_options = targ->dv_max_ppr_options;
-		} else {
-			/* Only narrow fallback is allowed. */
-			period++;
-			ppr_options = targ->dv_max_ppr_options;
 		}
-	} else {
-		return (-1);
-	}
-	offset = MAX_OFFSET;
-	ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_PACED);
-	ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, FALSE);
-	if (period == 0) {
-		period = 0;
-		offset = 0;
-		ppr_options = 0;
-		if (width == MSG_EXT_WDTR_BUS_8_BIT)
-			targ->dv_next_narrow_period = AHD_ASYNC_XFER_PERIOD;
-		else
-			targ->dv_next_wide_period = AHD_ASYNC_XFER_PERIOD;
-	}
-	ahd_set_syncrate(ahd, devinfo, period, offset,
-			 ppr_options, AHD_TRANS_GOAL, FALSE);
-	targ->dv_last_ppr_options = ppr_options;
-	return (0);
-}
-
-static void
-ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
-{
-	struct	ahd_softc *ahd;
-	struct	scb *scb;
-	u_long	flags;
-
-	ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
-	ahd_lock(ahd, &flags);
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV) {
-		printf("%s: Timeout while doing DV command %x.\n",
-		       ahd_name(ahd), cmd->cmnd[0]);
-		ahd_dump_card_state(ahd);
-	}
-#endif
-	
-	/*
-	 * Guard against "done race".  No action is
-	 * required if we just completed.
-	 */
-	if ((scb = (struct scb *)cmd->host_scribble) == NULL) {
-		ahd_unlock(ahd, &flags);
-		return;
+		if (ahd->platform_data->irq != AHD_LINUX_NOIRQ)
+			free_irq(ahd->platform_data->irq, ahd);
+		if (ahd->tags[0] == BUS_SPACE_PIO
+		 && ahd->bshs[0].ioport != 0)
+			release_region(ahd->bshs[0].ioport, 256);
+		if (ahd->tags[1] == BUS_SPACE_PIO
+		 && ahd->bshs[1].ioport != 0)
+			release_region(ahd->bshs[1].ioport, 256);
+		if (ahd->tags[0] == BUS_SPACE_MEMIO
+		 && ahd->bshs[0].maddr != NULL) {
+			iounmap(ahd->bshs[0].maddr);
+			release_mem_region(ahd->platform_data->mem_busaddr,
+					   0x1000);
+		}
+		free(ahd->platform_data, M_DEVBUF);
 	}
+}
 
+void
+ahd_platform_init(struct ahd_softc *ahd)
+{
 	/*
-	 * Command has not completed.  Mark this
-	 * SCB as having failing status prior to
-	 * resetting the bus, so we get the correct
-	 * error code.
+	 * Lookup and commit any modified IO Cell options.
 	 */
-	if ((scb->flags & SCB_SENSE) != 0)
-		ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
-	else
-		ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
-	ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE);
+	if (ahd->unit < NUM_ELEMENTS(aic79xx_iocell_info)) {
+		struct ahd_linux_iocell_opts *iocell_opts;
+
+		iocell_opts = &aic79xx_iocell_info[ahd->unit];
+		if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
+			AHD_SET_PRECOMP(ahd, iocell_opts->precomp);
+		if (iocell_opts->slewrate != AIC79XX_DEFAULT_SLEWRATE)
+			AHD_SET_SLEWRATE(ahd, iocell_opts->slewrate);
+		if (iocell_opts->amplitude != AIC79XX_DEFAULT_AMPLITUDE)
+			AHD_SET_AMPLITUDE(ahd, iocell_opts->amplitude);
+	}
 
-	/*
-	 * Add a minimal bus settle delay for devices that are slow to
-	 * respond after bus resets.
-	 */
-	ahd_freeze_simq(ahd);
-	init_timer(&ahd->platform_data->reset_timer);
-	ahd->platform_data->reset_timer.data = (u_long)ahd;
-	ahd->platform_data->reset_timer.expires = jiffies + HZ / 2;
-	ahd->platform_data->reset_timer.function =
-	    (ahd_linux_callback_t *)ahd_release_simq;
-	add_timer(&ahd->platform_data->reset_timer);
-	if (ahd_linux_next_device_to_run(ahd) != NULL)
-		ahd_schedule_runq(ahd);
-	ahd_linux_run_complete_queue(ahd);
-	ahd_unlock(ahd, &flags);
 }
 
-static void
-ahd_linux_dv_complete(struct scsi_cmnd *cmd)
+void
+ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
 {
-	struct ahd_softc *ahd;
+	ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
+				SCB_GET_CHANNEL(ahd, scb),
+				SCB_GET_LUN(scb), SCB_LIST_NULL,
+				ROLE_UNKNOWN, CAM_REQUEUE_REQ);
+}
 
-	ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
+void
+ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
+		      ahd_queue_alg alg)
+{
+	struct scsi_target *starget;
+	struct ahd_linux_target *targ;
+	struct ahd_linux_device *dev;
+	struct scsi_device *sdev;
+	int was_queuing;
+	int now_queuing;
 
-	/* Delete the DV timer before it goes off! */
-	scsi_delete_timer(cmd);
+	starget = ahd->platform_data->starget[devinfo->target];
+	targ = scsi_transport_target_data(starget);
+	BUG_ON(targ == NULL);
+	sdev = targ->sdev[devinfo->lun];
+	if (sdev == NULL)
+		return;
 
-#ifdef AHD_DEBUG
-	if (ahd_debug & AHD_SHOW_DV)
-		printf("%s:%c:%d: Command completed, status= 0x%x\n",
-		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
-		       cmd->result);
-#endif
+	dev = scsi_transport_device_data(sdev);
 
-	/* Wake up the state machine */
-	up(&ahd->platform_data->dv_cmd_sem);
-}
+	if (dev == NULL)
+		return;
+	was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
+	switch (alg) {
+	default:
+	case AHD_QUEUE_NONE:
+		now_queuing = 0;
+		break; 
+	case AHD_QUEUE_BASIC:
+		now_queuing = AHD_DEV_Q_BASIC;
+		break;
+	case AHD_QUEUE_TAGGED:
+		now_queuing = AHD_DEV_Q_TAGGED;
+		break;
+	}
+	if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0
+	 && (was_queuing != now_queuing)
+	 && (dev->active != 0)) {
+		dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY;
+		dev->qfrozen++;
+	}
 
-static void
-ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ)
-{
-	uint16_t b;
-	u_int	 i;
-	u_int	 j;
-
-	if (targ->dv_buffer != NULL)
-		free(targ->dv_buffer, M_DEVBUF);
-	targ->dv_buffer = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
-	if (targ->dv_buffer1 != NULL)
-		free(targ->dv_buffer1, M_DEVBUF);
-	targ->dv_buffer1 = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
-
-	i = 0;
-
-	b = 0x0001;
-	for (j = 0 ; i < targ->dv_echo_size; j++) {
-		if (j < 32) {
-			/*
-			 * 32bytes of sequential numbers.
-			 */
-			targ->dv_buffer[i++] = j & 0xff;
-		} else if (j < 48) {
-			/*
-			 * 32bytes of repeating 0x0000, 0xffff.
-			 */
-			targ->dv_buffer[i++] = (j & 0x02) ? 0xff : 0x00;
-		} else if (j < 64) {
+	dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);
+	if (now_queuing) {
+		u_int usertags;
+
+		usertags = ahd_linux_user_tagdepth(ahd, devinfo);
+		if (!was_queuing) {
 			/*
-			 * 32bytes of repeating 0x5555, 0xaaaa.
+			 * Start out agressively and allow our
+			 * dynamic queue depth algorithm to take
+			 * care of the rest.
 			 */
-			targ->dv_buffer[i++] = (j & 0x02) ? 0xaa : 0x55;
-		} else {
+			dev->maxtags = usertags;
+			dev->openings = dev->maxtags - dev->active;
+		}
+		if (dev->maxtags == 0) {
 			/*
-			 * Remaining buffer is filled with a repeating
-			 * patter of:
-			 *
-			 *	 0xffff
-			 *	~0x0001 << shifted once in each loop.
+			 * Queueing is disabled by the user.
 			 */
-			if (j & 0x02) {
-				if (j & 0x01) {
-					targ->dv_buffer[i++] = ~(b >> 8) & 0xff;
-					b <<= 1;
-					if (b == 0x0000)
-						b = 0x0001;
-				} else {
-					targ->dv_buffer[i++] = (~b & 0xff);
-				}
-			} else {
-				targ->dv_buffer[i++] = 0xff;
-			}
-		}
+			dev->openings = 1;
+		} else if (alg == AHD_QUEUE_TAGGED) {
+			dev->flags |= AHD_DEV_Q_TAGGED;
+			if (aic79xx_periodic_otag != 0)
+				dev->flags |= AHD_DEV_PERIODIC_OTAG;
+		} else
+			dev->flags |= AHD_DEV_Q_BASIC;
+	} else {
+		/* We can only have one opening. */
+		dev->maxtags = 0;
+		dev->openings =  1 - dev->active;
+	}
+
+	switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
+	case AHD_DEV_Q_BASIC:
+		scsi_adjust_queue_depth(sdev,
+					MSG_SIMPLE_TASK,
+					dev->openings + dev->active);
+		break;
+	case AHD_DEV_Q_TAGGED:
+		scsi_adjust_queue_depth(sdev,
+					MSG_ORDERED_TASK,
+					dev->openings + dev->active);
+		break;
+	default:
+		/*
+		 * We allow the OS to queue 2 untagged transactions to
+		 * us at any time even though we can only execute them
+		 * serially on the controller/device.  This should
+		 * remove some latency.
+		 */
+		scsi_adjust_queue_depth(sdev,
+					/*NON-TAGGED*/0,
+					/*queue depth*/2);
+		break;
 	}
 }
 
+int
+ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
+			int lun, u_int tag, role_t role, uint32_t status)
+{
+	return 0;
+}
+
 static u_int
 ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
 {
@@ -3800,100 +1395,23 @@ ahd_linux_user_tagdepth(struct ahd_softc
 	return (tags);
 }
 
-static u_int
-ahd_linux_user_dv_setting(struct ahd_softc *ahd)
-{
-	static int warned_user;
-	int dv;
-
-	if (ahd->unit >= NUM_ELEMENTS(aic79xx_dv_settings)) {
-
-		if (warned_user == 0) {
-			printf(KERN_WARNING
-"aic79xx: WARNING: Insufficient dv settings instances\n"
-"aic79xx: for installed controllers. Using defaults\n"
-"aic79xx: Please update the aic79xx_dv_settings array in"
-"aic79xx: the aic79xx_osm.c source file.\n");
-			warned_user++;
-		}
-		dv = -1;
-	} else {
-
-		dv = aic79xx_dv_settings[ahd->unit];
-	}
-
-	if (dv < 0) {
-		/*
-		 * Apply the default.
-		 */
-		dv = 1;
-		if (ahd->seep_config != 0)
-			dv = (ahd->seep_config->bios_control & CFENABLEDV);
-	}
-	return (dv);
-}
-
-static void
-ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd)
-{
-	static	int warned_user;
-	u_int	rd_strm_mask;
-	u_int	target_id;
-
-	/*
-	 * If we have specific read streaming info for this controller,
-	 * apply it.  Otherwise use the defaults.
-	 */
-	 if (ahd->unit >= NUM_ELEMENTS(aic79xx_rd_strm_info)) {
-
-		if (warned_user == 0) {
-
-			printf(KERN_WARNING
-"aic79xx: WARNING: Insufficient rd_strm instances\n"
-"aic79xx: for installed controllers. Using defaults\n"
-"aic79xx: Please update the aic79xx_rd_strm_info array\n"
-"aic79xx: in the aic79xx_osm.c source file.\n");
-			warned_user++;
-		}
-		rd_strm_mask = AIC79XX_CONFIGED_RD_STRM;
-	} else {
-
-		rd_strm_mask = aic79xx_rd_strm_info[ahd->unit];
-	}
-	for (target_id = 0; target_id < 16; target_id++) {
-		struct ahd_devinfo devinfo;
-		struct ahd_initiator_tinfo *tinfo;
-		struct ahd_tmode_tstate *tstate;
-
-		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
-					    target_id, &tstate);
-		ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
-				    CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
-		tinfo->user.ppr_options &= ~MSG_EXT_PPR_RD_STRM;
-		if ((rd_strm_mask & devinfo.target_mask) != 0)
-			tinfo->user.ppr_options |= MSG_EXT_PPR_RD_STRM;
-	}
-}
-
 /*
  * Determines the queue depth for a given device.
  */
 static void
-ahd_linux_device_queue_depth(struct ahd_softc *ahd,
-			     struct ahd_linux_device *dev)
+ahd_linux_device_queue_depth(struct scsi_device *sdev)
 {
 	struct	ahd_devinfo devinfo;
 	u_int	tags;
+	struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata);
 
 	ahd_compile_devinfo(&devinfo,
 			    ahd->our_id,
-			    dev->target->target, dev->lun,
-			    dev->target->channel == 0 ? 'A' : 'B',
+			    sdev->sdev_target->id, sdev->lun,
+			    sdev->sdev_target->channel == 0 ? 'A' : 'B',
 			    ROLE_INITIATOR);
 	tags = ahd_linux_user_tagdepth(ahd, &devinfo);
-	if (tags != 0
-	 && dev->scsi_device != NULL
-	 && dev->scsi_device->tagged_supported != 0) {
+	if (tags != 0 && sdev->tagged_supported != 0) {
 
 		ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);
 		ahd_print_devinfo(ahd, &devinfo);
@@ -3903,11 +1421,10 @@ ahd_linux_device_queue_depth(struct ahd_
 	}
 }
 
-static void
-ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
+static int
+ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+		      struct scsi_cmnd *cmd)
 {
-	struct	 ahd_cmd *acmd;
-	struct	 scsi_cmnd *cmd;
 	struct	 scb *scb;
 	struct	 hardware_scb *hscb;
 	struct	 ahd_initiator_tinfo *tinfo;
@@ -3915,157 +1432,122 @@ ahd_linux_run_device_queue(struct ahd_so
 	u_int	 col_idx;
 	uint16_t mask;
 
-	if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0)
-		panic("running device on run list");
-
-	while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
-	    && dev->openings > 0 && dev->qfrozen == 0) {
+	/*
+	 * Get an scb to use.
+	 */
+	tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
+				    cmd->device->id, &tstate);
+	if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
+	 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
+		col_idx = AHD_NEVER_COL_IDX;
+	} else {
+		col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
+					    cmd->device->lun);
+	}
+	if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
+		ahd->flags |= AHD_RESOURCE_SHORTAGE;
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 
-		/*
-		 * Schedule us to run later.  The only reason we are not
-		 * running is because the whole controller Q is frozen.
-		 */
-		if (ahd->platform_data->qfrozen != 0
-		 && AHD_DV_SIMQ_FROZEN(ahd) == 0) {
+	scb->io_ctx = cmd;
+	scb->platform_data->dev = dev;
+	hscb = scb->hscb;
+	cmd->host_scribble = (char *)scb;
 
-			TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
-					  dev, links);
-			dev->flags |= AHD_DEV_ON_RUN_LIST;
-			return;
-		}
+	/*
+	 * Fill out basics of the HSCB.
+	 */
+	hscb->control = 0;
+	hscb->scsiid = BUILD_SCSIID(ahd, cmd);
+	hscb->lun = cmd->device->lun;
+	scb->hscb->task_management = 0;
+	mask = SCB_GET_TARGET_MASK(ahd, scb);
 
-		cmd = &acmd_scsi_cmd(acmd);
+	if ((ahd->user_discenable & mask) != 0)
+		hscb->control |= DISCENB;
 
-		/*
-		 * Get an scb to use.
-		 */
-		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
-					    cmd->device->id, &tstate);
-		if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
-		 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
-			col_idx = AHD_NEVER_COL_IDX;
-		} else {
-			col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
-						    cmd->device->lun);
-		}
-		if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
-			TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
-					 dev, links);
-			dev->flags |= AHD_DEV_ON_RUN_LIST;
-			ahd->flags |= AHD_RESOURCE_SHORTAGE;
-			return;
-		}
-		TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
-		scb->io_ctx = cmd;
-		scb->platform_data->dev = dev;
-		hscb = scb->hscb;
-		cmd->host_scribble = (char *)scb;
+	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
+		scb->flags |= SCB_PACKETIZED;
 
-		/*
-		 * Fill out basics of the HSCB.
-		 */
-		hscb->control = 0;
-		hscb->scsiid = BUILD_SCSIID(ahd, cmd);
-		hscb->lun = cmd->device->lun;
-		scb->hscb->task_management = 0;
-		mask = SCB_GET_TARGET_MASK(ahd, scb);
-
-		if ((ahd->user_discenable & mask) != 0)
-			hscb->control |= DISCENB;
-
-	 	if (AHD_DV_CMD(cmd) != 0)
-			scb->flags |= SCB_SILENT;
-
-		if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
-			scb->flags |= SCB_PACKETIZED;
-
-		if ((tstate->auto_negotiate & mask) != 0) {
-			scb->flags |= SCB_AUTO_NEGOTIATE;
-			scb->hscb->control |= MK_MESSAGE;
-		}
+	if ((tstate->auto_negotiate & mask) != 0) {
+		scb->flags |= SCB_AUTO_NEGOTIATE;
+		scb->hscb->control |= MK_MESSAGE;
+	}
 
-		if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-			int	msg_bytes;
-			uint8_t tag_msgs[2];
-
-			msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
-			if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
-				hscb->control |= tag_msgs[0];
-				if (tag_msgs[0] == MSG_ORDERED_TASK)
-					dev->commands_since_idle_or_otag = 0;
-			} else
-#endif
-			if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
-			 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
-				hscb->control |= MSG_ORDERED_TASK;
+	if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
+		int	msg_bytes;
+		uint8_t tag_msgs[2];
+
+		msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
+		if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
+			hscb->control |= tag_msgs[0];
+			if (tag_msgs[0] == MSG_ORDERED_TASK)
 				dev->commands_since_idle_or_otag = 0;
-			} else {
-				hscb->control |= MSG_SIMPLE_TASK;
-			}
+		} else
+		if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
+		 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
+			hscb->control |= MSG_ORDERED_TASK;
+			dev->commands_since_idle_or_otag = 0;
+		} else {
+			hscb->control |= MSG_SIMPLE_TASK;
 		}
+	}
 
-		hscb->cdb_len = cmd->cmd_len;
-		memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
+	hscb->cdb_len = cmd->cmd_len;
+	memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
 
-		scb->sg_count = 0;
-		ahd_set_residual(scb, 0);
-		ahd_set_sense_residual(scb, 0);
-		if (cmd->use_sg != 0) {
-			void	*sg;
-			struct	 scatterlist *cur_seg;
-			u_int	 nseg;
-			int	 dir;
-
-			cur_seg = (struct scatterlist *)cmd->request_buffer;
-			dir = cmd->sc_data_direction;
-			nseg = pci_map_sg(ahd->dev_softc, cur_seg,
-					  cmd->use_sg, dir);
-			scb->platform_data->xfer_len = 0;
-			for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
-				dma_addr_t addr;
-				bus_size_t len;
-
-				addr = sg_dma_address(cur_seg);
-				len = sg_dma_len(cur_seg);
-				scb->platform_data->xfer_len += len;
-				sg = ahd_sg_setup(ahd, scb, sg, addr, len,
-						  /*last*/nseg == 1);
-			}
-		} else if (cmd->request_bufflen != 0) {
-			void *sg;
+	scb->platform_data->xfer_len = 0;
+	ahd_set_residual(scb, 0);
+	ahd_set_sense_residual(scb, 0);
+	scb->sg_count = 0;
+	if (cmd->use_sg != 0) {
+		void	*sg;
+		struct	 scatterlist *cur_seg;
+		u_int	 nseg;
+		int	 dir;
+
+		cur_seg = (struct scatterlist *)cmd->request_buffer;
+		dir = cmd->sc_data_direction;
+		nseg = pci_map_sg(ahd->dev_softc, cur_seg,
+				  cmd->use_sg, dir);
+		scb->platform_data->xfer_len = 0;
+		for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
 			dma_addr_t addr;
-			int dir;
+			bus_size_t len;
 
-			sg = scb->sg_list;
-			dir = cmd->sc_data_direction;
-			addr = pci_map_single(ahd->dev_softc,
-					      cmd->request_buffer,
-					      cmd->request_bufflen, dir);
-			scb->platform_data->xfer_len = cmd->request_bufflen;
-			scb->platform_data->buf_busaddr = addr;
-			sg = ahd_sg_setup(ahd, scb, sg, addr,
-					  cmd->request_bufflen, /*last*/TRUE);
+			addr = sg_dma_address(cur_seg);
+			len = sg_dma_len(cur_seg);
+			scb->platform_data->xfer_len += len;
+			sg = ahd_sg_setup(ahd, scb, sg, addr, len,
+					  /*last*/nseg == 1);
 		}
+	} else if (cmd->request_bufflen != 0) {
+		void *sg;
+		dma_addr_t addr;
+		int dir;
+
+		sg = scb->sg_list;
+		dir = cmd->sc_data_direction;
+		addr = pci_map_single(ahd->dev_softc,
+				      cmd->request_buffer,
+				      cmd->request_bufflen, dir);
+		scb->platform_data->xfer_len = cmd->request_bufflen;
+		scb->platform_data->buf_busaddr = addr;
+		sg = ahd_sg_setup(ahd, scb, sg, addr,
+				  cmd->request_bufflen, /*last*/TRUE);
+	}
 
-		LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
-		dev->openings--;
-		dev->active++;
-		dev->commands_issued++;
-
-		/* Update the error counting bucket and dump if needed */
-		if (dev->target->cmds_since_error) {
-			dev->target->cmds_since_error++;
-			if (dev->target->cmds_since_error >
-			    AHD_LINUX_ERR_THRESH)
-				dev->target->cmds_since_error = 0;
-		}
+	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
+	dev->openings--;
+	dev->active++;
+	dev->commands_issued++;
 
-		if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
-			dev->commands_since_idle_or_otag++;
-		scb->flags |= SCB_ACTIVE;
-		ahd_queue_scb(ahd, scb);
-	}
+	if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
+		dev->commands_since_idle_or_otag++;
+	scb->flags |= SCB_ACTIVE;
+	ahd_queue_scb(ahd, scb);
+
+	return 0;
 }
 
 /*
@@ -4081,9 +1563,6 @@ ahd_linux_isr(int irq, void *dev_id, str
 	ahd = (struct ahd_softc *) dev_id;
 	ahd_lock(ahd, &flags); 
 	ours = ahd_intr(ahd);
-	if (ahd_linux_next_device_to_run(ahd) != NULL)
-		ahd_schedule_runq(ahd);
-	ahd_linux_run_complete_queue(ahd);
 	ahd_unlock(ahd, &flags);
 	return IRQ_RETVAL(ours);
 }
@@ -4092,111 +1571,6 @@ void
 ahd_platform_flushwork(struct ahd_softc *ahd)
 {
 
-	while (ahd_linux_run_complete_queue(ahd) != NULL)
-		;
-}
-
-static struct ahd_linux_target*
-ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target)
-{
-	struct ahd_linux_target *targ;
-
-	targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT);
-	if (targ == NULL)
-		return (NULL);
-	memset(targ, 0, sizeof(*targ));
-	targ->channel = channel;
-	targ->target = target;
-	targ->ahd = ahd;
-	targ->flags = AHD_DV_REQUIRED;
-	ahd->platform_data->targets[target] = targ;
-	return (targ);
-}
-
-static void
-ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ)
-{
-	struct ahd_devinfo devinfo;
-	struct ahd_initiator_tinfo *tinfo;
-	struct ahd_tmode_tstate *tstate;
-	u_int our_id;
-	u_int target_offset;
-	char channel;
-
-	/*
-	 * Force a negotiation to async/narrow on any
-	 * future command to this device unless a bus
-	 * reset occurs between now and that command.
-	 */
-	channel = 'A' + targ->channel;
-	our_id = ahd->our_id;
-	target_offset = targ->target;
-	tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
-				    targ->target, &tstate);
-	ahd_compile_devinfo(&devinfo, our_id, targ->target, CAM_LUN_WILDCARD,
-			    channel, ROLE_INITIATOR);
-	ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
-			 AHD_TRANS_GOAL, /*paused*/FALSE);
-	ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
-		      AHD_TRANS_GOAL, /*paused*/FALSE);
-	ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS);
- 	ahd->platform_data->targets[target_offset] = NULL;
-	if (targ->inq_data != NULL)
-		free(targ->inq_data, M_DEVBUF);
-	if (targ->dv_buffer != NULL)
-		free(targ->dv_buffer, M_DEVBUF);
-	if (targ->dv_buffer1 != NULL)
-		free(targ->dv_buffer1, M_DEVBUF);
-	free(targ, M_DEVBUF);
-}
-
-static struct ahd_linux_device*
-ahd_linux_alloc_device(struct ahd_softc *ahd,
-		 struct ahd_linux_target *targ, u_int lun)
-{
-	struct ahd_linux_device *dev;
-
-	dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
-	if (dev == NULL)
-		return (NULL);
-	memset(dev, 0, sizeof(*dev));
-	init_timer(&dev->timer);
-	TAILQ_INIT(&dev->busyq);
-	dev->flags = AHD_DEV_UNCONFIGURED;
-	dev->lun = lun;
-	dev->target = targ;
-
-	/*
-	 * We start out life using untagged
-	 * transactions of which we allow one.
-	 */
-	dev->openings = 1;
-
-	/*
-	 * Set maxtags to 0.  This will be changed if we
-	 * later determine that we are dealing with
-	 * a tagged queuing capable device.
-	 */
-	dev->maxtags = 0;
-	
-	targ->refcount++;
-	targ->devices[lun] = dev;
-	return (dev);
-}
-
-static void
-ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev)
-{
-	struct ahd_linux_target *targ;
-
-	del_timer(&dev->timer);
-	targ = dev->target;
-	targ->devices[dev->lun] = NULL;
-	free(dev, M_DEVBUF);
-	targ->refcount--;
-	if (targ->refcount == 0
-	 && (targ->flags & AHD_DV_REQUIRED) == 0)
-		ahd_linux_free_target(ahd, targ);
 }
 
 void
@@ -4207,10 +1581,14 @@ ahd_send_async(struct ahd_softc *ahd, ch
 	case AC_TRANSFER_NEG:
 	{
 		char	buf[80];
+		struct  scsi_target *starget;
 		struct	ahd_linux_target *targ;
 		struct	info_str info;
 		struct	ahd_initiator_tinfo *tinfo;
 		struct	ahd_tmode_tstate *tstate;
+		unsigned int target_ppr_options;
+
+		BUG_ON(target == CAM_TARGET_WILDCARD);
 
 		info.buffer = buf;
 		info.length = sizeof(buf);
@@ -4234,58 +1612,47 @@ ahd_send_async(struct ahd_softc *ahd, ch
 		 * Don't bother reporting results that
 		 * are identical to those last reported.
 		 */
-		targ = ahd->platform_data->targets[target];
-		if (targ == NULL)
+		starget = ahd->platform_data->starget[target];
+		if (starget == NULL)
 			break;
-		if (tinfo->curr.period == targ->last_tinfo.period
-		 && tinfo->curr.width == targ->last_tinfo.width
-		 && tinfo->curr.offset == targ->last_tinfo.offset
-		 && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options)
+		targ = scsi_transport_target_data(starget);
+
+		target_ppr_options =
+			(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
+			+ (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
+			+ (spi_iu(starget) ?  MSG_EXT_PPR_IU_REQ : 0)
+			+ (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0)
+			+ (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0)
+			+ (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0)
+			+ (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0)
+			+ (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0);
+
+		if (tinfo->curr.period == spi_period(starget)
+		    && tinfo->curr.width == spi_width(starget)
+		    && tinfo->curr.offset == spi_offset(starget)
+		 && tinfo->curr.ppr_options == target_ppr_options)
 			if (bootverbose == 0)
 				break;
 
-		targ->last_tinfo.period = tinfo->curr.period;
-		targ->last_tinfo.width = tinfo->curr.width;
-		targ->last_tinfo.offset = tinfo->curr.offset;
-		targ->last_tinfo.ppr_options = tinfo->curr.ppr_options;
-
-		printf("(%s:%c:", ahd_name(ahd), channel);
-		if (target == CAM_TARGET_WILDCARD)
-			printf("*): ");
-		else
-			printf("%d): ", target);
-		ahd_format_transinfo(&info, &tinfo->curr);
-		if (info.pos < info.length)
-			*info.buffer = '\0';
-		else
-			buf[info.length - 1] = '\0';
-		printf("%s", buf);
+		spi_period(starget) = tinfo->curr.period;
+		spi_width(starget) = tinfo->curr.width;
+		spi_offset(starget) = tinfo->curr.offset;
+		spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
+		spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
+		spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
+		spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0;
+		spi_pcomp_en(starget) =  tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0;
+		spi_rti(starget) =  tinfo->curr.ppr_options &  MSG_EXT_PPR_RTI ? 1 : 0;
+		spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0;
+		spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0;
+		spi_display_xfer_agreement(starget);
 		break;
 	}
         case AC_SENT_BDR:
 	{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 		WARN_ON(lun != CAM_LUN_WILDCARD);
 		scsi_report_device_reset(ahd->platform_data->host,
 					 channel - 'A', target);
-#else
-		Scsi_Device *scsi_dev;
-
-		/*
-		 * Find the SCSI device associated with this
-		 * request and indicate that a UA is expected.
-		 */
-		for (scsi_dev = ahd->platform_data->host->host_queue;
-		     scsi_dev != NULL; scsi_dev = scsi_dev->next) {
-			if (channel - 'A' == scsi_dev->channel
-			 && target == scsi_dev->id
-			 && (lun == CAM_LUN_WILDCARD
-			  || lun == scsi_dev->lun)) {
-				scsi_dev->was_reset = 1;
-				scsi_dev->expecting_cc_ua = 1;
-			}
-		}
-#endif
 		break;
 	}
         case AC_BUS_RESET:
@@ -4305,7 +1672,7 @@ ahd_send_async(struct ahd_softc *ahd, ch
 void
 ahd_done(struct ahd_softc *ahd, struct scb *scb)
 {
-	Scsi_Cmnd *cmd;
+	struct scsi_cmnd *cmd;
 	struct	  ahd_linux_device *dev;
 
 	if ((scb->flags & SCB_ACTIVE) == 0) {
@@ -4373,19 +1740,8 @@ ahd_done(struct ahd_softc *ahd, struct s
 			ahd_set_transaction_status(scb, CAM_REQ_CMP);
 		}
 	} else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
-		ahd_linux_handle_scsi_status(ahd, dev, scb);
-	} else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
-		dev->flags |= AHD_DEV_UNCONFIGURED;
-		if (AHD_DV_CMD(cmd) == FALSE)
-			dev->target->flags &= ~AHD_DV_REQUIRED;
+		ahd_linux_handle_scsi_status(ahd, cmd->device, scb);
 	}
-	/*
-	 * Start DV for devices that require it assuming the first command
-	 * sent does not result in a selection timeout.
-	 */
-	if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT
-	 && (dev->target->flags & AHD_DV_REQUIRED) != 0)
-		ahd_linux_start_dv(ahd);
 
 	if (dev->openings == 1
 	 && ahd_get_transaction_status(scb) == CAM_REQ_CMP
@@ -4406,47 +1762,32 @@ ahd_done(struct ahd_softc *ahd, struct s
 	if (dev->active == 0)
 		dev->commands_since_idle_or_otag = 0;
 
-	if (TAILQ_EMPTY(&dev->busyq)) {
-		if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
-		 && dev->active == 0
-		 && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
-			ahd_linux_free_device(ahd, dev);
-	} else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
-		TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
-		dev->flags |= AHD_DEV_ON_RUN_LIST;
-	}
-
 	if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
 		printf("Recovery SCB completes\n");
 		if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
 		 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
 			ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
-		if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
-			scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+		if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
+			ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
 			up(&ahd->platform_data->eh_sem);
 		}
 	}
 
 	ahd_free_scb(ahd, scb);
 	ahd_linux_queue_cmd_complete(ahd, cmd);
-
-	if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0
-	 && LIST_FIRST(&ahd->pending_scbs) == NULL) {
-		ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY;
-		up(&ahd->platform_data->dv_sem);
-	}
 }
 
 static void
 ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
-			     struct ahd_linux_device *dev, struct scb *scb)
+			     struct scsi_device *sdev, struct scb *scb)
 {
 	struct	ahd_devinfo devinfo;
+	struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
 
 	ahd_compile_devinfo(&devinfo,
 			    ahd->our_id,
-			    dev->target->target, dev->lun,
-			    dev->target->channel == 0 ? 'A' : 'B',
+			    sdev->sdev_target->id, sdev->lun,
+			    sdev->sdev_target->channel == 0 ? 'A' : 'B',
 			    ROLE_INITIATOR);
 	
 	/*
@@ -4465,7 +1806,7 @@ ahd_linux_handle_scsi_status(struct ahd_
 	case SCSI_STATUS_CHECK_COND:
 	case SCSI_STATUS_CMD_TERMINATED:
 	{
-		Scsi_Cmnd *cmd;
+		struct scsi_cmnd *cmd;
 
 		/*
 		 * Copy sense information to the OS's cmd
@@ -4518,7 +1859,6 @@ ahd_linux_handle_scsi_status(struct ahd_
 		break;
 	}
 	case SCSI_STATUS_QUEUE_FULL:
-	{
 		/*
 		 * By the time the core driver has returned this
 		 * command, all other commands that were queued
@@ -4579,98 +1919,23 @@ ahd_linux_handle_scsi_status(struct ahd_
 			     (dev->flags & AHD_DEV_Q_BASIC)
 			   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
 		ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
-		/* FALLTHROUGH */
-	}
-	case SCSI_STATUS_BUSY:
-		/*
-		 * Set a short timer to defer sending commands for
-		 * a bit since Linux will not delay in this case.
-		 */
-		if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) {
-			printf("%s:%c:%d: Device Timer still active during "
-			       "busy processing\n", ahd_name(ahd),
-				dev->target->channel, dev->target->target);
-			break;
-		}
-		dev->flags |= AHD_DEV_TIMER_ACTIVE;
-		dev->qfrozen++;
-		init_timer(&dev->timer);
-		dev->timer.data = (u_long)dev;
-		dev->timer.expires = jiffies + (HZ/2);
-		dev->timer.function = ahd_linux_dev_timed_unfreeze;
-		add_timer(&dev->timer);
-		break;
 	}
 }
 
 static void
-ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd)
+ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
 {
 	/*
-	 * Typically, the complete queue has very few entries
-	 * queued to it before the queue is emptied by
-	 * ahd_linux_run_complete_queue, so sorting the entries
-	 * by generation number should be inexpensive.
-	 * We perform the sort so that commands that complete
-	 * with an error are retuned in the order origionally
-	 * queued to the controller so that any subsequent retries
-	 * are performed in order.  The underlying ahd routines do
-	 * not guarantee the order that aborted commands will be
-	 * returned to us.
-	 */
-	struct ahd_completeq *completeq;
-	struct ahd_cmd *list_cmd;
-	struct ahd_cmd *acmd;
-
-	/*
 	 * Map CAM error codes into Linux Error codes.  We
 	 * avoid the conversion so that the DV code has the
 	 * full error information available when making
 	 * state change decisions.
 	 */
-	if (AHD_DV_CMD(cmd) == FALSE) {
+	{
 		uint32_t status;
 		u_int new_status;
 
 		status = ahd_cmd_get_transaction_status(cmd);
-		if (status != CAM_REQ_CMP) {
-			struct ahd_linux_device *dev;
-			struct ahd_devinfo devinfo;
-			cam_status cam_status;
-			uint32_t action;
-			u_int scsi_status;
-
-			dev = ahd_linux_get_device(ahd, cmd->device->channel,
-						   cmd->device->id,
-						   cmd->device->lun,
-						   /*alloc*/FALSE);
-
-			if (dev == NULL)
-				goto no_fallback;
-
-			ahd_compile_devinfo(&devinfo,
-					    ahd->our_id,
-					    dev->target->target, dev->lun,
-					    dev->target->channel == 0 ? 'A':'B',
-					    ROLE_INITIATOR);
-
-			scsi_status = ahd_cmd_get_scsi_status(cmd);
-			cam_status = ahd_cmd_get_transaction_status(cmd);
-			action = aic_error_action(cmd, dev->target->inq_data,
-						  cam_status, scsi_status);
-			if ((action & SSQ_FALLBACK) != 0) {
-
-				/* Update stats */
-				dev->target->errors_detected++;
-				if (dev->target->cmds_since_error == 0)
-					dev->target->cmds_since_error++;
-				else {
-					dev->target->cmds_since_error = 0;
-					ahd_linux_fallback(ahd, &devinfo);
-				}
-			}
-		}
-no_fallback:
 		switch (status) {
 		case CAM_REQ_INPROG:
 		case CAM_REQ_CMP:
@@ -4715,26 +1980,7 @@ no_fallback:
 			new_status = DID_ERROR;
 			break;
 		case CAM_REQUEUE_REQ:
-			/*
-			 * If we want the request requeued, make sure there
-			 * are sufficent retries.  In the old scsi error code,
-			 * we used to be able to specify a result code that
-			 * bypassed the retry count.  Now we must use this
-			 * hack.  We also "fake" a check condition with
-			 * a sense code of ABORTED COMMAND.  This seems to
-			 * evoke a retry even if this command is being sent
-			 * via the eh thread.  Ick!  Ick!  Ick!
-			 */
-			if (cmd->retries > 0)
-				cmd->retries--;
-			new_status = DID_OK;
-			ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
-			cmd->result |= (DRIVER_SENSE << 24);
-			memset(cmd->sense_buffer, 0,
-			       sizeof(cmd->sense_buffer));
-			cmd->sense_buffer[0] = SSD_ERRCODE_VALID
-					     | SSD_CURRENT_ERROR;
-			cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND;
+			new_status = DID_REQUEUE;
 			break;
 		default:
 			/* We should never get here */
@@ -4742,275 +1988,801 @@ no_fallback:
 			break;
 		}
 
-		ahd_cmd_set_transaction_status(cmd, new_status);
+		ahd_cmd_set_transaction_status(cmd, new_status);
+	}
+
+	cmd->scsi_done(cmd);
+}
+
+static void
+ahd_linux_sem_timeout(u_long arg)
+{
+	struct	ahd_softc *ahd;
+	u_long	s;
+
+	ahd = (struct ahd_softc *)arg;
+
+	ahd_lock(ahd, &s);
+	if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
+		ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+		up(&ahd->platform_data->eh_sem);
+	}
+	ahd_unlock(ahd, &s);
+}
+
+void
+ahd_freeze_simq(struct ahd_softc *ahd)
+{
+	ahd->platform_data->qfrozen++;
+	if (ahd->platform_data->qfrozen == 1) {
+		scsi_block_requests(ahd->platform_data->host);
+		ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
+					CAM_LUN_WILDCARD, SCB_LIST_NULL,
+					ROLE_INITIATOR, CAM_REQUEUE_REQ);
+	}
+}
+
+void
+ahd_release_simq(struct ahd_softc *ahd)
+{
+	u_long s;
+	int    unblock_reqs;
+
+	unblock_reqs = 0;
+	ahd_lock(ahd, &s);
+	if (ahd->platform_data->qfrozen > 0)
+		ahd->platform_data->qfrozen--;
+	if (ahd->platform_data->qfrozen == 0) {
+		unblock_reqs = 1;
+	}
+	ahd_unlock(ahd, &s);
+	/*
+	 * There is still a race here.  The mid-layer
+	 * should keep its own freeze count and use
+	 * a bottom half handler to run the queues
+	 * so we can unblock with our own lock held.
+	 */
+	if (unblock_reqs)
+		scsi_unblock_requests(ahd->platform_data->host);
+}
+
+static int
+ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
+{
+	struct ahd_softc *ahd;
+	struct ahd_linux_device *dev;
+	struct scb *pending_scb;
+	u_int  saved_scbptr;
+	u_int  active_scbptr;
+	u_int  last_phase;
+	u_int  saved_scsiid;
+	u_int  cdb_byte;
+	int    retval;
+	int    was_paused;
+	int    paused;
+	int    wait;
+	int    disconnected;
+	ahd_mode_state saved_modes;
+
+	pending_scb = NULL;
+	paused = FALSE;
+	wait = FALSE;
+	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
+
+	printf("%s:%d:%d:%d: Attempting to queue a%s message:",
+	       ahd_name(ahd), cmd->device->channel,
+	       cmd->device->id, cmd->device->lun,
+	       flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
+
+	printf("CDB:");
+	for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
+		printf(" 0x%x", cmd->cmnd[cdb_byte]);
+	printf("\n");
+
+	spin_lock_irq(&ahd->platform_data->spin_lock);
+
+	/*
+	 * First determine if we currently own this command.
+	 * Start by searching the device queue.  If not found
+	 * there, check the pending_scb list.  If not found
+	 * at all, and the system wanted us to just abort the
+	 * command, return success.
+	 */
+	dev = scsi_transport_device_data(cmd->device);
+
+	if (dev == NULL) {
+		/*
+		 * No target device for this command exists,
+		 * so we must not still own the command.
+		 */
+		printf("%s:%d:%d:%d: Is not an active device\n",
+		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
+		       cmd->device->lun);
+		retval = SUCCESS;
+		goto no_cmd;
+	}
+
+	/*
+	 * See if we can find a matching cmd in the pending list.
+	 */
+	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+		if (pending_scb->io_ctx == cmd)
+			break;
+	}
+
+	if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
+
+		/* Any SCB for this device will do for a target reset */
+		LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+		  	if (ahd_match_scb(ahd, pending_scb, cmd->device->id,
+					  cmd->device->channel + 'A',
+					  CAM_LUN_WILDCARD,
+					  SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+				break;
+		}
+	}
+
+	if (pending_scb == NULL) {
+		printf("%s:%d:%d:%d: Command not found\n",
+		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
+		       cmd->device->lun);
+		goto no_cmd;
+	}
+
+	if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
+		/*
+		 * We can't queue two recovery actions using the same SCB
+		 */
+		retval = FAILED;
+		goto  done;
+	}
+
+	/*
+	 * Ensure that the card doesn't do anything
+	 * behind our back.  Also make sure that we
+	 * didn't "just" miss an interrupt that would
+	 * affect this cmd.
+	 */
+	was_paused = ahd_is_paused(ahd);
+	ahd_pause_and_flushwork(ahd);
+	paused = TRUE;
+
+	if ((pending_scb->flags & SCB_ACTIVE) == 0) {
+		printf("%s:%d:%d:%d: Command already completed\n",
+		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
+		       cmd->device->lun);
+		goto no_cmd;
+	}
+
+	printf("%s: At time of recovery, card was %spaused\n",
+	       ahd_name(ahd), was_paused ? "" : "not ");
+	ahd_dump_card_state(ahd);
+
+	disconnected = TRUE;
+	if (flag == SCB_ABORT) {
+		if (ahd_search_qinfifo(ahd, cmd->device->id, 
+				       cmd->device->channel + 'A',
+				       cmd->device->lun, 
+				       pending_scb->hscb->tag,
+				       ROLE_INITIATOR, CAM_REQ_ABORTED,
+				       SEARCH_COMPLETE) > 0) {
+			printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
+			       ahd_name(ahd), cmd->device->channel, 
+			       cmd->device->id, cmd->device->lun);
+			retval = SUCCESS;
+			goto done;
+		}
+	} else if (ahd_search_qinfifo(ahd, cmd->device->id,
+				      cmd->device->channel + 'A',
+				      cmd->device->lun, pending_scb->hscb->tag,
+				      ROLE_INITIATOR, /*status*/0,
+				      SEARCH_COUNT) > 0) {
+		disconnected = FALSE;
+	}
+
+	saved_modes = ahd_save_modes(ahd);
+	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+	last_phase = ahd_inb(ahd, LASTPHASE);
+	saved_scbptr = ahd_get_scbptr(ahd);
+	active_scbptr = saved_scbptr;
+	if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
+		struct scb *bus_scb;
+
+		bus_scb = ahd_lookup_scb(ahd, active_scbptr);
+		if (bus_scb == pending_scb)
+			disconnected = FALSE;
+		else if (flag != SCB_ABORT
+			 && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid
+			 && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb))
+			disconnected = FALSE;
+	}
+
+	/*
+	 * At this point, pending_scb is the scb associated with the
+	 * passed in command.  That command is currently active on the
+	 * bus or is in the disconnected state.
+	 */
+	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
+	if (last_phase != P_BUSFREE
+	 && (SCB_GET_TAG(pending_scb) == active_scbptr
+	     || (flag == SCB_DEVICE_RESET
+		 && SCSIID_TARGET(ahd, saved_scsiid) == cmd->device->id))) {
+
+		/*
+		 * We're active on the bus, so assert ATN
+		 * and hope that the target responds.
+		 */
+		pending_scb = ahd_lookup_scb(ahd, active_scbptr);
+		pending_scb->flags |= SCB_RECOVERY_SCB|flag;
+		ahd_outb(ahd, MSG_OUT, HOST_MSG);
+		ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
+		printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
+		       ahd_name(ahd), cmd->device->channel,
+		       cmd->device->id, cmd->device->lun);
+		wait = TRUE;
+	} else if (disconnected) {
+
+		/*
+		 * Actually re-queue this SCB in an attempt
+		 * to select the device before it reconnects.
+		 */
+		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
+		ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
+		pending_scb->hscb->cdb_len = 0;
+		pending_scb->hscb->task_attribute = 0;
+		pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
+
+		if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
+			/*
+			 * Mark the SCB has having an outstanding
+			 * task management function.  Should the command
+			 * complete normally before the task management
+			 * function can be sent, the host will be notified
+			 * to abort our requeued SCB.
+			 */
+			ahd_outb(ahd, SCB_TASK_MANAGEMENT,
+				 pending_scb->hscb->task_management);
+		} else {
+			/*
+			 * If non-packetized, set the MK_MESSAGE control
+			 * bit indicating that we desire to send a message.
+			 * We also set the disconnected flag since there is
+			 * no guarantee that our SCB control byte matches
+			 * the version on the card.  We don't want the
+			 * sequencer to abort the command thinking an
+			 * unsolicited reselection occurred.
+			 */
+			pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+
+			/*
+			 * The sequencer will never re-reference the
+			 * in-core SCB.  To make sure we are notified
+			 * during reslection, set the MK_MESSAGE flag in
+			 * the card's copy of the SCB.
+			 */
+			ahd_outb(ahd, SCB_CONTROL,
+				 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
+		}
+
+		/*
+		 * Clear out any entries in the QINFIFO first
+		 * so we are the next SCB for this target
+		 * to run.
+		 */
+		ahd_search_qinfifo(ahd, cmd->device->id,
+				   cmd->device->channel + 'A', cmd->device->lun,
+				   SCB_LIST_NULL, ROLE_INITIATOR,
+				   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
+		ahd_qinfifo_requeue_tail(ahd, pending_scb);
+		ahd_set_scbptr(ahd, saved_scbptr);
+		ahd_print_path(ahd, pending_scb);
+		printf("Device is disconnected, re-queuing SCB\n");
+		wait = TRUE;
+	} else {
+		printf("%s:%d:%d:%d: Unable to deliver message\n",
+		       ahd_name(ahd), cmd->device->channel,
+		       cmd->device->id, cmd->device->lun);
+		retval = FAILED;
+		goto done;
 	}
 
-	completeq = &ahd->platform_data->completeq;
-	list_cmd = TAILQ_FIRST(completeq);
-	acmd = (struct ahd_cmd *)cmd;
-	while (list_cmd != NULL
-	    && acmd_scsi_cmd(list_cmd).serial_number
-	     < acmd_scsi_cmd(acmd).serial_number)
-		list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
-	if (list_cmd != NULL)
-		TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
-	else
-		TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
+no_cmd:
+	/*
+	 * Our assumption is that if we don't have the command, no
+	 * recovery action was required, so we return success.  Again,
+	 * the semantics of the mid-layer recovery engine are not
+	 * well defined, so this may change in time.
+	 */
+	retval = SUCCESS;
+done:
+	if (paused)
+		ahd_unpause(ahd);
+	if (wait) {
+		struct timer_list timer;
+		int ret;
+
+		ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM;
+		spin_unlock_irq(&ahd->platform_data->spin_lock);
+		init_timer(&timer);
+		timer.data = (u_long)ahd;
+		timer.expires = jiffies + (5 * HZ);
+		timer.function = ahd_linux_sem_timeout;
+		add_timer(&timer);
+		printf("Recovery code sleeping\n");
+		down(&ahd->platform_data->eh_sem);
+		printf("Recovery code awake\n");
+        	ret = del_timer_sync(&timer);
+		if (ret == 0) {
+			printf("Timer Expired\n");
+			retval = FAILED;
+		}
+		spin_lock_irq(&ahd->platform_data->spin_lock);
+	}
+	spin_unlock_irq(&ahd->platform_data->spin_lock);
+	return (retval);
 }
 
-static void
-ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+static void ahd_linux_set_width(struct scsi_target *starget, int width)
 {
-	struct	scsi_inquiry_data *sid;
-	struct	ahd_initiator_tinfo *tinfo;
-	struct	ahd_transinfo *user;
-	struct	ahd_transinfo *goal;
-	struct	ahd_transinfo *curr;
-	struct	ahd_tmode_tstate *tstate;
-	struct	ahd_linux_device *dev;
-	u_int	width;
-	u_int	period;
-	u_int	offset;
-	u_int	ppr_options;
-	u_int	trans_version;
-	u_int	prot_version;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_devinfo devinfo;
+	unsigned long flags;
 
-	/*
-	 * Determine if this lun actually exists.  If so,
-	 * hold on to its corresponding device structure.
-	 * If not, make sure we release the device and
-	 * don't bother processing the rest of this inquiry
-	 * command.
-	 */
-	dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',
-				   devinfo->target, devinfo->lun,
-				   /*alloc*/TRUE);
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_lock(ahd, &flags);
+	ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
+}
 
-	sid = (struct scsi_inquiry_data *)dev->target->inq_data;
-	if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
+static void ahd_linux_set_period(struct scsi_target *starget, int period)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options;
+	unsigned int dt;
+	unsigned long flags;
+	unsigned long offset = tinfo->goal.offset;
 
-		dev->flags &= ~AHD_DEV_UNCONFIGURED;
-	} else {
-		dev->flags |= AHD_DEV_UNCONFIGURED;
-		return;
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: set period to %d\n", ahd_name(ahd), period);
+#endif
+	if (offset == 0)
+		offset = MAX_OFFSET;
+
+	if (period < 8)
+		period = 8;
+	if (period < 10) {
+		ppr_options |= MSG_EXT_PPR_DT_REQ;
+		if (period == 8)
+			ppr_options |= MSG_EXT_PPR_IU_REQ;
 	}
 
-	/*
-	 * Update our notion of this device's transfer
-	 * negotiation capabilities.
-	 */
-	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
-				    devinfo->our_scsiid,
-				    devinfo->target, &tstate);
-	user = &tinfo->user;
-	goal = &tinfo->goal;
-	curr = &tinfo->curr;
-	width = user->width;
-	period = user->period;
-	offset = user->offset;
-	ppr_options = user->ppr_options;
-	trans_version = user->transport_version;
-	prot_version = MIN(user->protocol_version, SID_ANSI_REV(sid));
+	dt = ppr_options & MSG_EXT_PPR_DT_REQ;
 
-	/*
-	 * Only attempt SPI3/4 once we've verified that
-	 * the device claims to support SPI3/4 features.
-	 */
-	if (prot_version < SCSI_REV_2)
-		trans_version = SID_ANSI_REV(sid);
-	else
-		trans_version = SCSI_REV_2;
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
 
-	if ((sid->flags & SID_WBus16) == 0)
-		width = MSG_EXT_WDTR_BUS_8_BIT;
-	if ((sid->flags & SID_Sync) == 0) {
-		period = 0;
-		offset = 0;
-		ppr_options = 0;
-	}
-	if ((sid->spi3data & SID_SPI_QAS) == 0)
-		ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
-	if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0)
-		ppr_options &= MSG_EXT_PPR_QAS_REQ;
-	if ((sid->spi3data & SID_SPI_IUS) == 0)
-		ppr_options &= (MSG_EXT_PPR_DT_REQ
-			      | MSG_EXT_PPR_QAS_REQ);
-
-	if (prot_version > SCSI_REV_2
-	 && ppr_options != 0)
-		trans_version = user->transport_version;
-
-	ahd_validate_width(ahd, /*tinfo limit*/NULL, &width, ROLE_UNKNOWN);
-	ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
-	ahd_validate_offset(ahd, /*tinfo limit*/NULL, period,
-			    &offset, width, ROLE_UNKNOWN);
-	if (offset == 0 || period == 0) {
-		period = 0;
-		offset = 0;
-		ppr_options = 0;
-	}
-	/* Apply our filtered user settings. */
-	curr->transport_version = trans_version;
-	curr->protocol_version = prot_version;
-	ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, /*paused*/FALSE);
-	ahd_set_syncrate(ahd, devinfo, period, offset, ppr_options,
-			 AHD_TRANS_GOAL, /*paused*/FALSE);
+	/* all PPR requests apart from QAS require wide transfers */
+	if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
+		if (spi_width(starget) == 0)
+			ppr_options &= MSG_EXT_PPR_QAS_REQ;
+	}
+
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
 }
 
-void
-ahd_freeze_simq(struct ahd_softc *ahd)
+static void ahd_linux_set_offset(struct scsi_target *starget, int offset)
 {
-	ahd->platform_data->qfrozen++;
-	if (ahd->platform_data->qfrozen == 1) {
-		scsi_block_requests(ahd->platform_data->host);
-		ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
-					CAM_LUN_WILDCARD, SCB_LIST_NULL,
-					ROLE_INITIATOR, CAM_REQUEUE_REQ);
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = 0;
+	unsigned int period = 0;
+	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+	unsigned long flags;
+
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: set offset to %d\n", ahd_name(ahd), offset);
+#endif
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	if (offset != 0) {
+		period = tinfo->goal.period;
+		ppr_options = tinfo->goal.ppr_options;
+		ahd_find_syncrate(ahd, &period, &ppr_options, 
+				  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
 	}
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
+			 AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
 }
 
-void
-ahd_release_simq(struct ahd_softc *ahd)
+static void ahd_linux_set_dt(struct scsi_target *starget, int dt)
 {
-	u_long s;
-	int    unblock_reqs;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_DT_REQ;
+	unsigned int period = tinfo->goal.period;
+	unsigned int width = tinfo->goal.width;
+	unsigned long flags;
 
-	unblock_reqs = 0;
-	ahd_lock(ahd, &s);
-	if (ahd->platform_data->qfrozen > 0)
-		ahd->platform_data->qfrozen--;
-	if (ahd->platform_data->qfrozen == 0) {
-		unblock_reqs = 1;
-	}
-	if (AHD_DV_SIMQ_FROZEN(ahd)
-	 && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) {
-		ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE;
-		up(&ahd->platform_data->dv_sem);
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: %s DT\n", ahd_name(ahd), 
+		       dt ? "enabling" : "disabling");
+#endif
+	if (dt) {
+		ppr_options |= MSG_EXT_PPR_DT_REQ;
+		if (!width)
+			ahd_linux_set_width(starget, 1);
+	} else {
+		if (period <= 9)
+			period = 10; /* If resetting DT, period must be >= 25ns */
+		/* IU is invalid without DT set */
+		ppr_options &= ~MSG_EXT_PPR_IU_REQ;
+	}
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_qas(struct scsi_target *starget, int qas)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_QAS_REQ;
+	unsigned int period = tinfo->goal.period;
+	unsigned int dt;
+	unsigned long flags;
+
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: %s QAS\n", ahd_name(ahd), 
+		       qas ? "enabling" : "disabling");
+#endif
+
+	if (qas) {
+		ppr_options |= MSG_EXT_PPR_QAS_REQ; 
 	}
-	ahd_schedule_runq(ahd);
-	ahd_unlock(ahd, &s);
-	/*
-	 * There is still a race here.  The mid-layer
-	 * should keep its own freeze count and use
-	 * a bottom half handler to run the queues
-	 * so we can unblock with our own lock held.
-	 */
-	if (unblock_reqs)
-		scsi_unblock_requests(ahd->platform_data->host);
+
+	dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
 }
 
-static void
-ahd_linux_sem_timeout(u_long arg)
+static void ahd_linux_set_iu(struct scsi_target *starget, int iu)
 {
-	struct	scb *scb;
-	struct	ahd_softc *ahd;
-	u_long	s;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_IU_REQ;
+	unsigned int period = tinfo->goal.period;
+	unsigned int dt;
+	unsigned long flags;
 
-	scb = (struct scb *)arg;
-	ahd = scb->ahd_softc;
-	ahd_lock(ahd, &s);
-	if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
-		scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
-		up(&ahd->platform_data->eh_sem);
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: %s IU\n", ahd_name(ahd),
+		       iu ? "enabling" : "disabling");
+#endif
+
+	if (iu) {
+		ppr_options |= MSG_EXT_PPR_IU_REQ;
+		ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */
 	}
-	ahd_unlock(ahd, &s);
+
+	dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
 }
 
-static void
-ahd_linux_dev_timed_unfreeze(u_long arg)
+static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm)
 {
-	struct ahd_linux_device *dev;
-	struct ahd_softc *ahd;
-	u_long s;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_RD_STRM;
+	unsigned int period = tinfo->goal.period;
+	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+	unsigned long flags;
 
-	dev = (struct ahd_linux_device *)arg;
-	ahd = dev->target->ahd;
-	ahd_lock(ahd, &s);
-	dev->flags &= ~AHD_DEV_TIMER_ACTIVE;
-	if (dev->qfrozen > 0)
-		dev->qfrozen--;
-	if (dev->qfrozen == 0
-	 && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0)
-		ahd_linux_run_device_queue(ahd, dev);
-	if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
-	 && dev->active == 0)
-		ahd_linux_free_device(ahd, dev);
-	ahd_unlock(ahd, &s);
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: %s Read Streaming\n", ahd_name(ahd), 
+		       rdstrm  ? "enabling" : "disabling");
+#endif
+
+	if (rdstrm)
+		ppr_options |= MSG_EXT_PPR_RD_STRM;
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
 }
 
-void
-ahd_platform_dump_card_state(struct ahd_softc *ahd)
+static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow)
 {
-	struct ahd_linux_device *dev;
-	int target;
-	int maxtarget;
-	int lun;
-	int i;
-
-	maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7;
-	for (target = 0; target <=maxtarget; target++) {
-
-		for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
-			struct ahd_cmd *acmd;
-
-			dev = ahd_linux_get_device(ahd, 0, target,
-						   lun, /*alloc*/FALSE);
-			if (dev == NULL)
-				continue;
-
-			printf("DevQ(%d:%d:%d): ", 0, target, lun);
-			i = 0;
-			TAILQ_FOREACH(acmd, &dev->busyq, acmd_links.tqe) {
-				if (i++ > AHD_SCB_MAX)
-					break;
-			}
-			printf("%d waiting\n", i);
-		}
-	}
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_WR_FLOW;
+	unsigned int period = tinfo->goal.period;
+	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+	unsigned long flags;
+
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: %s Write Flow Control\n", ahd_name(ahd),
+		       wrflow ? "enabling" : "disabling");
+#endif
+
+	if (wrflow)
+		ppr_options |= MSG_EXT_PPR_WR_FLOW;
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
 }
 
-static int __init
-ahd_linux_init(void)
+static void ahd_linux_set_rti(struct scsi_target *starget, int rti)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	return ahd_linux_detect(&aic79xx_driver_template);
-#else
-	scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template);
-	if (aic79xx_driver_template.present == 0) {
-		scsi_unregister_module(MODULE_SCSI_HA,
-				       &aic79xx_driver_template);
-		return (-ENODEV);
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_RTI;
+	unsigned int period = tinfo->goal.period;
+	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+	unsigned long flags;
+
+	if ((ahd->features & AHD_RTI) == 0) {
+#ifdef AHD_DEBUG
+		if ((ahd_debug & AHD_SHOW_DV) != 0)
+			printf("%s: RTI not available\n", ahd_name(ahd));
+#endif
+		return;
 	}
 
-	return (0);
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: %s RTI\n", ahd_name(ahd),
+		       rti ? "enabling" : "disabling");
 #endif
+
+	if (rti)
+		ppr_options |= MSG_EXT_PPR_RTI;
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
 }
 
-static void __exit
-ahd_linux_exit(void)
+static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
 {
-	struct ahd_softc *ahd;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_PCOMP_EN;
+	unsigned int period = tinfo->goal.period;
+	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+	unsigned long flags;
 
-	/*
-	 * Shutdown DV threads before going into the SCSI mid-layer.
-	 * This avoids situations where the mid-layer locks the entire
-	 * kernel so that waiting for our DV threads to exit leads
-	 * to deadlock.
-	 */
-	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
+#ifdef AHD_DEBUG
+	if ((ahd_debug & AHD_SHOW_DV) != 0)
+		printf("%s: %s Precompensation\n", ahd_name(ahd), 
+		       pcomp ? "Enable" : "Disable");
+#endif
 
-		ahd_linux_kill_dv_thread(ahd);
-	}
+	if (pcomp)
+		ppr_options |= MSG_EXT_PPR_PCOMP_EN;
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+	struct ahd_tmode_tstate *tstate;
+	struct ahd_initiator_tinfo *tinfo 
+		= ahd_fetch_transinfo(ahd,
+				      starget->channel + 'A',
+				      shost->this_id, starget->id, &tstate);
+	struct ahd_devinfo devinfo;
+	unsigned int ppr_options = tinfo->goal.ppr_options
+		& ~MSG_EXT_PPR_HOLD_MCS;
+	unsigned int period = tinfo->goal.period;
+	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+	unsigned long flags;
+
+	if (hold)
+		ppr_options |= MSG_EXT_PPR_HOLD_MCS;
+
+	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+			    starget->channel + 'A', ROLE_INITIATOR);
+	ahd_find_syncrate(ahd, &period, &ppr_options,
+			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+	ahd_lock(ahd, &flags);
+	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+			 ppr_options, AHD_TRANS_GOAL, FALSE);
+	ahd_unlock(ahd, &flags);
+}
+
+
+
+static struct spi_function_template ahd_linux_transport_functions = {
+	.set_offset	= ahd_linux_set_offset,
+	.show_offset	= 1,
+	.set_period	= ahd_linux_set_period,
+	.show_period	= 1,
+	.set_width	= ahd_linux_set_width,
+	.show_width	= 1,
+	.set_dt		= ahd_linux_set_dt,
+	.show_dt	= 1,
+	.set_iu		= ahd_linux_set_iu,
+	.show_iu	= 1,
+	.set_qas	= ahd_linux_set_qas,
+	.show_qas	= 1,
+	.set_rd_strm	= ahd_linux_set_rd_strm,
+	.show_rd_strm	= 1,
+	.set_wr_flow	= ahd_linux_set_wr_flow,
+	.show_wr_flow	= 1,
+	.set_rti	= ahd_linux_set_rti,
+	.show_rti	= 1,
+	.set_pcomp_en	= ahd_linux_set_pcomp_en,
+	.show_pcomp_en	= 1,
+	.set_hold_mcs	= ahd_linux_set_hold_mcs,
+	.show_hold_mcs	= 1,
+};
+
+static int __init
+ahd_linux_init(void)
+{
+	int	error = 0;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	/*
-	 * In 2.4 we have to unregister from the PCI core _after_
-	 * unregistering from the scsi midlayer to avoid dangling
-	 * references.
+	 * If we've been passed any parameters, process them now.
 	 */
-	scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template);
-#endif
+	if (aic79xx)
+		aic79xx_setup(aic79xx);
+
+	ahd_linux_transport_template =
+		spi_attach_transport(&ahd_linux_transport_functions);
+	if (!ahd_linux_transport_template)
+		return -ENODEV;
+
+	scsi_transport_reserve_target(ahd_linux_transport_template,
+				      sizeof(struct ahd_linux_target));
+	scsi_transport_reserve_device(ahd_linux_transport_template,
+				      sizeof(struct ahd_linux_device));
+
+	error = ahd_linux_pci_init();
+	if (error)
+		spi_release_transport(ahd_linux_transport_template);
+	return error;
+}
+
+static void __exit
+ahd_linux_exit(void)
+{
 	ahd_linux_pci_exit();
+	spi_release_transport(ahd_linux_transport_template);
 }
 
 module_init(ahd_linux_init);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -42,6 +42,7 @@
 #ifndef _AIC79XX_LINUX_H_
 #define _AIC79XX_LINUX_H_
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
@@ -49,18 +50,23 @@
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
 #include <linux/version.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
 
-#include <linux/interrupt.h> /* For tasklet support. */
-#include <linux/config.h>
-#include <linux/slab.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 /* Core SCSI definitions */
 #define AIC_LIB_PREFIX ahd
-#include "scsi.h"
-#include <scsi/scsi_host.h>
 
 /* Name space conflict with BSD queue macros */
 #ifdef LIST_HEAD
@@ -95,7 +101,7 @@
 /************************* Forward Declarations *******************************/
 struct ahd_softc;
 typedef struct pci_dev *ahd_dev_softc_t;
-typedef Scsi_Cmnd      *ahd_io_ctx_t;
+typedef struct scsi_cmnd      *ahd_io_ctx_t;
 
 /******************************* Byte Order ***********************************/
 #define ahd_htobe16(x)	cpu_to_be16(x)
@@ -114,8 +120,7 @@ typedef Scsi_Cmnd      *ahd_io_ctx_t;
 
 /************************* Configuration Data *********************************/
 extern uint32_t aic79xx_allow_memio;
-extern int aic79xx_detect_complete;
-extern Scsi_Host_Template aic79xx_driver_template;
+extern struct scsi_host_template aic79xx_driver_template;
 
 /***************************** Bus Space/DMA **********************************/
 
@@ -145,11 +150,7 @@ struct ahd_linux_dma_tag
 };
 typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
 
-struct ahd_linux_dmamap
-{
-	dma_addr_t	bus_addr;
-};
-typedef struct ahd_linux_dmamap* bus_dmamap_t;
+typedef dma_addr_t bus_dmamap_t;
 
 typedef int bus_dma_filter_t(void*, dma_addr_t);
 typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
@@ -226,12 +227,12 @@ typedef struct timer_list ahd_timer_t;
 #define ahd_timer_init init_timer
 #define ahd_timer_stop del_timer_sync
 typedef void ahd_linux_callback_t (u_long);  
-static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
+static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
 				     ahd_callback_t *func, void *arg);
 static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
 
 static __inline void
-ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
+ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
 {
 	struct ahd_softc *ahd;
 
@@ -252,43 +253,8 @@ ahd_scb_timer_reset(struct scb *scb, u_i
 /***************************** SMP support ************************************/
 #include <linux/spinlock.h>
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
-#define AHD_SCSI_HAS_HOST_LOCK 1
-#else
-#define AHD_SCSI_HAS_HOST_LOCK 0
-#endif
-
 #define AIC79XX_DRIVER_VERSION "1.3.11"
 
-/**************************** Front End Queues ********************************/
-/*
- * Data structure used to cast the Linux struct scsi_cmnd to something
- * that allows us to use the queue macros.  The linux structure has
- * plenty of space to hold the links fields as required by the queue
- * macros, but the queue macors require them to have the correct type.
- */
-struct ahd_cmd_internal {
-	/* Area owned by the Linux scsi layer. */
-	uint8_t	private[offsetof(struct scsi_cmnd, SCp.Status)];
-	union {
-		STAILQ_ENTRY(ahd_cmd)	ste;
-		LIST_ENTRY(ahd_cmd)	le;
-		TAILQ_ENTRY(ahd_cmd)	tqe;
-	} links;
-	uint32_t			end;
-};
-
-struct ahd_cmd {
-	union {
-		struct ahd_cmd_internal	icmd;
-		struct scsi_cmnd	scsi_cmd;
-	} un;
-};
-
-#define acmd_icmd(cmd) ((cmd)->un.icmd)
-#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
-#define acmd_links un.icmd.links
-
 /*************************** Device Data Structures ***************************/
 /*
  * A per probed device structure used to deal with some error recovery
@@ -297,22 +263,17 @@ struct ahd_cmd {
  * after a successfully completed inquiry command to the target when
  * that inquiry data indicates a lun is present.
  */
-TAILQ_HEAD(ahd_busyq, ahd_cmd);
+
 typedef enum {
-	AHD_DEV_UNCONFIGURED	 = 0x01,
 	AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
-	AHD_DEV_TIMER_ACTIVE	 = 0x04, /* Our timer is active */
-	AHD_DEV_ON_RUN_LIST	 = 0x08, /* Queued to be run later */
 	AHD_DEV_Q_BASIC		 = 0x10, /* Allow basic device queuing */
 	AHD_DEV_Q_TAGGED	 = 0x20, /* Allow full SCSI2 command queueing */
 	AHD_DEV_PERIODIC_OTAG	 = 0x40, /* Send OTAG to prevent starvation */
-	AHD_DEV_SLAVE_CONFIGURED = 0x80	 /* slave_configure() has been called */
 } ahd_linux_dev_flags;
 
 struct ahd_linux_target;
 struct ahd_linux_device {
 	TAILQ_ENTRY(ahd_linux_device) links;
-	struct			ahd_busyq busyq;
 
 	/*
 	 * The number of transactions currently
@@ -388,62 +349,12 @@ struct ahd_linux_device {
 	 */
 	u_int			commands_since_idle_or_otag;
 #define AHD_OTAG_THRESH	500
-
-	int			lun;
-	Scsi_Device	       *scsi_device;
-	struct			ahd_linux_target *target;
 };
 
-typedef enum {
-	AHD_DV_REQUIRED		 = 0x01,
-	AHD_INQ_VALID		 = 0x02,
-	AHD_BASIC_DV		 = 0x04,
-	AHD_ENHANCED_DV		 = 0x08
-} ahd_linux_targ_flags;
-
-/* DV States */
-typedef enum {
-	AHD_DV_STATE_EXIT = 0,
-	AHD_DV_STATE_INQ_SHORT_ASYNC,
-	AHD_DV_STATE_INQ_ASYNC,
-	AHD_DV_STATE_INQ_ASYNC_VERIFY,
-	AHD_DV_STATE_TUR,
-	AHD_DV_STATE_REBD,
-	AHD_DV_STATE_INQ_VERIFY,
-	AHD_DV_STATE_WEB,
-	AHD_DV_STATE_REB,
-	AHD_DV_STATE_SU,
-	AHD_DV_STATE_BUSY
-} ahd_dv_state;
-
 struct ahd_linux_target {
-	struct ahd_linux_device	 *devices[AHD_NUM_LUNS];
-	int			  channel;
-	int			  target;
-	int			  refcount;
+	struct scsi_device	 *sdev[AHD_NUM_LUNS];
 	struct ahd_transinfo	  last_tinfo;
 	struct ahd_softc	 *ahd;
-	ahd_linux_targ_flags	  flags;
-	struct scsi_inquiry_data *inq_data;
-	/*
-	 * The next "fallback" period to use for narrow/wide transfers.
-	 */
-	uint8_t			  dv_next_narrow_period;
-	uint8_t			  dv_next_wide_period;
-	uint8_t			  dv_max_width;
-	uint8_t			  dv_max_ppr_options;
-	uint8_t			  dv_last_ppr_options;
-	u_int			  dv_echo_size;
-	ahd_dv_state		  dv_state;
-	u_int			  dv_state_retry;
-	uint8_t			 *dv_buffer;
-	uint8_t			 *dv_buffer1;
-
-	/*
-	 * Cumulative counter of errors.
-	 */
-	u_long			errors_detected;
-	u_long			cmds_since_error;
 };
 
 /********************* Definitions Required by the Core ***********************/
@@ -453,32 +364,16 @@ struct ahd_linux_target {
  * manner and are allocated below 4GB, the number of S/G segments is
  * unrestricted.
  */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * We dynamically adjust the number of segments in pre-2.5 kernels to
- * avoid fragmentation issues in the SCSI mid-layer's private memory
- * allocator.  See aic79xx_osm.c ahd_linux_size_nseg() for details.
- */
-extern u_int ahd_linux_nseg;
-#define	AHD_NSEG ahd_linux_nseg
-#define	AHD_LINUX_MIN_NSEG 64
-#else
 #define	AHD_NSEG 128
-#endif
 
 /*
  * Per-SCB OSM storage.
  */
-typedef enum {
-	AHD_SCB_UP_EH_SEM = 0x1
-} ahd_linux_scb_flags;
-
 struct scb_platform_data {
 	struct ahd_linux_device	*dev;
 	dma_addr_t		 buf_busaddr;
 	uint32_t		 xfer_len;
 	uint32_t		 sense_resid;	/* Auto-Sense residual */
-	ahd_linux_scb_flags	 flags;
 };
 
 /*
@@ -487,44 +382,23 @@ struct scb_platform_data {
  * alignment restrictions of the various platforms supported by
  * this driver.
  */
-typedef enum {
-	AHD_DV_WAIT_SIMQ_EMPTY	 = 0x01,
-	AHD_DV_WAIT_SIMQ_RELEASE = 0x02,
-	AHD_DV_ACTIVE		 = 0x04,
-	AHD_DV_SHUTDOWN		 = 0x08,
-	AHD_RUN_CMPLT_Q_TIMER	 = 0x10
-} ahd_linux_softc_flags;
-
-TAILQ_HEAD(ahd_completeq, ahd_cmd);
-
 struct ahd_platform_data {
 	/*
 	 * Fields accessed from interrupt context.
 	 */
-	struct ahd_linux_target *targets[AHD_NUM_TARGETS]; 
-	TAILQ_HEAD(, ahd_linux_device) device_runq;
-	struct ahd_completeq	 completeq;
+	struct scsi_target *starget[AHD_NUM_TARGETS]; 
 
 	spinlock_t		 spin_lock;
-	struct tasklet_struct	 runq_tasklet;
 	u_int			 qfrozen;
-	pid_t			 dv_pid;
-	struct timer_list	 completeq_timer;
 	struct timer_list	 reset_timer;
-	struct timer_list	 stats_timer;
 	struct semaphore	 eh_sem;
-	struct semaphore	 dv_sem;
-	struct semaphore	 dv_cmd_sem;	/* XXX This needs to be in
-						 * the target struct
-						 */
-	struct scsi_device	*dv_scsi_dev;
 	struct Scsi_Host        *host;		/* pointer to scsi host */
 #define AHD_LINUX_NOIRQ	((uint32_t)~0)
 	uint32_t		 irq;		/* IRQ for this adapter */
 	uint32_t		 bios_address;
 	uint32_t		 mem_busaddr;	/* Mem Base Addr */
-	uint64_t		 hw_dma_mask;
-	ahd_linux_softc_flags	 flags;
+#define	AHD_SCB_UP_EH_SEM 0x1
+	uint32_t		 flags;
 };
 
 /************************** OS Utility Wrappers *******************************/
@@ -641,7 +515,7 @@ ahd_insb(struct ahd_softc * ahd, long po
 
 /**************************** Initialization **********************************/
 int		ahd_linux_register_host(struct ahd_softc *,
-					Scsi_Host_Template *);
+					struct scsi_host_template *);
 
 uint64_t	ahd_linux_get_memsize(void);
 
@@ -657,28 +531,6 @@ void	ahd_format_transinfo(struct info_st
 			     struct ahd_transinfo *tinfo);
 
 /******************************** Locking *************************************/
-/* Lock protecting internal data structures */
-static __inline void ahd_lockinit(struct ahd_softc *);
-static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags);
-static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags);
-
-/* Lock acquisition and release of the above lock in midlayer entry points. */
-static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *,
-						  unsigned long *flags);
-static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *,
-						    unsigned long *flags);
-
-/* Lock held during command compeletion to the upper layer */
-static __inline void ahd_done_lockinit(struct ahd_softc *);
-static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags);
-static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags);
-
-/* Lock held during ahd_list manipulation and ahd softc frees */
-extern spinlock_t ahd_list_spinlock;
-static __inline void ahd_list_lockinit(void);
-static __inline void ahd_list_lock(unsigned long *flags);
-static __inline void ahd_list_unlock(unsigned long *flags);
-
 static __inline void
 ahd_lockinit(struct ahd_softc *ahd)
 {
@@ -697,75 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsign
 	spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
 }
 
-static __inline void
-ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags)
-{
-	/*
-	 * In 2.5.X and some 2.4.X versions, the midlayer takes our
-	 * lock just before calling us, so we avoid locking again.
-	 * For other kernel versions, the io_request_lock is taken
-	 * just before our entry point is called.  In this case, we
-	 * trade the io_request_lock for our per-softc lock.
-	 */
-#if AHD_SCSI_HAS_HOST_LOCK == 0
-	spin_unlock(&io_request_lock);
-	spin_lock(&ahd->platform_data->spin_lock);
-#endif
-}
-
-static __inline void
-ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
-	spin_unlock(&ahd->platform_data->spin_lock);
-	spin_lock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_done_lockinit(struct ahd_softc *ahd)
-{
-	/*
-	 * In 2.5.X, our own lock is held during completions.
-	 * In previous versions, the io_request_lock is used.
-	 * In either case, we can't initialize this lock again.
-	 */
-}
-
-static __inline void
-ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
-	spin_lock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
-	spin_unlock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_list_lockinit(void)
-{
-	spin_lock_init(&ahd_list_spinlock);
-}
-
-static __inline void
-ahd_list_lock(unsigned long *flags)
-{
-	spin_lock_irqsave(&ahd_list_spinlock, *flags);
-}
-
-static __inline void
-ahd_list_unlock(unsigned long *flags)
-{
-	spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
-}
-
 /******************************* PCI Definitions ******************************/
 /*
  * PCIM_xxx: mask to locate subfield in register
@@ -925,27 +708,17 @@ ahd_flush_device_writes(struct ahd_softc
 }
 
 /**************************** Proc FS Support *********************************/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-int	ahd_linux_proc_info(char *, char **, off_t, int, int, int);
-#else
 int	ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
 			    off_t, int, int);
-#endif
-
-/*************************** Domain Validation ********************************/
-#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
-#define AHD_DV_SIMQ_FROZEN(ahd)					\
-	((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0)	\
-	 && (ahd)->platform_data->qfrozen == 1)
 
 /*********************** Transaction Access Wrappers **************************/
-static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
 static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
 static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
 static __inline uint32_t ahd_get_transaction_status(struct scb *);
-static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
 static __inline uint32_t ahd_get_scsi_status(struct scb *);
 static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
 static __inline u_long ahd_get_transfer_length(struct scb *);
@@ -964,7 +737,7 @@ static __inline void ahd_platform_scb_fr
 static __inline void ahd_freeze_scb(struct scb *scb);
 
 static __inline
-void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
 {
 	cmd->result &= ~(CAM_STATUS_MASK << 16);
 	cmd->result |= status << 16;
@@ -977,7 +750,7 @@ void ahd_set_transaction_status(struct s
 }
 
 static __inline
-void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
 {
 	cmd->result &= ~0xFFFF;
 	cmd->result |= status;
@@ -990,7 +763,7 @@ void ahd_set_scsi_status(struct scb *scb
 }
 
 static __inline
-uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd)
+uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
 {
 	return ((cmd->result >> 16) & CAM_STATUS_MASK);
 }
@@ -1002,7 +775,7 @@ uint32_t ahd_get_transaction_status(stru
 }
 
 static __inline
-uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
+uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
 {
 	return (cmd->result & 0xFFFF);
 }
@@ -1117,7 +890,6 @@ void	ahd_done(struct ahd_softc*, struct 
 void	ahd_send_async(struct ahd_softc *, char channel,
 		       u_int target, u_int lun, ac_code, void *);
 void	ahd_print_path(struct ahd_softc *, struct scb *);
-void	ahd_platform_dump_card_state(struct ahd_softc *ahd);
 
 #ifdef CONFIG_PCI
 #define AHD_PCI_CONFIG 1
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = {
 static void
 ahd_linux_pci_dev_remove(struct pci_dev *pdev)
 {
-	struct ahd_softc *ahd;
-	u_long l;
+	struct ahd_softc *ahd = pci_get_drvdata(pdev);
+	u_long s;
 
-	/*
-	 * We should be able to just perform
-	 * the free directly, but check our
-	 * list for extra sanity.
-	 */
-	ahd_list_lock(&l);
-	ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev));
-	if (ahd != NULL) {
-		u_long s;
-
-		TAILQ_REMOVE(&ahd_tailq, ahd, links);
-		ahd_list_unlock(&l);
-		ahd_lock(ahd, &s);
-		ahd_intr_enable(ahd, FALSE);
-		ahd_unlock(ahd, &s);
-		ahd_free(ahd);
-	} else
-		ahd_list_unlock(&l);
+	ahd_lock(ahd, &s);
+	ahd_intr_enable(ahd, FALSE);
+	ahd_unlock(ahd, &s);
+	ahd_free(ahd);
+}
+
+static void
+ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
+{
+	struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
+	unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+
+	master_pdev = pci_get_slot(pdev->bus, master_devfn);
+	if (master_pdev) {
+		struct ahd_softc *master = pci_get_drvdata(master_pdev);
+		if (master) {
+			ahd->flags &= ~AHD_BIOS_ENABLED;
+			ahd->flags |= master->flags & AHD_BIOS_ENABLED;
+		} else
+			printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
+		pci_dev_put(master_pdev);
+	}
 }
 
 static int
@@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 	char		*name;
 	int		 error;
 
-	/*
-	 * Some BIOSen report the same device multiple times.
-	 */
-	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-		struct pci_dev *probed_pdev;
-
-		probed_pdev = ahd->dev_softc;
-		if (probed_pdev->bus->number == pdev->bus->number
-		 && probed_pdev->devfn == pdev->devfn)
-			break;
-	}
-	if (ahd != NULL) {
-		/* Skip duplicate. */
-		return (-ENODEV);
-	}
-
 	pci = pdev;
 	entry = ahd_find_pci_device(pci);
 	if (entry == NULL)
@@ -177,15 +165,12 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 		if (memsize >= 0x8000000000ULL
 	 	 && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
 			ahd->flags |= AHD_64BIT_ADDRESSING;
-			ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK;
 		} else if (memsize > 0x80000000
 			&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
 			ahd->flags |= AHD_39BIT_ADDRESSING;
-			ahd->platform_data->hw_dma_mask = mask_39bit;
 		}
 	} else {
 		pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-		ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK;
 	}
 	ahd->dev_softc = pci;
 	error = ahd_pci_config(ahd, entry);
@@ -193,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 		ahd_free(ahd);
 		return (-error);
 	}
+
+	/*
+	 * Second Function PCI devices need to inherit some
+	 * * settings from function 0.
+	 */
+	if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
+		ahd_linux_pci_inherit_flags(ahd);
+
 	pci_set_drvdata(pdev, ahd);
-	if (aic79xx_detect_complete) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-		ahd_linux_register_host(ahd, &aic79xx_driver_template);
-#else
-		printf("aic79xx: ignoring PCI device found after "
-		       "initialization\n");
-		return (-ENODEV);
-#endif
-	}
+
+	ahd_linux_register_host(ahd, &aic79xx_driver_template);
 	return (0);
 }
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -283,7 +283,6 @@ int
 ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
 {
 	struct scb_data *shared_scb_data;
-	u_long		 l;
 	u_int		 command;
 	uint32_t	 devconfig;
 	uint16_t	 subvendor; 
@@ -373,16 +372,9 @@ ahd_pci_config(struct ahd_softc *ahd, st
 	 * Allow interrupts now that we are completely setup.
 	 */
 	error = ahd_pci_map_int(ahd);
-	if (error != 0)
-		return (error);
-
-	ahd_list_lock(&l);
-	/*
-	 * Link this softc in with all other ahd instances.
-	 */
-	ahd_softc_insert(ahd);
-	ahd_list_unlock(&l);
-	return (0);
+	if (!error)
+		ahd->init_level++;
+	return error;
 }
 
 /*
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -49,10 +49,53 @@ static void	ahd_dump_target_state(struct
 				      u_int our_id, char channel,
 				      u_int target_id, u_int target_offset);
 static void	ahd_dump_device_state(struct info_str *info,
-				      struct ahd_linux_device *dev);
+				      struct scsi_device *sdev);
 static int	ahd_proc_write_seeprom(struct ahd_softc *ahd,
 				       char *buffer, int length);
 
+/*
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+static struct {
+	u_int period_factor;
+	u_int period;	/* in 100ths of ns */
+} scsi_syncrates[] = {
+	{ 0x08, 625 },	/* FAST-160 */
+	{ 0x09, 1250 },	/* FAST-80 */
+	{ 0x0a, 2500 },	/* FAST-40 40MHz */
+	{ 0x0b, 3030 },	/* FAST-40 33MHz */
+	{ 0x0c, 5000 }	/* FAST-20 */
+};
+
+/*
+ * Return the frequency in kHz corresponding to the given
+ * sync period factor.
+ */
+static u_int
+ahd_calc_syncsrate(u_int period_factor)
+{
+	int i;
+	int num_syncrates;
+
+	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
+	/* See if the period is in the "exception" table */
+	for (i = 0; i < num_syncrates; i++) {
+
+		if (period_factor == scsi_syncrates[i].period_factor) {
+			/* Period in kHz */
+			return (100000000 / scsi_syncrates[i].period);
+		}
+	}
+
+	/*
+	 * Wasn't in the table, so use the standard
+	 * 4 times conversion.
+	 */
+	return (10000000 / (period_factor * 4 * 10));
+}
+
+
 static void
 copy_mem_info(struct info_str *info, char *data, int len)
 {
@@ -109,7 +152,7 @@ ahd_format_transinfo(struct info_str *in
         speed = 3300;
         freq = 0;
 	if (tinfo->offset != 0) {
-		freq = aic_calc_syncsrate(tinfo->period);
+		freq = ahd_calc_syncsrate(tinfo->period);
 		speed = freq;
 	}
 	speed *= (0x01 << tinfo->width);
@@ -167,6 +210,7 @@ ahd_dump_target_state(struct ahd_softc *
 		      u_int target_offset)
 {
 	struct	ahd_linux_target *targ;
+	struct  scsi_target *starget;
 	struct	ahd_initiator_tinfo *tinfo;
 	struct	ahd_tmode_tstate *tstate;
 	int	lun;
@@ -176,20 +220,20 @@ ahd_dump_target_state(struct ahd_softc *
 	copy_info(info, "Target %d Negotiation Settings\n", target_id);
 	copy_info(info, "\tUser: ");
 	ahd_format_transinfo(info, &tinfo->user);
-	targ = ahd->platform_data->targets[target_offset];
-	if (targ == NULL)
+	starget = ahd->platform_data->starget[target_offset];
+	if (starget == NULL)
 		return;
+	targ = scsi_transport_target_data(starget);
 
 	copy_info(info, "\tGoal: ");
 	ahd_format_transinfo(info, &tinfo->goal);
 	copy_info(info, "\tCurr: ");
 	ahd_format_transinfo(info, &tinfo->curr);
-	copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);
 
 	for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
-		struct ahd_linux_device *dev;
+		struct scsi_device *dev;
 
-		dev = targ->devices[lun];
+		dev = targ->sdev[lun];
 
 		if (dev == NULL)
 			continue;
@@ -199,10 +243,13 @@ ahd_dump_target_state(struct ahd_softc *
 }
 
 static void
-ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev)
+ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
 {
+	struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
+
 	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
-		  dev->target->channel + 'A', dev->target->target, dev->lun);
+		  sdev->sdev_target->channel + 'A',
+		  sdev->sdev_target->id, sdev->lun);
 
 	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
 	copy_info(info, "\t\tCommands Active %d\n", dev->active);
@@ -278,36 +325,16 @@ done:
  * Return information to handle /proc support for the driver.
  */
 int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ahd_linux_proc_info(char *buffer, char **start, off_t offset,
-		    int length, int hostno, int inout)
-#else
 ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
 		    off_t offset, int length, int inout)
-#endif
 {
-	struct	ahd_softc *ahd;
+	struct	ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
 	struct	info_str info;
 	char	ahd_info[256];
-	u_long	l;
 	u_int	max_targ;
 	u_int	i;
 	int	retval;
 
-	retval = -EINVAL;
-	ahd_list_lock(&l);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-		if (ahd->platform_data->host->host_no == hostno)
-			break;
-	}
-#else
-	ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
-#endif
-
-	if (ahd == NULL)
-		goto done;
-
 	 /* Has data been written to the file? */ 
 	if (inout == TRUE) {
 		retval = ahd_proc_write_seeprom(ahd, buffer, length);
@@ -357,6 +384,5 @@ ahd_linux_proc_info(struct Scsi_Host *sh
 	}
 	retval = info.pos > info.offset ? info.pos - info.offset : 0;
 done:
-	ahd_list_unlock(&l);
 	return (retval);
 }
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $
  *
  * $FreeBSD$
  */
@@ -243,7 +243,7 @@ typedef enum {
 	 */
 	AHC_AIC7850_FE	= AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
 	AHC_AIC7860_FE	= AHC_AIC7850_FE,
-	AHC_AIC7870_FE	= AHC_TARGETMODE,
+	AHC_AIC7870_FE	= AHC_TARGETMODE|AHC_AUTOPAUSE,
 	AHC_AIC7880_FE	= AHC_AIC7870_FE|AHC_ULTRA,
 	/*
 	 * Although we have space for both the initiator and
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -39,7 +39,7 @@
  *
  * $FreeBSD$
  */
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $"
 
 /*
  * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -1306,7 +1306,6 @@ scratch_ram {
 	 */
 	MWI_RESIDUAL {
 		size		1
-		alias	TARG_IMMEDIATE_SCB
 	}
 	/*
 	 * SCBID of the next SCB to be started by the controller.
@@ -1461,6 +1460,7 @@ scratch_ram {
 	 */
 	LAST_MSG {
 		size		1
+		alias	TARG_IMMEDIATE_SCB
 	}
 
 	/*
diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq
--- a/drivers/scsi/aic7xxx/aic7xxx.seq
+++ b/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -40,7 +40,7 @@
  * $FreeBSD$
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"
 PATCH_ARG_LIST = "struct ahc_softc *ahc"
 PREFIX = "ahc_"
 
@@ -679,6 +679,7 @@ await_busfree:
 		clr	SCSIBUSL;	/* Prevent bit leakage durint SELTO */
 	}
 	and	SXFRCTL0, ~SPIOEN;
+	mvi	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
 	test	SSTAT1,REQINIT|BUSFREE	jz .;
 	test	SSTAT1, BUSFREE jnz poll_for_work;
 	mvi	MISSED_BUSFREE call set_seqint;
@@ -1097,7 +1098,7 @@ ultra2_dmahalt:
 		test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
 		if ((ahc->flags & AHC_TARGETROLE) != 0) {
 			test	SSTAT0, TARGET jz dma_last_sg;
-			if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
+			if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
 				test	DMAPARAMS, DIRECTION jz dma_mid_sg;
 			}
 		}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
--- a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
@@ -28,9 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $
  */
 
 /*
@@ -64,7 +62,6 @@
  *   is preceded by an initial zero (leading 0, followed by 16-bits, MSB
  *   first).  The clock cycling from low to high initiates the next data
  *   bit to be sent from the chip.
- *
  */
 
 #ifdef __linux__
@@ -81,14 +78,22 @@
  * Right now, we only have to read the SEEPROM.  But we make it easier to
  * add other 93Cx6 functions.
  */
-static struct seeprom_cmd {
+struct seeprom_cmd {
   	uint8_t len;
- 	uint8_t bits[9];
-} seeprom_read = {3, {1, 1, 0}};
+ 	uint8_t bits[11];
+};
 
+/* Short opcodes for the c46 */
 static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
 static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Long opcodes for the C56/C66 */
+static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Common opcodes */
 static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+static struct seeprom_cmd seeprom_read  = {3, {1, 1, 0}};
 
 /*
  * Wait for the SEERDY to go high; about 800 ns.
@@ -222,12 +227,25 @@ int
 ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
 		  u_int start_addr, u_int count)
 {
+	struct seeprom_cmd *ewen, *ewds;
 	uint16_t v;
 	uint8_t temp;
 	int i, k;
 
 	/* Place the chip into write-enable mode */
-	send_seeprom_cmd(sd, &seeprom_ewen);
+	if (sd->sd_chip == C46) {
+		ewen = &seeprom_ewen;
+		ewds = &seeprom_ewds;
+	} else if (sd->sd_chip == C56_66) {
+		ewen = &seeprom_long_ewen;
+		ewds = &seeprom_long_ewds;
+	} else {
+		printf("ahc_write_seeprom: unsupported seeprom type %d\n",
+		       sd->sd_chip);
+		return (0);
+	}
+
+	send_seeprom_cmd(sd, ewen);
 	reset_seeprom(sd);
 
 	/* Write all requested data out to the seeprom. */
@@ -277,7 +295,7 @@ ahc_write_seeprom(struct seeprom_descrip
 	}
 
 	/* Put the chip back into write-protect mode */
-	send_seeprom_cmd(sd, &seeprom_ewds);
+	send_seeprom_cmd(sd, ewds);
 	reset_seeprom(sd);
 
 	return (1);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -37,9 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#155 $
  */
 
 #ifdef __linux__
@@ -287,10 +285,19 @@ ahc_restart(struct ahc_softc *ahc)
 		ahc_outb(ahc, SEQ_FLAGS2,
 			 ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
 	}
+
+	/*
+	 * Clear any pending sequencer interrupt.  It is no
+	 * longer relevant since we're resetting the Program
+	 * Counter.
+	 */
+	ahc_outb(ahc, CLRINT, CLRSEQINT);
+
 	ahc_outb(ahc, MWI_RESIDUAL, 0);
 	ahc_outb(ahc, SEQCTL, ahc->seqctl);
 	ahc_outb(ahc, SEQADDR0, 0);
 	ahc_outb(ahc, SEQADDR1, 0);
+
 	ahc_unpause(ahc);
 }
 
@@ -1174,19 +1181,20 @@ ahc_handle_scsiint(struct ahc_softc *ahc
 				       scb_index);
 			}
 #endif
-			/*
-			 * Force a renegotiation with this target just in
-			 * case the cable was pulled and will later be
-			 * re-attached.  The target may forget its negotiation
-			 * settings with us should it attempt to reselect
-			 * during the interruption.  The target will not issue
-			 * a unit attention in this case, so we must always
-			 * renegotiate.
-			 */
 			ahc_scb_devinfo(ahc, &devinfo, scb);
-			ahc_force_renegotiation(ahc, &devinfo);
 			ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
 			ahc_freeze_devq(ahc, scb);
+
+			/*
+			 * Cancel any pending transactions on the device
+			 * now that it seems to be missing.  This will
+			 * also revert us to async/narrow transfers until
+			 * we can renegotiate with the device.
+			 */
+			ahc_handle_devreset(ahc, &devinfo,
+					    CAM_SEL_TIMEOUT,
+					    "Selection Timeout",
+					    /*verbose_level*/1);
 		}
 		ahc_outb(ahc, CLRINT, CLRSCSIINT);
 		ahc_restart(ahc);
@@ -3763,8 +3771,9 @@ ahc_handle_devreset(struct ahc_softc *ah
 			 /*period*/0, /*offset*/0, /*ppr_options*/0,
 			 AHC_TRANS_CUR, /*paused*/TRUE);
 	
-	ahc_send_async(ahc, devinfo->channel, devinfo->target,
-		       CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+	if (status != CAM_SEL_TIMEOUT)
+		ahc_send_async(ahc, devinfo->channel, devinfo->target,
+			       CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
 
 	if (message != NULL
 	 && (verbose_level <= bootverbose))
@@ -4003,14 +4012,6 @@ ahc_reset(struct ahc_softc *ahc, int rei
 	 * to disturb the integrity of the bus.
 	 */
 	ahc_pause(ahc);
-	if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) {
-		/*
-		 * The chip has not been initialized since
-		 * PCI/EISA/VLB bus reset.  Don't trust
-		 * "left over BIOS data".
-		 */
-		ahc->flags |= AHC_NO_BIOS_INIT;
-	}
 	sxfrctl1_b = 0;
 	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
 		u_int sblkctl;
@@ -5036,14 +5037,23 @@ ahc_pause_and_flushwork(struct ahc_softc
 	ahc->flags |= AHC_ALL_INTERRUPTS;
 	paused = FALSE;
 	do {
-		if (paused)
+		if (paused) {
 			ahc_unpause(ahc);
+			/*
+			 * Give the sequencer some time to service
+			 * any active selections.
+			 */
+			ahc_delay(500);
+		}
 		ahc_intr(ahc);
 		ahc_pause(ahc);
 		paused = TRUE;
 		ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO);
-		ahc_clear_critical_section(ahc);
 		intstat = ahc_inb(ahc, INTSTAT);
+		if ((intstat & INT_PEND) == 0) {
+			ahc_clear_critical_section(ahc);
+			intstat = ahc_inb(ahc, INTSTAT);
+		}
 	} while (--maxloops
 	      && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
 	      && ((intstat & INT_PEND) != 0
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -125,12 +125,6 @@
 
 static struct scsi_transport_template *ahc_linux_transport_template = NULL;
 
-/*
- * Include aiclib.c as part of our
- * "module dependencies are hard" work around.
- */
-#include "aiclib.c"
-
 #include <linux/init.h>		/* __setup */
 #include <linux/mm.h>		/* For fetching system memory size */
 #include <linux/blkdev.h>		/* For block_size() */
@@ -391,7 +385,6 @@ static int ahc_linux_run_command(struct 
 				 struct ahc_linux_device *,
 				 struct scsi_cmnd *);
 static void ahc_linux_setup_tag_info_global(char *p);
-static aic_option_callback_t ahc_linux_setup_tag_info;
 static int  aic7xxx_setup(char *s);
 
 static int ahc_linux_unit;
@@ -635,6 +628,8 @@ ahc_linux_slave_alloc(struct scsi_device
 	
 	targ->sdev[sdev->lun] = sdev;
 
+	spi_period(starget) = 0;
+
 	return 0;
 }
 
@@ -918,6 +913,86 @@ ahc_linux_setup_tag_info(u_long arg, int
 	}
 }
 
+static char *
+ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
+		       void (*callback)(u_long, int, int, int32_t),
+		       u_long callback_arg)
+{
+	char	*tok_end;
+	char	*tok_end2;
+	int      i;
+	int      instance;
+	int	 targ;
+	int	 done;
+	char	 tok_list[] = {'.', ',', '{', '}', '\0'};
+
+	/* All options use a ':' name/arg separator */
+	if (*opt_arg != ':')
+		return (opt_arg);
+	opt_arg++;
+	instance = -1;
+	targ = -1;
+	done = FALSE;
+	/*
+	 * Restore separator that may be in
+	 * the middle of our option argument.
+	 */
+	tok_end = strchr(opt_arg, '\0');
+	if (tok_end < end)
+		*tok_end = ',';
+	while (!done) {
+		switch (*opt_arg) {
+		case '{':
+			if (instance == -1) {
+				instance = 0;
+			} else {
+				if (depth > 1) {
+					if (targ == -1)
+						targ = 0;
+				} else {
+					printf("Malformed Option %s\n",
+					       opt_name);
+					done = TRUE;
+				}
+			}
+			opt_arg++;
+			break;
+		case '}':
+			if (targ != -1)
+				targ = -1;
+			else if (instance != -1)
+				instance = -1;
+			opt_arg++;
+			break;
+		case ',':
+		case '.':
+			if (instance == -1)
+				done = TRUE;
+			else if (targ >= 0)
+				targ++;
+			else if (instance >= 0)
+				instance++;
+			opt_arg++;
+			break;
+		case '\0':
+			done = TRUE;
+			break;
+		default:
+			tok_end = end;
+			for (i = 0; tok_list[i]; i++) {
+				tok_end2 = strchr(opt_arg, tok_list[i]);
+				if ((tok_end2) && (tok_end2 < tok_end))
+					tok_end = tok_end2;
+			}
+			callback(callback_arg, instance, targ,
+				 simple_strtol(opt_arg, NULL, 0));
+			opt_arg = tok_end;
+			break;
+		}
+	}
+	return (opt_arg);
+}
+
 /*
  * Handle Linux boot parameters. This routine allows for assigning a value
  * to a parameter with a ':' between the parameter and the value.
@@ -972,7 +1047,7 @@ aic7xxx_setup(char *s)
 		if (strncmp(p, "global_tag_depth", n) == 0) {
 			ahc_linux_setup_tag_info_global(p + n);
 		} else if (strncmp(p, "tag_info", n) == 0) {
-			s = aic_parse_brace_option("tag_info", p + n, end,
+			s = ahc_parse_brace_option("tag_info", p + n, end,
 			    2, ahc_linux_setup_tag_info, 0);
 		} else if (p[n] == ':') {
 			*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
@@ -1612,9 +1687,9 @@ ahc_send_async(struct ahc_softc *ahc, ch
 		if (channel == 'B')
 			target_offset += 8;
 		starget = ahc->platform_data->starget[target_offset];
-		targ = scsi_transport_target_data(starget);
-		if (targ == NULL)
+		if (starget == NULL)
 			break;
+		targ = scsi_transport_target_data(starget);
 
 		target_ppr_options =
 			(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
@@ -2329,8 +2404,6 @@ ahc_platform_dump_card_state(struct ahc_
 {
 }
 
-static void ahc_linux_exit(void);
-
 static void ahc_linux_set_width(struct scsi_target *starget, int width)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -265,7 +265,7 @@ ahc_scb_timer_reset(struct scb *scb, u_i
 /***************************** SMP support ************************************/
 #include <linux/spinlock.h>
 
-#define AIC7XXX_DRIVER_VERSION "6.2.36"
+#define AIC7XXX_DRIVER_VERSION "7.0"
 
 /*************************** Device Data Structures ***************************/
 /*
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -149,6 +149,27 @@ ahc_linux_pci_dev_remove(struct pci_dev 
 	ahc_free(ahc);
 }
 
+static void
+ahc_linux_pci_inherit_flags(struct ahc_softc *ahc)
+{
+	struct pci_dev *pdev = ahc->dev_softc, *master_pdev;
+	unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+
+	master_pdev = pci_get_slot(pdev->bus, master_devfn);
+	if (master_pdev) {
+		struct ahc_softc *master = pci_get_drvdata(master_pdev);
+		if (master) {
+			ahc->flags &= ~AHC_BIOS_ENABLED; 
+			ahc->flags |= master->flags & AHC_BIOS_ENABLED;
+
+			ahc->flags &= ~AHC_PRIMARY_CHANNEL; 
+			ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL;
+		} else
+			printk(KERN_ERR "aic7xxx: no multichannel peer found!\n");
+		pci_dev_put(master_pdev);
+	} 
+}
+
 static int
 ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -203,6 +224,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 		ahc_free(ahc);
 		return (-error);
 	}
+
+	/*
+	 * Second Function PCI devices need to inherit some
+	 * settings from function 0.
+	 */
+	if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
+		ahc_linux_pci_inherit_flags(ahc);
+
 	pci_set_drvdata(pdev, ahc);
 	ahc_linux_register_host(ahc, &aic7xxx_driver_template);
 	return (0);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -54,6 +54,49 @@ static void	ahc_dump_device_state(struct
 static int	ahc_proc_write_seeprom(struct ahc_softc *ahc,
 				       char *buffer, int length);
 
+/*
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+static struct {
+	u_int period_factor;
+	u_int period;	/* in 100ths of ns */
+} scsi_syncrates[] = {
+	{ 0x08, 625 },	/* FAST-160 */
+	{ 0x09, 1250 },	/* FAST-80 */
+	{ 0x0a, 2500 },	/* FAST-40 40MHz */
+	{ 0x0b, 3030 },	/* FAST-40 33MHz */
+	{ 0x0c, 5000 }	/* FAST-20 */
+};
+
+/*
+ * Return the frequency in kHz corresponding to the given
+ * sync period factor.
+ */
+static u_int
+ahc_calc_syncsrate(u_int period_factor)
+{
+	int i;
+	int num_syncrates;
+
+	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
+	/* See if the period is in the "exception" table */
+	for (i = 0; i < num_syncrates; i++) {
+
+		if (period_factor == scsi_syncrates[i].period_factor) {
+			/* Period in kHz */
+			return (100000000 / scsi_syncrates[i].period);
+		}
+	}
+
+	/*
+	 * Wasn't in the table, so use the standard
+	 * 4 times conversion.
+	 */
+	return (10000000 / (period_factor * 4 * 10));
+}
+
+
 static void
 copy_mem_info(struct info_str *info, char *data, int len)
 {
@@ -106,7 +149,7 @@ ahc_format_transinfo(struct info_str *in
         speed = 3300;
         freq = 0;
 	if (tinfo->offset != 0) {
-		freq = aic_calc_syncsrate(tinfo->period);
+		freq = ahc_calc_syncsrate(tinfo->period);
 		speed = freq;
 	}
 	speed *= (0x01 << tinfo->width);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
--- a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
  */
 typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
 typedef struct ahc_reg_parse_entry {
@@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
 #define	CMDSIZE_TABLE_TAIL		0x34
 
 #define	MWI_RESIDUAL    		0x38
-#define	TARG_IMMEDIATE_SCB		0x38
 
 #define	NEXT_QUEUED_SCB 		0x39
 
@@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
 #define	RETURN_2        		0x52
 
 #define	LAST_MSG        		0x53
+#define	TARG_IMMEDIATE_SCB		0x53
 
 #define	SCSISEQ_TEMPLATE		0x54
 #define		ENSELO          	0x40
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
--- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
  */
 
 #include "aic7xxx_osm.h"
diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
--- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
@@ -2,13 +2,13 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
  */
 static uint8_t seqprog[] = {
 	0xb2, 0x00, 0x00, 0x08,
 	0xf7, 0x11, 0x22, 0x08,
-	0x00, 0x65, 0xec, 0x59,
+	0x00, 0x65, 0xee, 0x59,
 	0xf7, 0x01, 0x02, 0x08,
 	0xff, 0x6a, 0x24, 0x08,
 	0x40, 0x00, 0x40, 0x68,
@@ -21,15 +21,15 @@ static uint8_t seqprog[] = {
 	0x01, 0x4d, 0xc8, 0x30,
 	0x00, 0x4c, 0x12, 0x70,
 	0x01, 0x39, 0xa2, 0x30,
-	0x00, 0x6a, 0xc0, 0x5e,
+	0x00, 0x6a, 0xc2, 0x5e,
 	0x01, 0x51, 0x20, 0x31,
 	0x01, 0x57, 0xae, 0x00,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x51, 0x12, 0x5e,
+	0x00, 0x51, 0x14, 0x5e,
 	0x01, 0x51, 0xc8, 0x30,
 	0x00, 0x39, 0xc8, 0x60,
 	0x00, 0xbb, 0x30, 0x70,
-	0xc1, 0x6a, 0xd8, 0x5e,
+	0xc1, 0x6a, 0xda, 0x5e,
 	0x01, 0xbf, 0x72, 0x30,
 	0x01, 0x40, 0x7e, 0x31,
 	0x01, 0x90, 0x80, 0x30,
@@ -49,10 +49,10 @@ static uint8_t seqprog[] = {
 	0x08, 0x6a, 0x78, 0x00,
 	0x01, 0x50, 0xc8, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xfc, 0x5d,
+	0x48, 0x6a, 0xfe, 0x5d,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xfc, 0x5d,
+	0x48, 0x6a, 0xfe, 0x5d,
 	0x01, 0x6a, 0x26, 0x01,
 	0xf0, 0x19, 0x7a, 0x08,
 	0x0f, 0x18, 0xc8, 0x08,
@@ -93,7 +93,7 @@ static uint8_t seqprog[] = {
 	0x00, 0x65, 0x20, 0x41,
 	0x02, 0x57, 0xae, 0x00,
 	0x00, 0x65, 0x9e, 0x40,
-	0x61, 0x6a, 0xd8, 0x5e,
+	0x61, 0x6a, 0xda, 0x5e,
 	0x08, 0x51, 0x20, 0x71,
 	0x02, 0x0b, 0xb2, 0x78,
 	0x00, 0x65, 0xae, 0x40,
@@ -106,7 +106,7 @@ static uint8_t seqprog[] = {
 	0x80, 0x3d, 0x7a, 0x00,
 	0x20, 0x6a, 0x16, 0x00,
 	0x00, 0x65, 0xcc, 0x41,
-	0x00, 0x65, 0xb2, 0x5e,
+	0x00, 0x65, 0xb4, 0x5e,
 	0x00, 0x65, 0x12, 0x40,
 	0x20, 0x11, 0xd2, 0x68,
 	0x20, 0x6a, 0x18, 0x00,
@@ -140,27 +140,27 @@ static uint8_t seqprog[] = {
 	0x80, 0x0b, 0xc4, 0x79,
 	0x12, 0x01, 0x02, 0x00,
 	0x01, 0xab, 0xac, 0x30,
-	0xe4, 0x6a, 0x6e, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
 	0x40, 0x6a, 0x16, 0x00,
-	0x80, 0x3e, 0x84, 0x5d,
+	0x80, 0x3e, 0x86, 0x5d,
 	0x20, 0xb8, 0x18, 0x79,
-	0x20, 0x6a, 0x84, 0x5d,
-	0x00, 0xab, 0x84, 0x5d,
+	0x20, 0x6a, 0x86, 0x5d,
+	0x00, 0xab, 0x86, 0x5d,
 	0x01, 0xa9, 0x78, 0x30,
 	0x10, 0xb8, 0x20, 0x79,
-	0xe4, 0x6a, 0x6e, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
 	0x00, 0x65, 0xae, 0x40,
 	0x10, 0x03, 0x3c, 0x69,
 	0x08, 0x3c, 0x5a, 0x69,
 	0x04, 0x3c, 0x92, 0x69,
 	0x02, 0x3c, 0x98, 0x69,
 	0x01, 0x3c, 0x44, 0x79,
-	0xff, 0x6a, 0x70, 0x00,
+	0xff, 0x6a, 0xa6, 0x00,
 	0x00, 0x65, 0xa4, 0x59,
-	0x00, 0x6a, 0xc0, 0x5e,
-	0xff, 0x38, 0x30, 0x71,
+	0x00, 0x6a, 0xc2, 0x5e,
+	0xff, 0x53, 0x30, 0x71,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x38, 0x12, 0x5e,
+	0x00, 0x53, 0x14, 0x5e,
 	0x00, 0x65, 0xea, 0x58,
 	0x12, 0x01, 0x02, 0x00,
 	0x00, 0x65, 0x18, 0x41,
@@ -168,10 +168,10 @@ static uint8_t seqprog[] = {
 	0x00, 0x65, 0xf2, 0x58,
 	0xfd, 0x57, 0xae, 0x08,
 	0x00, 0x65, 0xae, 0x40,
-	0xe4, 0x6a, 0x6e, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
 	0x20, 0x3c, 0x4a, 0x79,
-	0x02, 0x6a, 0x84, 0x5d,
-	0x04, 0x6a, 0x84, 0x5d,
+	0x02, 0x6a, 0x86, 0x5d,
+	0x04, 0x6a, 0x86, 0x5d,
 	0x01, 0x03, 0x4c, 0x69,
 	0xf7, 0x11, 0x22, 0x08,
 	0xff, 0x6a, 0x24, 0x08,
@@ -182,13 +182,13 @@ static uint8_t seqprog[] = {
 	0x80, 0x86, 0xc8, 0x08,
 	0x01, 0x4f, 0xc8, 0x30,
 	0x00, 0x50, 0x6c, 0x61,
-	0xc4, 0x6a, 0x6e, 0x5d,
+	0xc4, 0x6a, 0x70, 0x5d,
 	0x40, 0x3c, 0x68, 0x79,
-	0x28, 0x6a, 0x84, 0x5d,
+	0x28, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x4c, 0x41,
-	0x08, 0x6a, 0x84, 0x5d,
+	0x08, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x4c, 0x41,
-	0x84, 0x6a, 0x6e, 0x5d,
+	0x84, 0x6a, 0x70, 0x5d,
 	0x00, 0x65, 0xf2, 0x58,
 	0x01, 0x66, 0xc8, 0x30,
 	0x01, 0x64, 0xd8, 0x31,
@@ -208,16 +208,16 @@ static uint8_t seqprog[] = {
 	0xf7, 0x3c, 0x78, 0x08,
 	0x00, 0x65, 0x20, 0x41,
 	0x40, 0xaa, 0x7e, 0x10,
-	0x04, 0xaa, 0x6e, 0x5d,
-	0x00, 0x65, 0x56, 0x42,
-	0xc4, 0x6a, 0x6e, 0x5d,
+	0x04, 0xaa, 0x70, 0x5d,
+	0x00, 0x65, 0x58, 0x42,
+	0xc4, 0x6a, 0x70, 0x5d,
 	0xc0, 0x6a, 0x7e, 0x00,
-	0x00, 0xa8, 0x84, 0x5d,
+	0x00, 0xa8, 0x86, 0x5d,
 	0xe4, 0x6a, 0x06, 0x00,
-	0x00, 0x6a, 0x84, 0x5d,
+	0x00, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x4c, 0x41,
 	0x10, 0x3c, 0xa8, 0x69,
-	0x00, 0xbb, 0x8a, 0x44,
+	0x00, 0xbb, 0x8c, 0x44,
 	0x18, 0x6a, 0xda, 0x01,
 	0x01, 0x69, 0xd8, 0x31,
 	0x1c, 0x6a, 0xd0, 0x01,
@@ -227,31 +227,32 @@ static uint8_t seqprog[] = {
 	0x01, 0x93, 0x26, 0x01,
 	0x03, 0x6a, 0x2a, 0x01,
 	0x01, 0x69, 0x32, 0x31,
-	0x1c, 0x6a, 0xe0, 0x5d,
+	0x1c, 0x6a, 0xe2, 0x5d,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x5e,
+	0x00, 0x65, 0xaa, 0x5e,
 	0x01, 0x50, 0xa0, 0x18,
 	0x02, 0x6a, 0x22, 0x05,
 	0x1a, 0x01, 0x02, 0x00,
 	0x80, 0x6a, 0x74, 0x00,
 	0x40, 0x6a, 0x78, 0x00,
 	0x40, 0x6a, 0x16, 0x00,
-	0x00, 0x65, 0xd8, 0x5d,
+	0x00, 0x65, 0xda, 0x5d,
 	0x01, 0x3f, 0xc8, 0x30,
-	0xbf, 0x64, 0x56, 0x7a,
-	0x80, 0x64, 0x9e, 0x73,
-	0xa0, 0x64, 0x00, 0x74,
-	0xc0, 0x64, 0xf4, 0x73,
-	0xe0, 0x64, 0x30, 0x74,
-	0x01, 0x6a, 0xd8, 0x5e,
+	0xbf, 0x64, 0x58, 0x7a,
+	0x80, 0x64, 0xa0, 0x73,
+	0xa0, 0x64, 0x02, 0x74,
+	0xc0, 0x64, 0xf6, 0x73,
+	0xe0, 0x64, 0x32, 0x74,
+	0x01, 0x6a, 0xda, 0x5e,
 	0x00, 0x65, 0xcc, 0x41,
 	0xf7, 0x11, 0x22, 0x08,
 	0x01, 0x06, 0xd4, 0x30,
 	0xff, 0x6a, 0x24, 0x08,
 	0xf7, 0x01, 0x02, 0x08,
-	0x09, 0x0c, 0xe6, 0x79,
+	0xc0, 0x6a, 0x78, 0x00,
+	0x09, 0x0c, 0xe8, 0x79,
 	0x08, 0x0c, 0x04, 0x68,
-	0xb1, 0x6a, 0xd8, 0x5e,
+	0xb1, 0x6a, 0xda, 0x5e,
 	0xff, 0x6a, 0x26, 0x09,
 	0x12, 0x01, 0x02, 0x00,
 	0x02, 0x6a, 0x08, 0x30,
@@ -264,29 +265,29 @@ static uint8_t seqprog[] = {
 	0x00, 0xa5, 0x4a, 0x21,
 	0x00, 0xa6, 0x4c, 0x21,
 	0x00, 0xa7, 0x4e, 0x25,
-	0x08, 0xeb, 0xdc, 0x7e,
-	0x80, 0xeb, 0x06, 0x7a,
+	0x08, 0xeb, 0xde, 0x7e,
+	0x80, 0xeb, 0x08, 0x7a,
 	0xff, 0x6a, 0xd6, 0x09,
-	0x08, 0xeb, 0x0a, 0x6a,
+	0x08, 0xeb, 0x0c, 0x6a,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x80, 0xa3, 0xdc, 0x6e,
-	0x88, 0xeb, 0x20, 0x72,
-	0x08, 0xeb, 0xdc, 0x6e,
-	0x04, 0xea, 0x24, 0xe2,
-	0x08, 0xee, 0xdc, 0x6e,
+	0x80, 0xa3, 0xde, 0x6e,
+	0x88, 0xeb, 0x22, 0x72,
+	0x08, 0xeb, 0xde, 0x6e,
+	0x04, 0xea, 0x26, 0xe2,
+	0x08, 0xee, 0xde, 0x6e,
 	0x04, 0x6a, 0xd0, 0x81,
 	0x05, 0xa4, 0xc0, 0x89,
 	0x03, 0xa5, 0xc2, 0x31,
 	0x09, 0x6a, 0xd6, 0x05,
-	0x00, 0x65, 0x08, 0x5a,
+	0x00, 0x65, 0x0a, 0x5a,
 	0x06, 0xa4, 0xd4, 0x89,
-	0x80, 0x94, 0xdc, 0x7e,
+	0x80, 0x94, 0xde, 0x7e,
 	0x07, 0xe9, 0x10, 0x31,
 	0x01, 0xe9, 0x46, 0x31,
-	0x00, 0xa3, 0xba, 0x5e,
-	0x00, 0x65, 0xfa, 0x59,
+	0x00, 0xa3, 0xbc, 0x5e,
+	0x00, 0x65, 0xfc, 0x59,
 	0x01, 0xa4, 0xca, 0x30,
-	0x80, 0xa3, 0x34, 0x7a,
+	0x80, 0xa3, 0x36, 0x7a,
 	0x02, 0x65, 0xca, 0x00,
 	0x01, 0x65, 0xf8, 0x31,
 	0x80, 0x93, 0x26, 0x01,
@@ -294,162 +295,162 @@ static uint8_t seqprog[] = {
 	0x01, 0x8c, 0xc8, 0x30,
 	0x00, 0x88, 0xc8, 0x18,
 	0x02, 0x64, 0xc8, 0x88,
-	0xff, 0x64, 0xdc, 0x7e,
-	0xff, 0x8d, 0x4a, 0x6a,
-	0xff, 0x8e, 0x4a, 0x6a,
+	0xff, 0x64, 0xde, 0x7e,
+	0xff, 0x8d, 0x4c, 0x6a,
+	0xff, 0x8e, 0x4c, 0x6a,
 	0x03, 0x8c, 0xd4, 0x98,
-	0x00, 0x65, 0xdc, 0x56,
+	0x00, 0x65, 0xde, 0x56,
 	0x01, 0x64, 0x70, 0x30,
 	0xff, 0x64, 0xc8, 0x10,
 	0x01, 0x64, 0xc8, 0x18,
 	0x00, 0x8c, 0x18, 0x19,
 	0xff, 0x8d, 0x1a, 0x21,
 	0xff, 0x8e, 0x1c, 0x25,
-	0xc0, 0x3c, 0x5a, 0x7a,
-	0x21, 0x6a, 0xd8, 0x5e,
+	0xc0, 0x3c, 0x5c, 0x7a,
+	0x21, 0x6a, 0xda, 0x5e,
 	0xa8, 0x6a, 0x76, 0x00,
 	0x79, 0x6a, 0x76, 0x00,
-	0x40, 0x3f, 0x62, 0x6a,
+	0x40, 0x3f, 0x64, 0x6a,
 	0x04, 0x3b, 0x76, 0x00,
 	0x04, 0x6a, 0xd4, 0x81,
-	0x20, 0x3c, 0x6a, 0x7a,
-	0x51, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x82, 0x42,
+	0x20, 0x3c, 0x6c, 0x7a,
+	0x51, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x84, 0x42,
 	0x20, 0x3c, 0x78, 0x00,
-	0x00, 0xb3, 0xba, 0x5e,
+	0x00, 0xb3, 0xbc, 0x5e,
 	0x07, 0xac, 0x10, 0x31,
 	0x05, 0xb3, 0x46, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xac, 0x6a, 0xee, 0x5d,
+	0xac, 0x6a, 0xf0, 0x5d,
 	0xa3, 0x6a, 0xcc, 0x00,
-	0xb3, 0x6a, 0xf2, 0x5d,
-	0x00, 0x65, 0x3a, 0x5a,
+	0xb3, 0x6a, 0xf4, 0x5d,
+	0x00, 0x65, 0x3c, 0x5a,
 	0xfd, 0xa4, 0x48, 0x09,
 	0x03, 0x8c, 0x10, 0x30,
-	0x00, 0x65, 0xe6, 0x5d,
-	0x01, 0xa4, 0x94, 0x7a,
+	0x00, 0x65, 0xe8, 0x5d,
+	0x01, 0xa4, 0x96, 0x7a,
 	0x04, 0x3b, 0x76, 0x08,
 	0x01, 0x3b, 0x26, 0x31,
 	0x80, 0x02, 0x04, 0x00,
-	0x10, 0x0c, 0x8a, 0x7a,
-	0x03, 0x9e, 0x8c, 0x6a,
+	0x10, 0x0c, 0x8c, 0x7a,
+	0x03, 0x9e, 0x8e, 0x6a,
 	0x7f, 0x02, 0x04, 0x08,
-	0x91, 0x6a, 0xd8, 0x5e,
+	0x91, 0x6a, 0xda, 0x5e,
 	0x00, 0x65, 0xcc, 0x41,
 	0x01, 0xa4, 0xca, 0x30,
-	0x80, 0xa3, 0x9a, 0x7a,
+	0x80, 0xa3, 0x9c, 0x7a,
 	0x02, 0x65, 0xca, 0x00,
 	0x01, 0x65, 0xf8, 0x31,
 	0x01, 0x3b, 0x26, 0x31,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x01, 0xfc, 0xa8, 0x6a,
-	0x80, 0x0b, 0x9e, 0x6a,
-	0x10, 0x0c, 0x9e, 0x7a,
-	0x20, 0x93, 0x9e, 0x6a,
+	0x00, 0x65, 0x10, 0x5a,
+	0x01, 0xfc, 0xaa, 0x6a,
+	0x80, 0x0b, 0xa0, 0x6a,
+	0x10, 0x0c, 0xa0, 0x7a,
+	0x20, 0x93, 0xa0, 0x6a,
 	0x02, 0x93, 0x26, 0x01,
-	0x02, 0xfc, 0xb2, 0x7a,
-	0x40, 0x0d, 0xc6, 0x6a,
+	0x02, 0xfc, 0xb4, 0x7a,
+	0x40, 0x0d, 0xc8, 0x6a,
 	0x01, 0xa4, 0x48, 0x01,
-	0x00, 0x65, 0xc6, 0x42,
-	0x40, 0x0d, 0xb8, 0x6a,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x00, 0x65, 0xaa, 0x42,
-	0x80, 0xfc, 0xc2, 0x7a,
-	0x80, 0xa4, 0xc2, 0x6a,
+	0x00, 0x65, 0xc8, 0x42,
+	0x40, 0x0d, 0xba, 0x6a,
+	0x00, 0x65, 0x10, 0x5a,
+	0x00, 0x65, 0xac, 0x42,
+	0x80, 0xfc, 0xc4, 0x7a,
+	0x80, 0xa4, 0xc4, 0x6a,
 	0xff, 0xa5, 0x4a, 0x19,
 	0xff, 0xa6, 0x4c, 0x21,
 	0xff, 0xa7, 0x4e, 0x21,
 	0xf8, 0xfc, 0x48, 0x09,
 	0x7f, 0xa3, 0x46, 0x09,
-	0x04, 0x3b, 0xe2, 0x6a,
+	0x04, 0x3b, 0xe4, 0x6a,
 	0x02, 0x93, 0x26, 0x01,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0xa4, 0xe0, 0x7a,
-	0x01, 0xfc, 0xd6, 0x7a,
-	0x01, 0x94, 0xe2, 0x6a,
-	0x01, 0x94, 0xe2, 0x6a,
-	0x01, 0x94, 0xe2, 0x6a,
-	0x00, 0x65, 0x82, 0x42,
-	0x01, 0x94, 0xe0, 0x7a,
-	0x10, 0x94, 0xe2, 0x6a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0xa4, 0xe2, 0x7a,
+	0x01, 0xfc, 0xd8, 0x7a,
+	0x01, 0x94, 0xe4, 0x6a,
+	0x01, 0x94, 0xe4, 0x6a,
+	0x01, 0x94, 0xe4, 0x6a,
+	0x00, 0x65, 0x84, 0x42,
+	0x01, 0x94, 0xe2, 0x7a,
+	0x10, 0x94, 0xe4, 0x6a,
 	0xd7, 0x93, 0x26, 0x09,
-	0x28, 0x93, 0xe6, 0x6a,
+	0x28, 0x93, 0xe8, 0x6a,
 	0x01, 0x85, 0x0a, 0x01,
-	0x02, 0xfc, 0xee, 0x6a,
+	0x02, 0xfc, 0xf0, 0x6a,
 	0x01, 0x14, 0x46, 0x31,
 	0xff, 0x6a, 0x10, 0x09,
 	0xfe, 0x85, 0x0a, 0x09,
-	0xff, 0x38, 0xfc, 0x6a,
-	0x80, 0xa3, 0xfc, 0x7a,
-	0x80, 0x0b, 0xfa, 0x7a,
-	0x04, 0x3b, 0xfc, 0x7a,
+	0xff, 0x38, 0xfe, 0x6a,
+	0x80, 0xa3, 0xfe, 0x7a,
+	0x80, 0x0b, 0xfc, 0x7a,
+	0x04, 0x3b, 0xfe, 0x7a,
 	0xbf, 0x3b, 0x76, 0x08,
 	0x01, 0x3b, 0x26, 0x31,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x01, 0x0b, 0x0a, 0x6b,
-	0x10, 0x0c, 0xfe, 0x7a,
-	0x04, 0x93, 0x08, 0x6b,
-	0x01, 0x94, 0x06, 0x7b,
-	0x10, 0x94, 0x08, 0x6b,
+	0x00, 0x65, 0x10, 0x5a,
+	0x01, 0x0b, 0x0c, 0x6b,
+	0x10, 0x0c, 0x00, 0x7b,
+	0x04, 0x93, 0x0a, 0x6b,
+	0x01, 0x94, 0x08, 0x7b,
+	0x10, 0x94, 0x0a, 0x6b,
 	0xc7, 0x93, 0x26, 0x09,
 	0x01, 0x99, 0xd4, 0x30,
-	0x38, 0x93, 0x0c, 0x6b,
-	0xff, 0x08, 0x5a, 0x6b,
-	0xff, 0x09, 0x5a, 0x6b,
-	0xff, 0x0a, 0x5a, 0x6b,
-	0xff, 0x38, 0x28, 0x7b,
+	0x38, 0x93, 0x0e, 0x6b,
+	0xff, 0x08, 0x5c, 0x6b,
+	0xff, 0x09, 0x5c, 0x6b,
+	0xff, 0x0a, 0x5c, 0x6b,
+	0xff, 0x38, 0x2a, 0x7b,
 	0x04, 0x14, 0x10, 0x31,
 	0x01, 0x38, 0x18, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xf4, 0x5d,
-	0x00, 0x38, 0xe0, 0x5d,
+	0x14, 0x6a, 0xf6, 0x5d,
+	0x00, 0x38, 0xe2, 0x5d,
 	0xff, 0x6a, 0x70, 0x08,
-	0x00, 0x65, 0x54, 0x43,
-	0x80, 0xa3, 0x2e, 0x7b,
+	0x00, 0x65, 0x56, 0x43,
+	0x80, 0xa3, 0x30, 0x7b,
 	0x01, 0xa4, 0x48, 0x01,
-	0x00, 0x65, 0x5a, 0x43,
-	0x08, 0xeb, 0x34, 0x7b,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x08, 0xeb, 0x30, 0x6b,
+	0x00, 0x65, 0x5c, 0x43,
+	0x08, 0xeb, 0x36, 0x7b,
+	0x00, 0x65, 0x10, 0x5a,
+	0x08, 0xeb, 0x32, 0x6b,
 	0x07, 0xe9, 0x10, 0x31,
 	0x01, 0xe9, 0xca, 0x30,
 	0x01, 0x65, 0x46, 0x31,
-	0x00, 0x6a, 0xba, 0x5e,
+	0x00, 0x6a, 0xbc, 0x5e,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xa4, 0x6a, 0xf4, 0x5d,
-	0x08, 0x6a, 0xe0, 0x5d,
+	0xa4, 0x6a, 0xf6, 0x5d,
+	0x08, 0x6a, 0xe2, 0x5d,
 	0x0d, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x5e,
+	0x00, 0x65, 0xaa, 0x5e,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x00, 0x65, 0x8a, 0x5e,
+	0x00, 0x65, 0x8c, 0x5e,
 	0x01, 0x99, 0x46, 0x31,
-	0x00, 0xa3, 0xba, 0x5e,
+	0x00, 0xa3, 0xbc, 0x5e,
 	0x01, 0x88, 0x10, 0x31,
-	0x00, 0x65, 0x3a, 0x5a,
-	0x00, 0x65, 0xfa, 0x59,
+	0x00, 0x65, 0x3c, 0x5a,
+	0x00, 0x65, 0xfc, 0x59,
 	0x03, 0x8c, 0x10, 0x30,
-	0x00, 0x65, 0xe6, 0x5d,
-	0x80, 0x0b, 0x82, 0x6a,
-	0x80, 0x0b, 0x62, 0x6b,
-	0x01, 0x0c, 0x5c, 0x7b,
-	0x10, 0x0c, 0x82, 0x7a,
-	0x03, 0x9e, 0x82, 0x6a,
-	0x00, 0x65, 0x04, 0x5a,
-	0x00, 0x6a, 0xba, 0x5e,
-	0x01, 0xa4, 0x82, 0x6b,
-	0xff, 0x38, 0x78, 0x7b,
+	0x00, 0x65, 0xe8, 0x5d,
+	0x80, 0x0b, 0x84, 0x6a,
+	0x80, 0x0b, 0x64, 0x6b,
+	0x01, 0x0c, 0x5e, 0x7b,
+	0x10, 0x0c, 0x84, 0x7a,
+	0x03, 0x9e, 0x84, 0x6a,
+	0x00, 0x65, 0x06, 0x5a,
+	0x00, 0x6a, 0xbc, 0x5e,
+	0x01, 0xa4, 0x84, 0x6b,
+	0xff, 0x38, 0x7a, 0x7b,
 	0x01, 0x38, 0xc8, 0x30,
 	0x00, 0x08, 0x40, 0x19,
 	0xff, 0x6a, 0xc8, 0x08,
 	0x00, 0x09, 0x42, 0x21,
 	0x00, 0x0a, 0x44, 0x21,
 	0xff, 0x6a, 0x70, 0x08,
-	0x00, 0x65, 0x7a, 0x43,
+	0x00, 0x65, 0x7c, 0x43,
 	0x03, 0x08, 0x40, 0x31,
 	0x03, 0x08, 0x40, 0x31,
 	0x01, 0x08, 0x40, 0x31,
@@ -461,16 +462,16 @@ static uint8_t seqprog[] = {
 	0x04, 0x3c, 0xcc, 0x79,
 	0xfb, 0x3c, 0x78, 0x08,
 	0x04, 0x93, 0x20, 0x79,
-	0x01, 0x0c, 0x8e, 0x6b,
+	0x01, 0x0c, 0x90, 0x6b,
 	0x80, 0xba, 0x20, 0x79,
 	0x80, 0x04, 0x20, 0x79,
-	0xe4, 0x6a, 0x6e, 0x5d,
-	0x23, 0x6a, 0x84, 0x5d,
-	0x01, 0x6a, 0x84, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
+	0x23, 0x6a, 0x86, 0x5d,
+	0x01, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x20, 0x41,
 	0x00, 0x65, 0xcc, 0x41,
-	0x80, 0x3c, 0xa2, 0x7b,
-	0x21, 0x6a, 0xd8, 0x5e,
+	0x80, 0x3c, 0xa4, 0x7b,
+	0x21, 0x6a, 0xda, 0x5e,
 	0x01, 0xbc, 0x18, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x02, 0x6a, 0xf8, 0x01,
@@ -480,16 +481,16 @@ static uint8_t seqprog[] = {
 	0xff, 0x6a, 0x12, 0x08,
 	0xff, 0x6a, 0x14, 0x08,
 	0xf3, 0xbc, 0xd4, 0x18,
-	0xa0, 0x6a, 0xc8, 0x53,
+	0xa0, 0x6a, 0xca, 0x53,
 	0x04, 0xa0, 0x10, 0x31,
 	0xac, 0x6a, 0x26, 0x01,
 	0x04, 0xa0, 0x10, 0x31,
 	0x03, 0x08, 0x18, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xa0, 0x6a, 0xf4, 0x5d,
-	0x00, 0xbc, 0xe0, 0x5d,
+	0xa0, 0x6a, 0xf6, 0x5d,
+	0x00, 0xbc, 0xe2, 0x5d,
 	0x3d, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0xe0, 0x43,
+	0x00, 0x65, 0xe2, 0x43,
 	0xff, 0x6a, 0x10, 0x09,
 	0xa4, 0x6a, 0x26, 0x01,
 	0x0c, 0xa0, 0x32, 0x31,
@@ -499,128 +500,128 @@ static uint8_t seqprog[] = {
 	0x36, 0x6a, 0x26, 0x01,
 	0x02, 0x93, 0x26, 0x01,
 	0x35, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0x9c, 0x5e,
-	0x00, 0x65, 0x9c, 0x5e,
+	0x00, 0x65, 0x9e, 0x5e,
+	0x00, 0x65, 0x9e, 0x5e,
 	0x02, 0x93, 0x26, 0x01,
 	0xbf, 0x3c, 0x78, 0x08,
-	0x04, 0x0b, 0xe6, 0x6b,
-	0x10, 0x0c, 0xe2, 0x7b,
-	0x01, 0x03, 0xe6, 0x6b,
-	0x20, 0x93, 0xe8, 0x6b,
-	0x04, 0x0b, 0xee, 0x6b,
+	0x04, 0x0b, 0xe8, 0x6b,
+	0x10, 0x0c, 0xe4, 0x7b,
+	0x01, 0x03, 0xe8, 0x6b,
+	0x20, 0x93, 0xea, 0x6b,
+	0x04, 0x0b, 0xf0, 0x6b,
 	0x40, 0x3c, 0x78, 0x00,
 	0xc7, 0x93, 0x26, 0x09,
-	0x38, 0x93, 0xf0, 0x6b,
+	0x38, 0x93, 0xf2, 0x6b,
 	0x00, 0x65, 0xcc, 0x41,
-	0x80, 0x3c, 0x56, 0x6c,
+	0x80, 0x3c, 0x58, 0x6c,
 	0x01, 0x06, 0x50, 0x31,
 	0x80, 0xb8, 0x70, 0x01,
 	0x00, 0x65, 0xcc, 0x41,
 	0x10, 0x3f, 0x06, 0x00,
 	0x10, 0x6a, 0x06, 0x00,
 	0x01, 0x3a, 0xca, 0x30,
-	0x80, 0x65, 0x1c, 0x64,
-	0x10, 0xb8, 0x40, 0x6c,
+	0x80, 0x65, 0x1e, 0x64,
+	0x10, 0xb8, 0x42, 0x6c,
 	0xc0, 0x3e, 0xca, 0x00,
-	0x40, 0xb8, 0x0c, 0x6c,
+	0x40, 0xb8, 0x0e, 0x6c,
 	0xbf, 0x65, 0xca, 0x08,
-	0x20, 0xb8, 0x20, 0x7c,
+	0x20, 0xb8, 0x22, 0x7c,
 	0x01, 0x65, 0x0c, 0x30,
-	0x00, 0x65, 0xd8, 0x5d,
-	0xa0, 0x3f, 0x28, 0x64,
+	0x00, 0x65, 0xda, 0x5d,
+	0xa0, 0x3f, 0x2a, 0x64,
 	0x23, 0xb8, 0x0c, 0x08,
-	0x00, 0x65, 0xd8, 0x5d,
-	0xa0, 0x3f, 0x28, 0x64,
-	0x00, 0xbb, 0x20, 0x44,
-	0xff, 0x65, 0x20, 0x64,
-	0x00, 0x65, 0x40, 0x44,
+	0x00, 0x65, 0xda, 0x5d,
+	0xa0, 0x3f, 0x2a, 0x64,
+	0x00, 0xbb, 0x22, 0x44,
+	0xff, 0x65, 0x22, 0x64,
+	0x00, 0x65, 0x42, 0x44,
 	0x40, 0x6a, 0x18, 0x00,
 	0x01, 0x65, 0x0c, 0x30,
-	0x00, 0x65, 0xd8, 0x5d,
-	0xa0, 0x3f, 0xfc, 0x73,
+	0x00, 0x65, 0xda, 0x5d,
+	0xa0, 0x3f, 0xfe, 0x73,
 	0x40, 0x6a, 0x18, 0x00,
 	0x01, 0x3a, 0xa6, 0x30,
 	0x08, 0x6a, 0x74, 0x00,
 	0x00, 0x65, 0xcc, 0x41,
-	0x64, 0x6a, 0x68, 0x5d,
-	0x80, 0x64, 0xd8, 0x6c,
-	0x04, 0x64, 0x9a, 0x74,
-	0x02, 0x64, 0xaa, 0x74,
-	0x00, 0x6a, 0x60, 0x74,
-	0x03, 0x64, 0xc8, 0x74,
-	0x23, 0x64, 0x48, 0x74,
-	0x08, 0x64, 0x5c, 0x74,
-	0x61, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0xd8, 0x5d,
+	0x64, 0x6a, 0x6a, 0x5d,
+	0x80, 0x64, 0xda, 0x6c,
+	0x04, 0x64, 0x9c, 0x74,
+	0x02, 0x64, 0xac, 0x74,
+	0x00, 0x6a, 0x62, 0x74,
+	0x03, 0x64, 0xca, 0x74,
+	0x23, 0x64, 0x4a, 0x74,
+	0x08, 0x64, 0x5e, 0x74,
+	0x61, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0xda, 0x5d,
 	0x08, 0x51, 0xce, 0x71,
-	0x00, 0x65, 0x40, 0x44,
-	0x80, 0x04, 0x5a, 0x7c,
-	0x51, 0x6a, 0x5e, 0x5d,
-	0x01, 0x51, 0x5a, 0x64,
-	0x01, 0xa4, 0x52, 0x7c,
-	0x80, 0xba, 0x5c, 0x6c,
-	0x41, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x5c, 0x44,
-	0x21, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x5c, 0x44,
-	0x07, 0x6a, 0x54, 0x5d,
+	0x00, 0x65, 0x42, 0x44,
+	0x80, 0x04, 0x5c, 0x7c,
+	0x51, 0x6a, 0x60, 0x5d,
+	0x01, 0x51, 0x5c, 0x64,
+	0x01, 0xa4, 0x54, 0x7c,
+	0x80, 0xba, 0x5e, 0x6c,
+	0x41, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x5e, 0x44,
+	0x21, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x5e, 0x44,
+	0x07, 0x6a, 0x56, 0x5d,
 	0x01, 0x06, 0xd4, 0x30,
 	0x00, 0x65, 0xcc, 0x41,
-	0x80, 0xb8, 0x56, 0x7c,
-	0xc0, 0x3c, 0x6a, 0x7c,
-	0x80, 0x3c, 0x56, 0x6c,
-	0xff, 0xa8, 0x6a, 0x6c,
-	0x40, 0x3c, 0x56, 0x6c,
-	0x10, 0xb8, 0x6e, 0x7c,
-	0xa1, 0x6a, 0xd8, 0x5e,
-	0x01, 0xb4, 0x74, 0x6c,
-	0x02, 0xb4, 0x76, 0x6c,
-	0x01, 0xa4, 0x76, 0x7c,
-	0xff, 0xa8, 0x86, 0x7c,
+	0x80, 0xb8, 0x58, 0x7c,
+	0xc0, 0x3c, 0x6c, 0x7c,
+	0x80, 0x3c, 0x58, 0x6c,
+	0xff, 0xa8, 0x6c, 0x6c,
+	0x40, 0x3c, 0x58, 0x6c,
+	0x10, 0xb8, 0x70, 0x7c,
+	0xa1, 0x6a, 0xda, 0x5e,
+	0x01, 0xb4, 0x76, 0x6c,
+	0x02, 0xb4, 0x78, 0x6c,
+	0x01, 0xa4, 0x78, 0x7c,
+	0xff, 0xa8, 0x88, 0x7c,
 	0x04, 0xb4, 0x68, 0x01,
 	0x01, 0x6a, 0x76, 0x00,
-	0x00, 0xbb, 0x12, 0x5e,
-	0xff, 0xa8, 0x86, 0x7c,
-	0x71, 0x6a, 0xd8, 0x5e,
-	0x40, 0x51, 0x86, 0x64,
-	0x00, 0x65, 0xb2, 0x5e,
+	0x00, 0xbb, 0x14, 0x5e,
+	0xff, 0xa8, 0x88, 0x7c,
+	0x71, 0x6a, 0xda, 0x5e,
+	0x40, 0x51, 0x88, 0x64,
+	0x00, 0x65, 0xb4, 0x5e,
 	0x00, 0x65, 0xde, 0x41,
-	0x00, 0xbb, 0x8a, 0x5c,
+	0x00, 0xbb, 0x8c, 0x5c,
 	0x00, 0x65, 0xde, 0x41,
-	0x00, 0x65, 0xb2, 0x5e,
+	0x00, 0x65, 0xb4, 0x5e,
 	0x01, 0x65, 0xa2, 0x30,
 	0x01, 0xf8, 0xc8, 0x30,
 	0x01, 0x4e, 0xc8, 0x30,
-	0x00, 0x6a, 0xb6, 0xdd,
-	0x00, 0x51, 0xc8, 0x5d,
+	0x00, 0x6a, 0xb8, 0xdd,
+	0x00, 0x51, 0xca, 0x5d,
 	0x01, 0x4e, 0x9c, 0x18,
 	0x02, 0x6a, 0x22, 0x05,
-	0xc0, 0x3c, 0x56, 0x6c,
+	0xc0, 0x3c, 0x58, 0x6c,
 	0x04, 0xb8, 0x70, 0x01,
-	0x00, 0x65, 0xd4, 0x5e,
+	0x00, 0x65, 0xd6, 0x5e,
 	0x20, 0xb8, 0xde, 0x69,
 	0x01, 0xbb, 0xa2, 0x30,
 	0x3f, 0xba, 0x7c, 0x08,
-	0x00, 0xb9, 0xce, 0x5c,
+	0x00, 0xb9, 0xd0, 0x5c,
 	0x00, 0x65, 0xde, 0x41,
 	0x01, 0x06, 0xd4, 0x30,
 	0x20, 0x3c, 0xcc, 0x79,
-	0x20, 0x3c, 0x5c, 0x7c,
-	0x01, 0xa4, 0xb8, 0x7c,
+	0x20, 0x3c, 0x5e, 0x7c,
+	0x01, 0xa4, 0xba, 0x7c,
 	0x01, 0xb4, 0x68, 0x01,
 	0x00, 0x65, 0xcc, 0x41,
-	0x00, 0x65, 0x5c, 0x44,
+	0x00, 0x65, 0x5e, 0x44,
 	0x04, 0x14, 0x58, 0x31,
 	0x01, 0x06, 0xd4, 0x30,
 	0x08, 0xa0, 0x60, 0x31,
 	0xac, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xf4, 0x5d,
+	0x14, 0x6a, 0xf6, 0x5d,
 	0x01, 0x06, 0xd4, 0x30,
-	0xa0, 0x6a, 0xec, 0x5d,
+	0xa0, 0x6a, 0xee, 0x5d,
 	0x00, 0x65, 0xcc, 0x41,
 	0xdf, 0x3c, 0x78, 0x08,
 	0x12, 0x01, 0x02, 0x00,
-	0x00, 0x65, 0x5c, 0x44,
+	0x00, 0x65, 0x5e, 0x44,
 	0x4c, 0x65, 0xcc, 0x28,
 	0x01, 0x3e, 0x20, 0x31,
 	0xd0, 0x66, 0xcc, 0x18,
@@ -631,102 +632,102 @@ static uint8_t seqprog[] = {
 	0xd0, 0x65, 0xca, 0x18,
 	0x01, 0x3e, 0x20, 0x31,
 	0x30, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xe6, 0x4c,
+	0x00, 0x65, 0xe8, 0x4c,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x20, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xee, 0x54,
+	0x00, 0x65, 0xf0, 0x54,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x20, 0x65, 0xca, 0x18,
 	0xe0, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xf8, 0x4c,
+	0x00, 0x65, 0xfa, 0x4c,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xd0, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0x00, 0x55,
+	0x00, 0x65, 0x02, 0x55,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x01, 0x6c, 0xa2, 0x30,
-	0xff, 0x51, 0x12, 0x75,
-	0x00, 0x51, 0x8e, 0x5d,
+	0xff, 0x51, 0x14, 0x75,
+	0x00, 0x51, 0x90, 0x5d,
 	0x01, 0x51, 0x20, 0x31,
-	0x00, 0x65, 0x34, 0x45,
+	0x00, 0x65, 0x36, 0x45,
 	0x3f, 0xba, 0xc8, 0x08,
-	0x00, 0x3e, 0x34, 0x75,
-	0x00, 0x65, 0xb0, 0x5e,
+	0x00, 0x3e, 0x36, 0x75,
+	0x00, 0x65, 0xb2, 0x5e,
 	0x80, 0x3c, 0x78, 0x00,
 	0x01, 0x06, 0xd4, 0x30,
-	0x00, 0x65, 0xd8, 0x5d,
+	0x00, 0x65, 0xda, 0x5d,
 	0x01, 0x3c, 0x78, 0x00,
-	0xe0, 0x3f, 0x50, 0x65,
+	0xe0, 0x3f, 0x52, 0x65,
 	0x02, 0x3c, 0x78, 0x00,
-	0x20, 0x12, 0x50, 0x65,
-	0x51, 0x6a, 0x5e, 0x5d,
-	0x00, 0x51, 0x8e, 0x5d,
-	0x51, 0x6a, 0x5e, 0x5d,
+	0x20, 0x12, 0x52, 0x65,
+	0x51, 0x6a, 0x60, 0x5d,
+	0x00, 0x51, 0x90, 0x5d,
+	0x51, 0x6a, 0x60, 0x5d,
 	0x01, 0x51, 0x20, 0x31,
 	0x04, 0x3c, 0x78, 0x00,
 	0x01, 0xb9, 0xc8, 0x30,
-	0x00, 0x3d, 0x4e, 0x65,
+	0x00, 0x3d, 0x50, 0x65,
 	0x08, 0x3c, 0x78, 0x00,
 	0x3f, 0xba, 0xc8, 0x08,
-	0x00, 0x3e, 0x4e, 0x65,
+	0x00, 0x3e, 0x50, 0x65,
 	0x10, 0x3c, 0x78, 0x00,
-	0x04, 0xb8, 0x4e, 0x7d,
+	0x04, 0xb8, 0x50, 0x7d,
 	0xfb, 0xb8, 0x70, 0x09,
-	0x20, 0xb8, 0x44, 0x6d,
+	0x20, 0xb8, 0x46, 0x6d,
 	0x01, 0x90, 0xc8, 0x30,
 	0xff, 0x6a, 0xa2, 0x00,
-	0x00, 0x3d, 0xce, 0x5c,
+	0x00, 0x3d, 0xd0, 0x5c,
 	0x01, 0x64, 0x20, 0x31,
 	0xff, 0x6a, 0x78, 0x08,
 	0x00, 0x65, 0xea, 0x58,
-	0x10, 0xb8, 0x5c, 0x7c,
-	0xff, 0x6a, 0x54, 0x5d,
-	0x00, 0x65, 0x5c, 0x44,
-	0x00, 0x65, 0xb0, 0x5e,
-	0x31, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x5c, 0x44,
+	0x10, 0xb8, 0x5e, 0x7c,
+	0xff, 0x6a, 0x56, 0x5d,
+	0x00, 0x65, 0x5e, 0x44,
+	0x00, 0x65, 0xb2, 0x5e,
+	0x31, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x5e, 0x44,
 	0x10, 0x3f, 0x06, 0x00,
 	0x10, 0x6a, 0x06, 0x00,
 	0x01, 0x65, 0x74, 0x34,
-	0x81, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x60, 0x45,
+	0x81, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x62, 0x45,
 	0x01, 0x06, 0xd4, 0x30,
-	0x01, 0x0c, 0x60, 0x7d,
-	0x04, 0x0c, 0x5a, 0x6d,
+	0x01, 0x0c, 0x62, 0x7d,
+	0x04, 0x0c, 0x5c, 0x6d,
 	0xe0, 0x03, 0x7e, 0x08,
 	0xe0, 0x3f, 0xcc, 0x61,
 	0x01, 0x65, 0xcc, 0x30,
 	0x01, 0x12, 0xda, 0x34,
 	0x01, 0x06, 0xd4, 0x34,
-	0x01, 0x03, 0x6e, 0x6d,
+	0x01, 0x03, 0x70, 0x6d,
 	0x40, 0x03, 0xcc, 0x08,
 	0x01, 0x65, 0x06, 0x30,
 	0x40, 0x65, 0xc8, 0x08,
-	0x00, 0x66, 0x7c, 0x75,
-	0x40, 0x65, 0x7c, 0x7d,
-	0x00, 0x65, 0x7c, 0x5d,
+	0x00, 0x66, 0x7e, 0x75,
+	0x40, 0x65, 0x7e, 0x7d,
+	0x00, 0x65, 0x7e, 0x5d,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0x86, 0x7d,
+	0x02, 0x0b, 0x88, 0x7d,
 	0x01, 0x65, 0x0c, 0x30,
-	0x02, 0x0b, 0x8a, 0x7d,
+	0x02, 0x0b, 0x8c, 0x7d,
 	0xf7, 0x01, 0x02, 0x0c,
 	0x01, 0x65, 0xc8, 0x30,
-	0xff, 0x41, 0xae, 0x75,
+	0xff, 0x41, 0xb0, 0x75,
 	0x01, 0x41, 0x20, 0x31,
 	0xff, 0x6a, 0xa4, 0x00,
-	0x00, 0x65, 0x9e, 0x45,
-	0xff, 0xbf, 0xae, 0x75,
+	0x00, 0x65, 0xa0, 0x45,
+	0xff, 0xbf, 0xb0, 0x75,
 	0x01, 0x90, 0xa4, 0x30,
 	0x01, 0xbf, 0x20, 0x31,
-	0x00, 0xbb, 0x98, 0x65,
-	0xff, 0x52, 0xac, 0x75,
+	0x00, 0xbb, 0x9a, 0x65,
+	0xff, 0x52, 0xae, 0x75,
 	0x01, 0xbf, 0xcc, 0x30,
 	0x01, 0x90, 0xca, 0x30,
 	0x01, 0x52, 0x20, 0x31,
@@ -734,28 +735,28 @@ static uint8_t seqprog[] = {
 	0x01, 0x65, 0x20, 0x35,
 	0x01, 0xbf, 0x82, 0x34,
 	0x01, 0x64, 0xa2, 0x30,
-	0x00, 0x6a, 0xc0, 0x5e,
+	0x00, 0x6a, 0xc2, 0x5e,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x51, 0x12, 0x46,
+	0x00, 0x51, 0x14, 0x46,
 	0x01, 0x65, 0xa4, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0x06, 0x5e,
+	0x48, 0x6a, 0x08, 0x5e,
 	0x01, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x05,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0x06, 0x5e,
-	0x01, 0x6a, 0xe0, 0x5d,
+	0x48, 0x6a, 0x08, 0x5e,
+	0x01, 0x6a, 0xe2, 0x5d,
 	0x01, 0x6a, 0x26, 0x05,
 	0x01, 0x65, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0xcc, 0x7d,
+	0x80, 0xee, 0xce, 0x7d,
 	0xff, 0x6a, 0xdc, 0x0d,
 	0x01, 0x65, 0x32, 0x31,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x46,
-	0x81, 0x6a, 0xd8, 0x5e,
-	0x01, 0x0c, 0xd8, 0x7d,
-	0x04, 0x0c, 0xd6, 0x6d,
+	0x00, 0x65, 0xaa, 0x46,
+	0x81, 0x6a, 0xda, 0x5e,
+	0x01, 0x0c, 0xda, 0x7d,
+	0x04, 0x0c, 0xd8, 0x6d,
 	0xe0, 0x03, 0x06, 0x08,
 	0xe0, 0x03, 0x7e, 0x0c,
 	0x01, 0x65, 0x18, 0x31,
@@ -774,7 +775,7 @@ static uint8_t seqprog[] = {
 	0x01, 0x6c, 0xda, 0x34,
 	0x3d, 0x64, 0xa4, 0x28,
 	0x55, 0x64, 0xc8, 0x28,
-	0x00, 0x65, 0x06, 0x46,
+	0x00, 0x65, 0x08, 0x46,
 	0x2e, 0x64, 0xa4, 0x28,
 	0x66, 0x64, 0xc8, 0x28,
 	0x00, 0x6c, 0xda, 0x18,
@@ -785,63 +786,63 @@ static uint8_t seqprog[] = {
 	0x00, 0x6c, 0xda, 0x24,
 	0x01, 0x65, 0xc8, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x44, 0x6a, 0x02, 0x5e,
+	0x44, 0x6a, 0x04, 0x5e,
 	0x01, 0x90, 0xe2, 0x31,
-	0x04, 0x3b, 0x26, 0x7e,
+	0x04, 0x3b, 0x28, 0x7e,
 	0x30, 0x6a, 0xd0, 0x01,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x1d, 0x6a, 0xdc, 0x01,
-	0xdc, 0xee, 0x22, 0x66,
-	0x00, 0x65, 0x3e, 0x46,
+	0xdc, 0xee, 0x24, 0x66,
+	0x00, 0x65, 0x40, 0x46,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x20, 0xa0, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x2e, 0x7e,
+	0x80, 0xee, 0x30, 0x7e,
 	0x11, 0x6a, 0xdc, 0x01,
-	0x50, 0xee, 0x32, 0x66,
+	0x50, 0xee, 0x34, 0x66,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x09, 0x6a, 0xdc, 0x01,
-	0x88, 0xee, 0x38, 0x66,
+	0x88, 0xee, 0x3a, 0x66,
 	0x19, 0x6a, 0xdc, 0x01,
-	0xd8, 0xee, 0x3c, 0x66,
+	0xd8, 0xee, 0x3e, 0x66,
 	0xff, 0x6a, 0xdc, 0x09,
-	0x18, 0xee, 0x40, 0x6e,
+	0x18, 0xee, 0x42, 0x6e,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x44, 0x6a, 0x02, 0x5e,
-	0x20, 0x6a, 0xe0, 0x5d,
+	0x44, 0x6a, 0x04, 0x5e,
+	0x20, 0x6a, 0xe2, 0x5d,
 	0x01, 0x3b, 0x26, 0x31,
-	0x04, 0x3b, 0x5a, 0x6e,
+	0x04, 0x3b, 0x5c, 0x6e,
 	0xa0, 0x6a, 0xca, 0x00,
 	0x20, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0x98, 0x5e,
-	0x00, 0x65, 0x52, 0x66,
+	0x00, 0x65, 0x9a, 0x5e,
+	0x00, 0x65, 0x54, 0x66,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x46,
+	0x00, 0x65, 0xaa, 0x46,
 	0xa0, 0x6a, 0xcc, 0x00,
 	0xff, 0x6a, 0xc8, 0x08,
-	0x20, 0x94, 0x5e, 0x6e,
-	0x10, 0x94, 0x60, 0x6e,
-	0x08, 0x94, 0x7a, 0x6e,
-	0x08, 0x94, 0x7a, 0x6e,
-	0x08, 0x94, 0x7a, 0x6e,
+	0x20, 0x94, 0x60, 0x6e,
+	0x10, 0x94, 0x62, 0x6e,
+	0x08, 0x94, 0x7c, 0x6e,
+	0x08, 0x94, 0x7c, 0x6e,
+	0x08, 0x94, 0x7c, 0x6e,
 	0xff, 0x8c, 0xc8, 0x10,
 	0xc1, 0x64, 0xc8, 0x18,
 	0xf8, 0x64, 0xc8, 0x08,
 	0x01, 0x99, 0xda, 0x30,
-	0x00, 0x66, 0x6e, 0x66,
-	0xc0, 0x66, 0xaa, 0x76,
+	0x00, 0x66, 0x70, 0x66,
+	0xc0, 0x66, 0xac, 0x76,
 	0x60, 0x66, 0xc8, 0x18,
 	0x3d, 0x64, 0xc8, 0x28,
-	0x00, 0x65, 0x5e, 0x46,
+	0x00, 0x65, 0x60, 0x46,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x7c, 0x6e,
+	0x08, 0x93, 0x7e, 0x6e,
 	0x00, 0x62, 0xc4, 0x18,
-	0x00, 0x65, 0xa8, 0x5e,
-	0x00, 0x65, 0x88, 0x5e,
-	0x00, 0x65, 0x88, 0x5e,
-	0x00, 0x65, 0x88, 0x5e,
+	0x00, 0x65, 0xaa, 0x5e,
+	0x00, 0x65, 0x8a, 0x5e,
+	0x00, 0x65, 0x8a, 0x5e,
+	0x00, 0x65, 0x8a, 0x5e,
 	0x01, 0x99, 0xda, 0x30,
 	0x01, 0x99, 0xda, 0x30,
 	0x01, 0x99, 0xda, 0x30,
@@ -858,11 +859,11 @@ static uint8_t seqprog[] = {
 	0x01, 0x6c, 0x32, 0x31,
 	0x01, 0x6c, 0x32, 0x31,
 	0x01, 0x6c, 0x32, 0x35,
-	0x08, 0x94, 0xa8, 0x7e,
+	0x08, 0x94, 0xaa, 0x7e,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0xac, 0x6e,
+	0x08, 0x93, 0xae, 0x6e,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x04, 0xb8, 0xd4, 0x6e,
+	0x04, 0xb8, 0xd6, 0x6e,
 	0x01, 0x42, 0x7e, 0x31,
 	0xff, 0x6a, 0x76, 0x01,
 	0x01, 0x90, 0x84, 0x34,
@@ -870,14 +871,14 @@ static uint8_t seqprog[] = {
 	0x01, 0x85, 0x0a, 0x01,
 	0x7f, 0x65, 0x10, 0x09,
 	0xfe, 0x85, 0x0a, 0x0d,
-	0xff, 0x42, 0xd0, 0x66,
-	0xff, 0x41, 0xc8, 0x66,
-	0xd1, 0x6a, 0xd8, 0x5e,
+	0xff, 0x42, 0xd2, 0x66,
+	0xff, 0x41, 0xca, 0x66,
+	0xd1, 0x6a, 0xda, 0x5e,
 	0xff, 0x6a, 0xca, 0x04,
 	0x01, 0x41, 0x20, 0x31,
 	0x01, 0xbf, 0x82, 0x30,
 	0x01, 0x6a, 0x76, 0x00,
-	0x00, 0xbb, 0x12, 0x46,
+	0x00, 0xbb, 0x14, 0x46,
 	0x01, 0x42, 0x20, 0x31,
 	0x01, 0xbf, 0x84, 0x34,
 	0x01, 0x41, 0x7e, 0x31,
@@ -941,7 +942,7 @@ static ahc_patch_func_t ahc_patch17_func
 static int
 ahc_patch17_func(struct ahc_softc *ahc)
 {
-	return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0);
+	return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0);
 }
 
 static ahc_patch_func_t ahc_patch16_func;
@@ -1142,152 +1143,152 @@ static struct patch {
 	{ ahc_patch0_func, 196, 1, 1 },
 	{ ahc_patch9_func, 212, 6, 2 },
 	{ ahc_patch0_func, 218, 6, 1 },
-	{ ahc_patch8_func, 226, 20, 2 },
+	{ ahc_patch8_func, 226, 21, 2 },
 	{ ahc_patch1_func, 241, 1, 1 },
-	{ ahc_patch1_func, 248, 1, 2 },
-	{ ahc_patch0_func, 249, 2, 2 },
-	{ ahc_patch11_func, 250, 1, 1 },
-	{ ahc_patch9_func, 258, 27, 3 },
-	{ ahc_patch1_func, 274, 10, 2 },
-	{ ahc_patch13_func, 277, 1, 1 },
-	{ ahc_patch14_func, 285, 14, 1 },
-	{ ahc_patch1_func, 301, 1, 2 },
-	{ ahc_patch0_func, 302, 1, 1 },
-	{ ahc_patch9_func, 305, 1, 1 },
-	{ ahc_patch13_func, 310, 1, 1 },
-	{ ahc_patch9_func, 311, 2, 2 },
-	{ ahc_patch0_func, 313, 4, 1 },
-	{ ahc_patch14_func, 317, 1, 1 },
-	{ ahc_patch15_func, 319, 2, 3 },
-	{ ahc_patch9_func, 319, 1, 2 },
-	{ ahc_patch0_func, 320, 1, 1 },
-	{ ahc_patch6_func, 325, 1, 2 },
-	{ ahc_patch0_func, 326, 1, 1 },
-	{ ahc_patch1_func, 330, 47, 11 },
-	{ ahc_patch6_func, 337, 2, 4 },
-	{ ahc_patch7_func, 337, 1, 1 },
-	{ ahc_patch8_func, 338, 1, 1 },
-	{ ahc_patch0_func, 339, 1, 1 },
-	{ ahc_patch16_func, 340, 1, 1 },
-	{ ahc_patch6_func, 356, 6, 3 },
-	{ ahc_patch16_func, 356, 5, 1 },
-	{ ahc_patch0_func, 362, 7, 1 },
-	{ ahc_patch13_func, 372, 5, 1 },
-	{ ahc_patch0_func, 377, 52, 17 },
-	{ ahc_patch14_func, 377, 1, 1 },
-	{ ahc_patch7_func, 379, 2, 2 },
-	{ ahc_patch17_func, 380, 1, 1 },
-	{ ahc_patch9_func, 383, 1, 1 },
-	{ ahc_patch18_func, 390, 1, 1 },
-	{ ahc_patch14_func, 395, 9, 3 },
-	{ ahc_patch9_func, 396, 3, 2 },
-	{ ahc_patch0_func, 399, 3, 1 },
-	{ ahc_patch9_func, 407, 6, 2 },
-	{ ahc_patch0_func, 413, 9, 2 },
-	{ ahc_patch13_func, 413, 1, 1 },
-	{ ahc_patch13_func, 422, 2, 1 },
-	{ ahc_patch14_func, 424, 1, 1 },
-	{ ahc_patch9_func, 426, 1, 2 },
-	{ ahc_patch0_func, 427, 1, 1 },
-	{ ahc_patch7_func, 428, 1, 1 },
+	{ ahc_patch1_func, 249, 1, 2 },
+	{ ahc_patch0_func, 250, 2, 2 },
+	{ ahc_patch11_func, 251, 1, 1 },
+	{ ahc_patch9_func, 259, 27, 3 },
+	{ ahc_patch1_func, 275, 10, 2 },
+	{ ahc_patch13_func, 278, 1, 1 },
+	{ ahc_patch14_func, 286, 14, 1 },
+	{ ahc_patch1_func, 302, 1, 2 },
+	{ ahc_patch0_func, 303, 1, 1 },
+	{ ahc_patch9_func, 306, 1, 1 },
+	{ ahc_patch13_func, 311, 1, 1 },
+	{ ahc_patch9_func, 312, 2, 2 },
+	{ ahc_patch0_func, 314, 4, 1 },
+	{ ahc_patch14_func, 318, 1, 1 },
+	{ ahc_patch15_func, 320, 2, 3 },
+	{ ahc_patch9_func, 320, 1, 2 },
+	{ ahc_patch0_func, 321, 1, 1 },
+	{ ahc_patch6_func, 326, 1, 2 },
+	{ ahc_patch0_func, 327, 1, 1 },
+	{ ahc_patch1_func, 331, 47, 11 },
+	{ ahc_patch6_func, 338, 2, 4 },
+	{ ahc_patch7_func, 338, 1, 1 },
+	{ ahc_patch8_func, 339, 1, 1 },
+	{ ahc_patch0_func, 340, 1, 1 },
+	{ ahc_patch16_func, 341, 1, 1 },
+	{ ahc_patch6_func, 357, 6, 3 },
+	{ ahc_patch16_func, 357, 5, 1 },
+	{ ahc_patch0_func, 363, 7, 1 },
+	{ ahc_patch13_func, 373, 5, 1 },
+	{ ahc_patch0_func, 378, 52, 17 },
+	{ ahc_patch14_func, 378, 1, 1 },
+	{ ahc_patch7_func, 380, 2, 2 },
+	{ ahc_patch17_func, 381, 1, 1 },
+	{ ahc_patch9_func, 384, 1, 1 },
+	{ ahc_patch18_func, 391, 1, 1 },
+	{ ahc_patch14_func, 396, 9, 3 },
+	{ ahc_patch9_func, 397, 3, 2 },
+	{ ahc_patch0_func, 400, 3, 1 },
+	{ ahc_patch9_func, 408, 6, 2 },
+	{ ahc_patch0_func, 414, 9, 2 },
+	{ ahc_patch13_func, 414, 1, 1 },
+	{ ahc_patch13_func, 423, 2, 1 },
+	{ ahc_patch14_func, 425, 1, 1 },
+	{ ahc_patch9_func, 427, 1, 2 },
+	{ ahc_patch0_func, 428, 1, 1 },
 	{ ahc_patch7_func, 429, 1, 1 },
-	{ ahc_patch8_func, 430, 3, 3 },
-	{ ahc_patch6_func, 431, 1, 2 },
-	{ ahc_patch0_func, 432, 1, 1 },
-	{ ahc_patch9_func, 433, 1, 1 },
-	{ ahc_patch15_func, 434, 1, 2 },
-	{ ahc_patch13_func, 434, 1, 1 },
-	{ ahc_patch14_func, 436, 9, 4 },
-	{ ahc_patch9_func, 436, 1, 1 },
-	{ ahc_patch9_func, 443, 2, 1 },
-	{ ahc_patch0_func, 445, 4, 3 },
-	{ ahc_patch9_func, 445, 1, 2 },
-	{ ahc_patch0_func, 446, 3, 1 },
-	{ ahc_patch1_func, 450, 2, 1 },
-	{ ahc_patch7_func, 452, 10, 2 },
-	{ ahc_patch0_func, 462, 1, 1 },
-	{ ahc_patch8_func, 463, 118, 22 },
-	{ ahc_patch1_func, 465, 3, 2 },
-	{ ahc_patch0_func, 468, 5, 3 },
-	{ ahc_patch9_func, 468, 2, 2 },
-	{ ahc_patch0_func, 470, 3, 1 },
-	{ ahc_patch1_func, 475, 2, 2 },
-	{ ahc_patch0_func, 477, 6, 3 },
-	{ ahc_patch9_func, 477, 2, 2 },
-	{ ahc_patch0_func, 479, 3, 1 },
-	{ ahc_patch1_func, 485, 2, 2 },
-	{ ahc_patch0_func, 487, 9, 7 },
-	{ ahc_patch9_func, 487, 5, 6 },
-	{ ahc_patch19_func, 487, 1, 2 },
-	{ ahc_patch0_func, 488, 1, 1 },
-	{ ahc_patch19_func, 490, 1, 2 },
-	{ ahc_patch0_func, 491, 1, 1 },
-	{ ahc_patch0_func, 492, 4, 1 },
-	{ ahc_patch6_func, 497, 3, 2 },
-	{ ahc_patch0_func, 500, 1, 1 },
-	{ ahc_patch6_func, 510, 1, 2 },
-	{ ahc_patch0_func, 511, 1, 1 },
-	{ ahc_patch20_func, 548, 7, 1 },
-	{ ahc_patch3_func, 583, 1, 2 },
-	{ ahc_patch0_func, 584, 1, 1 },
-	{ ahc_patch21_func, 587, 1, 1 },
-	{ ahc_patch8_func, 589, 106, 33 },
-	{ ahc_patch4_func, 591, 1, 1 },
-	{ ahc_patch1_func, 597, 2, 2 },
-	{ ahc_patch0_func, 599, 1, 1 },
-	{ ahc_patch1_func, 602, 1, 2 },
-	{ ahc_patch0_func, 603, 1, 1 },
-	{ ahc_patch9_func, 604, 3, 3 },
-	{ ahc_patch15_func, 605, 1, 1 },
-	{ ahc_patch0_func, 607, 4, 1 },
-	{ ahc_patch19_func, 616, 2, 2 },
-	{ ahc_patch0_func, 618, 1, 1 },
-	{ ahc_patch19_func, 622, 10, 3 },
-	{ ahc_patch5_func, 624, 8, 1 },
-	{ ahc_patch0_func, 632, 9, 2 },
-	{ ahc_patch5_func, 633, 8, 1 },
-	{ ahc_patch4_func, 643, 1, 2 },
-	{ ahc_patch0_func, 644, 1, 1 },
-	{ ahc_patch19_func, 645, 1, 2 },
-	{ ahc_patch0_func, 646, 3, 2 },
-	{ ahc_patch4_func, 648, 1, 1 },
-	{ ahc_patch5_func, 649, 1, 1 },
-	{ ahc_patch5_func, 652, 1, 1 },
-	{ ahc_patch5_func, 654, 1, 1 },
-	{ ahc_patch4_func, 656, 2, 2 },
-	{ ahc_patch0_func, 658, 2, 1 },
-	{ ahc_patch5_func, 660, 1, 1 },
-	{ ahc_patch5_func, 663, 1, 1 },
-	{ ahc_patch5_func, 666, 1, 1 },
-	{ ahc_patch19_func, 670, 1, 1 },
-	{ ahc_patch19_func, 673, 1, 1 },
-	{ ahc_patch4_func, 679, 1, 1 },
-	{ ahc_patch6_func, 682, 1, 2 },
-	{ ahc_patch0_func, 683, 1, 1 },
-	{ ahc_patch7_func, 695, 16, 1 },
-	{ ahc_patch4_func, 711, 20, 1 },
-	{ ahc_patch9_func, 732, 4, 2 },
-	{ ahc_patch0_func, 736, 4, 1 },
-	{ ahc_patch9_func, 740, 4, 2 },
-	{ ahc_patch0_func, 744, 3, 1 },
-	{ ahc_patch6_func, 750, 1, 1 },
-	{ ahc_patch22_func, 752, 14, 1 },
-	{ ahc_patch7_func, 766, 3, 1 },
-	{ ahc_patch9_func, 778, 24, 8 },
-	{ ahc_patch19_func, 782, 1, 2 },
-	{ ahc_patch0_func, 783, 1, 1 },
-	{ ahc_patch15_func, 788, 4, 2 },
-	{ ahc_patch0_func, 792, 7, 3 },
-	{ ahc_patch23_func, 792, 5, 2 },
-	{ ahc_patch0_func, 797, 2, 1 },
-	{ ahc_patch0_func, 802, 42, 3 },
-	{ ahc_patch18_func, 814, 18, 2 },
-	{ ahc_patch0_func, 832, 1, 1 },
-	{ ahc_patch4_func, 856, 1, 1 },
-	{ ahc_patch4_func, 857, 3, 2 },
-	{ ahc_patch0_func, 860, 1, 1 },
-	{ ahc_patch13_func, 861, 3, 1 },
-	{ ahc_patch4_func, 864, 12, 1 }
+	{ ahc_patch7_func, 430, 1, 1 },
+	{ ahc_patch8_func, 431, 3, 3 },
+	{ ahc_patch6_func, 432, 1, 2 },
+	{ ahc_patch0_func, 433, 1, 1 },
+	{ ahc_patch9_func, 434, 1, 1 },
+	{ ahc_patch15_func, 435, 1, 2 },
+	{ ahc_patch13_func, 435, 1, 1 },
+	{ ahc_patch14_func, 437, 9, 4 },
+	{ ahc_patch9_func, 437, 1, 1 },
+	{ ahc_patch9_func, 444, 2, 1 },
+	{ ahc_patch0_func, 446, 4, 3 },
+	{ ahc_patch9_func, 446, 1, 2 },
+	{ ahc_patch0_func, 447, 3, 1 },
+	{ ahc_patch1_func, 451, 2, 1 },
+	{ ahc_patch7_func, 453, 10, 2 },
+	{ ahc_patch0_func, 463, 1, 1 },
+	{ ahc_patch8_func, 464, 118, 22 },
+	{ ahc_patch1_func, 466, 3, 2 },
+	{ ahc_patch0_func, 469, 5, 3 },
+	{ ahc_patch9_func, 469, 2, 2 },
+	{ ahc_patch0_func, 471, 3, 1 },
+	{ ahc_patch1_func, 476, 2, 2 },
+	{ ahc_patch0_func, 478, 6, 3 },
+	{ ahc_patch9_func, 478, 2, 2 },
+	{ ahc_patch0_func, 480, 3, 1 },
+	{ ahc_patch1_func, 486, 2, 2 },
+	{ ahc_patch0_func, 488, 9, 7 },
+	{ ahc_patch9_func, 488, 5, 6 },
+	{ ahc_patch19_func, 488, 1, 2 },
+	{ ahc_patch0_func, 489, 1, 1 },
+	{ ahc_patch19_func, 491, 1, 2 },
+	{ ahc_patch0_func, 492, 1, 1 },
+	{ ahc_patch0_func, 493, 4, 1 },
+	{ ahc_patch6_func, 498, 3, 2 },
+	{ ahc_patch0_func, 501, 1, 1 },
+	{ ahc_patch6_func, 511, 1, 2 },
+	{ ahc_patch0_func, 512, 1, 1 },
+	{ ahc_patch20_func, 549, 7, 1 },
+	{ ahc_patch3_func, 584, 1, 2 },
+	{ ahc_patch0_func, 585, 1, 1 },
+	{ ahc_patch21_func, 588, 1, 1 },
+	{ ahc_patch8_func, 590, 106, 33 },
+	{ ahc_patch4_func, 592, 1, 1 },
+	{ ahc_patch1_func, 598, 2, 2 },
+	{ ahc_patch0_func, 600, 1, 1 },
+	{ ahc_patch1_func, 603, 1, 2 },
+	{ ahc_patch0_func, 604, 1, 1 },
+	{ ahc_patch9_func, 605, 3, 3 },
+	{ ahc_patch15_func, 606, 1, 1 },
+	{ ahc_patch0_func, 608, 4, 1 },
+	{ ahc_patch19_func, 617, 2, 2 },
+	{ ahc_patch0_func, 619, 1, 1 },
+	{ ahc_patch19_func, 623, 10, 3 },
+	{ ahc_patch5_func, 625, 8, 1 },
+	{ ahc_patch0_func, 633, 9, 2 },
+	{ ahc_patch5_func, 634, 8, 1 },
+	{ ahc_patch4_func, 644, 1, 2 },
+	{ ahc_patch0_func, 645, 1, 1 },
+	{ ahc_patch19_func, 646, 1, 2 },
+	{ ahc_patch0_func, 647, 3, 2 },
+	{ ahc_patch4_func, 649, 1, 1 },
+	{ ahc_patch5_func, 650, 1, 1 },
+	{ ahc_patch5_func, 653, 1, 1 },
+	{ ahc_patch5_func, 655, 1, 1 },
+	{ ahc_patch4_func, 657, 2, 2 },
+	{ ahc_patch0_func, 659, 2, 1 },
+	{ ahc_patch5_func, 661, 1, 1 },
+	{ ahc_patch5_func, 664, 1, 1 },
+	{ ahc_patch5_func, 667, 1, 1 },
+	{ ahc_patch19_func, 671, 1, 1 },
+	{ ahc_patch19_func, 674, 1, 1 },
+	{ ahc_patch4_func, 680, 1, 1 },
+	{ ahc_patch6_func, 683, 1, 2 },
+	{ ahc_patch0_func, 684, 1, 1 },
+	{ ahc_patch7_func, 696, 16, 1 },
+	{ ahc_patch4_func, 712, 20, 1 },
+	{ ahc_patch9_func, 733, 4, 2 },
+	{ ahc_patch0_func, 737, 4, 1 },
+	{ ahc_patch9_func, 741, 4, 2 },
+	{ ahc_patch0_func, 745, 3, 1 },
+	{ ahc_patch6_func, 751, 1, 1 },
+	{ ahc_patch22_func, 753, 14, 1 },
+	{ ahc_patch7_func, 767, 3, 1 },
+	{ ahc_patch9_func, 779, 24, 8 },
+	{ ahc_patch19_func, 783, 1, 2 },
+	{ ahc_patch0_func, 784, 1, 1 },
+	{ ahc_patch15_func, 789, 4, 2 },
+	{ ahc_patch0_func, 793, 7, 3 },
+	{ ahc_patch23_func, 793, 5, 2 },
+	{ ahc_patch0_func, 798, 2, 1 },
+	{ ahc_patch0_func, 803, 42, 3 },
+	{ ahc_patch18_func, 815, 18, 2 },
+	{ ahc_patch0_func, 833, 1, 1 },
+	{ ahc_patch4_func, 857, 1, 1 },
+	{ ahc_patch4_func, 858, 3, 2 },
+	{ ahc_patch0_func, 861, 1, 1 },
+	{ ahc_patch13_func, 862, 3, 1 },
+	{ ahc_patch4_func, 865, 12, 1 }
 };
 
 static struct cs {
@@ -1296,11 +1297,11 @@ static struct cs {
 } critical_sections[] = {
 	{ 11, 18 },
 	{ 21, 30 },
-	{ 711, 727 },
-	{ 857, 860 },
-	{ 864, 870 },
-	{ 872, 874 },
-	{ 874, 876 }
+	{ 712, 728 },
+	{ 858, 861 },
+	{ 865, 871 },
+	{ 873, 875 },
+	{ 875, 877 }
 };
 
 static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c
--- a/drivers/scsi/aic7xxx/aiclib.c
+++ b/drivers/scsi/aic7xxx/aiclib.c
@@ -30,1382 +30,5 @@
  * $Id$
  */
 
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/version.h>
-
-/* Core SCSI definitions */
-#include <scsi/scsi_host.h>
 #include "aiclib.h"
-#include "cam.h"
-
-#ifndef FALSE
-#define FALSE   0
-#endif /* FALSE */
-#ifndef TRUE
-#define TRUE    1
-#endif /* TRUE */
-#ifndef ERESTART
-#define ERESTART        -1              /* restart syscall */
-#endif
-#ifndef EJUSTRETURN
-#define EJUSTRETURN     -2              /* don't modify regs, just return */
-#endif
-
-static int	ascentrycomp(const void *key, const void *member);
-static int	senseentrycomp(const void *key, const void *member);
-static void	fetchtableentries(int sense_key, int asc, int ascq,
-				  struct scsi_inquiry_data *,
-				  const struct sense_key_table_entry **,
-				  const struct asc_table_entry **);
-static void *	scsibsearch(const void *key, const void *base, size_t nmemb,
-			    size_t size,
-			    int (*compar)(const void *, const void *));
-typedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
-static int	cam_strmatch(const u_int8_t *str, const u_int8_t *pattern,
-			     int str_len);
-static caddr_t	cam_quirkmatch(caddr_t target, caddr_t quirk_table,
-			       int num_entries, int entry_size,
-			       cam_quirkmatch_t *comp_func);
-
-#define SCSI_NO_SENSE_STRINGS 1
-#if !defined(SCSI_NO_SENSE_STRINGS)
-#define SST(asc, ascq, action, desc) \
-	asc, ascq, action, desc
-#else 
-static const char empty_string[] = "";
-
-#define SST(asc, ascq, action, desc) \
-	asc, ascq, action, empty_string
-#endif 
-
-static const struct sense_key_table_entry sense_key_table[] = 
-{
-	{ SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
-	{ SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
-	{
-	  SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
-	  "NOT READY"
-	},
-	{ SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
-	{ SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
-	{ SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
-	{ SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
-	{ SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
-	{ SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
-	{ SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
-	{ SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
-	{ SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
-	{ SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
-	{ SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
-	{ SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
-	{ SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
-};
-
-static const int sense_key_table_size =
-    sizeof(sense_key_table)/sizeof(sense_key_table[0]);
-
-static struct asc_table_entry quantum_fireball_entries[] = {
-	{SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO, 
-	     "Logical unit not ready, initializing cmd. required")}
-};
-
-static struct asc_table_entry sony_mo_entries[] = {
-	{SST(0x04, 0x00, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
-	     "Logical unit not ready, cause not reportable")}
-};
-
-static struct scsi_sense_quirk_entry sense_quirk_table[] = {
-	{
-		/*
-		 * The Quantum Fireball ST and SE like to return 0x04 0x0b when
-		 * they really should return 0x04 0x02.  0x04,0x0b isn't
-		 * defined in any SCSI spec, and it isn't mentioned in the
-		 * hardware manual for these drives.
-		 */
-		{T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
-		/*num_sense_keys*/0,
-		sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
-		/*sense key entries*/NULL,
-		quantum_fireball_entries
-	},
-	{
-		/*
-		 * This Sony MO drive likes to return 0x04, 0x00 when it
-		 * isn't spun up.
-		 */
-		{T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
-		/*num_sense_keys*/0,
-		sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
-		/*sense key entries*/NULL,
-		sony_mo_entries
-	}
-};
-
-static const int sense_quirk_table_size =
-    sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
-
-static struct asc_table_entry asc_table[] = {
-/*
- * From File: ASC-NUM.TXT
- * SCSI ASC/ASCQ Assignments
- * Numeric Sorted Listing
- * as of  5/12/97
- *
- * D - DIRECT ACCESS DEVICE (SBC)                     device column key
- * .T - SEQUENTIAL ACCESS DEVICE (SSC)               -------------------
- * . L - PRINTER DEVICE (SSC)                           blank = reserved
- * .  P - PROCESSOR DEVICE (SPC)                     not blank = allowed
- * .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
- * .  . R - CD DEVICE (MMC)
- * .  .  S - SCANNER DEVICE (SGC)
- * .  .  .O - OPTICAL MEMORY DEVICE (SBC)
- * .  .  . M - MEDIA CHANGER DEVICE (SMC)
- * .  .  .  C - COMMUNICATION DEVICE (SSC)
- * .  .  .  .A - STORAGE ARRAY DEVICE (SCC)
- * .  .  .  . E - ENCLOSURE SERVICES DEVICE (SES)
- * DTLPWRSOMCAE        ASC   ASCQ  Action  Description
- * ------------        ----  ----  ------  -----------------------------------*/
-/* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP,
-			"No additional sense information") },
-/*  T    S      */{SST(0x00, 0x01, SS_RDEF,
-			"Filemark detected") },
-/*  T    S      */{SST(0x00, 0x02, SS_RDEF,
-			"End-of-partition/medium detected") },
-/*  T           */{SST(0x00, 0x03, SS_RDEF,
-			"Setmark detected") },
-/*  T    S      */{SST(0x00, 0x04, SS_RDEF,
-			"Beginning-of-partition/medium detected") },
-/*  T    S      */{SST(0x00, 0x05, SS_RDEF,
-			"End-of-data detected") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF,
-			"I/O process terminated") },
-/*      R       */{SST(0x00, 0x11, SS_FATAL|EBUSY,
-			"Audio play operation in progress") },
-/*      R       */{SST(0x00, 0x12, SS_NOP,
-			"Audio play operation paused") },
-/*      R       */{SST(0x00, 0x13, SS_NOP,
-			"Audio play operation successfully completed") },
-/*      R       */{SST(0x00, 0x14, SS_RDEF,
-			"Audio play operation stopped due to error") },
-/*      R       */{SST(0x00, 0x15, SS_NOP,
-			"No current audio status to return") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY,
-			"Operation in progress") },
-/* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF,
-			"Cleaning requested") },
-/* D   W  O     */{SST(0x01, 0x00, SS_RDEF,
-			"No index/sector signal") },
-/* D   WR OM    */{SST(0x02, 0x00, SS_RDEF,
-			"No seek complete") },
-/* DTL W SO     */{SST(0x03, 0x00, SS_RDEF,
-			"Peripheral device write fault") },
-/*  T           */{SST(0x03, 0x01, SS_RDEF,
-			"No write current") },
-/*  T           */{SST(0x03, 0x02, SS_RDEF,
-			"Excessive write errors") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x00,
-			SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
-			"Logical unit not ready, cause not reportable") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x01,
-			SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
-			"Logical unit is in process of becoming ready") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
-			"Logical unit not ready, initializing cmd. required") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO,
-			"Logical unit not ready, manual intervention required")},
-/* DTL    O     */{SST(0x04, 0x04, SS_FATAL|EBUSY,
-			"Logical unit not ready, format in progress") },
-/* DT  W  OMCA  */{SST(0x04, 0x05, SS_FATAL|EBUSY,
-			"Logical unit not ready, rebuild in progress") },
-/* DT  W  OMCA  */{SST(0x04, 0x06, SS_FATAL|EBUSY,
-			"Logical unit not ready, recalculation in progress") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY,
-			"Logical unit not ready, operation in progress") },
-/*      R       */{SST(0x04, 0x08, SS_FATAL|EBUSY,
-			"Logical unit not ready, long write in progress") },
-/* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF,
-			"Logical unit does not respond to selection") },
-/* D   WR OM    */{SST(0x06, 0x00, SS_RDEF,
-			"No reference position found") },
-/* DTL WRSOM    */{SST(0x07, 0x00, SS_RDEF,
-			"Multiple peripheral devices selected") },
-/* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF,
-			"Logical unit communication failure") },
-/* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF,
-			"Logical unit communication time-out") },
-/* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF,
-			"Logical unit communication parity error") },
-/* DT   R OM    */{SST(0x08, 0x03, SS_RDEF,
-			"Logical unit communication crc error (ultra-dma/32)")},
-/* DT  WR O     */{SST(0x09, 0x00, SS_RDEF,
-			"Track following error") },
-/*     WR O     */{SST(0x09, 0x01, SS_RDEF,
-			"Tracking servo failure") },
-/*     WR O     */{SST(0x09, 0x02, SS_RDEF,
-			"Focus servo failure") },
-/*     WR O     */{SST(0x09, 0x03, SS_RDEF,
-			"Spindle servo failure") },
-/* DT  WR O     */{SST(0x09, 0x04, SS_RDEF,
-			"Head select fault") },
-/* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC,
-			"Error log overflow") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF,
-			"Warning") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF,
-			"Specified temperature exceeded") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF,
-			"Enclosure degraded") },
-/*  T   RS      */{SST(0x0C, 0x00, SS_RDEF,
-			"Write error") },
-/* D   W  O     */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
-			"Write error - recovered with auto reallocation") },
-/* D   W  O     */{SST(0x0C, 0x02, SS_RDEF,
-			"Write error - auto reallocation failed") },
-/* D   W  O     */{SST(0x0C, 0x03, SS_RDEF,
-			"Write error - recommend reassignment") },
-/* DT  W  O     */{SST(0x0C, 0x04, SS_RDEF,
-			"Compression check miscompare error") },
-/* DT  W  O     */{SST(0x0C, 0x05, SS_RDEF,
-			"Data expansion occurred during compression") },
-/* DT  W  O     */{SST(0x0C, 0x06, SS_RDEF,
-			"Block not compressible") },
-/*      R       */{SST(0x0C, 0x07, SS_RDEF,
-			"Write error - recovery needed") },
-/*      R       */{SST(0x0C, 0x08, SS_RDEF,
-			"Write error - recovery failed") },
-/*      R       */{SST(0x0C, 0x09, SS_RDEF,
-			"Write error - loss of streaming") },
-/*      R       */{SST(0x0C, 0x0A, SS_RDEF,
-			"Write error - padding blocks added") },
-/* D   W  O     */{SST(0x10, 0x00, SS_RDEF,
-			"ID CRC or ECC error") },
-/* DT  WRSO     */{SST(0x11, 0x00, SS_RDEF,
-			"Unrecovered read error") },
-/* DT  W SO     */{SST(0x11, 0x01, SS_RDEF,
-			"Read retries exhausted") },
-/* DT  W SO     */{SST(0x11, 0x02, SS_RDEF,
-			"Error too long to correct") },
-/* DT  W SO     */{SST(0x11, 0x03, SS_RDEF,
-			"Multiple read errors") },
-/* D   W  O     */{SST(0x11, 0x04, SS_RDEF,
-			"Unrecovered read error - auto reallocate failed") },
-/*     WR O     */{SST(0x11, 0x05, SS_RDEF,
-			"L-EC uncorrectable error") },
-/*     WR O     */{SST(0x11, 0x06, SS_RDEF,
-			"CIRC unrecovered error") },
-/*     W  O     */{SST(0x11, 0x07, SS_RDEF,
-			"Data re-synchronization error") },
-/*  T           */{SST(0x11, 0x08, SS_RDEF,
-			"Incomplete block read") },
-/*  T           */{SST(0x11, 0x09, SS_RDEF,
-			"No gap found") },
-/* DT     O     */{SST(0x11, 0x0A, SS_RDEF,
-			"Miscorrected error") },
-/* D   W  O     */{SST(0x11, 0x0B, SS_RDEF,
-			"Unrecovered read error - recommend reassignment") },
-/* D   W  O     */{SST(0x11, 0x0C, SS_RDEF,
-			"Unrecovered read error - recommend rewrite the data")},
-/* DT  WR O     */{SST(0x11, 0x0D, SS_RDEF,
-			"De-compression CRC error") },
-/* DT  WR O     */{SST(0x11, 0x0E, SS_RDEF,
-			"Cannot decompress using declared algorithm") },
-/*      R       */{SST(0x11, 0x0F, SS_RDEF,
-			"Error reading UPC/EAN number") },
-/*      R       */{SST(0x11, 0x10, SS_RDEF,
-			"Error reading ISRC number") },
-/*      R       */{SST(0x11, 0x11, SS_RDEF,
-			"Read error - loss of streaming") },
-/* D   W  O     */{SST(0x12, 0x00, SS_RDEF,
-			"Address mark not found for id field") },
-/* D   W  O     */{SST(0x13, 0x00, SS_RDEF,
-			"Address mark not found for data field") },
-/* DTL WRSO     */{SST(0x14, 0x00, SS_RDEF,
-			"Recorded entity not found") },
-/* DT  WR O     */{SST(0x14, 0x01, SS_RDEF,
-			"Record not found") },
-/*  T           */{SST(0x14, 0x02, SS_RDEF,
-			"Filemark or setmark not found") },
-/*  T           */{SST(0x14, 0x03, SS_RDEF,
-			"End-of-data not found") },
-/*  T           */{SST(0x14, 0x04, SS_RDEF,
-			"Block sequence error") },
-/* DT  W  O     */{SST(0x14, 0x05, SS_RDEF,
-			"Record not found - recommend reassignment") },
-/* DT  W  O     */{SST(0x14, 0x06, SS_RDEF,
-			"Record not found - data auto-reallocated") },
-/* DTL WRSOM    */{SST(0x15, 0x00, SS_RDEF,
-			"Random positioning error") },
-/* DTL WRSOM    */{SST(0x15, 0x01, SS_RDEF,
-			"Mechanical positioning error") },
-/* DT  WR O     */{SST(0x15, 0x02, SS_RDEF,
-			"Positioning error detected by read of medium") },
-/* D   W  O     */{SST(0x16, 0x00, SS_RDEF,
-			"Data synchronization mark error") },
-/* D   W  O     */{SST(0x16, 0x01, SS_RDEF,
-			"Data sync error - data rewritten") },
-/* D   W  O     */{SST(0x16, 0x02, SS_RDEF,
-			"Data sync error - recommend rewrite") },
-/* D   W  O     */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE,
-			"Data sync error - data auto-reallocated") },
-/* D   W  O     */{SST(0x16, 0x04, SS_RDEF,
-			"Data sync error - recommend reassignment") },
-/* DT  WRSO     */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with no error correction applied") },
-/* DT  WRSO     */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with retries") },
-/* DT  WR O     */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with positive head offset") },
-/* DT  WR O     */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with negative head offset") },
-/*     WR O     */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with retries and/or CIRC applied") },
-/* D   WR O     */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data using previous sector id") },
-/* D   W  O     */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data without ECC - data auto-reallocated") },
-/* D   W  O     */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data without ECC - recommend reassignment")},
-/* D   W  O     */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data without ECC - recommend rewrite") },
-/* D   W  O     */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data without ECC - data rewritten") },
-/* D   W  O     */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with error correction applied") },
-/* D   WR O     */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with error corr. & retries applied") },
-/* D   WR O     */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data - data auto-reallocated") },
-/*      R       */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with CIRC") },
-/*      R       */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with L-EC") },
-/* D   WR O     */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data - recommend reassignment") },
-/* D   WR O     */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data - recommend rewrite") },
-/* D   W  O     */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered data with ECC - data rewritten") },
-/* D      O     */{SST(0x19, 0x00, SS_RDEF,
-			"Defect list error") },
-/* D      O     */{SST(0x19, 0x01, SS_RDEF,
-			"Defect list not available") },
-/* D      O     */{SST(0x19, 0x02, SS_RDEF,
-			"Defect list error in primary list") },
-/* D      O     */{SST(0x19, 0x03, SS_RDEF,
-			"Defect list error in grown list") },
-/* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF,
-			"Parameter list length error") },
-/* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF,
-			"Synchronous data transfer error") },
-/* D      O     */{SST(0x1C, 0x00, SS_RDEF,
-			"Defect list not found") },
-/* D      O     */{SST(0x1C, 0x01, SS_RDEF,
-			"Primary defect list not found") },
-/* D      O     */{SST(0x1C, 0x02, SS_RDEF,
-			"Grown defect list not found") },
-/* D   W  O     */{SST(0x1D, 0x00, SS_FATAL,
-			"Miscompare during verify operation" )},
-/* D   W  O     */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE,
-			"Recovered id with ecc correction") },
-/* D      O     */{SST(0x1F, 0x00, SS_RDEF,
-			"Partial defect list transfer") },
-/* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL,
-			"Invalid command operation code") },
-/* DT  WR OM    */{SST(0x21, 0x00, SS_FATAL|EINVAL,
-			"Logical block address out of range" )},
-/* DT  WR OM    */{SST(0x21, 0x01, SS_FATAL|EINVAL,
-			"Invalid element address") },
-/* D            */{SST(0x22, 0x00, SS_FATAL|EINVAL,
-			"Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
-/* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL,
-			"Invalid field in CDB") },
-/* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO,
-			"Logical unit not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL,
-			"Invalid field in parameter list") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL,
-			"Parameter not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL,
-			"Parameter value invalid") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL,
-			"Threshold parameters not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL,
-			"Invalid release of active persistent reservation") },
-/* DT  W  O     */{SST(0x27, 0x00, SS_FATAL|EACCES,
-			"Write protected") },
-/* DT  W  O     */{SST(0x27, 0x01, SS_FATAL|EACCES,
-			"Hardware write protected") },
-/* DT  W  O     */{SST(0x27, 0x02, SS_FATAL|EACCES,
-			"Logical unit software write protected") },
-/*  T           */{SST(0x27, 0x03, SS_FATAL|EACCES,
-			"Associated write protect") },
-/*  T           */{SST(0x27, 0x04, SS_FATAL|EACCES,
-			"Persistent write protect") },
-/*  T           */{SST(0x27, 0x05, SS_FATAL|EACCES,
-			"Permanent write protect") },
-/* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_RDEF,
-			"Not ready to ready change, medium may have changed") },
-/* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO,
-			"Import or export element accessed") },
-/*
- * XXX JGibbs - All of these should use the same errno, but I don't think
- * ENXIO is the correct choice.  Should we borrow from the networking
- * errnos?  ECONNRESET anyone?
- */
-/* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_RDEF,
-			"Power on, reset, or bus device reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF,
-			"Power on occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF,
-			"Scsi bus reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF,
-			"Bus device reset function occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF,
-			"Device internal reset") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF,
-			"Transceiver mode changed to single-ended") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF,
-			"Transceiver mode changed to LVD") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF,
-			"Parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF,
-			"Mode parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF,
-			"Log parameters changed") },
-/* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF,
-			"Reservations preempted") },
-/* DTLPWRSO C   */{SST(0x2B, 0x00, SS_RDEF,
-			"Copy cannot execute since host cannot disconnect") },
-/* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF,
-			"Command sequence error") },
-/*       S      */{SST(0x2C, 0x01, SS_RDEF,
-			"Too many windows specified") },
-/*       S      */{SST(0x2C, 0x02, SS_RDEF,
-			"Invalid combination of windows specified") },
-/*      R       */{SST(0x2C, 0x03, SS_RDEF,
-			"Current program area is not empty") },
-/*      R       */{SST(0x2C, 0x04, SS_RDEF,
-			"Current program area is empty") },
-/*  T           */{SST(0x2D, 0x00, SS_RDEF,
-			"Overwrite error on update in place") },
-/* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF,
-			"Commands cleared by another initiator") },
-/* DT  WR OM    */{SST(0x30, 0x00, SS_RDEF,
-			"Incompatible medium installed") },
-/* DT  WR O     */{SST(0x30, 0x01, SS_RDEF,
-			"Cannot read medium - unknown format") },
-/* DT  WR O     */{SST(0x30, 0x02, SS_RDEF,
-			"Cannot read medium - incompatible format") },
-/* DT           */{SST(0x30, 0x03, SS_RDEF,
-			"Cleaning cartridge installed") },
-/* DT  WR O     */{SST(0x30, 0x04, SS_RDEF,
-			"Cannot write medium - unknown format") },
-/* DT  WR O     */{SST(0x30, 0x05, SS_RDEF,
-			"Cannot write medium - incompatible format") },
-/* DT  W  O     */{SST(0x30, 0x06, SS_RDEF,
-			"Cannot format medium - incompatible medium") },
-/* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF,
-			"Cleaning failure") },
-/*      R       */{SST(0x30, 0x08, SS_RDEF,
-			"Cannot write - application code mismatch") },
-/*      R       */{SST(0x30, 0x09, SS_RDEF,
-			"Current session not fixated for append") },
-/* DT  WR O     */{SST(0x31, 0x00, SS_RDEF,
-			"Medium format corrupted") },
-/* D L  R O     */{SST(0x31, 0x01, SS_RDEF,
-			"Format command failed") },
-/* D   W  O     */{SST(0x32, 0x00, SS_RDEF,
-			"No defect spare location available") },
-/* D   W  O     */{SST(0x32, 0x01, SS_RDEF,
-			"Defect list update failure") },
-/*  T           */{SST(0x33, 0x00, SS_RDEF,
-			"Tape length error") },
-/* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF,
-			"Enclosure failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF,
-			"Enclosure services failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF,
-			"Unsupported enclosure function") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF,
-			"Enclosure services unavailable") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF,
-			"Enclosure services transfer failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF,
-			"Enclosure services transfer refused") },
-/*   L          */{SST(0x36, 0x00, SS_RDEF,
-			"Ribbon, ink, or toner failure") },
-/* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF,
-			"Rounded parameter") },
-/* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF,
-			"Saving parameters not supported") },
-/* DTL WRSOM    */{SST(0x3A, 0x00, SS_NOP,
-			"Medium not present") },
-/* DT  WR OM    */{SST(0x3A, 0x01, SS_NOP,
-			"Medium not present - tray closed") },
-/* DT  WR OM    */{SST(0x3A, 0x01, SS_NOP,
-			"Medium not present - tray open") },
-/* DT  WR OM    */{SST(0x3A, 0x03, SS_NOP,
-			"Medium not present - Loadable") },
-/* DT  WR OM    */{SST(0x3A, 0x04, SS_NOP,
-			"Medium not present - medium auxiliary "
-			"memory accessible") },
-/* DT  WR OM    */{SST(0x3A, 0xFF, SS_NOP, NULL) },/* Range 0x05->0xFF */
-/*  TL          */{SST(0x3B, 0x00, SS_RDEF,
-			"Sequential positioning error") },
-/*  T           */{SST(0x3B, 0x01, SS_RDEF,
-			"Tape position error at beginning-of-medium") },
-/*  T           */{SST(0x3B, 0x02, SS_RDEF,
-			"Tape position error at end-of-medium") },
-/*   L          */{SST(0x3B, 0x03, SS_RDEF,
-			"Tape or electronic vertical forms unit not ready") },
-/*   L          */{SST(0x3B, 0x04, SS_RDEF,
-			"Slew failure") },
-/*   L          */{SST(0x3B, 0x05, SS_RDEF,
-			"Paper jam") },
-/*   L          */{SST(0x3B, 0x06, SS_RDEF,
-			"Failed to sense top-of-form") },
-/*   L          */{SST(0x3B, 0x07, SS_RDEF,
-			"Failed to sense bottom-of-form") },
-/*  T           */{SST(0x3B, 0x08, SS_RDEF,
-			"Reposition error") },
-/*       S      */{SST(0x3B, 0x09, SS_RDEF,
-			"Read past end of medium") },
-/*       S      */{SST(0x3B, 0x0A, SS_RDEF,
-			"Read past beginning of medium") },
-/*       S      */{SST(0x3B, 0x0B, SS_RDEF,
-			"Position past end of medium") },
-/*  T    S      */{SST(0x3B, 0x0C, SS_RDEF,
-			"Position past beginning of medium") },
-/* DT  WR OM    */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC,
-			"Medium destination element full") },
-/* DT  WR OM    */{SST(0x3B, 0x0E, SS_RDEF,
-			"Medium source element empty") },
-/*      R       */{SST(0x3B, 0x0F, SS_RDEF,
-			"End of medium reached") },
-/* DT  WR OM    */{SST(0x3B, 0x11, SS_RDEF,
-			"Medium magazine not accessible") },
-/* DT  WR OM    */{SST(0x3B, 0x12, SS_RDEF,
-			"Medium magazine removed") },
-/* DT  WR OM    */{SST(0x3B, 0x13, SS_RDEF,
-			"Medium magazine inserted") },
-/* DT  WR OM    */{SST(0x3B, 0x14, SS_RDEF,
-			"Medium magazine locked") },
-/* DT  WR OM    */{SST(0x3B, 0x15, SS_RDEF,
-			"Medium magazine unlocked") },
-/* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF,
-			"Invalid bits in identify message") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF,
-			"Logical unit has not self-configured yet") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF,
-			"Logical unit failure") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF,
-			"Timeout on logical unit") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF,
-			"Target operating conditions have changed") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF,
-			"Microcode has been changed") },
-/* DTLPWRSOMC   */{SST(0x3F, 0x02, SS_RDEF,
-			"Changed operating definition") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_INQ_REFRESH|SSQ_DECREMENT_COUNT,
-			"Inquiry data has changed") },
-/* DT  WR OMCAE */{SST(0x3F, 0x04, SS_RDEF,
-			"Component device attached") },
-/* DT  WR OMCAE */{SST(0x3F, 0x05, SS_RDEF,
-			"Device identifier changed") },
-/* DT  WR OMCAE */{SST(0x3F, 0x06, SS_RDEF,
-			"Redundancy group created or modified") },
-/* DT  WR OMCAE */{SST(0x3F, 0x07, SS_RDEF,
-			"Redundancy group deleted") },
-/* DT  WR OMCAE */{SST(0x3F, 0x08, SS_RDEF,
-			"Spare created or modified") },
-/* DT  WR OMCAE */{SST(0x3F, 0x09, SS_RDEF,
-			"Spare deleted") },
-/* DT  WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF,
-			"Volume set created or modified") },
-/* DT  WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF,
-			"Volume set deleted") },
-/* DT  WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF,
-			"Volume set deassigned") },
-/* DT  WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF,
-			"Volume set reassigned") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x0E, SS_RDEF,
-			"Reported luns data has changed") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x0F, SS_RETRY|SSQ_DECREMENT_COUNT
-				 | SSQ_DELAY_RANDOM|EBUSY,
-			"Echo buffer overwritten") },
-/* DT  WR OM   B*/{SST(0x3F, 0x0F, SS_RDEF, "Medium Loadable") },
-/* DT  WR OM   B*/{SST(0x3F, 0x0F, SS_RDEF,
-			"Medium auxiliary memory accessible") },
-/* D            */{SST(0x40, 0x00, SS_RDEF,
-			"Ram failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF,
-			"Diagnostic failure: ASCQ = Component ID") },
-/* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE,
-			NULL) },/* Range 0x80->0xFF */
-/* D            */{SST(0x41, 0x00, SS_RDEF,
-			"Data path failure") }, /* deprecated - use 40 NN instead */
-/* D            */{SST(0x42, 0x00, SS_RDEF,
-			"Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF,
-			"Message error") },
-/* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF,
-			"Internal target failure") },
-/* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF,
-			"Select or reselect failure") },
-/* DTLPWRSOMC   */{SST(0x46, 0x00, SS_RDEF,
-			"Unsuccessful soft reset") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF|SSQ_FALLBACK,
-			"SCSI parity error") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x01, SS_RDEF|SSQ_FALLBACK,
-			"Data Phase CRC error detected") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x02, SS_RDEF|SSQ_FALLBACK,
-			"SCSI parity error detected during ST data phase") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x03, SS_RDEF|SSQ_FALLBACK,
-			"Information Unit iuCRC error") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x04, SS_RDEF|SSQ_FALLBACK,
-			"Asynchronous information protection error detected") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x05, SS_RDEF|SSQ_FALLBACK,
-			"Protocol server CRC error") },
-/* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF|SSQ_FALLBACK,
-			"Initiator detected error message received") },
-/* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF,
-			"Invalid message error") },
-/* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF,
-			"Command phase error") },
-/* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF,
-			"Data phase error") },
-/* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF,
-			"Logical unit failed self-configuration") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF,
-			"Tagged overlapped commands: ASCQ = Queue tag ID") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE,
-			NULL)}, /* Range 0x00->0xFF */
-/* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF,
-			"Overlapped commands attempted") },
-/*  T           */{SST(0x50, 0x00, SS_RDEF,
-			"Write append error") },
-/*  T           */{SST(0x50, 0x01, SS_RDEF,
-			"Write append position error") },
-/*  T           */{SST(0x50, 0x02, SS_RDEF,
-			"Position error related to timing") },
-/*  T     O     */{SST(0x51, 0x00, SS_RDEF,
-			"Erase failure") },
-/*  T           */{SST(0x52, 0x00, SS_RDEF,
-			"Cartridge fault") },
-/* DTL WRSOM    */{SST(0x53, 0x00, SS_RDEF,
-			"Media load or eject failed") },
-/*  T           */{SST(0x53, 0x01, SS_RDEF,
-			"Unload tape failure") },
-/* DT  WR OM    */{SST(0x53, 0x02, SS_RDEF,
-			"Medium removal prevented") },
-/*    P         */{SST(0x54, 0x00, SS_RDEF,
-			"Scsi to host system interface failure") },
-/*    P         */{SST(0x55, 0x00, SS_RDEF,
-			"System resource failure") },
-/* D      O     */{SST(0x55, 0x01, SS_FATAL|ENOSPC,
-			"System buffer full") },
-/*      R       */{SST(0x57, 0x00, SS_RDEF,
-			"Unable to recover table-of-contents") },
-/*        O     */{SST(0x58, 0x00, SS_RDEF,
-			"Generation does not exist") },
-/*        O     */{SST(0x59, 0x00, SS_RDEF,
-			"Updated block read") },
-/* DTLPWRSOM    */{SST(0x5A, 0x00, SS_RDEF,
-			"Operator request or state change input") },
-/* DT  WR OM    */{SST(0x5A, 0x01, SS_RDEF,
-			"Operator medium removal request") },
-/* DT  W  O     */{SST(0x5A, 0x02, SS_RDEF,
-			"Operator selected write protect") },
-/* DT  W  O     */{SST(0x5A, 0x03, SS_RDEF,
-			"Operator selected write permit") },
-/* DTLPWRSOM    */{SST(0x5B, 0x00, SS_RDEF,
-			"Log exception") },
-/* DTLPWRSOM    */{SST(0x5B, 0x01, SS_RDEF,
-			"Threshold condition met") },
-/* DTLPWRSOM    */{SST(0x5B, 0x02, SS_RDEF,
-			"Log counter at maximum") },
-/* DTLPWRSOM    */{SST(0x5B, 0x03, SS_RDEF,
-			"Log list codes exhausted") },
-/* D      O     */{SST(0x5C, 0x00, SS_RDEF,
-			"RPL status change") },
-/* D      O     */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
-			"Spindles synchronized") },
-/* D      O     */{SST(0x5C, 0x02, SS_RDEF,
-			"Spindles not synchronized") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF,
-			"Failure prediction threshold exceeded") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF,
-			"Failure prediction threshold exceeded (false)") },
-/* DTLPWRSO CA  */{SST(0x5E, 0x00, SS_RDEF,
-			"Low power condition on") },
-/* DTLPWRSO CA  */{SST(0x5E, 0x01, SS_RDEF,
-			"Idle condition activated by timer") },
-/* DTLPWRSO CA  */{SST(0x5E, 0x02, SS_RDEF,
-			"Standby condition activated by timer") },
-/* DTLPWRSO CA  */{SST(0x5E, 0x03, SS_RDEF,
-			"Idle condition activated by command") },
-/* DTLPWRSO CA  */{SST(0x5E, 0x04, SS_RDEF,
-			"Standby condition activated by command") },
-/*       S      */{SST(0x60, 0x00, SS_RDEF,
-			"Lamp failure") },
-/*       S      */{SST(0x61, 0x00, SS_RDEF,
-			"Video acquisition error") },
-/*       S      */{SST(0x61, 0x01, SS_RDEF,
-			"Unable to acquire video") },
-/*       S      */{SST(0x61, 0x02, SS_RDEF,
-			"Out of focus") },
-/*       S      */{SST(0x62, 0x00, SS_RDEF,
-			"Scan head positioning error") },
-/*      R       */{SST(0x63, 0x00, SS_RDEF,
-			"End of user area encountered on this track") },
-/*      R       */{SST(0x63, 0x01, SS_FATAL|ENOSPC,
-			"Packet does not fit in available space") },
-/*      R       */{SST(0x64, 0x00, SS_RDEF,
-			"Illegal mode for this track") },
-/*      R       */{SST(0x64, 0x01, SS_RDEF,
-			"Invalid packet size") },
-/* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF,
-			"Voltage fault") },
-/*       S      */{SST(0x66, 0x00, SS_RDEF,
-			"Automatic document feeder cover up") },
-/*       S      */{SST(0x66, 0x01, SS_RDEF,
-			"Automatic document feeder lift up") },
-/*       S      */{SST(0x66, 0x02, SS_RDEF,
-			"Document jam in automatic document feeder") },
-/*       S      */{SST(0x66, 0x03, SS_RDEF,
-			"Document miss feed automatic in document feeder") },
-/*           A  */{SST(0x67, 0x00, SS_RDEF,
-			"Configuration failure") },
-/*           A  */{SST(0x67, 0x01, SS_RDEF,
-			"Configuration of incapable logical units failed") },
-/*           A  */{SST(0x67, 0x02, SS_RDEF,
-			"Add logical unit failed") },
-/*           A  */{SST(0x67, 0x03, SS_RDEF,
-			"Modification of logical unit failed") },
-/*           A  */{SST(0x67, 0x04, SS_RDEF,
-			"Exchange of logical unit failed") },
-/*           A  */{SST(0x67, 0x05, SS_RDEF,
-			"Remove of logical unit failed") },
-/*           A  */{SST(0x67, 0x06, SS_RDEF,
-			"Attachment of logical unit failed") },
-/*           A  */{SST(0x67, 0x07, SS_RDEF,
-			"Creation of logical unit failed") },
-/*           A  */{SST(0x68, 0x00, SS_RDEF,
-			"Logical unit not configured") },
-/*           A  */{SST(0x69, 0x00, SS_RDEF,
-			"Data loss on logical unit") },
-/*           A  */{SST(0x69, 0x01, SS_RDEF,
-			"Multiple logical unit failures") },
-/*           A  */{SST(0x69, 0x02, SS_RDEF,
-			"Parity/data mismatch") },
-/*           A  */{SST(0x6A, 0x00, SS_RDEF,
-			"Informational, refer to log") },
-/*           A  */{SST(0x6B, 0x00, SS_RDEF,
-			"State change has occurred") },
-/*           A  */{SST(0x6B, 0x01, SS_RDEF,
-			"Redundancy level got better") },
-/*           A  */{SST(0x6B, 0x02, SS_RDEF,
-			"Redundancy level got worse") },
-/*           A  */{SST(0x6C, 0x00, SS_RDEF,
-			"Rebuild failure occurred") },
-/*           A  */{SST(0x6D, 0x00, SS_RDEF,
-			"Recalculate failure occurred") },
-/*           A  */{SST(0x6E, 0x00, SS_RDEF,
-			"Command to logical unit failed") },
-/*  T           */{SST(0x70, 0x00, SS_RDEF,
-			"Decompression exception short: ASCQ = Algorithm ID") },
-/*  T           */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE,
-			NULL) }, /* Range 0x00 -> 0xFF */
-/*  T           */{SST(0x71, 0x00, SS_RDEF,
-			"Decompression exception long: ASCQ = Algorithm ID") },
-/*  T           */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE,
-			NULL) }, /* Range 0x00 -> 0xFF */	
-/*      R       */{SST(0x72, 0x00, SS_RDEF,
-			"Session fixation error") },
-/*      R       */{SST(0x72, 0x01, SS_RDEF,
-			"Session fixation error writing lead-in") },
-/*      R       */{SST(0x72, 0x02, SS_RDEF,
-			"Session fixation error writing lead-out") },
-/*      R       */{SST(0x72, 0x03, SS_RDEF,
-			"Session fixation error - incomplete track in session") },
-/*      R       */{SST(0x72, 0x04, SS_RDEF,
-			"Empty or partially written reserved track") },
-/*      R       */{SST(0x73, 0x00, SS_RDEF,
-			"CD control error") },
-/*      R       */{SST(0x73, 0x01, SS_RDEF,
-			"Power calibration area almost full") },
-/*      R       */{SST(0x73, 0x02, SS_FATAL|ENOSPC,
-			"Power calibration area is full") },
-/*      R       */{SST(0x73, 0x03, SS_RDEF,
-			"Power calibration area error") },
-/*      R       */{SST(0x73, 0x04, SS_RDEF,
-			"Program memory area update failure") },
-/*      R       */{SST(0x73, 0x05, SS_RDEF,
-			"program memory area is full") }
-};
-
-static const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
-
-struct asc_key
-{
-	int asc;
-	int ascq;
-};
-
-static int
-ascentrycomp(const void *key, const void *member)
-{
-	int asc;
-	int ascq;
-	const struct asc_table_entry *table_entry;
-
-	asc = ((const struct asc_key *)key)->asc;
-	ascq = ((const struct asc_key *)key)->ascq;
-	table_entry = (const struct asc_table_entry *)member;
-
-	if (asc >= table_entry->asc) {
-
-		if (asc > table_entry->asc)
-			return (1);
-
-		if (ascq <= table_entry->ascq) {
-			/* Check for ranges */
-			if (ascq == table_entry->ascq
-		 	 || ((table_entry->action & SSQ_RANGE) != 0
-		  	   && ascq >= (table_entry - 1)->ascq))
-				return (0);
-			return (-1);
-		}
-		return (1);
-	}
-	return (-1);
-}
-
-static int
-senseentrycomp(const void *key, const void *member)
-{
-	int sense_key;
-	const struct sense_key_table_entry *table_entry;
-
-	sense_key = *((const int *)key);
-	table_entry = (const struct sense_key_table_entry *)member;
-
-	if (sense_key >= table_entry->sense_key) {
-		if (sense_key == table_entry->sense_key)
-			return (0);
-		return (1);
-	}
-	return (-1);
-}
-
-static void
-fetchtableentries(int sense_key, int asc, int ascq,
-		  struct scsi_inquiry_data *inq_data,
-		  const struct sense_key_table_entry **sense_entry,
-		  const struct asc_table_entry **asc_entry)
-{
-	void *match;
-	const struct asc_table_entry *asc_tables[2];
-	const struct sense_key_table_entry *sense_tables[2];
-	struct asc_key asc_ascq;
-	size_t asc_tables_size[2];
-	size_t sense_tables_size[2];
-	int num_asc_tables;
-	int num_sense_tables;
-	int i;
-
-	/* Default to failure */
-	*sense_entry = NULL;
-	*asc_entry = NULL;
-	match = NULL;
-	if (inq_data != NULL)
-		match = cam_quirkmatch((void *)inq_data,
-				       (void *)sense_quirk_table,
-				       sense_quirk_table_size,
-				       sizeof(*sense_quirk_table),
-				       aic_inquiry_match);
-
-	if (match != NULL) {
-		struct scsi_sense_quirk_entry *quirk;
-
-		quirk = (struct scsi_sense_quirk_entry *)match;
-		asc_tables[0] = quirk->asc_info;
-		asc_tables_size[0] = quirk->num_ascs;
-		asc_tables[1] = asc_table;
-		asc_tables_size[1] = asc_table_size;
-		num_asc_tables = 2;
-		sense_tables[0] = quirk->sense_key_info;
-		sense_tables_size[0] = quirk->num_sense_keys;
-		sense_tables[1] = sense_key_table;
-		sense_tables_size[1] = sense_key_table_size;
-		num_sense_tables = 2;
-	} else {
-		asc_tables[0] = asc_table;
-		asc_tables_size[0] = asc_table_size;
-		num_asc_tables = 1;
-		sense_tables[0] = sense_key_table;
-		sense_tables_size[0] = sense_key_table_size;
-		num_sense_tables = 1;
-	}
-
-	asc_ascq.asc = asc;
-	asc_ascq.ascq = ascq;
-	for (i = 0; i < num_asc_tables; i++) {
-		void *found_entry;
-
-		found_entry = scsibsearch(&asc_ascq, asc_tables[i],
-					  asc_tables_size[i],
-					  sizeof(**asc_tables),
-					  ascentrycomp);
-
-		if (found_entry) {
-			*asc_entry = (struct asc_table_entry *)found_entry;
-			break;
-		}
-	}
-
-	for (i = 0; i < num_sense_tables; i++) {
-		void *found_entry;
-
-		found_entry = scsibsearch(&sense_key, sense_tables[i],
-					  sense_tables_size[i],
-					  sizeof(**sense_tables),
-					  senseentrycomp);
-
-		if (found_entry) {
-			*sense_entry =
-			    (struct sense_key_table_entry *)found_entry;
-			break;
-		}
-	}
-}
-
-static void *
-scsibsearch(const void *key, const void *base, size_t nmemb, size_t size,
-		 int (*compar)(const void *, const void *))
-{
-	const void *entry;
-	u_int l;
-	u_int u;
-	u_int m;
-
-	l = -1;
-	u = nmemb;
-	while (l + 1 != u) {
-		m = (l + u) / 2;
-		entry = base + m * size;
-		if (compar(key, entry) > 0)
-			l = m;
-		else
-			u = m;
-	}
-
-	entry = base + u * size;
-	if (u == nmemb
-	 || compar(key, entry) != 0)
-		return (NULL);
-
-	return ((void *)entry);
-}
-
-/*
- * Compare string with pattern, returning 0 on match.
- * Short pattern matches trailing blanks in name,
- * wildcard '*' in pattern matches rest of name,
- * wildcard '?' matches a single non-space character.
- */
-static int
-cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len)
-{
-
-	while (*pattern != '\0'&& str_len > 0) {  
-
-		if (*pattern == '*') {
-			return (0);
-		}
-		if ((*pattern != *str)
-		 && (*pattern != '?' || *str == ' ')) {
-			return (1);
-		}
-		pattern++;
-		str++;
-		str_len--;
-	}
-	while (str_len > 0 && *str++ == ' ')
-		str_len--;
-
-	return (str_len);
-}
-
-static caddr_t
-cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
-	       int entry_size, cam_quirkmatch_t *comp_func)
-{
-	for (; num_entries > 0; num_entries--, quirk_table += entry_size) {
-		if ((*comp_func)(target, quirk_table) == 0)
-			return (quirk_table);
-	}
-	return (NULL);
-}
-
-void
-aic_sense_desc(int sense_key, int asc, int ascq,
-	       struct scsi_inquiry_data *inq_data,
-	       const char **sense_key_desc, const char **asc_desc)
-{
-	const struct asc_table_entry *asc_entry;
-	const struct sense_key_table_entry *sense_entry;
-
-	fetchtableentries(sense_key, asc, ascq,
-			  inq_data,
-			  &sense_entry,
-			  &asc_entry);
-
-	*sense_key_desc = sense_entry->desc;
-
-	if (asc_entry != NULL)
-		*asc_desc = asc_entry->desc;
-	else if (asc >= 0x80 && asc <= 0xff)
-		*asc_desc = "Vendor Specific ASC";
-	else if (ascq >= 0x80 && ascq <= 0xff)
-		*asc_desc = "Vendor Specific ASCQ";
-	else
-		*asc_desc = "Reserved ASC/ASCQ pair";
-}
-
-/*
- * Given sense and device type information, return the appropriate action.
- * If we do not understand the specific error as identified by the ASC/ASCQ
- * pair, fall back on the more generic actions derived from the sense key.
- */
-aic_sense_action
-aic_sense_error_action(struct scsi_sense_data *sense_data,
-		       struct scsi_inquiry_data *inq_data, uint32_t sense_flags)
-{
-	const struct asc_table_entry *asc_entry;
-	const struct sense_key_table_entry *sense_entry;
-	int error_code, sense_key, asc, ascq;
-	aic_sense_action action;
-
-	scsi_extract_sense(sense_data, &error_code, &sense_key, &asc, &ascq);
-
-	if (error_code == SSD_DEFERRED_ERROR) {
-		/*
-		 * XXX dufault@FreeBSD.org
-		 * This error doesn't relate to the command associated
-		 * with this request sense.  A deferred error is an error
-		 * for a command that has already returned GOOD status
-		 * (see SCSI2 8.2.14.2).
-		 *
-		 * By my reading of that section, it looks like the current
-		 * command has been cancelled, we should now clean things up
-		 * (hopefully recovering any lost data) and then retry the
-		 * current command.  There are two easy choices, both wrong:
-		 *
-		 * 1. Drop through (like we had been doing), thus treating
-		 *    this as if the error were for the current command and
-		 *    return and stop the current command.
-		 * 
-		 * 2. Issue a retry (like I made it do) thus hopefully
-		 *    recovering the current transfer, and ignoring the
-		 *    fact that we've dropped a command.
-		 *
-		 * These should probably be handled in a device specific
-		 * sense handler or punted back up to a user mode daemon
-		 */
-		action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
-	} else {
-		fetchtableentries(sense_key, asc, ascq,
-				  inq_data,
-				  &sense_entry,
-				  &asc_entry);
-
-		/*
-		 * Override the 'No additional Sense' entry (0,0)
-		 * with the error action of the sense key.
-		 */
-		if (asc_entry != NULL
-		 && (asc != 0 || ascq != 0))
-			action = asc_entry->action;
-		else
-			action = sense_entry->action;
-
-		if (sense_key == SSD_KEY_RECOVERED_ERROR) {
-			/*
-			 * The action succeeded but the device wants
-			 * the user to know that some recovery action
-			 * was required.
-			 */
-			action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
-			action |= SS_NOP|SSQ_PRINT_SENSE;
-		} else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
-			if ((sense_flags & SF_QUIET_IR) != 0)
-				action &= ~SSQ_PRINT_SENSE;
-		} else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
-			if ((sense_flags & SF_RETRY_UA) != 0
-			 && (action & SS_MASK) == SS_FAIL) {
-				action &= ~(SS_MASK|SSQ_MASK);
-				action |= SS_RETRY|SSQ_DECREMENT_COUNT|
-					  SSQ_PRINT_SENSE;
-			}
-		}
-	}
-
-	if ((sense_flags & SF_PRINT_ALWAYS) != 0)
-		action |= SSQ_PRINT_SENSE;
-	else if ((sense_flags & SF_NO_PRINT) != 0)
-		action &= ~SSQ_PRINT_SENSE;
-
-	return (action);
-}
-
-/*      
- * Try make as good a match as possible with
- * available sub drivers
- */
-int
-aic_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
-{
-	struct scsi_inquiry_pattern *entry;
-	struct scsi_inquiry_data *inq;
- 
-	entry = (struct scsi_inquiry_pattern *)table_entry;
-	inq = (struct scsi_inquiry_data *)inqbuffer;
-
-	if (((SID_TYPE(inq) == entry->type)
-	  || (entry->type == T_ANY))
-	 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
-				   : entry->media_type & SIP_MEDIA_FIXED)
-	 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
-	 && (cam_strmatch(inq->product, entry->product,
-			  sizeof(inq->product)) == 0)
-	 && (cam_strmatch(inq->revision, entry->revision,
-			  sizeof(inq->revision)) == 0)) {
-		return (0);
-	}
-        return (-1);
-}
-
-/*
- * Table of syncrates that don't follow the "divisible by 4"
- * rule. This table will be expanded in future SCSI specs.
- */
-static struct {
-	u_int period_factor;
-	u_int period;	/* in 100ths of ns */
-} scsi_syncrates[] = {
-	{ 0x08, 625 },	/* FAST-160 */
-	{ 0x09, 1250 },	/* FAST-80 */
-	{ 0x0a, 2500 },	/* FAST-40 40MHz */
-	{ 0x0b, 3030 },	/* FAST-40 33MHz */
-	{ 0x0c, 5000 }	/* FAST-20 */
-};
-
-/*
- * Return the frequency in kHz corresponding to the given
- * sync period factor.
- */
-u_int
-aic_calc_syncsrate(u_int period_factor)
-{
-	int i;
-	int num_syncrates;
-
-	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
-	/* See if the period is in the "exception" table */
-	for (i = 0; i < num_syncrates; i++) {
-
-		if (period_factor == scsi_syncrates[i].period_factor) {
-			/* Period in kHz */
-			return (100000000 / scsi_syncrates[i].period);
-		}
-	}
-
-	/*
-	 * Wasn't in the table, so use the standard
-	 * 4 times conversion.
-	 */
-	return (10000000 / (period_factor * 4 * 10));
-}
-
-/*
- * Return speed in KB/s.
- */
-u_int
-aic_calc_speed(u_int width, u_int period, u_int offset, u_int min_rate)
-{
-	u_int freq;
-
-	if (offset != 0 && period < min_rate)
-		freq  = aic_calc_syncsrate(period);
-	else
-		/* Roughly 3.3MB/s for async */
-		freq  = 3300;
-	freq <<= width;
-	return (freq);
-}
-
-uint32_t
-aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,
-		 cam_status status, u_int scsi_status)
-{
-	aic_sense_action  err_action;
-	int		  sense;
-
-	sense  = (cmd->result >> 24) == DRIVER_SENSE;
-
-	switch (status) {
-	case CAM_REQ_CMP:
-		err_action = SS_NOP;
-		break;
-	case CAM_AUTOSENSE_FAIL:
-	case CAM_SCSI_STATUS_ERROR:
-
-		switch (scsi_status) {
-		case SCSI_STATUS_OK:
-		case SCSI_STATUS_COND_MET:
-		case SCSI_STATUS_INTERMED:
-		case SCSI_STATUS_INTERMED_COND_MET:
-			err_action = SS_NOP;
-			break;
-		case SCSI_STATUS_CMD_TERMINATED:
-		case SCSI_STATUS_CHECK_COND:
-			if (sense != 0) {
-				struct scsi_sense_data *sense;
-
-				sense = (struct scsi_sense_data *)
-				    &cmd->sense_buffer;
-				err_action =
-				    aic_sense_error_action(sense, inq_data, 0);
-
-			} else {
-				err_action = SS_RETRY|SSQ_FALLBACK
-					   | SSQ_DECREMENT_COUNT|EIO;
-			}
-			break;
-		case SCSI_STATUS_QUEUE_FULL:
-		case SCSI_STATUS_BUSY:
-			err_action = SS_RETRY|SSQ_DELAY|SSQ_MANY
-				   | SSQ_DECREMENT_COUNT|EBUSY;
-			break;
-		case SCSI_STATUS_RESERV_CONFLICT:
-		default:
-			err_action = SS_FAIL|EBUSY;
-			break;
-		}
-		break;
-	case CAM_CMD_TIMEOUT:
-	case CAM_REQ_CMP_ERR:
-	case CAM_UNEXP_BUSFREE:
-	case CAM_UNCOR_PARITY:
-	case CAM_DATA_RUN_ERR:
-		err_action = SS_RETRY|SSQ_FALLBACK|EIO;
-		break;
-	case CAM_UA_ABORT:
-	case CAM_UA_TERMIO:
-	case CAM_MSG_REJECT_REC:
-	case CAM_SEL_TIMEOUT:
-		err_action = SS_FAIL|EIO;
-		break;
-	case CAM_REQ_INVALID:
-	case CAM_PATH_INVALID:
-	case CAM_DEV_NOT_THERE:
-	case CAM_NO_HBA:
-	case CAM_PROVIDE_FAIL:
-	case CAM_REQ_TOO_BIG:		
-	case CAM_RESRC_UNAVAIL:
-	case CAM_BUSY:
-	default:
-		/* panic??  These should never occur in our application. */
-		err_action = SS_FAIL|EIO;
-		break;
-	case CAM_SCSI_BUS_RESET:
-	case CAM_BDR_SENT:		
-	case CAM_REQUEUE_REQ:
-		/* Unconditional requeue */
-		err_action = SS_RETRY;
-		break;
-	}
-
-	return (err_action);
-}
-
-char *
-aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
-		       aic_option_callback_t *callback, u_long callback_arg)
-{
-	char	*tok_end;
-	char	*tok_end2;
-	int      i;
-	int      instance;
-	int	 targ;
-	int	 done;
-	char	 tok_list[] = {'.', ',', '{', '}', '\0'};
 
-	/* All options use a ':' name/arg separator */
-	if (*opt_arg != ':')
-		return (opt_arg);
-	opt_arg++;
-	instance = -1;
-	targ = -1;
-	done = FALSE;
-	/*
-	 * Restore separator that may be in
-	 * the middle of our option argument.
-	 */
-	tok_end = strchr(opt_arg, '\0');
-	if (tok_end < end)
-		*tok_end = ',';
-	while (!done) {
-		switch (*opt_arg) {
-		case '{':
-			if (instance == -1) {
-				instance = 0;
-			} else {
-				if (depth > 1) {
-					if (targ == -1)
-						targ = 0;
-				} else {
-					printf("Malformed Option %s\n",
-					       opt_name);
-					done = TRUE;
-				}
-			}
-			opt_arg++;
-			break;
-		case '}':
-			if (targ != -1)
-				targ = -1;
-			else if (instance != -1)
-				instance = -1;
-			opt_arg++;
-			break;
-		case ',':
-		case '.':
-			if (instance == -1)
-				done = TRUE;
-			else if (targ >= 0)
-				targ++;
-			else if (instance >= 0)
-				instance++;
-			opt_arg++;
-			break;
-		case '\0':
-			done = TRUE;
-			break;
-		default:
-			tok_end = end;
-			for (i = 0; tok_list[i]; i++) {
-				tok_end2 = strchr(opt_arg, tok_list[i]);
-				if ((tok_end2) && (tok_end2 < tok_end))
-					tok_end = tok_end2;
-			}
-			callback(callback_arg, instance, targ,
-				 simple_strtol(opt_arg, NULL, 0));
-			opt_arg = tok_end;
-			break;
-		}
-	}
-	return (opt_arg);
-}
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h
--- a/drivers/scsi/aic7xxx/aiclib.h
+++ b/drivers/scsi/aic7xxx/aiclib.h
@@ -57,121 +57,6 @@
 #ifndef	_AICLIB_H
 #define _AICLIB_H
 
-/*
- * Linux Interrupt Support.
- */
-#ifndef IRQ_RETVAL
-typedef void irqreturn_t;
-#define	IRQ_RETVAL(x)
-#endif
-
-/*
- * SCSI command format
- */
-
-/*
- * Define dome bits that are in ALL (or a lot of) scsi commands
- */
-#define SCSI_CTL_LINK		0x01
-#define SCSI_CTL_FLAG		0x02
-#define SCSI_CTL_VENDOR		0xC0
-#define	SCSI_CMD_LUN		0xA0	/* these two should not be needed */
-#define	SCSI_CMD_LUN_SHIFT	5	/* LUN in the cmd is no longer SCSI */
-
-#define SCSI_MAX_CDBLEN		16	/* 
-					 * 16 byte commands are in the 
-					 * SCSI-3 spec 
-					 */
-/* 6byte CDBs special case 0 length to be 256 */
-#define SCSI_CDB6_LEN(len)	((len) == 0 ? 256 : len)
-
-/*
- * This type defines actions to be taken when a particular sense code is
- * received.  Right now, these flags are only defined to take up 16 bits,
- * but can be expanded in the future if necessary.
- */
-typedef enum {
-	SS_NOP		= 0x000000, /* Do nothing */
-	SS_RETRY	= 0x010000, /* Retry the command */
-	SS_FAIL		= 0x020000, /* Bail out */
-	SS_START	= 0x030000, /* Send a Start Unit command to the device,
-				     * then retry the original command.
-				     */
-	SS_TUR		= 0x040000, /* Send a Test Unit Ready command to the
-				     * device, then retry the original command.
-				     */
-	SS_REQSENSE	= 0x050000, /* Send a RequestSense command to the
-				     * device, then retry the original command.
-				     */
-	SS_INQ_REFRESH	= 0x060000,
-	SS_MASK		= 0xff0000
-} aic_sense_action;
-
-typedef enum {
-	SSQ_NONE		= 0x0000,
-	SSQ_DECREMENT_COUNT	= 0x0100,  /* Decrement the retry count */
-	SSQ_MANY		= 0x0200,  /* send lots of recovery commands */
-	SSQ_RANGE		= 0x0400,  /*
-					    * This table entry represents the
-					    * end of a range of ASCQs that
-					    * have identical error actions
-					    * and text.
-					    */
-	SSQ_PRINT_SENSE		= 0x0800,
-	SSQ_DELAY		= 0x1000,  /* Delay before retry. */
-	SSQ_DELAY_RANDOM	= 0x2000,  /* Randomized delay before retry. */
-	SSQ_FALLBACK		= 0x4000,  /* Do a speed fallback to recover */
-	SSQ_MASK		= 0xff00
-} aic_sense_action_qualifier;
-
-/* Mask for error status values */
-#define SS_ERRMASK	0xff
-
-/* The default, retyable, error action */
-#define SS_RDEF		SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO
-
-/* The retyable, error action, with table specified error code */
-#define SS_RET		SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE
-
-/* Fatal error action, with table specified error code */
-#define SS_FATAL	SS_FAIL|SSQ_PRINT_SENSE
-
-struct scsi_generic
-{
-	uint8_t opcode;
-	uint8_t bytes[11];
-};
-
-struct scsi_request_sense
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t unused[2];
-	uint8_t length;
-	uint8_t control;
-};
-
-struct scsi_test_unit_ready
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t unused[3];
-	uint8_t control;
-};
-
-struct scsi_send_diag
-{
-	uint8_t opcode;
-	uint8_t byte2;
-#define	SSD_UOL		0x01
-#define	SSD_DOL		0x02
-#define	SSD_SELFTEST	0x04
-#define	SSD_PF		0x10
-	uint8_t unused[1];
-	uint8_t paramlen[2];
-	uint8_t control;
-};
-
 struct scsi_sense
 {
 	uint8_t opcode;
@@ -181,537 +66,12 @@ struct scsi_sense
 	uint8_t control;
 };
 
-struct scsi_inquiry
-{
-	uint8_t opcode;
-	uint8_t byte2;
-#define	SI_EVPD 0x01
-	uint8_t page_code;
-	uint8_t reserved;
-	uint8_t length;
-	uint8_t control;
-};
-
-struct scsi_mode_sense_6
-{
-	uint8_t opcode;
-	uint8_t byte2;
-#define	SMS_DBD				0x08
-	uint8_t page;
-#define	SMS_PAGE_CODE 			0x3F
-#define SMS_VENDOR_SPECIFIC_PAGE	0x00
-#define SMS_DISCONNECT_RECONNECT_PAGE	0x02
-#define SMS_PERIPHERAL_DEVICE_PAGE	0x09
-#define SMS_CONTROL_MODE_PAGE		0x0A
-#define SMS_ALL_PAGES_PAGE		0x3F
-#define	SMS_PAGE_CTRL_MASK		0xC0
-#define	SMS_PAGE_CTRL_CURRENT 		0x00
-#define	SMS_PAGE_CTRL_CHANGEABLE 	0x40
-#define	SMS_PAGE_CTRL_DEFAULT 		0x80
-#define	SMS_PAGE_CTRL_SAVED 		0xC0
-	uint8_t unused;
-	uint8_t length;
-	uint8_t control;
-};
-
-struct scsi_mode_sense_10
-{
-	uint8_t opcode;
-	uint8_t byte2;		/* same bits as small version */
-	uint8_t page; 		/* same bits as small version */
-	uint8_t unused[4];
-	uint8_t length[2];
-	uint8_t control;
-};
-
-struct scsi_mode_select_6
-{
-	uint8_t opcode;
-	uint8_t byte2;
-#define	SMS_SP	0x01
-#define	SMS_PF	0x10
-	uint8_t unused[2];
-	uint8_t length;
-	uint8_t control;
-};
-
-struct scsi_mode_select_10
-{
-	uint8_t opcode;
-	uint8_t byte2;		/* same bits as small version */
-	uint8_t unused[5];
-	uint8_t length[2];
-	uint8_t control;
-};
-
-/*
- * When sending a mode select to a tape drive, the medium type must be 0.
- */
-struct scsi_mode_hdr_6
-{
-	uint8_t datalen;
-	uint8_t medium_type;
-	uint8_t dev_specific;
-	uint8_t block_descr_len;
-};
-
-struct scsi_mode_hdr_10
-{
-	uint8_t datalen[2];
-	uint8_t medium_type;
-	uint8_t dev_specific;
-	uint8_t reserved[2];
-	uint8_t block_descr_len[2];
-};
-
-struct scsi_mode_block_descr
-{
-	uint8_t density_code;
-	uint8_t num_blocks[3];
-	uint8_t reserved;
-	uint8_t block_len[3];
-};
-
-struct scsi_log_sense
-{
-	uint8_t opcode;
-	uint8_t byte2;
-#define	SLS_SP				0x01
-#define	SLS_PPC				0x02
-	uint8_t page;
-#define	SLS_PAGE_CODE 			0x3F
-#define	SLS_ALL_PAGES_PAGE		0x00
-#define	SLS_OVERRUN_PAGE		0x01
-#define	SLS_ERROR_WRITE_PAGE		0x02
-#define	SLS_ERROR_READ_PAGE		0x03
-#define	SLS_ERROR_READREVERSE_PAGE	0x04
-#define	SLS_ERROR_VERIFY_PAGE		0x05
-#define	SLS_ERROR_NONMEDIUM_PAGE	0x06
-#define	SLS_ERROR_LASTN_PAGE		0x07
-#define	SLS_PAGE_CTRL_MASK		0xC0
-#define	SLS_PAGE_CTRL_THRESHOLD		0x00
-#define	SLS_PAGE_CTRL_CUMULATIVE	0x40
-#define	SLS_PAGE_CTRL_THRESH_DEFAULT	0x80
-#define	SLS_PAGE_CTRL_CUMUL_DEFAULT	0xC0
-	uint8_t reserved[2];
-	uint8_t paramptr[2];
-	uint8_t length[2];
-	uint8_t control;
-};
-
-struct scsi_log_select
-{
-	uint8_t opcode;
-	uint8_t byte2;
-/*	SLS_SP				0x01 */
-#define	SLS_PCR				0x02
-	uint8_t page;
-/*	SLS_PAGE_CTRL_MASK		0xC0 */
-/*	SLS_PAGE_CTRL_THRESHOLD		0x00 */
-/*	SLS_PAGE_CTRL_CUMULATIVE	0x40 */
-/*	SLS_PAGE_CTRL_THRESH_DEFAULT	0x80 */
-/*	SLS_PAGE_CTRL_CUMUL_DEFAULT	0xC0 */
-	uint8_t reserved[4];
-	uint8_t length[2];
-	uint8_t control;
-};
-
-struct scsi_log_header
-{
-	uint8_t page;
-	uint8_t reserved;
-	uint8_t datalen[2];
-};
-
-struct scsi_log_param_header {
-	uint8_t param_code[2];
-	uint8_t param_control;
-#define	SLP_LP				0x01
-#define	SLP_LBIN			0x02
-#define	SLP_TMC_MASK			0x0C
-#define	SLP_TMC_ALWAYS			0x00
-#define	SLP_TMC_EQUAL			0x04
-#define	SLP_TMC_NOTEQUAL		0x08
-#define	SLP_TMC_GREATER			0x0C
-#define	SLP_ETC				0x10
-#define	SLP_TSD				0x20
-#define	SLP_DS				0x40
-#define	SLP_DU				0x80
-	uint8_t param_len;
-};
-
-struct scsi_control_page {
-	uint8_t page_code;
-	uint8_t page_length;
-	uint8_t rlec;
-#define SCB_RLEC			0x01	/*Report Log Exception Cond*/
-	uint8_t queue_flags;
-#define SCP_QUEUE_ALG_MASK		0xF0
-#define SCP_QUEUE_ALG_RESTRICTED	0x00
-#define SCP_QUEUE_ALG_UNRESTRICTED	0x10
-#define SCP_QUEUE_ERR			0x02	/*Queued I/O aborted for CACs*/
-#define SCP_QUEUE_DQUE			0x01	/*Queued I/O disabled*/
-	uint8_t eca_and_aen;
-#define SCP_EECA			0x80	/*Enable Extended CA*/
-#define SCP_RAENP			0x04	/*Ready AEN Permission*/
-#define SCP_UAAENP			0x02	/*UA AEN Permission*/
-#define SCP_EAENP			0x01	/*Error AEN Permission*/
-	uint8_t reserved;
-	uint8_t aen_holdoff_period[2];
-};
-
-struct scsi_reserve
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t unused[2];
-	uint8_t length;
-	uint8_t control;
-};
-
-struct scsi_release
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t unused[2];
-	uint8_t length;
-	uint8_t control;
-};
-
-struct scsi_prevent
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t unused[2];
-	uint8_t how;
-	uint8_t control;
-};
-#define	PR_PREVENT 0x01
-#define PR_ALLOW   0x00
-
-struct scsi_sync_cache
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t begin_lba[4];
-	uint8_t reserved;
-	uint8_t lb_count[2];
-	uint8_t control;	
-};
-
-
-struct scsi_changedef
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t unused1;
-	uint8_t how;
-	uint8_t unused[4];
-	uint8_t datalen;
-	uint8_t control;
-};
-
-struct scsi_read_buffer
-{
-	uint8_t opcode;
-	uint8_t byte2;
-#define	RWB_MODE		0x07
-#define	RWB_MODE_HDR_DATA	0x00
-#define	RWB_MODE_DATA		0x02
-#define	RWB_MODE_DOWNLOAD	0x04
-#define	RWB_MODE_DOWNLOAD_SAVE	0x05
-        uint8_t buffer_id;
-        uint8_t offset[3];
-        uint8_t length[3];
-        uint8_t control;
-};
-
-struct scsi_write_buffer
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t buffer_id;
-	uint8_t offset[3];
-	uint8_t length[3];
-	uint8_t control;
-};
-
-struct scsi_rw_6
-{
-	uint8_t opcode;
-	uint8_t addr[3];
-/* only 5 bits are valid in the MSB address byte */
-#define	SRW_TOPADDR	0x1F
-	uint8_t length;
-	uint8_t control;
-};
-
-struct scsi_rw_10
-{
-	uint8_t opcode;
-#define	SRW10_RELADDR	0x01
-#define SRW10_FUA	0x08
-#define	SRW10_DPO	0x10
-	uint8_t byte2;
-	uint8_t addr[4];
-	uint8_t reserved;
-	uint8_t length[2];
-	uint8_t control;
-};
-
-struct scsi_rw_12
-{
-	uint8_t opcode;
-#define	SRW12_RELADDR	0x01
-#define SRW12_FUA	0x08
-#define	SRW12_DPO	0x10
-	uint8_t byte2;
-	uint8_t addr[4];
-	uint8_t length[4];
-	uint8_t reserved;
-	uint8_t control;
-};
-
-struct scsi_start_stop_unit
-{
-	uint8_t opcode;
-	uint8_t byte2;
-#define	SSS_IMMED		0x01
-	uint8_t reserved[2];
-	uint8_t how;
-#define	SSS_START		0x01
-#define	SSS_LOEJ		0x02
-	uint8_t control;
-};
-
-#define SC_SCSI_1 0x01
-#define SC_SCSI_2 0x03
-
-/*
- * Opcodes
- */
-
-#define	TEST_UNIT_READY		0x00
-#define REQUEST_SENSE		0x03
-#define	READ_6			0x08
-#define WRITE_6			0x0a
-#define INQUIRY			0x12
-#define MODE_SELECT_6		0x15
-#define MODE_SENSE_6		0x1a
-#define START_STOP_UNIT		0x1b
-#define START_STOP		0x1b
-#define RESERVE      		0x16
-#define RELEASE      		0x17
-#define	RECEIVE_DIAGNOSTIC	0x1c
-#define	SEND_DIAGNOSTIC		0x1d
-#define PREVENT_ALLOW		0x1e
-#define	READ_CAPACITY		0x25
-#define	READ_10			0x28
-#define WRITE_10		0x2a
-#define POSITION_TO_ELEMENT	0x2b
-#define	SYNCHRONIZE_CACHE	0x35
-#define	WRITE_BUFFER            0x3b
-#define	READ_BUFFER             0x3c
-#define	CHANGE_DEFINITION	0x40
-#define	LOG_SELECT		0x4c
-#define	LOG_SENSE		0x4d
-#ifdef XXXCAM
-#define	MODE_SENSE_10		0x5A
-#endif
-#define	MODE_SELECT_10		0x55
-#define MOVE_MEDIUM     	0xa5
-#define READ_12			0xa8
-#define WRITE_12		0xaa
-#define READ_ELEMENT_STATUS	0xb8
-
-
-/*
- * Device Types
- */
-#define T_DIRECT	0x00
-#define T_SEQUENTIAL	0x01
-#define T_PRINTER	0x02
-#define T_PROCESSOR	0x03
-#define T_WORM		0x04
-#define T_CDROM		0x05
-#define T_SCANNER 	0x06
-#define T_OPTICAL 	0x07
-#define T_CHANGER	0x08
-#define T_COMM		0x09
-#define T_ASC0		0x0a
-#define T_ASC1		0x0b
-#define	T_STORARRAY	0x0c
-#define	T_ENCLOSURE	0x0d
-#define	T_RBC		0x0e
-#define	T_OCRW		0x0f
-#define T_NODEVICE	0x1F
-#define	T_ANY		0xFF	/* Used in Quirk table matches */
-
-#define T_REMOV		1
-#define	T_FIXED		0
-
-/*
- * This length is the initial inquiry length used by the probe code, as    
- * well as the legnth necessary for aic_print_inquiry() to function 
- * correctly.  If either use requires a different length in the future, 
- * the two values should be de-coupled.
- */
-#define	SHORT_INQUIRY_LENGTH	36
-
-struct scsi_inquiry_data
-{
-	uint8_t device;
-#define	SID_TYPE(inq_data) ((inq_data)->device & 0x1f)
-#define	SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5)
-#define	SID_QUAL_LU_CONNECTED	0x00	/*
-					 * The specified peripheral device
-					 * type is currently connected to
-					 * logical unit.  If the target cannot
-					 * determine whether or not a physical
-					 * device is currently connected, it
-					 * shall also use this peripheral
-					 * qualifier when returning the INQUIRY
-					 * data.  This peripheral qualifier
-					 * does not mean that the device is
-					 * ready for access by the initiator.
-					 */
-#define	SID_QUAL_LU_OFFLINE	0x01	/*
-					 * The target is capable of supporting
-					 * the specified peripheral device type
-					 * on this logical unit; however, the
-					 * physical device is not currently
-					 * connected to this logical unit.
-					 */
-#define SID_QUAL_RSVD		0x02
-#define	SID_QUAL_BAD_LU		0x03	/*
-					 * The target is not capable of
-					 * supporting a physical device on
-					 * this logical unit. For this
-					 * peripheral qualifier the peripheral
-					 * device type shall be set to 1Fh to
-					 * provide compatibility with previous
-					 * versions of SCSI. All other
-					 * peripheral device type values are
-					 * reserved for this peripheral
-					 * qualifier.
-					 */
-#define	SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0)
-	uint8_t dev_qual2;
-#define	SID_QUAL2	0x7F
-#define	SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0)
-	uint8_t version;
-#define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07)
 #define		SCSI_REV_0		0
 #define		SCSI_REV_CCS		1
 #define		SCSI_REV_2		2
 #define		SCSI_REV_SPC		3
 #define		SCSI_REV_SPC2		4
 
-#define SID_ECMA	0x38
-#define SID_ISO		0xC0
-	uint8_t response_format;
-#define SID_AENC	0x80
-#define SID_TrmIOP	0x40
-	uint8_t additional_length;
-	uint8_t reserved[2];
-	uint8_t flags;
-#define	SID_SftRe	0x01
-#define	SID_CmdQue	0x02
-#define	SID_Linked	0x08
-#define	SID_Sync	0x10
-#define	SID_WBus16	0x20
-#define	SID_WBus32	0x40
-#define	SID_RelAdr	0x80
-#define SID_VENDOR_SIZE   8
-	char	 vendor[SID_VENDOR_SIZE];
-#define SID_PRODUCT_SIZE  16
-	char	 product[SID_PRODUCT_SIZE];
-#define SID_REVISION_SIZE 4
-	char	 revision[SID_REVISION_SIZE];
-	/*
-	 * The following fields were taken from SCSI Primary Commands - 2
-	 * (SPC-2) Revision 14, Dated 11 November 1999
-	 */
-#define	SID_VENDOR_SPECIFIC_0_SIZE	20
-	uint8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE];
-	/*
-	 * An extension of SCSI Parallel Specific Values
-	 */
-#define	SID_SPI_IUS		0x01
-#define	SID_SPI_QAS		0x02
-#define	SID_SPI_CLOCK_ST	0x00
-#define	SID_SPI_CLOCK_DT	0x04
-#define	SID_SPI_CLOCK_DT_ST	0x0C
-#define	SID_SPI_MASK		0x0F
-	uint8_t spi3data;
-	uint8_t reserved2;
-	/*
-	 * Version Descriptors, stored 2 byte values.
-	 */
-	uint8_t version1[2];
-	uint8_t version2[2];
-	uint8_t version3[2];
-	uint8_t version4[2];
-	uint8_t version5[2];
-	uint8_t version6[2];
-	uint8_t version7[2];
-	uint8_t version8[2];
-
-	uint8_t reserved3[22];
-
-#define	SID_VENDOR_SPECIFIC_1_SIZE	160
-	uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE];
-};
-
-struct scsi_vpd_unit_serial_number
-{
-	uint8_t device;
-	uint8_t page_code;
-#define SVPD_UNIT_SERIAL_NUMBER	0x80
-	uint8_t reserved;
-	uint8_t length; /* serial number length */
-#define SVPD_SERIAL_NUM_SIZE 251
-	uint8_t serial_num[SVPD_SERIAL_NUM_SIZE];
-};
-
-struct scsi_read_capacity
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t addr[4];
-	uint8_t unused[3];
-	uint8_t control;
-};
-
-struct scsi_read_capacity_data
-{
-	uint8_t addr[4];
-	uint8_t length[4];
-};
-
-struct scsi_report_luns
-{
-	uint8_t opcode;
-	uint8_t byte2;
-	uint8_t unused[3];
-	uint8_t addr[4];
-	uint8_t control;
-};
-
-struct scsi_report_luns_data {
-	uint8_t length[4];	/* length of LUN inventory, in bytes */
-	uint8_t reserved[4];	/* unused */
-	/*
-	 * LUN inventory- we only support the type zero form for now.
-	 */
-	struct {
-		uint8_t lundata[8];
-	} luns[1];
-};
-#define	RPL_LUNDATA_ATYP_MASK	0xc0	/* MBZ for type 0 lun */
-#define	RPL_LUNDATA_T0LUN	1	/* @ lundata[1] */
-
-
 struct scsi_sense_data
 {
 	uint8_t error_code;
@@ -757,41 +117,6 @@ struct scsi_sense_data
 #define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
 };
 
-struct scsi_mode_header_6
-{
-	uint8_t data_length;	/* Sense data length */
-	uint8_t medium_type;
-	uint8_t dev_spec;
-	uint8_t blk_desc_len;
-};
-
-struct scsi_mode_header_10
-{
-	uint8_t data_length[2];/* Sense data length */
-	uint8_t medium_type;
-	uint8_t dev_spec;
-	uint8_t unused[2];
-	uint8_t blk_desc_len[2];
-};
-
-struct scsi_mode_page_header
-{
-	uint8_t page_code;
-	uint8_t page_length;
-};
-
-struct scsi_mode_blk_desc
-{
-	uint8_t density;
-	uint8_t nblocks[3];
-	uint8_t reserved;
-	uint8_t blklen[3];
-};
-
-#define	SCSI_DEFAULT_DENSITY	0x00	/* use 'default' density */
-#define	SCSI_SAME_DENSITY	0x7f	/* use 'same' density- >= SCSI-2 only */
-
-
 /*
  * Status Byte
  */
@@ -807,76 +132,7 @@ struct scsi_mode_blk_desc
 #define SCSI_STATUS_ACA_ACTIVE		0x30
 #define SCSI_STATUS_TASK_ABORTED	0x40
 
-struct scsi_inquiry_pattern {
-	uint8_t   type;
-	uint8_t   media_type;
-#define	SIP_MEDIA_REMOVABLE	0x01
-#define	SIP_MEDIA_FIXED		0x02
-	const char *vendor;
-	const char *product;
-	const char *revision;
-}; 
-
-struct scsi_static_inquiry_pattern {
-	uint8_t   type;
-	uint8_t   media_type;
-	char       vendor[SID_VENDOR_SIZE+1];
-	char       product[SID_PRODUCT_SIZE+1];
-	char       revision[SID_REVISION_SIZE+1];
-};
-
-struct scsi_sense_quirk_entry {
-	struct scsi_inquiry_pattern	inq_pat;
-	int				num_sense_keys;
-	int				num_ascs;
-	struct sense_key_table_entry	*sense_key_info;
-	struct asc_table_entry		*asc_info;
-};
-
-struct sense_key_table_entry {
-	uint8_t    sense_key;
-	uint32_t   action;
-	const char *desc;
-};
-
-struct asc_table_entry {
-	uint8_t    asc;
-	uint8_t    ascq;
-	uint32_t   action;
-	const char *desc;
-};
-
-struct op_table_entry {
-	uint8_t    opcode;
-	uint16_t   opmask;
-	const char  *desc;
-};
-
-struct scsi_op_quirk_entry {
-	struct scsi_inquiry_pattern	inq_pat;
-	int				num_ops;
-	struct op_table_entry		*op_table;
-};
-
-typedef enum {
-	SSS_FLAG_NONE		= 0x00,
-	SSS_FLAG_PRINT_COMMAND	= 0x01
-} scsi_sense_string_flags;
-
-extern const char *scsi_sense_key_text[];
-
 /************************* Large Disk Handling ********************************/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static __inline int aic_sector_div(u_long capacity, int heads, int sectors);
-
-static __inline int
-aic_sector_div(u_long capacity, int heads, int sectors)
-{
-	return (capacity / (heads * sectors));
-}
-#else
-static __inline int aic_sector_div(sector_t capacity, int heads, int sectors);
-
 static __inline int
 aic_sector_div(sector_t capacity, int heads, int sectors)
 {
@@ -884,152 +140,6 @@ aic_sector_div(sector_t capacity, int he
 	sector_div(capacity, (heads * sectors));
 	return (int)capacity;
 }
-#endif
-
-/**************************** Module Library Hack *****************************/
-/*
- * What we'd like to do is have a single "scsi library" module that both the
- * aic7xxx and aic79xx drivers could load and depend on.  A cursory examination
- * of implementing module dependencies in Linux (handling the install and
- * initrd cases) does not look promissing.  For now, we just duplicate this
- * code in both drivers using a simple symbol renaming scheme that hides this
- * hack from the drivers.
- */
-#define AIC_LIB_ENTRY_CONCAT(x, prefix)	prefix ## x
-#define	AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix)
-#define AIC_LIB_ENTRY(x)		AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX)
-
-#define	aic_sense_desc			AIC_LIB_ENTRY(_sense_desc)
-#define	aic_sense_error_action		AIC_LIB_ENTRY(_sense_error_action)
-#define	aic_error_action		AIC_LIB_ENTRY(_error_action)
-#define	aic_op_desc			AIC_LIB_ENTRY(_op_desc)
-#define	aic_cdb_string			AIC_LIB_ENTRY(_cdb_string)
-#define aic_print_inquiry		AIC_LIB_ENTRY(_print_inquiry)
-#define aic_calc_syncsrate		AIC_LIB_ENTRY(_calc_syncrate)
-#define	aic_calc_syncparam		AIC_LIB_ENTRY(_calc_syncparam)
-#define	aic_calc_speed			AIC_LIB_ENTRY(_calc_speed)
-#define	aic_inquiry_match		AIC_LIB_ENTRY(_inquiry_match)
-#define	aic_static_inquiry_match	AIC_LIB_ENTRY(_static_inquiry_match)
-#define	aic_parse_brace_option		AIC_LIB_ENTRY(_parse_brace_option)
-
-/******************************************************************************/
-
-void			aic_sense_desc(int /*sense_key*/, int /*asc*/,
-				       int /*ascq*/, struct scsi_inquiry_data*,
-				       const char** /*sense_key_desc*/,
-				       const char** /*asc_desc*/);
-aic_sense_action	aic_sense_error_action(struct scsi_sense_data*,
-					       struct scsi_inquiry_data*,
-					       uint32_t /*sense_flags*/);
-uint32_t		aic_error_action(struct scsi_cmnd *,
-					 struct scsi_inquiry_data *,
-					 cam_status, u_int);
-
-#define	SF_RETRY_UA	0x01
-#define SF_NO_PRINT	0x02
-#define SF_QUIET_IR	0x04	/* Be quiet about Illegal Request reponses */
-#define SF_PRINT_ALWAYS	0x08
-
-
-const char *	aic_op_desc(uint16_t /*opcode*/, struct scsi_inquiry_data*);
-char *		aic_cdb_string(uint8_t* /*cdb_ptr*/, char* /*cdb_string*/,
-			       size_t /*len*/);
-void		aic_print_inquiry(struct scsi_inquiry_data*);
-
-u_int		aic_calc_syncsrate(u_int /*period_factor*/);
-u_int		aic_calc_syncparam(u_int /*period*/);
-u_int		aic_calc_speed(u_int width, u_int period, u_int offset,
-			       u_int min_rate);
-	
-int		aic_inquiry_match(caddr_t /*inqbuffer*/,
-				  caddr_t /*table_entry*/);
-int		aic_static_inquiry_match(caddr_t /*inqbuffer*/,
-					 caddr_t /*table_entry*/);
-
-typedef void aic_option_callback_t(u_long, int, int, int32_t);
-char *		aic_parse_brace_option(char *opt_name, char *opt_arg,
-				       char *end, int depth,
-				       aic_option_callback_t *, u_long);
-
-static __inline void	 scsi_extract_sense(struct scsi_sense_data *sense,
-					    int *error_code, int *sense_key,
-					    int *asc, int *ascq);
-static __inline void	 scsi_ulto2b(uint32_t val, uint8_t *bytes);
-static __inline void	 scsi_ulto3b(uint32_t val, uint8_t *bytes);
-static __inline void	 scsi_ulto4b(uint32_t val, uint8_t *bytes);
-static __inline uint32_t scsi_2btoul(uint8_t *bytes);
-static __inline uint32_t scsi_3btoul(uint8_t *bytes);
-static __inline int32_t	 scsi_3btol(uint8_t *bytes);
-static __inline uint32_t scsi_4btoul(uint8_t *bytes);
-
-static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
-				       int *error_code, int *sense_key,
-				       int *asc, int *ascq)
-{
-	*error_code = sense->error_code & SSD_ERRCODE;
-	*sense_key = sense->flags & SSD_KEY;
-	*asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
-	*ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
-}
-
-static __inline void
-scsi_ulto2b(uint32_t val, uint8_t *bytes)
-{
-
-	bytes[0] = (val >> 8) & 0xff;
-	bytes[1] = val & 0xff;
-}
-
-static __inline void
-scsi_ulto3b(uint32_t val, uint8_t *bytes)
-{
-
-	bytes[0] = (val >> 16) & 0xff;
-	bytes[1] = (val >> 8) & 0xff;
-	bytes[2] = val & 0xff;
-}
-
-static __inline void
-scsi_ulto4b(uint32_t val, uint8_t *bytes)
-{
-
-	bytes[0] = (val >> 24) & 0xff;
-	bytes[1] = (val >> 16) & 0xff;
-	bytes[2] = (val >> 8) & 0xff;
-	bytes[3] = val & 0xff;
-}
-
-static __inline uint32_t
-scsi_2btoul(uint8_t *bytes)
-{
-	uint32_t rv;
-
-	rv = (bytes[0] << 8) |
-	     bytes[1];
-	return (rv);
-}
-
-static __inline uint32_t
-scsi_3btoul(uint8_t *bytes)
-{
-	uint32_t rv;
-
-	rv = (bytes[0] << 16) |
-	     (bytes[1] << 8) |
-	     bytes[2];
-	return (rv);
-}
-
-static __inline int32_t 
-scsi_3btol(uint8_t *bytes)
-{
-	uint32_t rc = scsi_3btoul(bytes);
- 
-	if (rc & 0x00800000)
-		rc |= 0xff000000;
-
-	return (int32_t) rc;
-}
 
 static __inline uint32_t
 scsi_4btoul(uint8_t *bytes)
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -20,7 +20,6 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/completion.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/ioctl32.h>
 #include <linux/compat.h>
 #include <linux/chio.h>			/* here are all the ioctls */
@@ -31,7 +30,7 @@
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_eh.h>
 #include <scsi/scsi_dbg.h>
 
 #define CH_DT_MAX       16
@@ -181,17 +180,17 @@ static struct {
 
 /* ------------------------------------------------------------------- */
 
-static int ch_find_errno(unsigned char *sense_buffer)
+static int ch_find_errno(struct scsi_sense_hdr *sshdr)
 {
 	int i,errno = 0;
 
 	/* Check to see if additional sense information is available */
-	if (sense_buffer[7]  > 5 &&
-	    sense_buffer[12] != 0) {
+	if (scsi_sense_valid(sshdr) &&
+	    sshdr->asc != 0) {
 		for (i = 0; err[i].errno != 0; i++) {
-			if (err[i].sense == sense_buffer[ 2] &&
-			    err[i].asc   == sense_buffer[12] &&
-			    err[i].ascq  == sense_buffer[13]) {
+			if (err[i].sense == sshdr->sense_key &&
+			    err[i].asc   == sshdr->asc &&
+			    err[i].ascq  == sshdr->ascq) {
 				errno = -err[i].errno;
 				break;
 			}
@@ -207,13 +206,9 @@ ch_do_scsi(scsi_changer *ch, unsigned ch
 	   void *buffer, unsigned buflength,
 	   enum dma_data_direction direction)
 {
-	int errno, retries = 0, timeout;
-	struct scsi_request *sr;
+	int errno, retries = 0, timeout, result;
+	struct scsi_sense_hdr sshdr;
 	
-	sr = scsi_allocate_request(ch->device, GFP_KERNEL);
-	if (NULL == sr)
-		return -ENOMEM;
-
 	timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
 		? timeout_init : timeout_move;
 
@@ -224,16 +219,17 @@ ch_do_scsi(scsi_changer *ch, unsigned ch
 		__scsi_print_command(cmd);
 	}
 
-        scsi_wait_req(sr, cmd, buffer, buflength,
-		      timeout * HZ, MAX_RETRIES);
+        result = scsi_execute_req(ch->device, cmd, direction, buffer,
+				  buflength, &sshdr, timeout * HZ,
+				  MAX_RETRIES);
 
-	dprintk("result: 0x%x\n",sr->sr_result);
-	if (driver_byte(sr->sr_result) & DRIVER_SENSE) {
+	dprintk("result: 0x%x\n",result);
+	if (driver_byte(result) & DRIVER_SENSE) {
 		if (debug)
-			scsi_print_req_sense(ch->name, sr);
-		errno = ch_find_errno(sr->sr_sense_buffer);
+			scsi_print_sense_hdr(ch->name, &sshdr);
+		errno = ch_find_errno(&sshdr);
 
-		switch(sr->sr_sense_buffer[2] & 0xf) {
+		switch(sshdr.sense_key) {
 		case UNIT_ATTENTION:
 			ch->unit_attention = 1;
 			if (retries++ < 3)
@@ -241,7 +237,6 @@ ch_do_scsi(scsi_changer *ch, unsigned ch
 			break;
 		}
 	}
-	scsi_release_request(sr);
 	return errno;
 }
 
@@ -940,8 +935,6 @@ static int ch_probe(struct device *dev)
 	if (init)
 		ch_init_elem(ch);
 
-	devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
-		      S_IFCHR | S_IRUGO | S_IWUGO, ch->name);
 	class_device_create(ch_sysfs_class,
 			    MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
 			    dev, "s%s", ch->name);
@@ -974,7 +967,6 @@ static int ch_remove(struct device *dev)
 
 	class_device_destroy(ch_sysfs_class,
 			     MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
-	devfs_remove(ch->name);
 	kfree(ch->dt);
 	kfree(ch);
 	ch_devcount--;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -17,6 +17,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_request.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_dbg.h>
 
 
 
@@ -1155,6 +1156,31 @@ scsi_show_extd_sense(unsigned char asc, 
 	}
 }
 
+void
+scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+{
+	const char *sense_txt;
+	/* An example of deferred is when an earlier write to disk cache
+	 * succeeded, but now the disk discovers that it cannot write the
+	 * data to the magnetic media.
+	 */
+	const char *error = scsi_sense_is_deferred(sshdr) ? 
+		"<<DEFERRED>>" : "Current";
+	printk(KERN_INFO "%s: %s", name, error);
+	if (sshdr->response_code >= 0x72)
+		printk(" [descriptor]");
+
+	sense_txt = scsi_sense_key_string(sshdr->sense_key);
+	if (sense_txt)
+		printk(": sense key: %s\n", sense_txt);
+	else
+		printk(": sense key=0x%x\n", sshdr->sense_key);
+	printk(KERN_INFO "    ");
+	scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+	printk("\n");
+}
+EXPORT_SYMBOL(scsi_print_sense_hdr);
+
 /* Print sense information */
 void
 __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
@@ -1162,8 +1188,6 @@ __scsi_print_sense(const char *name, con
 {
 	int k, num, res;
 	unsigned int info;
-	const char *error;
-	const char *sense_txt;
 	struct scsi_sense_hdr ssh;
     
 	res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
@@ -1181,26 +1205,7 @@ __scsi_print_sense(const char *name, con
 		printk("\n");
 		return;
 	}
-
-	/* An example of deferred is when an earlier write to disk cache
-	 * succeeded, but now the disk discovers that it cannot write the
-	 * data to the magnetic media.
-	 */
-	error = scsi_sense_is_deferred(&ssh) ? 
-			"<<DEFERRED>>" : "Current";
-	printk(KERN_INFO "%s: %s", name, error);
-	if (ssh.response_code >= 0x72)
-		printk(" [descriptor]");
-
-	sense_txt = scsi_sense_key_string(ssh.sense_key);
-	if (sense_txt)
-		printk(": sense key: %s\n", sense_txt);
-	else
-		printk(": sense key=0x%x\n", ssh.sense_key);
-	printk(KERN_INFO "    ");
-	scsi_show_extd_sense(ssh.asc, ssh.ascq);
-	printk("\n");
-
+	scsi_print_sense_hdr(name, &ssh);
 	if (ssh.response_code < 0x72) {
 		/* only decode extras for "fixed" format now */
 		char buff[80];
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/blkdev.h>
 #include <linux/kernel.h>
+#include <linux/kthread.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/init.h>
@@ -52,21 +53,80 @@ static struct class shost_class = {
 };
 
 /**
- * scsi_host_cancel - cancel outstanding IO to this host
- * @shost:	pointer to struct Scsi_Host
- * recovery:	recovery requested to run.
+ *	scsi_host_set_state - Take the given host through the host
+ *		state model.
+ *	@shost:	scsi host to change the state of.
+ *	@state:	state to change to.
+ *
+ *	Returns zero if unsuccessful or an error if the requested
+ *	transition is illegal.
  **/
-static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
+int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
 {
-	struct scsi_device *sdev;
+	enum scsi_host_state oldstate = shost->shost_state;
+
+	if (state == oldstate)
+		return 0;
+
+	switch (state) {
+	case SHOST_CREATED:
+		/* There are no legal states that come back to
+		 * created.  This is the manually initialised start
+		 * state */
+		goto illegal;
+
+	case SHOST_RUNNING:
+		switch (oldstate) {
+		case SHOST_CREATED:
+		case SHOST_RECOVERY:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case SHOST_RECOVERY:
+		switch (oldstate) {
+		case SHOST_RUNNING:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case SHOST_CANCEL:
+		switch (oldstate) {
+		case SHOST_CREATED:
+		case SHOST_RUNNING:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case SHOST_DEL:
+		switch (oldstate) {
+		case SHOST_CANCEL:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
 
-	set_bit(SHOST_CANCEL, &shost->shost_state);
-	shost_for_each_device(sdev, shost) {
-		scsi_device_cancel(sdev, recovery);
 	}
-	wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY,
-						&shost->shost_state)));
+	shost->shost_state = state;
+	return 0;
+
+ illegal:
+	SCSI_LOG_ERROR_RECOVERY(1,
+				dev_printk(KERN_ERR, &shost->shost_gendev,
+					   "Illegal host state transition"
+					   "%s->%s\n",
+					   scsi_host_state_name(oldstate),
+					   scsi_host_state_name(state)));
+	return -EINVAL;
 }
+EXPORT_SYMBOL(scsi_host_set_state);
 
 /**
  * scsi_remove_host - remove a scsi host
@@ -74,11 +134,13 @@ static void scsi_host_cancel(struct Scsi
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
+	down(&shost->scan_mutex);
+	scsi_host_set_state(shost, SHOST_CANCEL);
+	up(&shost->scan_mutex);
 	scsi_forget_host(shost);
-	scsi_host_cancel(shost, 0);
 	scsi_proc_host_rm(shost);
 
-	set_bit(SHOST_DEL, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_DEL);
 
 	transport_unregister_device(&shost->shost_gendev);
 	class_device_unregister(&shost->shost_classdev);
@@ -115,7 +177,7 @@ int scsi_add_host(struct Scsi_Host *shos
 	if (error)
 		goto out;
 
-	set_bit(SHOST_ADD, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_RUNNING);
 	get_device(shost->shost_gendev.parent);
 
 	error = class_device_add(&shost->shost_classdev);
@@ -164,15 +226,8 @@ static void scsi_host_dev_release(struct
 	struct Scsi_Host *shost = dev_to_shost(dev);
 	struct device *parent = dev->parent;
 
-	if (shost->ehandler) {
-		DECLARE_COMPLETION(sem);
-		shost->eh_notify = &sem;
-		shost->eh_kill = 1;
-		up(shost->eh_wait);
-		wait_for_completion(&sem);
-		shost->eh_notify = NULL;
-	}
-
+	if (shost->ehandler)
+		kthread_stop(shost->ehandler);
 	if (shost->work_q)
 		destroy_workqueue(shost->work_q);
 
@@ -202,7 +257,6 @@ struct Scsi_Host *scsi_host_alloc(struct
 {
 	struct Scsi_Host *shost;
 	int gfp_mask = GFP_KERNEL, rval;
-	DECLARE_COMPLETION(complete);
 
 	if (sht->unchecked_isa_dma && privsize)
 		gfp_mask |= __GFP_DMA;
@@ -226,6 +280,7 @@ struct Scsi_Host *scsi_host_alloc(struct
 
 	spin_lock_init(&shost->default_lock);
 	scsi_assign_lock(shost, &shost->default_lock);
+	shost->shost_state = SHOST_CREATED;
 	INIT_LIST_HEAD(&shost->__devices);
 	INIT_LIST_HEAD(&shost->__targets);
 	INIT_LIST_HEAD(&shost->eh_cmd_q);
@@ -307,12 +362,12 @@ struct Scsi_Host *scsi_host_alloc(struct
 	snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
 		  shost->host_no);
 
-	shost->eh_notify = &complete;
-	rval = kernel_thread(scsi_error_handler, shost, 0);
-	if (rval < 0)
+	shost->ehandler = kthread_run(scsi_error_handler, shost,
+			"scsi_eh_%d", shost->host_no);
+	if (IS_ERR(shost->ehandler)) {
+		rval = PTR_ERR(shost->ehandler);
 		goto fail_destroy_freelist;
-	wait_for_completion(&complete);
-	shost->eh_notify = NULL;
+	}
 
 	scsi_proc_hostdir_add(shost->hostt);
 	return shost;
@@ -382,7 +437,7 @@ EXPORT_SYMBOL(scsi_host_lookup);
  **/
 struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)
 {
-	if (test_bit(SHOST_DEL, &shost->shost_state) ||
+	if ((shost->shost_state == SHOST_DEL) ||
 		!get_device(&shost->shost_gendev))
 		return NULL;
 	return shost;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@ static int max_channel = 3;
 static int init_timeout = 5;
 static int max_requests = 50;
 
-#define IBMVSCSI_VERSION "1.5.6"
+#define IBMVSCSI_VERSION "1.5.7"
 
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
@@ -145,6 +145,8 @@ static int initialize_event_pool(struct 
 			sizeof(*evt->xfer_iu) * i;
 		evt->xfer_iu = pool->iu_storage + i;
 		evt->hostdata = hostdata;
+		evt->ext_list = NULL;
+		evt->ext_list_token = 0;
 	}
 
 	return 0;
@@ -161,9 +163,16 @@ static void release_event_pool(struct ev
 			       struct ibmvscsi_host_data *hostdata)
 {
 	int i, in_use = 0;
-	for (i = 0; i < pool->size; ++i)
+	for (i = 0; i < pool->size; ++i) {
 		if (atomic_read(&pool->events[i].free) != 1)
 			++in_use;
+		if (pool->events[i].ext_list) {
+			dma_free_coherent(hostdata->dev,
+				  SG_ALL * sizeof(struct memory_descriptor),
+				  pool->events[i].ext_list,
+				  pool->events[i].ext_list_token);
+		}
+	}
 	if (in_use)
 		printk(KERN_WARNING
 		       "ibmvscsi: releasing event pool with %d "
@@ -286,24 +295,41 @@ static void set_srp_direction(struct scs
 	} else {
 		if (cmd->sc_data_direction == DMA_TO_DEVICE) {
 			srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
-			srp_cmd->data_out_count = numbuf;
+			srp_cmd->data_out_count =
+				numbuf < MAX_INDIRECT_BUFS ?
+					numbuf: MAX_INDIRECT_BUFS;
 		} else {
 			srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
-			srp_cmd->data_in_count = numbuf;
+			srp_cmd->data_in_count =
+				numbuf < MAX_INDIRECT_BUFS ?
+					numbuf: MAX_INDIRECT_BUFS;
 		}
 	}
 }
 
+static void unmap_sg_list(int num_entries, 
+		struct device *dev,
+		struct memory_descriptor *md)
+{ 
+	int i;
+
+	for (i = 0; i < num_entries; ++i) {
+		dma_unmap_single(dev,
+			md[i].virtual_address,
+			md[i].length, DMA_BIDIRECTIONAL);
+	}
+}
+
 /**
  * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format
  * @cmd:	srp_cmd whose additional_data member will be unmapped
  * @dev:	device for which the memory is mapped
  *
 */
-static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
+static void unmap_cmd_data(struct srp_cmd *cmd,
+			   struct srp_event_struct *evt_struct,
+			   struct device *dev)
 {
-	int i;
-
 	if ((cmd->data_out_format == SRP_NO_BUFFER) &&
 	    (cmd->data_in_format == SRP_NO_BUFFER))
 		return;
@@ -318,15 +344,34 @@ static void unmap_cmd_data(struct srp_cm
 			(struct indirect_descriptor *)cmd->additional_data;
 		int num_mapped = indirect->head.length / 
 			sizeof(indirect->list[0]);
-		for (i = 0; i < num_mapped; ++i) {
-			struct memory_descriptor *data = &indirect->list[i];
-			dma_unmap_single(dev,
-					 data->virtual_address,
-					 data->length, DMA_BIDIRECTIONAL);
+
+		if (num_mapped <= MAX_INDIRECT_BUFS) {
+			unmap_sg_list(num_mapped, dev, &indirect->list[0]);
+			return;
 		}
+
+		unmap_sg_list(num_mapped, dev, evt_struct->ext_list);
 	}
 }
 
+static int map_sg_list(int num_entries, 
+		       struct scatterlist *sg,
+		       struct memory_descriptor *md)
+{
+	int i;
+	u64 total_length = 0;
+
+	for (i = 0; i < num_entries; ++i) {
+		struct memory_descriptor *descr = md + i;
+		struct scatterlist *sg_entry = &sg[i];
+		descr->virtual_address = sg_dma_address(sg_entry);
+		descr->length = sg_dma_len(sg_entry);
+		descr->memory_handle = 0;
+		total_length += sg_dma_len(sg_entry);
+ 	}
+	return total_length;
+}
+
 /**
  * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
  * @cmd:	Scsi_Cmnd with the scatterlist
@@ -337,10 +382,11 @@ static void unmap_cmd_data(struct srp_cm
  * Returns 1 on success.
 */
 static int map_sg_data(struct scsi_cmnd *cmd,
+		       struct srp_event_struct *evt_struct,
 		       struct srp_cmd *srp_cmd, struct device *dev)
 {
 
-	int i, sg_mapped;
+	int sg_mapped;
 	u64 total_length = 0;
 	struct scatterlist *sg = cmd->request_buffer;
 	struct memory_descriptor *data =
@@ -363,27 +409,46 @@ static int map_sg_data(struct scsi_cmnd 
 		return 1;
 	}
 
-	if (sg_mapped > MAX_INDIRECT_BUFS) {
+	if (sg_mapped > SG_ALL) {
 		printk(KERN_ERR
 		       "ibmvscsi: More than %d mapped sg entries, got %d\n",
-		       MAX_INDIRECT_BUFS, sg_mapped);
+		       SG_ALL, sg_mapped);
 		return 0;
 	}
 
 	indirect->head.virtual_address = 0;
 	indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
 	indirect->head.memory_handle = 0;
-	for (i = 0; i < sg_mapped; ++i) {
-		struct memory_descriptor *descr = &indirect->list[i];
-		struct scatterlist *sg_entry = &sg[i];
-		descr->virtual_address = sg_dma_address(sg_entry);
-		descr->length = sg_dma_len(sg_entry);
-		descr->memory_handle = 0;
-		total_length += sg_dma_len(sg_entry);
+
+	if (sg_mapped <= MAX_INDIRECT_BUFS) {
+		total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]);
+		indirect->total_length = total_length;
+		return 1;
 	}
-	indirect->total_length = total_length;
 
-	return 1;
+	/* get indirect table */
+	if (!evt_struct->ext_list) {
+		evt_struct->ext_list =(struct memory_descriptor*)
+			dma_alloc_coherent(dev, 
+				SG_ALL * sizeof(struct memory_descriptor),
+				&evt_struct->ext_list_token, 0);
+		if (!evt_struct->ext_list) {
+		    printk(KERN_ERR
+		   	"ibmvscsi: Can't allocate memory for indirect table\n");
+			return 0;
+			
+		}
+	}
+
+	total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list);	
+
+	indirect->total_length = total_length;
+	indirect->head.virtual_address = evt_struct->ext_list_token;
+	indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
+	memcpy(indirect->list, evt_struct->ext_list,
+		MAX_INDIRECT_BUFS * sizeof(struct memory_descriptor));
+	
+ 	return 1;
 }
 
 /**
@@ -428,6 +493,7 @@ static int map_single_data(struct scsi_c
  * Returns 1 on success.
 */
 static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
+				struct srp_event_struct *evt_struct,
 				struct srp_cmd *srp_cmd, struct device *dev)
 {
 	switch (cmd->sc_data_direction) {
@@ -450,7 +516,7 @@ static int map_data_for_srp_cmd(struct s
 	if (!cmd->request_buffer)
 		return 1;
 	if (cmd->use_sg)
-		return map_sg_data(cmd, srp_cmd, dev);
+		return map_sg_data(cmd, evt_struct, srp_cmd, dev);
 	return map_single_data(cmd, srp_cmd, dev);
 }
 
@@ -486,6 +552,7 @@ static int ibmvscsi_send_srp_event(struc
 		printk(KERN_WARNING 
 		       "ibmvscsi: Warning, request_limit exceeded\n");
 		unmap_cmd_data(&evt_struct->iu.srp.cmd,
+			       evt_struct,
 			       hostdata->dev);
 		free_event_struct(&hostdata->pool, evt_struct);
 		return SCSI_MLQUEUE_HOST_BUSY;
@@ -513,7 +580,7 @@ static int ibmvscsi_send_srp_event(struc
 	return 0;
 
  send_error:
-	unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+	unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
 
 	if ((cmnd = evt_struct->cmnd) != NULL) {
 		cmnd->result = DID_ERROR << 16;
@@ -551,6 +618,7 @@ static void handle_cmd_rsp(struct srp_ev
 			       rsp->sense_and_response_data,
 			       rsp->sense_data_list_length);
 		unmap_cmd_data(&evt_struct->iu.srp.cmd, 
+			       evt_struct, 
 			       evt_struct->hostdata->dev);
 
 		if (rsp->doover)
@@ -583,6 +651,7 @@ static int ibmvscsi_queuecommand(struct 
 {
 	struct srp_cmd *srp_cmd;
 	struct srp_event_struct *evt_struct;
+	struct indirect_descriptor *indirect;
 	struct ibmvscsi_host_data *hostdata =
 		(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
 	u16 lun = lun_from_dev(cmnd->device);
@@ -591,14 +660,6 @@ static int ibmvscsi_queuecommand(struct 
 	if (!evt_struct)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
-	init_event_struct(evt_struct,
-			  handle_cmd_rsp,
-			  VIOSRP_SRP_FORMAT,
-			  cmnd->timeout);
-
-	evt_struct->cmnd = cmnd;
-	evt_struct->cmnd_done = done;
-
 	/* Set up the actual SRP IU */
 	srp_cmd = &evt_struct->iu.srp.cmd;
 	memset(srp_cmd, 0x00, sizeof(*srp_cmd));
@@ -606,17 +667,25 @@ static int ibmvscsi_queuecommand(struct 
 	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
 	srp_cmd->lun = ((u64) lun) << 48;
 
-	if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) {
+	if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
 		printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
 		free_event_struct(&hostdata->pool, evt_struct);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	init_event_struct(evt_struct,
+			  handle_cmd_rsp,
+			  VIOSRP_SRP_FORMAT,
+			  cmnd->timeout_per_command/HZ);
+
+	evt_struct->cmnd = cmnd;
+	evt_struct->cmnd_done = done;
+
 	/* Fix up dma address of the buffer itself */
-	if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
-	    (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) {
-		struct indirect_descriptor *indirect =
-		    (struct indirect_descriptor *)srp_cmd->additional_data;
+	indirect = (struct indirect_descriptor *)srp_cmd->additional_data;
+	if (((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
+	    (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) &&
+	    (indirect->head.virtual_address == 0)) {
 		indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
 		    offsetof(struct srp_cmd, additional_data) +
 		    offsetof(struct indirect_descriptor, list);
@@ -826,11 +895,13 @@ static int ibmvscsi_eh_abort_handler(str
 	struct srp_event_struct *tmp_evt, *found_evt;
 	union viosrp_iu srp_rsp;
 	int rsp_rc;
+	unsigned long flags;
 	u16 lun = lun_from_dev(cmd->device);
 
 	/* First, find this command in our sent list so we can figure
 	 * out the correct tag
 	 */
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	found_evt = NULL;
 	list_for_each_entry(tmp_evt, &hostdata->sent, list) {
 		if (tmp_evt->cmnd == cmd) {
@@ -839,11 +910,14 @@ static int ibmvscsi_eh_abort_handler(str
 		}
 	}
 
-	if (!found_evt) 
+	if (!found_evt) {
+		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 		return FAILED;
+	}
 
 	evt = get_event_struct(&hostdata->pool);
 	if (evt == NULL) {
+		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 		printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
 		return FAILED;
 	}
@@ -867,7 +941,9 @@ static int ibmvscsi_eh_abort_handler(str
 
 	evt->sync_srp = &srp_rsp;
 	init_completion(&evt->comp);
-	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+	rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+	if (rsp_rc != 0) {
 		printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
 		return FAILED;
 	}
@@ -901,6 +977,7 @@ static int ibmvscsi_eh_abort_handler(str
 	 * The event is no longer in our list.  Make sure it didn't
 	 * complete while we were aborting
 	 */
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	found_evt = NULL;
 	list_for_each_entry(tmp_evt, &hostdata->sent, list) {
 		if (tmp_evt->cmnd == cmd) {
@@ -910,6 +987,7 @@ static int ibmvscsi_eh_abort_handler(str
 	}
 
 	if (found_evt == NULL) {
+		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 		printk(KERN_INFO
 		       "ibmvscsi: aborted task tag 0x%lx completed\n",
 		       tsk_mgmt->managed_task_tag);
@@ -922,8 +1000,10 @@ static int ibmvscsi_eh_abort_handler(str
 
 	cmd->result = (DID_ABORT << 16);
 	list_del(&found_evt->list);
-	unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
+	unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt,
+		       found_evt->hostdata->dev);
 	free_event_struct(&found_evt->hostdata->pool, found_evt);
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 	atomic_inc(&hostdata->request_limit);
 	return SUCCESS;
 }
@@ -943,10 +1023,13 @@ static int ibmvscsi_eh_device_reset_hand
 	struct srp_event_struct *tmp_evt, *pos;
 	union viosrp_iu srp_rsp;
 	int rsp_rc;
+	unsigned long flags;
 	u16 lun = lun_from_dev(cmd->device);
 
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	evt = get_event_struct(&hostdata->pool);
 	if (evt == NULL) {
+		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 		printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
 		return FAILED;
 	}
@@ -969,7 +1052,9 @@ static int ibmvscsi_eh_device_reset_hand
 
 	evt->sync_srp = &srp_rsp;
 	init_completion(&evt->comp);
-	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+	rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+	if (rsp_rc != 0) {
 		printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
 		return FAILED;
 	}
@@ -1002,12 +1087,14 @@ static int ibmvscsi_eh_device_reset_hand
 	/* We need to find all commands for this LUN that have not yet been
 	 * responded to, and fail them with DID_RESET
 	 */
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
 		if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
 			if (tmp_evt->cmnd)
 				tmp_evt->cmnd->result = (DID_RESET << 16);
 			list_del(&tmp_evt->list);
-			unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev);
+			unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt,
+				       tmp_evt->hostdata->dev);
 			free_event_struct(&tmp_evt->hostdata->pool,
 						   tmp_evt);
 			atomic_inc(&hostdata->request_limit);
@@ -1017,6 +1104,7 @@ static int ibmvscsi_eh_device_reset_hand
 				tmp_evt->done(tmp_evt);
 		}
 	}
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 	return SUCCESS;
 }
 
@@ -1035,6 +1123,7 @@ static void purge_requests(struct ibmvsc
 		if (tmp_evt->cmnd) {
 			tmp_evt->cmnd->result = (DID_ERROR << 16);
 			unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
+				       tmp_evt,	
 				       tmp_evt->hostdata->dev);
 			if (tmp_evt->cmnd_done)
 				tmp_evt->cmnd_done(tmp_evt->cmnd);
@@ -1339,7 +1428,7 @@ static struct scsi_host_template driver_
 	.cmd_per_lun = 16,
 	.can_queue = 1,		/* Updated after SRP_LOGIN */
 	.this_id = -1,
-	.sg_tablesize = MAX_INDIRECT_BUFS,
+	.sg_tablesize = SG_ALL,
 	.use_clustering = ENABLE_CLUSTERING,
 	.shost_attrs = ibmvscsi_attrs,
 };
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -68,6 +68,8 @@ struct srp_event_struct {
 	void (*cmnd_done) (struct scsi_cmnd *);
 	struct completion comp;
 	union viosrp_iu *sync_srp;
+	struct memory_descriptor *ext_list;
+	dma_addr_t ext_list_token;
 };
 
 /* a pool of event structs for use */
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -342,9 +342,6 @@ struct lpfc_hba {
 #define VPD_MASK            0xf         /* mask for any vpd data */
 
 	struct timer_list els_tmofunc;
-
-	void *link_stats;
-
 	/*
 	 * stat  counters
 	 */
@@ -370,6 +367,8 @@ struct lpfc_hba {
 	struct list_head freebufList;
 	struct list_head ctrspbuflist;
 	struct list_head rnidrspbuflist;
+
+	struct fc_host_statistics link_stats;
 };
 
 
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -23,6 +23,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
@@ -988,8 +989,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
 {
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
 	struct lpfc_sli *psli = &phba->sli;
-	struct fc_host_statistics *hs =
-			(struct fc_host_statistics *)phba->link_stats;
+	struct fc_host_statistics *hs = &phba->link_stats;
 	LPFC_MBOXQ_t *pmboxq;
 	MAILBOX_t *pmb;
 	int rc=0;
@@ -1020,6 +1020,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
 		return NULL;
 	}
 
+	memset(hs, 0, sizeof (struct fc_host_statistics));
+
 	hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
 	hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
 	hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -27,8 +27,10 @@
 #include <linux/interrupt.h>
 #include <linux/utsname.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
 
 #include "lpfc_hw.h"
 #include "lpfc_sli.h"
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -23,6 +23,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport_fc.h>
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -24,6 +24,7 @@
 #include <linux/kthread.h>
 #include <linux/interrupt.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport_fc.h>
@@ -1135,6 +1136,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, st
 	switch(list) {
 	case NLP_NO_LIST: /* No list, just remove it */
 		lpfc_nlp_remove(phba, nlp);
+		/* as node removed - stop further transport calls */
+		rport_del = none;
 		break;
 	case NLP_UNUSED_LIST:
 		spin_lock_irq(phba->host->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport_fc.h>
@@ -1339,14 +1340,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev,
 	if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
 		goto out_disable_device;
 
-	host = scsi_host_alloc(&lpfc_template,
-			sizeof (struct lpfc_hba) + sizeof (unsigned long));
+	host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
 	if (!host)
 		goto out_release_regions;
 
 	phba = (struct lpfc_hba*)host->hostdata;
 	memset(phba, 0, sizeof (struct lpfc_hba));
-	phba->link_stats = (void *)&phba[1];
 	phba->host = host;
 
 	phba->fc_flag |= FC_LOADING;
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -23,6 +23,11 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include <scsi/scsi.h>
+
 #include "lpfc_hw.h"
 #include "lpfc_sli.h"
 #include "lpfc_disc.h"
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -23,6 +23,11 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include <scsi/scsi.h>
+
 #include "lpfc_hw.h"
 #include "lpfc_sli.h"
 #include "lpfc_disc.h"
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -23,6 +23,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport_fc.h>
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -40,11 +40,6 @@
 #define LPFC_RESET_WAIT  2
 #define LPFC_ABORT_WAIT  2
 
-static inline void lpfc_put_lun(struct fcp_cmnd *fcmd, unsigned int lun)
-{
-	fcmd->fcpLunLsl = 0;
-	fcmd->fcpLunMsl = swab16((uint16_t)lun);
-}
 
 /*
  * This routine allocates a scsi buffer, which contains all the necessary
@@ -238,6 +233,8 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *
 		bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
 		if (datadir == DMA_TO_DEVICE)
 			bpl->tus.f.bdeFlags = 0;
+		else
+			bpl->tus.f.bdeFlags = BUFF_USE_RCV;
 		bpl->tus.w = le32_to_cpu(bpl->tus.w);
 		num_bde = 1;
 		bpl++;
@@ -245,8 +242,11 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *
 
 	/*
 	 * Finish initializing those IOCB fields that are dependent on the
-	 * scsi_cmnd request_buffer
+	 * scsi_cmnd request_buffer.  Note that the bdeSize is explicitly
+	 * reinitialized since all iocb memory resources are used many times
+	 * for transmit, receive, and continuation bpl's.
 	 */
+	iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
 	iocb_cmd->un.fcpi64.bdl.bdeSize +=
 		(num_bde * sizeof (struct ulp_bde64));
 	iocb_cmd->ulpBdeCount = 1;
@@ -445,8 +445,11 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * ph
 	int datadir = scsi_cmnd->sc_data_direction;
 
 	lpfc_cmd->fcp_rsp->rspSnsLen = 0;
+	/* clear task management bits */
+	lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
 
-	lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+	int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+			&lpfc_cmd->fcp_cmnd->fcp_lun);
 
 	memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16);
 
@@ -545,7 +548,8 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc
 	piocb = &piocbq->iocb;
 
 	fcp_cmnd = lpfc_cmd->fcp_cmnd;
-	lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+	int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+			&lpfc_cmd->fcp_cmnd->fcp_lun);
 	fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
 
 	piocb->ulpCommand = CMD_FCP_ICMND64_CR;
@@ -746,6 +750,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd
 			cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
 			goto out_fail_command;
 		}
+		else if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
+			cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+			goto out_fail_command;
+		}
 		/*
 		 * The device is most likely recovered and the driver
 		 * needs a bit more time to finish.  Ask the midlayer
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -78,18 +78,7 @@ struct fcp_rsp {
 };
 
 struct fcp_cmnd {
-	uint32_t fcpLunMsl;	/* most  significant lun word (32 bits) */
-	uint32_t fcpLunLsl;	/* least significant lun word (32 bits) */
-	/* # of bits to shift lun id to end up in right
-	 * payload word, little endian = 8, big = 16.
-	 */
-#ifdef __BIG_ENDIAN
-#define FC_LUN_SHIFT         16
-#define FC_ADDR_MODE_SHIFT   24
-#else	/*  __LITTLE_ENDIAN */
-#define FC_LUN_SHIFT         8
-#define FC_ADDR_MODE_SHIFT   0
-#endif
+	struct scsi_lun  fcp_lun;
 
 	uint8_t fcpCntl0;	/* FCP_CNTL byte 0 (reserved) */
 	uint8_t fcpCntl1;	/* FCP_CNTL byte 1 task codes */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -24,9 +24,11 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
 
 #include "lpfc_hw.h"
 #include "lpfc_sli.h"
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.0.29"
+#define LPFC_DRIVER_VERSION "8.0.30"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -996,7 +996,6 @@ qla1280_error_action(struct scsi_cmnd *c
 		break;
 
 	case ABORT_DEVICE:
-		ha->flags.in_reset = 1;
 		if (qla1280_verbose)
 			printk(KERN_INFO
 			       "scsi(%ld:%d:%d:%d): Queueing abort device "
@@ -1010,7 +1009,6 @@ qla1280_error_action(struct scsi_cmnd *c
 			printk(KERN_INFO
 			       "scsi(%ld:%d:%d:%d): Queueing device reset "
 			       "command.\n", ha->host_no, bus, target, lun);
-		ha->flags.in_reset = 1;
 		if (qla1280_device_reset(ha, bus, target) == 0)
 			result = SUCCESS;
 		break;
@@ -1019,7 +1017,6 @@ qla1280_error_action(struct scsi_cmnd *c
 		if (qla1280_verbose)
 			printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS "
 			       "DEVICE RESET\n", ha->host_no, bus);
-		ha->flags.in_reset = 1;
 		if (qla1280_bus_reset(ha, bus == 0))
 			result = SUCCESS;
 
@@ -1047,7 +1044,6 @@ qla1280_error_action(struct scsi_cmnd *c
 
 	if (!list_empty(&ha->done_q))
 		qla1280_done(ha);
-	ha->flags.in_reset = 0;
 
 	/* If we didn't manage to issue the action, or we have no
 	 * command to wait for, exit here */
@@ -1269,6 +1265,22 @@ qla1280_biosparam_old(Disk * disk, kdev_
 	return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);
 }
 #endif
+ 
+/* disable risc and host interrupts */
+static inline void
+qla1280_disable_intrs(struct scsi_qla_host *ha)
+{
+	WRT_REG_WORD(&ha->iobase->ictrl, 0);
+	RD_REG_WORD(&ha->iobase->ictrl);	/* PCI Posted Write flush */
+}
+
+/* enable risc and host interrupts */
+static inline void
+qla1280_enable_intrs(struct scsi_qla_host *ha)
+{
+	WRT_REG_WORD(&ha->iobase->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+	RD_REG_WORD(&ha->iobase->ictrl);	/* PCI Posted Write flush */
+}
 
 /**************************************************************************
  * qla1280_intr_handler
@@ -1290,7 +1302,7 @@ qla1280_intr_handler(int irq, void *dev_
 	ha->isr_count++;
 	reg = ha->iobase;
 
-	WRT_REG_WORD(&reg->ictrl, 0);	/* disable our interrupt. */
+	qla1280_disable_intrs(ha);
 
 	data = qla1280_debounce_register(&reg->istatus);
 	/* Check for pending interrupts. */
@@ -1303,8 +1315,7 @@ qla1280_intr_handler(int irq, void *dev_
 
 	spin_unlock(HOST_LOCK);
 
-	/* enable our interrupt. */
-	WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+	qla1280_enable_intrs(ha);
 
 	LEAVE_INTR("qla1280_intr_handler");
 	return IRQ_RETVAL(handled);
@@ -1317,7 +1328,7 @@ qla1280_set_target_parameters(struct scs
 	uint8_t mr;
 	uint16_t mb[MAILBOX_REGISTER_COUNT];
 	struct nvram *nv;
-	int status;
+	int status, lun;
 
 	nv = &ha->nvram;
 
@@ -1325,24 +1336,38 @@ qla1280_set_target_parameters(struct scs
 
 	/* Set Target Parameters. */
 	mb[0] = MBC_SET_TARGET_PARAMETERS;
-	mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
-	mb[1] <<= 8;
-
-	mb[2] = (nv->bus[bus].target[target].parameter.c << 8);
+	mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+	mb[2] = nv->bus[bus].target[target].parameter.renegotiate_on_error << 8;
+	mb[2] |= nv->bus[bus].target[target].parameter.stop_queue_on_check << 9;
+	mb[2] |= nv->bus[bus].target[target].parameter.auto_request_sense << 10;
+	mb[2] |= nv->bus[bus].target[target].parameter.tag_queuing << 11;
+	mb[2] |= nv->bus[bus].target[target].parameter.enable_sync << 12;
+	mb[2] |= nv->bus[bus].target[target].parameter.enable_wide << 13;
+	mb[2] |= nv->bus[bus].target[target].parameter.parity_checking << 14;
+	mb[2] |= nv->bus[bus].target[target].parameter.disconnect_allowed << 15;
 
 	if (IS_ISP1x160(ha)) {
 		mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
-		mb[3] =	(nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |
-			 nv->bus[bus].target[target].sync_period;
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8);
 		mb[6] =	(nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |
 			 nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
 		mr |= BIT_6;
 	} else {
-		mb[3] =	(nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |
-			 nv->bus[bus].target[target].sync_period;
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8);
 	}
+	mb[3] |= nv->bus[bus].target[target].sync_period;
 
-	status = qla1280_mailbox_command(ha, mr, &mb[0]);
+	status = qla1280_mailbox_command(ha, mr, mb);
+
+	/* Set Device Queue Parameters. */
+	for (lun = 0; lun < MAX_LUNS; lun++) {
+		mb[0] = MBC_SET_DEVICE_QUEUE;
+		mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+		mb[1] |= lun;
+		mb[2] = nv->bus[bus].max_queue_depth;
+		mb[3] = nv->bus[bus].target[target].execution_throttle;
+		status |= qla1280_mailbox_command(ha, 0x0f, mb);
+	}
 
 	if (status)
 		printk(KERN_WARNING "scsi(%ld:%i:%i): "
@@ -1389,19 +1414,19 @@ qla1280_slave_configure(struct scsi_devi
 	}
 
 #if LINUX_VERSION_CODE > 0x020500
-	nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr;
-	nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr;
+	nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
+	nv->bus[bus].target[target].parameter.enable_wide = device->wdtr;
 	nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;
 #endif
 
 	if (driver_setup.no_sync ||
 	    (driver_setup.sync_mask &&
 	     (~driver_setup.sync_mask & (1 << target))))
-		nv->bus[bus].target[target].parameter.f.enable_sync = 0;
+		nv->bus[bus].target[target].parameter.enable_sync = 0;
 	if (driver_setup.no_wide ||
 	    (driver_setup.wide_mask &&
 	     (~driver_setup.wide_mask & (1 << target))))
-		nv->bus[bus].target[target].parameter.f.enable_wide = 0;
+		nv->bus[bus].target[target].parameter.enable_wide = 0;
 	if (IS_ISP1x160(ha)) {
 		if (driver_setup.no_ppr ||
 		    (driver_setup.ppr_mask &&
@@ -1410,7 +1435,7 @@ qla1280_slave_configure(struct scsi_devi
 	}
 
 	spin_lock_irqsave(HOST_LOCK, flags);
-	if (nv->bus[bus].target[target].parameter.f.enable_sync)
+	if (nv->bus[bus].target[target].parameter.enable_sync)
 		status = qla1280_set_target_parameters(ha, bus, target);
 	qla1280_get_target_parameters(ha, device);
 	spin_unlock_irqrestore(HOST_LOCK, flags);
@@ -1448,7 +1473,6 @@ qla1280_select_queue_depth(struct Scsi_H
  *
  * Input:
  *      ha           = adapter block pointer.
- *      done_q       = done queue.
  */
 static void
 qla1280_done(struct scsi_qla_host *ha)
@@ -1522,7 +1546,7 @@ qla1280_return_status(struct response * 
 	int host_status = DID_ERROR;
 	uint16_t comp_status = le16_to_cpu(sts->comp_status);
 	uint16_t state_flags = le16_to_cpu(sts->state_flags);
-	uint16_t residual_length = le16_to_cpu(sts->residual_length);
+	uint16_t residual_length = le32_to_cpu(sts->residual_length);
 	uint16_t scsi_status = le16_to_cpu(sts->scsi_status);
 #if DEBUG_QLA1280_INTR
 	static char *reason[] = {
@@ -1582,7 +1606,7 @@ qla1280_return_status(struct response * 
 
 	case CS_DATA_OVERRUN:
 		dprintk(2, "Data overrun 0x%x\n", residual_length);
-		dprintk(2, "qla1280_isr: response packet data\n");
+		dprintk(2, "qla1280_return_status: response packet data\n");
 		qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);
 		host_status = DID_ERROR;
 		break;
@@ -1617,40 +1641,6 @@ qla1280_return_status(struct response * 
 /*                QLogic ISP1280 Hardware Support Functions.                */
 /****************************************************************************/
 
- /*
-  * qla2100_enable_intrs
-  * qla2100_disable_intrs
-  *
-  * Input:
-  *      ha = adapter block pointer.
-  *
-  * Returns:
-  *      None
-  */
-static inline void
-qla1280_enable_intrs(struct scsi_qla_host *ha)
-{
-	struct device_reg __iomem *reg;
-
-	reg = ha->iobase;
-	/* enable risc and host interrupts */
-	WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
-	RD_REG_WORD(&reg->ictrl);	/* PCI Posted Write flush */
-	ha->flags.ints_enabled = 1;
-}
-
-static inline void
-qla1280_disable_intrs(struct scsi_qla_host *ha)
-{
-	struct device_reg __iomem *reg;
-
-	reg = ha->iobase;
-	/* disable risc and host interrupts */
-	WRT_REG_WORD(&reg->ictrl, 0);
-	RD_REG_WORD(&reg->ictrl);	/* PCI Posted Write flush */
-	ha->flags.ints_enabled = 0;
-}
-
 /*
  * qla1280_initialize_adapter
  *      Initialize board.
@@ -1679,7 +1669,6 @@ qla1280_initialize_adapter(struct scsi_q
 	ha->flags.reset_active = 0;
 	ha->flags.abort_isp_active = 0;
 
-	ha->flags.ints_enabled = 0;
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
 	if (ia64_platform_is("sn2")) {
 		printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
@@ -1758,69 +1747,6 @@ qla1280_initialize_adapter(struct scsi_q
 	return status;
 }
 
-
-/*
- * ISP Firmware Test
- *      Checks if present version of RISC firmware is older than
- *      driver firmware.
- *
- * Input:
- *      ha = adapter block pointer.
- *
- * Returns:
- *      0 = firmware does not need to be loaded.
- */
-static int
-qla1280_isp_firmware(struct scsi_qla_host *ha)
-{
-	struct nvram *nv = (struct nvram *) ha->response_ring;
-	int status = 0;		/* dg 2/27 always loads RISC */
-	uint16_t mb[MAILBOX_REGISTER_COUNT];
-
-	ENTER("qla1280_isp_firmware");
-
-	dprintk(1, "scsi(%li): Determining if RISC is loaded\n", ha->host_no);
-
-	/* Bad NVRAM data, load RISC code. */
-	if (!ha->nvram_valid) {
-		ha->flags.disable_risc_code_load = 0;
-	} else
-		ha->flags.disable_risc_code_load =
-			nv->cntr_flags_1.disable_loading_risc_code;
-
-	if (ha->flags.disable_risc_code_load) {
-		dprintk(3, "qla1280_isp_firmware: Telling RISC to verify "
-			"checksum of loaded BIOS code.\n");
-
-		/* Verify checksum of loaded RISC code. */
-		mb[0] = MBC_VERIFY_CHECKSUM;
-		/* mb[1] = ql12_risc_code_addr01; */
-		mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-
-		if (!(status =
-		      qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
-			/* Start firmware execution. */
-			dprintk(3, "qla1280_isp_firmware: Startng F/W "
-				"execution.\n");
-
-			mb[0] = MBC_EXECUTE_FIRMWARE;
-			/* mb[1] = ql12_risc_code_addr01; */
-			mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-			qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-		} else
-			printk(KERN_INFO "qla1280: RISC checksum failed.\n");
-	} else {
-		dprintk(1, "qla1280: NVRAM configured to load RISC load.\n");
-		status = 1;
-	}
-
-	if (status)
-		dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n");
-
-	LEAVE("qla1280_isp_firmware");
-	return status;
-}
-
 /*
  * Chip diagnostics
  *      Test chip for proper operation.
@@ -2006,7 +1932,7 @@ qla1280_load_firmware_dma(struct scsi_ql
 			"%d,%d(0x%x)\n",
 			risc_code_address, cnt, num, risc_address);
 		for(i = 0; i < cnt; i++)
-			((uint16_t *)ha->request_ring)[i] =
+			((__le16 *)ha->request_ring)[i] =
 				cpu_to_le16(risc_code_address[i]);
 
 		mb[0] = MBC_LOAD_RAM;
@@ -2085,7 +2011,7 @@ qla1280_start_firmware(struct scsi_qla_h
 	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
 	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
 	if (err) {
-		printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no);
+		printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no);
 		return err;
 	}
 
@@ -2105,14 +2031,7 @@ qla1280_start_firmware(struct scsi_qla_h
 static int
 qla1280_load_firmware(struct scsi_qla_host *ha)
 {
-	int err = -ENODEV;
-
-	/* If firmware needs to be loaded */
-	if (!qla1280_isp_firmware(ha)) {
-		printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
-				ha->host_no);
-		goto out;
-	}
+	int err;
 
 	err = qla1280_chip_diag(ha);
 	if (err)
@@ -2246,17 +2165,17 @@ qla1280_set_target_defaults(struct scsi_
 {
 	struct nvram *nv = &ha->nvram;
 
-	nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1;
-	nv->bus[bus].target[target].parameter.f.auto_request_sense = 1;
-	nv->bus[bus].target[target].parameter.f.tag_queuing = 1;
-	nv->bus[bus].target[target].parameter.f.enable_sync = 1;
+	nv->bus[bus].target[target].parameter.renegotiate_on_error = 1;
+	nv->bus[bus].target[target].parameter.auto_request_sense = 1;
+	nv->bus[bus].target[target].parameter.tag_queuing = 1;
+	nv->bus[bus].target[target].parameter.enable_sync = 1;
 #if 1	/* Some SCSI Processors do not seem to like this */
-	nv->bus[bus].target[target].parameter.f.enable_wide = 1;
+	nv->bus[bus].target[target].parameter.enable_wide = 1;
 #endif
-	nv->bus[bus].target[target].parameter.f.parity_checking = 1;
-	nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
 	nv->bus[bus].target[target].execution_throttle =
 		nv->bus[bus].max_queue_depth - 1;
+	nv->bus[bus].target[target].parameter.parity_checking = 1;
+	nv->bus[bus].target[target].parameter.disconnect_allowed = 1;
 
 	if (IS_ISP1x160(ha)) {
 		nv->bus[bus].target[target].flags.flags1x160.device_enable = 1;
@@ -2284,9 +2203,9 @@ qla1280_set_defaults(struct scsi_qla_hos
 	/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
 	nv->firmware_feature.f.enable_fast_posting = 1;
 	nv->firmware_feature.f.disable_synchronous_backoff = 1;
-	nv->termination.f.scsi_bus_0_control = 3;
-	nv->termination.f.scsi_bus_1_control = 3;
-	nv->termination.f.auto_term_support = 1;
+	nv->termination.scsi_bus_0_control = 3;
+	nv->termination.scsi_bus_1_control = 3;
+	nv->termination.auto_term_support = 1;
 
 	/*
 	 * Set default FIFO magic - What appropriate values would be here
@@ -2296,7 +2215,12 @@ qla1280_set_defaults(struct scsi_qla_hos
 	 * header file provided by QLogic seems to be bogus or incomplete
 	 * at best.
 	 */
-	nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128;
+	nv->isp_config.burst_enable = 1;
+	if (IS_ISP1040(ha))
+		nv->isp_config.fifo_threshold |= 3;
+	else
+		nv->isp_config.fifo_threshold |= 4;
+
 	if (IS_ISP1x160(ha))
 		nv->isp_parameter = 0x01; /* fast memory enable */
 
@@ -2327,66 +2251,53 @@ qla1280_config_target(struct scsi_qla_ho
 	struct nvram *nv = &ha->nvram;
 	uint16_t mb[MAILBOX_REGISTER_COUNT];
 	int status, lun;
+	uint16_t flag;
 
 	/* Set Target Parameters. */
 	mb[0] = MBC_SET_TARGET_PARAMETERS;
-	mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
-	mb[1] <<= 8;
-
-	/*
-	 * Do not enable wide, sync, and ppr for the initial
-	 * INQUIRY run. We enable this later if we determine
-	 * the target actually supports it.
-	 */
-	nv->bus[bus].target[target].parameter.f.
-		auto_request_sense = 1;
-	nv->bus[bus].target[target].parameter.f.
-		stop_queue_on_check = 0;
-
-	if (IS_ISP1x160(ha))
-		nv->bus[bus].target[target].ppr_1x160.
-			flags.enable_ppr = 0;
+	mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
 
 	/*
-	 * No sync, wide, etc. while probing
+	 * Do not enable sync and ppr for the initial INQUIRY run. We
+	 * enable this later if we determine the target actually
+	 * supports it.
 	 */
-	mb[2] = (nv->bus[bus].target[target].parameter.c << 8) &
-		~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
+	mb[2] = (TP_RENEGOTIATE | TP_AUTO_REQUEST_SENSE | TP_TAGGED_QUEUE
+		 | TP_WIDE | TP_PARITY | TP_DISCONNECT);
 
 	if (IS_ISP1x160(ha))
 		mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
 	else
 		mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
 	mb[3] |= nv->bus[bus].target[target].sync_period;
-
-	status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
+	status = qla1280_mailbox_command(ha, 0x0f, mb);
 
 	/* Save Tag queuing enable flag. */
-	mb[0] = BIT_0 << target;
-	if (nv->bus[bus].target[target].parameter.f.tag_queuing)
-		ha->bus_settings[bus].qtag_enables |= mb[0];
+	flag = (BIT_0 << target) & mb[0];
+	if (nv->bus[bus].target[target].parameter.tag_queuing)
+		ha->bus_settings[bus].qtag_enables |= flag;
 
 	/* Save Device enable flag. */
 	if (IS_ISP1x160(ha)) {
 		if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
-			ha->bus_settings[bus].device_enables |= mb[0];
+			ha->bus_settings[bus].device_enables |= flag;
 		ha->bus_settings[bus].lun_disables |= 0;
 	} else {
 		if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
-			ha->bus_settings[bus].device_enables |= mb[0];
+			ha->bus_settings[bus].device_enables |= flag;
 		/* Save LUN disable flag. */
 		if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
-			ha->bus_settings[bus].lun_disables |= mb[0];
+			ha->bus_settings[bus].lun_disables |= flag;
 	}
 
 	/* Set Device Queue Parameters. */
 	for (lun = 0; lun < MAX_LUNS; lun++) {
 		mb[0] = MBC_SET_DEVICE_QUEUE;
-		mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
-		mb[1] = mb[1] << 8 | lun;
+		mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+		mb[1] |= lun;
 		mb[2] = nv->bus[bus].max_queue_depth;
 		mb[3] = nv->bus[bus].target[target].execution_throttle;
-		status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]);
+		status |= qla1280_mailbox_command(ha, 0x0f, mb);
 	}
 
 	return status;
@@ -2431,7 +2342,6 @@ qla1280_nvram_config(struct scsi_qla_hos
 	struct nvram *nv = &ha->nvram;
 	int bus, target, status = 0;
 	uint16_t mb[MAILBOX_REGISTER_COUNT];
-	uint16_t mask;
 
 	ENTER("qla1280_nvram_config");
 
@@ -2439,7 +2349,7 @@ qla1280_nvram_config(struct scsi_qla_hos
 		/* Always force AUTO sense for LINUX SCSI */
 		for (bus = 0; bus < MAX_BUSES; bus++)
 			for (target = 0; target < MAX_TARGETS; target++) {
-				nv->bus[bus].target[target].parameter.f.
+				nv->bus[bus].target[target].parameter.
 					auto_request_sense = 1;
 			}
 	} else {
@@ -2457,31 +2367,40 @@ qla1280_nvram_config(struct scsi_qla_hos
 
 		hwrev = RD_REG_WORD(&reg->cfg_0) & ISP_CFG0_HWMSK;
 
-		cfg1 = RD_REG_WORD(&reg->cfg_1);
+		cfg1 = RD_REG_WORD(&reg->cfg_1) & ~(BIT_4 | BIT_5 | BIT_6);
 		cdma_conf = RD_REG_WORD(&reg->cdma_cfg);
 		ddma_conf = RD_REG_WORD(&reg->ddma_cfg);
 
 		/* Busted fifo, says mjacob. */
-		if (hwrev == ISP_CFG0_1040A)
-			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64);
-		else
-			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB);
+		if (hwrev != ISP_CFG0_1040A)
+			cfg1 |= nv->isp_config.fifo_threshold << 4;
+
+		cfg1 |= nv->isp_config.burst_enable << 2;
+		WRT_REG_WORD(&reg->cfg_1, cfg1);
 
 		WRT_REG_WORD(&reg->cdma_cfg, cdma_conf | CDMA_CONF_BENAB);
 		WRT_REG_WORD(&reg->ddma_cfg, cdma_conf | DDMA_CONF_BENAB);
 	} else {
+		uint16_t cfg1, term;
+
 		/* Set ISP hardware DMA burst */
-		mb[0] = nv->isp_config.c;
+		cfg1 = nv->isp_config.fifo_threshold << 4;
+		cfg1 |= nv->isp_config.burst_enable << 2;
 		/* Enable DMA arbitration on dual channel controllers */
 		if (ha->ports > 1)
-			mb[0] |= BIT_13;
-		WRT_REG_WORD(&reg->cfg_1, mb[0]);
+			cfg1 |= BIT_13;
+		WRT_REG_WORD(&reg->cfg_1, cfg1);
 
 		/* Set SCSI termination. */
-		WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
-		mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
-		WRT_REG_WORD(&reg->gpio_data, mb[0]);
+		WRT_REG_WORD(&reg->gpio_enable,
+			     BIT_7 | BIT_3 | BIT_2 | BIT_1 | BIT_0);
+		term = nv->termination.scsi_bus_1_control;
+		term |= nv->termination.scsi_bus_0_control << 2;
+		term |= nv->termination.auto_term_support << 7;
+		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
+		WRT_REG_WORD(&reg->gpio_data, term);
 	}
+	RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
 
 	/* ISP parameter word. */
 	mb[0] = MBC_SET_SYSTEM_PARAMETER;
@@ -2497,16 +2416,17 @@ qla1280_nvram_config(struct scsi_qla_hos
 
 	/* Firmware feature word. */
 	mb[0] = MBC_SET_FIRMWARE_FEATURES;
-	mask = BIT_5 | BIT_1 | BIT_0;
-	mb[1] = le16_to_cpu(nv->firmware_feature.w) & (mask);
+	mb[1] = nv->firmware_feature.f.enable_fast_posting;
+	mb[1] |= nv->firmware_feature.f.report_lvd_bus_transition << 1;
+	mb[1] |= nv->firmware_feature.f.disable_synchronous_backoff << 5;
 #if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2)
 	if (ia64_platform_is("sn2")) {
 		printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
 		       "workaround\n", ha->host_no);
-		mb[1] |= BIT_9;
+		mb[1] |= nv->firmware_feature.f.unused_9 << 9; /* XXX */
 	}
 #endif
-	status |= qla1280_mailbox_command(ha, mask, &mb[0]);
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
 
 	/* Retry count and delay. */
 	mb[0] = MBC_SET_RETRY_COUNT;
@@ -2535,27 +2455,27 @@ qla1280_nvram_config(struct scsi_qla_hos
 		mb[2] |= BIT_5;
 	if (nv->bus[1].config_2.data_line_active_negation)
 		mb[2] |= BIT_4;
-	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
 
 	mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY;
 	mb[1] = 2;	/* Reset SCSI bus and return all outstanding IO */
-	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
 
 	/* thingy */
 	mb[0] = MBC_SET_PCI_CONTROL;
-	mb[1] = 2;	/* Data DMA Channel Burst Enable */
-	mb[2] = 2;	/* Command DMA Channel Burst Enable */
-	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+	mb[1] = BIT_1;	/* Data DMA Channel Burst Enable */
+	mb[2] = BIT_1;	/* Command DMA Channel Burst Enable */
+	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
 
 	mb[0] = MBC_SET_TAG_AGE_LIMIT;
 	mb[1] = 8;
-	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
 
 	/* Selection timeout. */
 	mb[0] = MBC_SET_SELECTION_TIMEOUT;
 	mb[1] = nv->bus[0].selection_timeout;
 	mb[2] = nv->bus[1].selection_timeout;
-	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
 
 	for (bus = 0; bus < ha->ports; bus++)
 		status |= qla1280_config_bus(ha, bus);
@@ -3066,7 +2986,7 @@ qla1280_64bit_start_scsi(struct scsi_qla
 	struct scsi_cmnd *cmd = sp->cmd;
 	cmd_a64_entry_t *pkt;
 	struct scatterlist *sg = NULL;
-	u32 *dword_ptr;
+	__le32 *dword_ptr;
 	dma_addr_t dma_handle;
 	int status = 0;
 	int cnt;
@@ -3104,10 +3024,13 @@ qla1280_64bit_start_scsi(struct scsi_qla
 				REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
 	}
 
+	dprintk(3, "Number of free entries=(%d) seg_cnt=0x%x\n",
+		ha->req_q_cnt, seg_cnt);
+
 	/* If room for request in request ring. */
 	if ((req_cnt + 2) >= ha->req_q_cnt) {
 		status = 1;
-		dprintk(2, "qla1280_64bit_start_scsi: in-ptr=0x%x  req_q_cnt="
+		dprintk(2, "qla1280_start_scsi: in-ptr=0x%x  req_q_cnt="
 			"0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
 			req_cnt);
 		goto out;
@@ -3119,7 +3042,7 @@ qla1280_64bit_start_scsi(struct scsi_qla
 
 	if (cnt >= MAX_OUTSTANDING_COMMANDS) {
 		status = 1;
-		dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN "
+		dprintk(2, "qla1280_start_scsi: NO ROOM IN "
 			"OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt);
 		goto out;
 	}
@@ -3128,7 +3051,7 @@ qla1280_64bit_start_scsi(struct scsi_qla
 	ha->req_q_cnt -= req_cnt;
 	CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1);
 
-	dprintk(2, "64bit_start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
+	dprintk(2, "start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
 		cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd));
 	dprintk(2, "             bus %i, target %i, lun %i\n",
 		SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
@@ -3350,7 +3273,7 @@ qla1280_32bit_start_scsi(struct scsi_qla
 	struct scsi_cmnd *cmd = sp->cmd;
 	struct cmd_entry *pkt;
 	struct scatterlist *sg = NULL;
-	uint32_t *dword_ptr;
+	__le32 *dword_ptr;
 	int status = 0;
 	int cnt;
 	int req_cnt;
@@ -3993,21 +3916,21 @@ qla1280_get_target_options(struct scsi_c
 	result = cmd->request_buffer;
 	n = &ha->nvram;
 
-	n->bus[bus].target[target].parameter.f.enable_wide = 0;
-	n->bus[bus].target[target].parameter.f.enable_sync = 0;
+	n->bus[bus].target[target].parameter.enable_wide = 0;
+	n->bus[bus].target[target].parameter.enable_sync = 0;
 	n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
 
         if (result[7] & 0x60)
-		n->bus[bus].target[target].parameter.f.enable_wide = 1;
+		n->bus[bus].target[target].parameter.enable_wide = 1;
         if (result[7] & 0x10)
-		n->bus[bus].target[target].parameter.f.enable_sync = 1;
+		n->bus[bus].target[target].parameter.enable_sync = 1;
 	if ((result[2] >= 3) && (result[4] + 5 > 56) &&
 	    (result[56] & 0x4))
 		n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
 
 	dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n",
-		n->bus[bus].target[target].parameter.f.enable_wide,
-		n->bus[bus].target[target].parameter.f.enable_sync,
+		n->bus[bus].target[target].parameter.enable_wide,
+		n->bus[bus].target[target].parameter.enable_sync,
 		n->bus[bus].target[target].ppr_1x160.flags.enable_ppr);
 }
 #endif
@@ -4071,7 +3994,7 @@ qla1280_status_entry(struct scsi_qla_hos
 		/* Save ISP completion status */
 		CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd);
 
-		if (scsi_status & SS_CHECK_CONDITION) {
+		if (scsi_status & SAM_STAT_CHECK_CONDITION) {
 			if (comp_status != CS_ARS_FAILED) {
 				uint16_t req_sense_length =
 					le16_to_cpu(pkt->req_sense_length);
@@ -4650,7 +4573,7 @@ qla1280_probe_one(struct pci_dev *pdev, 
 	if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
 		if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
 			printk(KERN_WARNING "scsi(%li): Unable to set a "
-			       " suitable DMA mask - aboring\n", ha->host_no);
+			       "suitable DMA mask - aborting\n", ha->host_no);
 			error = -ENODEV;
 			goto error_free_irq;
 		}
@@ -4660,14 +4583,14 @@ qla1280_probe_one(struct pci_dev *pdev, 
 #else
 	if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
 		printk(KERN_WARNING "scsi(%li): Unable to set a "
-		       " suitable DMA mask - aboring\n", ha->host_no);
+		       "suitable DMA mask - aborting\n", ha->host_no);
 		error = -ENODEV;
 		goto error_free_irq;
 	}
 #endif
 
 	ha->request_ring = pci_alloc_consistent(ha->pdev,
-			((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+			((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
 			&ha->request_dma);
 	if (!ha->request_ring) {
 		printk(KERN_INFO "qla1280: Failed to get request memory\n");
@@ -4675,7 +4598,7 @@ qla1280_probe_one(struct pci_dev *pdev, 
 	}
 
 	ha->response_ring = pci_alloc_consistent(ha->pdev,
-			((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
+			((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
 			&ha->response_dma);
 	if (!ha->response_ring) {
 		printk(KERN_INFO "qla1280: Failed to get response memory\n");
@@ -4758,7 +4681,7 @@ qla1280_probe_one(struct pci_dev *pdev, 
 
 #if LINUX_VERSION_CODE >= 0x020600
  error_disable_adapter:
-	WRT_REG_WORD(&ha->iobase->ictrl, 0);
+	qla1280_disable_intrs(ha);
 #endif
  error_free_irq:
 	free_irq(pdev->irq, ha);
@@ -4770,11 +4693,11 @@ qla1280_probe_one(struct pci_dev *pdev, 
 #endif
  error_free_response_ring:
 	pci_free_consistent(ha->pdev,
-			((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
+			((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
 			ha->response_ring, ha->response_dma);
  error_free_request_ring:
 	pci_free_consistent(ha->pdev,
-			((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+			((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
 			ha->request_ring, ha->request_dma);
  error_put_host:
 	scsi_host_put(host);
@@ -4795,7 +4718,7 @@ qla1280_remove_one(struct pci_dev *pdev)
 	scsi_remove_host(host);
 #endif
 
-	WRT_REG_WORD(&ha->iobase->ictrl, 0);
+	qla1280_disable_intrs(ha);
 
 	free_irq(pdev->irq, ha);
 
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -94,9 +94,6 @@
 #define REQUEST_ENTRY_CNT		256 /* Number of request entries. */
 #define RESPONSE_ENTRY_CNT		16  /* Number of response entries. */
 
-/* Number of segments 1 - 65535 */
-#define SG_SEGMENTS			32  /* Cmd entry + 6 continuations */
-
 /*
  * SCSI Request Block structure  (sp)  that is placed
  * on cmd->SCp location of every I/O
@@ -378,29 +375,23 @@ struct nvram {
 	uint16_t unused_12;	/* 12, 13 */
 	uint16_t unused_14;	/* 14, 15 */
 
-	union {
-		uint8_t c;
-		struct {
-			uint8_t reserved:2;
-			uint8_t burst_enable:1;
-			uint8_t reserved_1:1;
-			uint8_t fifo_threshold:4;
-		} f;
+	struct {
+		uint8_t reserved:2;
+		uint8_t burst_enable:1;
+		uint8_t reserved_1:1;
+		uint8_t fifo_threshold:4;
 	} isp_config;		/* 16 */
 
 	/* Termination
 	 * 0 = Disable, 1 = high only, 3 = Auto term
 	 */
-	union {
-		uint8_t c;
-		struct {
-			uint8_t scsi_bus_1_control:2;
-			uint8_t scsi_bus_0_control:2;
-			uint8_t unused_0:1;
-			uint8_t unused_1:1;
-			uint8_t unused_2:1;
-			uint8_t auto_term_support:1;
-		} f;
+	struct {
+		uint8_t scsi_bus_1_control:2;
+		uint8_t scsi_bus_0_control:2;
+		uint8_t unused_0:1;
+		uint8_t unused_1:1;
+		uint8_t unused_2:1;
+		uint8_t auto_term_support:1;
 	} termination;		/* 17 */
 
 	uint16_t isp_parameter;	/* 18, 19 */
@@ -460,18 +451,15 @@ struct nvram {
 		uint16_t unused_38;	/* 38, 39 */
 
 		struct {
-			union {
-				uint8_t c;
-				struct {
-					uint8_t renegotiate_on_error:1;
-					uint8_t stop_queue_on_check:1;
-					uint8_t auto_request_sense:1;
-					uint8_t tag_queuing:1;
-					uint8_t enable_sync:1;
-					uint8_t enable_wide:1;
-					uint8_t parity_checking:1;
-					uint8_t disconnect_allowed:1;
-				} f;
+			struct {
+				uint8_t renegotiate_on_error:1;
+				uint8_t stop_queue_on_check:1;
+				uint8_t auto_request_sense:1;
+				uint8_t tag_queuing:1;
+				uint8_t enable_sync:1;
+				uint8_t enable_wide:1;
+				uint8_t parity_checking:1;
+				uint8_t disconnect_allowed:1;
 			} parameter;	/* 40 */
 
 			uint8_t execution_throttle;	/* 41 */
@@ -528,23 +516,23 @@ struct cmd_entry {
 	uint8_t entry_count;		/* Entry count. */
 	uint8_t sys_define;		/* System defined. */
 	uint8_t entry_status;		/* Entry Status. */
-	uint32_t handle;		/* System handle. */
+	__le32 handle;			/* System handle. */
 	uint8_t lun;			/* SCSI LUN */
 	uint8_t target;			/* SCSI ID */
-	uint16_t cdb_len;		/* SCSI command length. */
-	uint16_t control_flags;		/* Control flags. */
-	uint16_t reserved;
-	uint16_t timeout;		/* Command timeout. */
-	uint16_t dseg_count;		/* Data segment count. */
+	__le16 cdb_len;			/* SCSI command length. */
+	__le16 control_flags;		/* Control flags. */
+	__le16 reserved;
+	__le16 timeout;			/* Command timeout. */
+	__le16 dseg_count;		/* Data segment count. */
 	uint8_t scsi_cdb[MAX_CMDSZ];	/* SCSI command words. */
-	uint32_t dseg_0_address;	/* Data segment 0 address. */
-	uint32_t dseg_0_length;		/* Data segment 0 length. */
-	uint32_t dseg_1_address;	/* Data segment 1 address. */
-	uint32_t dseg_1_length;		/* Data segment 1 length. */
-	uint32_t dseg_2_address;	/* Data segment 2 address. */
-	uint32_t dseg_2_length;		/* Data segment 2 length. */
-	uint32_t dseg_3_address;	/* Data segment 3 address. */
-	uint32_t dseg_3_length;		/* Data segment 3 length. */
+	__le32 dseg_0_address;		/* Data segment 0 address. */
+	__le32 dseg_0_length;		/* Data segment 0 length. */
+	__le32 dseg_1_address;		/* Data segment 1 address. */
+	__le32 dseg_1_length;		/* Data segment 1 length. */
+	__le32 dseg_2_address;		/* Data segment 2 address. */
+	__le32 dseg_2_length;		/* Data segment 2 length. */
+	__le32 dseg_3_address;		/* Data segment 3 address. */
+	__le32 dseg_3_length;		/* Data segment 3 length. */
 };
 
 /*
@@ -556,21 +544,21 @@ struct cont_entry {
 	uint8_t entry_count;		/* Entry count. */
 	uint8_t sys_define;		/* System defined. */
 	uint8_t entry_status;		/* Entry Status. */
-	uint32_t reserved;		/* Reserved */
-	uint32_t dseg_0_address;	/* Data segment 0 address. */
-	uint32_t dseg_0_length;		/* Data segment 0 length. */
-	uint32_t dseg_1_address;	/* Data segment 1 address. */
-	uint32_t dseg_1_length;		/* Data segment 1 length. */
-	uint32_t dseg_2_address;	/* Data segment 2 address. */
-	uint32_t dseg_2_length;		/* Data segment 2 length. */
-	uint32_t dseg_3_address;	/* Data segment 3 address. */
-	uint32_t dseg_3_length;		/* Data segment 3 length. */
-	uint32_t dseg_4_address;	/* Data segment 4 address. */
-	uint32_t dseg_4_length;		/* Data segment 4 length. */
-	uint32_t dseg_5_address;	/* Data segment 5 address. */
-	uint32_t dseg_5_length;		/* Data segment 5 length. */
-	uint32_t dseg_6_address;	/* Data segment 6 address. */
-	uint32_t dseg_6_length;		/* Data segment 6 length. */
+	__le32 reserved;		/* Reserved */
+	__le32 dseg_0_address;		/* Data segment 0 address. */
+	__le32 dseg_0_length;		/* Data segment 0 length. */
+	__le32 dseg_1_address;		/* Data segment 1 address. */
+	__le32 dseg_1_length;		/* Data segment 1 length. */
+	__le32 dseg_2_address;		/* Data segment 2 address. */
+	__le32 dseg_2_length;		/* Data segment 2 length. */
+	__le32 dseg_3_address;		/* Data segment 3 address. */
+	__le32 dseg_3_length;		/* Data segment 3 length. */
+	__le32 dseg_4_address;		/* Data segment 4 address. */
+	__le32 dseg_4_length;		/* Data segment 4 length. */
+	__le32 dseg_5_address;		/* Data segment 5 address. */
+	__le32 dseg_5_length;		/* Data segment 5 length. */
+	__le32 dseg_6_address;		/* Data segment 6 address. */
+	__le32 dseg_6_length;		/* Data segment 6 length. */
 };
 
 /*
@@ -586,22 +574,22 @@ struct response {
 #define RF_FULL         BIT_1	/* Full */
 #define RF_BAD_HEADER   BIT_2	/* Bad header. */
 #define RF_BAD_PAYLOAD  BIT_3	/* Bad payload. */
-	uint32_t handle;	/* System handle. */
-	uint16_t scsi_status;	/* SCSI status. */
-	uint16_t comp_status;	/* Completion status. */
-	uint16_t state_flags;	/* State flags. */
-#define SF_TRANSFER_CMPL BIT_14	/* Transfer Complete. */
-#define SF_GOT_SENSE    BIT_13	/* Got Sense */
-#define SF_GOT_STATUS    BIT_12	/* Got Status */
-#define SF_TRANSFERRED_DATA BIT_11	/* Transferred data */
-#define SF_SENT_CDB   BIT_10	/* Send CDB */
-#define SF_GOT_TARGET  BIT_9	/*  */
-#define SF_GOT_BUS     BIT_8	/*  */
-	uint16_t status_flags;	/* Status flags. */
-	uint16_t time;		/* Time. */
-	uint16_t req_sense_length;	/* Request sense data length. */
-	uint32_t residual_length;	/* Residual transfer length. */
-	uint16_t reserved[4];
+	__le32 handle;		/* System handle. */
+	__le16 scsi_status;	/* SCSI status. */
+	__le16 comp_status;	/* Completion status. */
+	__le16 state_flags;	/* State flags. */
+#define SF_TRANSFER_CMPL	BIT_14	/* Transfer Complete. */
+#define SF_GOT_SENSE	 	BIT_13	/* Got Sense */
+#define SF_GOT_STATUS	 	BIT_12	/* Got Status */
+#define SF_TRANSFERRED_DATA	BIT_11	/* Transferred data */
+#define SF_SENT_CDB	 	BIT_10	/* Send CDB */
+#define SF_GOT_TARGET	 	BIT_9	/*  */
+#define SF_GOT_BUS	 	BIT_8	/*  */
+	__le16 status_flags;	/* Status flags. */
+	__le16 time;		/* Time. */
+	__le16 req_sense_length;/* Request sense data length. */
+	__le32 residual_length;	/* Residual transfer length. */
+	__le16 reserved[4];
 	uint8_t req_sense_data[32];	/* Request sense data. */
 };
 
@@ -614,7 +602,7 @@ struct mrk_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t sys_define;	/* System defined. */
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved;
+	__le32 reserved;
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t target;		/* SCSI ID */
 	uint8_t modifier;	/* Modifier (7-0). */
@@ -638,11 +626,11 @@ struct ecmd_entry {
 	uint32_t handle;	/* System handle. */
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t target;		/* SCSI ID */
-	uint16_t cdb_len;	/* SCSI command length. */
-	uint16_t control_flags;	/* Control flags. */
-	uint16_t reserved;
-	uint16_t timeout;	/* Command timeout. */
-	uint16_t dseg_count;	/* Data segment count. */
+	__le16 cdb_len;		/* SCSI command length. */
+	__le16 control_flags;	/* Control flags. */
+	__le16 reserved;
+	__le16 timeout;		/* Command timeout. */
+	__le16 dseg_count;	/* Data segment count. */
 	uint8_t scsi_cdb[88];	/* SCSI command words. */
 };
 
@@ -655,20 +643,20 @@ typedef struct {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t sys_define;	/* System defined. */
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t handle;	/* System handle. */
+	__le32 handle;	/* System handle. */
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t target;		/* SCSI ID */
-	uint16_t cdb_len;	/* SCSI command length. */
-	uint16_t control_flags;	/* Control flags. */
-	uint16_t reserved;
-	uint16_t timeout;	/* Command timeout. */
-	uint16_t dseg_count;	/* Data segment count. */
+	__le16 cdb_len;	/* SCSI command length. */
+	__le16 control_flags;	/* Control flags. */
+	__le16 reserved;
+	__le16 timeout;	/* Command timeout. */
+	__le16 dseg_count;	/* Data segment count. */
 	uint8_t scsi_cdb[MAX_CMDSZ];	/* SCSI command words. */
-	uint32_t reserved_1[2];	/* unused */
-	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
-	uint32_t dseg_0_length;	/* Data segment 0 length. */
-	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
-	uint32_t dseg_1_length;	/* Data segment 1 length. */
+	__le32 reserved_1[2];	/* unused */
+	__le32 dseg_0_address[2];	/* Data segment 0 address. */
+	__le32 dseg_0_length;	/* Data segment 0 length. */
+	__le32 dseg_1_address[2];	/* Data segment 1 address. */
+	__le32 dseg_1_length;	/* Data segment 1 length. */
 } cmd_a64_entry_t, request_t;
 
 /*
@@ -680,16 +668,16 @@ struct cont_a64_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t sys_define;	/* System defined. */
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
-	uint32_t dseg_0_length;	/* Data segment 0 length. */
-	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
-	uint32_t dseg_1_length;	/* Data segment 1 length. */
-	uint32_t dseg_2_address[2];	/* Data segment 2 address. */
-	uint32_t dseg_2_length;	/* Data segment 2 length. */
-	uint32_t dseg_3_address[2];	/* Data segment 3 address. */
-	uint32_t dseg_3_length;	/* Data segment 3 length. */
-	uint32_t dseg_4_address[2];	/* Data segment 4 address. */
-	uint32_t dseg_4_length;	/* Data segment 4 length. */
+	__le32 dseg_0_address[2];	/* Data segment 0 address. */
+	__le32 dseg_0_length;		/* Data segment 0 length. */
+	__le32 dseg_1_address[2];	/* Data segment 1 address. */
+	__le32 dseg_1_length;		/* Data segment 1 length. */
+	__le32 dseg_2_address[2];	/* Data segment 2 address. */
+	__le32 dseg_2_length;		/* Data segment 2 length. */
+	__le32 dseg_3_address[2];	/* Data segment 3 address. */
+	__le32 dseg_3_length;		/* Data segment 3 length. */
+	__le32 dseg_4_address[2];	/* Data segment 4 address. */
+	__le32 dseg_4_length;		/* Data segment 4 length. */
 };
 
 /*
@@ -701,10 +689,10 @@ struct elun_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status not used. */
-	uint32_t reserved_2;
-	uint16_t lun;		/* Bit 15 is bus number. */
-	uint16_t reserved_4;
-	uint32_t option_flags;
+	__le32 reserved_2;
+	__le16 lun;		/* Bit 15 is bus number. */
+	__le16 reserved_4;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t reserved_5;
 	uint8_t command_count;	/* Number of ATIOs allocated. */
@@ -714,8 +702,8 @@ struct elun_entry {
 	/* commands (2-26). */
 	uint8_t group_7_length;	/* SCSI CDB length for group 7 */
 	/* commands (2-26). */
-	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
-	uint16_t reserved_6[20];
+	__le16 timeout;		/* 0 = 30 seconds, 0xFFFF = disable */
+	__le16 reserved_6[20];
 };
 
 /*
@@ -729,20 +717,20 @@ struct modify_lun_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t reserved_3;
 	uint8_t operators;
 	uint8_t reserved_4;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t reserved_5;
 	uint8_t command_count;	/* Number of ATIOs allocated. */
 	uint8_t immed_notify_count;	/* Number of Immediate Notify */
 	/* entries allocated. */
-	uint16_t reserved_6;
-	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
-	uint16_t reserved_7[20];
+	__le16 reserved_6;
+	__le16 timeout;		/* 0 = 30 seconds, 0xFFFF = disable */
+	__le16 reserved_7[20];
 };
 
 /*
@@ -754,20 +742,20 @@ struct notify_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;
 	uint8_t initiator_id;
 	uint8_t reserved_3;
 	uint8_t target_id;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t reserved_4;
 	uint8_t tag_value;	/* Received queue tag message value */
 	uint8_t tag_type;	/* Received queue tag message type */
 	/* entries allocated. */
-	uint16_t seq_id;
+	__le16 seq_id;
 	uint8_t scsi_msg[8];	/* SCSI message not handled by ISP */
-	uint16_t reserved_5[8];
+	__le16 reserved_5[8];
 	uint8_t sense_data[18];
 };
 
@@ -780,16 +768,16 @@ struct nack_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;
 	uint8_t initiator_id;
 	uint8_t reserved_3;
 	uint8_t target_id;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t event;
-	uint16_t seq_id;
-	uint16_t reserved_4[22];
+	__le16 seq_id;
+	__le16 reserved_4[22];
 };
 
 /*
@@ -801,12 +789,12 @@ struct atio_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;
 	uint8_t initiator_id;
 	uint8_t cdb_len;
 	uint8_t target_id;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t scsi_status;
 	uint8_t tag_value;	/* Received queue tag message value */
@@ -824,28 +812,28 @@ struct ctio_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t initiator_id;
 	uint8_t reserved_3;
 	uint8_t target_id;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t scsi_status;
 	uint8_t tag_value;	/* Received queue tag message value */
 	uint8_t tag_type;	/* Received queue tag message type */
-	uint32_t transfer_length;
-	uint32_t residual;
-	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
-	uint16_t dseg_count;	/* Data segment count. */
-	uint32_t dseg_0_address;	/* Data segment 0 address. */
-	uint32_t dseg_0_length;	/* Data segment 0 length. */
-	uint32_t dseg_1_address;	/* Data segment 1 address. */
-	uint32_t dseg_1_length;	/* Data segment 1 length. */
-	uint32_t dseg_2_address;	/* Data segment 2 address. */
-	uint32_t dseg_2_length;	/* Data segment 2 length. */
-	uint32_t dseg_3_address;	/* Data segment 3 address. */
-	uint32_t dseg_3_length;	/* Data segment 3 length. */
+	__le32 transfer_length;
+	__le32 residual;
+	__le16 timeout;		/* 0 = 30 seconds, 0xFFFF = disable */
+	__le16 dseg_count;	/* Data segment count. */
+	__le32 dseg_0_address;	/* Data segment 0 address. */
+	__le32 dseg_0_length;	/* Data segment 0 length. */
+	__le32 dseg_1_address;	/* Data segment 1 address. */
+	__le32 dseg_1_length;	/* Data segment 1 length. */
+	__le32 dseg_2_address;	/* Data segment 2 address. */
+	__le32 dseg_2_length;	/* Data segment 2 length. */
+	__le32 dseg_3_address;	/* Data segment 3 address. */
+	__le32 dseg_3_length;	/* Data segment 3 length. */
 };
 
 /*
@@ -857,24 +845,24 @@ struct ctio_ret_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t initiator_id;
 	uint8_t reserved_3;
 	uint8_t target_id;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t scsi_status;
 	uint8_t tag_value;	/* Received queue tag message value */
 	uint8_t tag_type;	/* Received queue tag message type */
-	uint32_t transfer_length;
-	uint32_t residual;
-	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
-	uint16_t dseg_count;	/* Data segment count. */
-	uint32_t dseg_0_address;	/* Data segment 0 address. */
-	uint32_t dseg_0_length;	/* Data segment 0 length. */
-	uint32_t dseg_1_address;	/* Data segment 1 address. */
-	uint16_t dseg_1_length;	/* Data segment 1 length. */
+	__le32 transfer_length;
+	__le32 residual;
+	__le16 timeout;		/* 0 = 30 seconds, 0xFFFF = disable */
+	__le16 dseg_count;	/* Data segment count. */
+	__le32 dseg_0_address;	/* Data segment 0 address. */
+	__le32 dseg_0_length;	/* Data segment 0 length. */
+	__le32 dseg_1_address;	/* Data segment 1 address. */
+	__le16 dseg_1_length;	/* Data segment 1 length. */
 	uint8_t sense_data[18];
 };
 
@@ -887,25 +875,25 @@ struct ctio_a64_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t initiator_id;
 	uint8_t reserved_3;
 	uint8_t target_id;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t scsi_status;
 	uint8_t tag_value;	/* Received queue tag message value */
 	uint8_t tag_type;	/* Received queue tag message type */
-	uint32_t transfer_length;
-	uint32_t residual;
-	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
-	uint16_t dseg_count;	/* Data segment count. */
-	uint32_t reserved_4[2];
-	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
-	uint32_t dseg_0_length;	/* Data segment 0 length. */
-	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
-	uint32_t dseg_1_length;	/* Data segment 1 length. */
+	__le32 transfer_length;
+	__le32 residual;
+	__le16 timeout;		/* 0 = 30 seconds, 0xFFFF = disable */
+	__le16 dseg_count;	/* Data segment count. */
+	__le32 reserved_4[2];
+	__le32 dseg_0_address[2];/* Data segment 0 address. */
+	__le32 dseg_0_length;	/* Data segment 0 length. */
+	__le32 dseg_1_address[2];/* Data segment 1 address. */
+	__le32 dseg_1_length;	/* Data segment 1 length. */
 };
 
 /*
@@ -917,21 +905,21 @@ struct ctio_a64_ret_entry {
 	uint8_t entry_count;	/* Entry count. */
 	uint8_t reserved_1;
 	uint8_t entry_status;	/* Entry Status. */
-	uint32_t reserved_2;
+	__le32 reserved_2;
 	uint8_t lun;		/* SCSI LUN */
 	uint8_t initiator_id;
 	uint8_t reserved_3;
 	uint8_t target_id;
-	uint32_t option_flags;
+	__le32 option_flags;
 	uint8_t status;
 	uint8_t scsi_status;
 	uint8_t tag_value;	/* Received queue tag message value */
 	uint8_t tag_type;	/* Received queue tag message type */
-	uint32_t transfer_length;
-	uint32_t residual;
-	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
-	uint16_t dseg_count;	/* Data segment count. */
-	uint16_t reserved_4[7];
+	__le32 transfer_length;
+	__le32 residual;
+	__le16 timeout;		/* 0 = 30 seconds, 0xFFFF = disable */
+	__le16 dseg_count;	/* Data segment count. */
+	__le16 reserved_4[7];
 	uint8_t sense_data[18];
 };
 
@@ -979,14 +967,6 @@ struct ctio_a64_ret_entry {
 #define CS_RETRY            0x82	/* Driver defined */
 
 /*
- * ISP status entry - SCSI status byte bit definitions.
- */
-#define SS_CHECK_CONDITION  BIT_1
-#define SS_CONDITION_MET    BIT_2
-#define SS_BUSY_CONDITION   BIT_3
-#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3)
-
-/*
  * ISP target entries - Option flags bit definitions.
  */
 #define OF_ENABLE_TAG       BIT_1	/* Tagged queue action enable */
@@ -1082,10 +1062,6 @@ struct scsi_qla_host {
 		uint32_t reset_active:1;		/* 3 */
 		uint32_t abort_isp_active:1;		/* 4 */
 		uint32_t disable_risc_code_load:1;	/* 5 */
-		uint32_t enable_64bit_addressing:1;	/* 6 */
-		uint32_t in_reset:1;			/* 7 */
-		uint32_t ints_enabled:1;
-		uint32_t ignore_nvram:1;
 #ifdef __ia64__
 		uint32_t use_pci_vchannel:1;
 #endif
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -211,6 +211,138 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t 
 	sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
 }
 
+/* Scsi_Host attributes. */
+
+static ssize_t
+qla2x00_drvr_version_show(struct class_device *cdev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
+}
+
+static ssize_t
+qla2x00_fw_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	char fw_str[30];
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+	    ha->isp_ops.fw_version_str(ha, fw_str));
+}
+
+static ssize_t
+qla2x00_serial_num_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	uint32_t sn;
+
+	sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
+	return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
+	    sn % 100000);
+}
+
+static ssize_t
+qla2x00_isp_name_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	return snprintf(buf, PAGE_SIZE, "%s\n", ha->brd_info->isp_name);
+}
+
+static ssize_t
+qla2x00_isp_id_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
+	    ha->product_id[0], ha->product_id[1], ha->product_id[2],
+	    ha->product_id[3]);
+}
+
+static ssize_t
+qla2x00_model_name_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number);
+}
+
+static ssize_t
+qla2x00_model_desc_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+	    ha->model_desc ? ha->model_desc: "");
+}
+
+static ssize_t
+qla2x00_pci_info_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	char pci_info[30];
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+	    ha->isp_ops.pci_info_str(ha, pci_info));
+}
+
+static ssize_t
+qla2x00_state_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+	int len = 0;
+
+	if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+	    atomic_read(&ha->loop_state) == LOOP_DEAD)
+		len = snprintf(buf, PAGE_SIZE, "Link Down\n");
+	else if (atomic_read(&ha->loop_state) != LOOP_READY ||
+	    test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
+	    test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags))
+		len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n");
+	else {
+		len = snprintf(buf, PAGE_SIZE, "Link Up - ");
+
+		switch (ha->current_topology) {
+		case ISP_CFG_NL:
+			len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
+			break;
+		case ISP_CFG_FL:
+			len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n");
+			break;
+		case ISP_CFG_N:
+			len += snprintf(buf + len, PAGE_SIZE-len,
+			    "N_Port to N_Port\n");
+			break;
+		case ISP_CFG_F:
+			len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n");
+			break;
+		default:
+			len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
+			break;
+		}
+	}
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
+	NULL);
+static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
+static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
+static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
+static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
+static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
+static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
+static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
+static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
+
+struct class_device_attribute *qla2x00_host_attrs[] = {
+	&class_device_attr_driver_version,
+	&class_device_attr_fw_version,
+	&class_device_attr_serial_num,
+	&class_device_attr_isp_name,
+	&class_device_attr_isp_id,
+	&class_device_attr_model_name,
+	&class_device_attr_model_desc,
+	&class_device_attr_pci_info,
+	&class_device_attr_state,
+	NULL,
+};
+
 /* Host attributes. */
 
 static void
@@ -304,10 +436,13 @@ struct fc_function_template qla2xxx_tran
 
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+
 	.get_host_port_id = qla2x00_get_host_port_id,
 	.show_host_port_id = 1,
 
 	.dd_fcrport_size = sizeof(struct fc_port *),
+	.show_rport_supported_classes = 1,
 
 	.get_starget_node_name = qla2x00_get_starget_node_name,
 	.show_starget_node_name = 1,
@@ -329,4 +464,5 @@ qla2x00_init_host_attr(scsi_qla_host_t *
 	    be64_to_cpu(*(uint64_t *)ha->init_cb->node_name);
 	fc_host_port_name(ha->host) =
 	    be64_to_cpu(*(uint64_t *)ha->init_cb->port_name);
+	fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
 }
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -81,6 +81,7 @@
 #define DEBUG2_3_11(x)  do {x;} while (0);
 #define DEBUG2_9_10(x)    do {x;} while (0);
 #define DEBUG2_11(x)    do {x;} while (0);
+#define DEBUG2_13(x)    do {x;} while (0);
 #else
 #define DEBUG2(x)	do {} while (0);
 #endif
@@ -169,8 +170,14 @@
 
 #if defined(QL_DEBUG_LEVEL_13)
 #define DEBUG13(x)      do {x;} while (0)
+#if !defined(DEBUG2_13)
+#define DEBUG2_13(x)    do {x;} while(0)
+#endif
 #else
 #define DEBUG13(x)	do {} while (0)
+#if !defined(QL_DEBUG_LEVEL_2)
+#define DEBUG2_13(x)	do {} while(0)
+#endif
 #endif
 
 #if defined(QL_DEBUG_LEVEL_14)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -214,6 +214,7 @@
  * valid range of an N-PORT id is 0 through 0x7ef.
  */
 #define NPH_LAST_HANDLE		0x7ef
+#define NPH_MGMT_SERVER		0x7fa		/*  FFFFFA */
 #define NPH_SNS			0x7fc		/*  FFFFFC */
 #define NPH_FABRIC_CONTROLLER	0x7fd		/*  FFFFFD */
 #define NPH_F_PORT		0x7fe		/*  FFFFFE */
@@ -630,6 +631,7 @@ typedef struct {
 #define MBC_WRITE_RAM_WORD_EXTENDED	0xd	/* Write RAM word extended */
 #define MBC_READ_RAM_EXTENDED		0xf	/* Read RAM extended. */
 #define MBC_IOCB_COMMAND		0x12	/* Execute IOCB command. */
+#define MBC_STOP_FIRMWARE		0x14	/* Stop firmware. */
 #define MBC_ABORT_COMMAND		0x15	/* Abort IOCB command. */
 #define MBC_ABORT_DEVICE		0x16	/* Abort device (ID/LUN). */
 #define MBC_ABORT_TARGET		0x17	/* Abort target (ID). */
@@ -913,7 +915,7 @@ typedef struct {
 	 * MSB BIT 1 =
 	 * MSB BIT 2 =
 	 * MSB BIT 3 =
-	 * MSB BIT 4 =
+	 * MSB BIT 4 = LED mode
 	 * MSB BIT 5 = enable 50 ohm termination
 	 * MSB BIT 6 = Data Rate (2300 only)
 	 * MSB BIT 7 = Data Rate (2300 only)
@@ -1035,7 +1037,7 @@ typedef struct {
 	 * MSB BIT 1 =
 	 * MSB BIT 2 =
 	 * MSB BIT 3 =
-	 * MSB BIT 4 =
+	 * MSB BIT 4 = LED mode
 	 * MSB BIT 5 = enable 50 ohm termination
 	 * MSB BIT 6 = Data Rate (2300 only)
 	 * MSB BIT 7 = Data Rate (2300 only)
@@ -1131,10 +1133,7 @@ typedef struct {
 
 	uint8_t link_down_timeout;
 
-	uint8_t adapter_id_0[4];
-	uint8_t adapter_id_1[4];
-	uint8_t adapter_id_2[4];
-	uint8_t adapter_id_3[4];
+	uint8_t adapter_id[16];
 
 	uint8_t alt1_boot_node_name[WWN_SIZE];
 	uint16_t alt1_boot_lun_number;
@@ -1673,6 +1672,7 @@ typedef struct fc_port {
     	uint8_t cur_path;		/* current path id */
 
 	struct fc_rport *rport;
+	u32 supported_classes;
 } fc_port_t;
 
 /*
@@ -1727,6 +1727,8 @@ typedef struct fc_port {
 
 #define CT_REJECT_RESPONSE	0x8001
 #define CT_ACCEPT_RESPONSE	0x8002
+#define CT_REASON_CANNOT_PERFORM	0x09
+#define CT_EXPL_ALREADY_REGISTERED	0x10
 
 #define NS_N_PORT_TYPE	0x01
 #define NS_NL_PORT_TYPE	0x02
@@ -1768,6 +1770,100 @@ typedef struct fc_port {
 #define	RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255)
 #define	RSNN_NN_RSP_SIZE 16
 
+/*
+ * HBA attribute types.
+ */
+#define FDMI_HBA_ATTR_COUNT			9
+#define FDMI_HBA_NODE_NAME			1
+#define FDMI_HBA_MANUFACTURER			2
+#define FDMI_HBA_SERIAL_NUMBER			3
+#define FDMI_HBA_MODEL				4
+#define FDMI_HBA_MODEL_DESCRIPTION		5
+#define FDMI_HBA_HARDWARE_VERSION		6
+#define FDMI_HBA_DRIVER_VERSION			7
+#define FDMI_HBA_OPTION_ROM_VERSION		8
+#define FDMI_HBA_FIRMWARE_VERSION		9
+#define FDMI_HBA_OS_NAME_AND_VERSION		0xa
+#define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH	0xb
+
+struct ct_fdmi_hba_attr {
+	uint16_t type;
+	uint16_t len;
+	union {
+		uint8_t node_name[WWN_SIZE];
+		uint8_t manufacturer[32];
+		uint8_t serial_num[8];
+		uint8_t model[16];
+		uint8_t model_desc[80];
+		uint8_t hw_version[16];
+		uint8_t driver_version[32];
+		uint8_t orom_version[16];
+		uint8_t fw_version[16];
+		uint8_t os_version[128];
+		uint8_t max_ct_len[4];
+	} a;
+};
+
+struct ct_fdmi_hba_attributes {
+	uint32_t count;
+	struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT];
+};
+
+/*
+ * Port attribute types.
+ */
+#define FDMI_PORT_ATTR_COUNT		5
+#define FDMI_PORT_FC4_TYPES		1
+#define FDMI_PORT_SUPPORT_SPEED		2
+#define FDMI_PORT_CURRENT_SPEED		3
+#define FDMI_PORT_MAX_FRAME_SIZE	4
+#define FDMI_PORT_OS_DEVICE_NAME	5
+#define FDMI_PORT_HOST_NAME		6
+
+struct ct_fdmi_port_attr {
+	uint16_t type;
+	uint16_t len;
+	union {
+		uint8_t fc4_types[32];
+		uint32_t sup_speed;
+		uint32_t cur_speed;
+		uint32_t max_frame_size;
+		uint8_t os_dev_name[32];
+		uint8_t host_name[32];
+	} a;
+};
+
+/*
+ * Port Attribute Block.
+ */
+struct ct_fdmi_port_attributes {
+	uint32_t count;
+	struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT];
+};
+
+/* FDMI definitions. */
+#define GRHL_CMD	0x100
+#define GHAT_CMD	0x101
+#define GRPL_CMD	0x102
+#define GPAT_CMD	0x110
+
+#define RHBA_CMD	0x200
+#define RHBA_RSP_SIZE	16
+
+#define RHAT_CMD	0x201
+#define RPRT_CMD	0x210
+
+#define RPA_CMD		0x211
+#define RPA_RSP_SIZE	16
+
+#define DHBA_CMD	0x300
+#define DHBA_REQ_SIZE	(16 + 8)
+#define DHBA_RSP_SIZE	16
+
+#define DHAT_CMD	0x301
+#define DPRT_CMD	0x310
+#define DPA_CMD		0x311
+
 /* CT command header -- request/response common fields */
 struct ct_cmd_hdr {
 	uint8_t revision;
@@ -1825,6 +1921,43 @@ struct ct_sns_req {
 			uint8_t name_len;
 			uint8_t sym_node_name[255];
 		} rsnn_nn;
+
+		struct {
+			uint8_t hba_indentifier[8];
+		} ghat;
+
+		struct {
+			uint8_t hba_identifier[8];
+			uint32_t entry_count;
+			uint8_t port_name[8];
+			struct ct_fdmi_hba_attributes attrs;
+		} rhba;
+
+		struct {
+			uint8_t hba_identifier[8];
+			struct ct_fdmi_hba_attributes attrs;
+		} rhat;
+
+		struct {
+			uint8_t port_name[8];
+			struct ct_fdmi_port_attributes attrs;
+		} rpa;
+
+		struct {
+			uint8_t port_name[8];
+		} dhba;
+
+		struct {
+			uint8_t port_name[8];
+		} dhat;
+
+		struct {
+			uint8_t port_name[8];
+		} dprt;
+
+		struct {
+			uint8_t port_name[8];
+		} dpa;
 	} req;
 };
 
@@ -1882,6 +2015,12 @@ struct ct_sns_rsp {
 		struct {
 			uint8_t fc4_types[32];
 		} gft_id;
+
+		struct {
+			uint32_t entry_count;
+			uint8_t port_name[8];
+			struct ct_fdmi_hba_attributes attrs;
+		} ghat;
 	} rsp;
 };
 
@@ -2032,6 +2171,8 @@ struct isp_operations {
 	uint16_t (*calc_req_entries) (uint16_t);
 	void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
 	void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
+	void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
+	    uint32_t);
 
 	uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
 		uint32_t, uint32_t);
@@ -2111,6 +2252,7 @@ typedef struct scsi_qla_host {
 #define IOCTL_ERROR_RECOVERY	23
 #define LOOP_RESET_NEEDED	24
 #define BEACON_BLINK_NEEDED	25
+#define REGISTER_FDMI_NEEDED	26
 
 	uint32_t	device_flags;
 #define DFLG_LOCAL_DEVICES		BIT_0
@@ -2204,6 +2346,7 @@ typedef struct scsi_qla_host {
 	int		port_down_retry_count;
 	uint8_t		mbx_count;
 	uint16_t	last_loop_id;
+	uint16_t	mgmt_svr_loop_id;
 
         uint32_t	login_retry_count;
 
@@ -2318,6 +2461,7 @@ typedef struct scsi_qla_host {
 	uint8_t		model_number[16+1];
 #define BINZERO		"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 	char		*model_desc;
+	uint8_t		adapter_id[16+1];
 
 	uint8_t		*node_name;
 	uint8_t		*port_name;
@@ -2377,6 +2521,7 @@ typedef struct scsi_qla_host {
 #define QLA_SUSPENDED			0x106
 #define QLA_BUSY			0x107
 #define QLA_RSCNS_HANDLED		0x108
+#define QLA_ALREADY_REGISTERED		0x109
 
 /*
 * Stat info for all adpaters
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -79,6 +79,7 @@ extern int ql2xplogiabsentdevice;
 extern int ql2xenablezio;
 extern int ql2xintrdelaytimer;
 extern int ql2xloginretrycount;
+extern int ql2xfdmienable;
 
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
@@ -147,9 +148,6 @@ qla2x00_abort_target(fc_port_t *);
 #endif
 
 extern int
-qla2x00_target_reset(scsi_qla_host_t *, struct fc_port *);
-
-extern int
 qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
     uint8_t *, uint16_t *);
 
@@ -215,6 +213,9 @@ qla2x00_get_serdes_params(scsi_qla_host_
 extern int
 qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
 
+extern int
+qla2x00_stop_firmware(scsi_qla_host_t *);
+
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
@@ -269,6 +270,9 @@ extern int qla2x00_rft_id(scsi_qla_host_
 extern int qla2x00_rff_id(scsi_qla_host_t *);
 extern int qla2x00_rnn_id(scsi_qla_host_t *);
 extern int qla2x00_rsnn_nn(scsi_qla_host_t *);
+extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
+extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
+extern int qla2x00_fdmi_register(scsi_qla_host_t *);
 
 /*
  * Global Function Prototypes in qla_rscn.c source file.
@@ -289,6 +293,8 @@ extern void qla2x00_cancel_io_descriptor
 /*
  * Global Function Prototypes in qla_attr.c source file.
  */
+struct class_device_attribute;
+extern struct class_device_attribute *qla2x00_host_attrs[];
 struct fc_function_template;
 extern struct fc_function_template qla2xxx_transport_functions;
 extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1099,3 +1099,567 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
 
 	return (rval);
 }
+
+/**
+ * qla2x00_mgmt_svr_login() - Login to fabric Managment Service.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_mgmt_svr_login(scsi_qla_host_t *ha)
+{
+	int ret;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+
+	ret = QLA_SUCCESS;
+	if (ha->flags.management_server_logged_in)
+		return ret;
+
+	ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa,
+	    mb, BIT_1);
+	if (mb[0] != MBS_COMMAND_COMPLETE) {
+		DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: "
+		    "loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n",
+		    __func__, ha->host_no, ha->mgmt_svr_loop_id, mb[0], mb[1],
+		    mb[2], mb[6], mb[7]));
+		ret = QLA_FUNCTION_FAILED;
+	} else
+		ha->flags.management_server_logged_in = 1;
+
+	return ret;
+}
+
+/**
+ * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
+ * @ha: HA context
+ * @req_size: request size in bytes
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the @ha's ms_iocb.
+ */
+void *
+qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
+    uint32_t rsp_size)
+{
+	ms_iocb_entry_t *ms_pkt;
+
+	ms_pkt = ha->ms_iocb;
+	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
+
+	ms_pkt->entry_type = MS_IOCB_TYPE;
+	ms_pkt->entry_count = 1;
+	SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id);
+	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
+	ms_pkt->timeout = __constant_cpu_to_le16(59);
+	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
+	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
+	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
+	ms_pkt->req_bytecount = cpu_to_le32(req_size);
+
+	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+
+	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
+
+	return ms_pkt;
+}
+
+/**
+ * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
+ * @ha: HA context
+ * @req_size: request size in bytes
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the @ha's ms_iocb.
+ */
+void *
+qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
+    uint32_t rsp_size)
+{
+	struct ct_entry_24xx *ct_pkt;
+
+	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
+
+	ct_pkt->entry_type = CT_IOCB_TYPE;
+	ct_pkt->entry_count = 1;
+	ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
+	ct_pkt->timeout = __constant_cpu_to_le16(59);
+	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
+	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
+	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
+	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+
+	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+
+	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+
+	return ct_pkt;
+}
+
+static inline ms_iocb_entry_t *
+qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size)
+{
+	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
+	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+
+	if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+		ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+	} else {
+		ms_pkt->req_bytecount = cpu_to_le32(req_size);
+		ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+	}
+
+	return ms_pkt;
+}
+
+/**
+ * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
+ * @ct_req: CT request buffer
+ * @cmd: GS command
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the intitialized @ct_req.
+ */
+static inline struct ct_sns_req *
+qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
+    uint16_t rsp_size)
+{
+	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
+
+	ct_req->header.revision = 0x01;
+	ct_req->header.gs_type = 0xFA;
+	ct_req->header.gs_subtype = 0x10;
+	ct_req->command = cpu_to_be16(cmd);
+	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
+
+	return ct_req;
+}
+
+/**
+ * qla2x00_fdmi_rhba() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rhba(scsi_qla_host_t *ha)
+{
+	int rval, alen;
+	uint32_t size, sn;
+
+	ms_iocb_entry_t *ms_pkt;
+	struct ct_sns_req *ct_req;
+	struct ct_sns_rsp *ct_rsp;
+	uint8_t *entries;
+	struct ct_fdmi_hba_attr *eiter;
+
+	/* Issue RHBA */
+	/* Prepare common MS IOCB */
+	/*   Request size adjusted after CT preparation */
+	ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE);
+
+	/* Prepare CT request */
+	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
+	    RHBA_RSP_SIZE);
+	ct_rsp = &ha->ct_sns->p.rsp;
+
+	/* Prepare FDMI command arguments -- attribute block, attributes. */
+	memcpy(ct_req->req.rhba.hba_identifier, ha->port_name, WWN_SIZE);
+	ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
+	memcpy(ct_req->req.rhba.port_name, ha->port_name, WWN_SIZE);
+	size = 2 * WWN_SIZE + 4 + 4;
+
+	/* Attributes */
+	ct_req->req.rhba.attrs.count =
+	    __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
+	entries = ct_req->req.rhba.hba_identifier;
+
+	/* Nodename. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
+	eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
+	memcpy(eiter->a.node_name, ha->node_name, WWN_SIZE);
+	size += 4 + WWN_SIZE;
+
+	DEBUG13(printk("%s(%ld): NODENAME=%02x%02x%02x%02x%02x%02x%02x%02x.\n",
+	    __func__, ha->host_no,
+	    eiter->a.node_name[0], eiter->a.node_name[1], eiter->a.node_name[2],
+	    eiter->a.node_name[3], eiter->a.node_name[4], eiter->a.node_name[5],
+	    eiter->a.node_name[6], eiter->a.node_name[7]));
+
+	/* Manufacturer. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
+	strcpy(eiter->a.manufacturer, "QLogic Corporation");
+	alen = strlen(eiter->a.manufacturer);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): MANUFACTURER=%s.\n", __func__, ha->host_no,
+	    eiter->a.manufacturer));
+
+	/* Serial number. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
+	sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
+	sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
+	alen = strlen(eiter->a.serial_num);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): SERIALNO=%s.\n", __func__, ha->host_no,
+	    eiter->a.serial_num));
+
+	/* Model name. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
+	strcpy(eiter->a.model, ha->model_number);
+	alen = strlen(eiter->a.model);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): MODEL_NAME=%s.\n", __func__, ha->host_no,
+	    eiter->a.model));
+
+	/* Model description. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
+	if (ha->model_desc)
+		strncpy(eiter->a.model_desc, ha->model_desc, 80);
+	alen = strlen(eiter->a.model_desc);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): MODEL_DESC=%s.\n", __func__, ha->host_no,
+	    eiter->a.model_desc));
+
+	/* Hardware version. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
+	strcpy(eiter->a.hw_version, ha->adapter_id);
+	alen = strlen(eiter->a.hw_version);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): HARDWAREVER=%s.\n", __func__, ha->host_no,
+	    eiter->a.hw_version));
+
+	/* Driver version. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
+	strcpy(eiter->a.driver_version, qla2x00_version_str);
+	alen = strlen(eiter->a.driver_version);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): DRIVERVER=%s.\n", __func__, ha->host_no,
+	    eiter->a.driver_version));
+
+	/* Option ROM version. */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
+	strcpy(eiter->a.orom_version, "0.00");
+	alen = strlen(eiter->a.orom_version);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): OPTROMVER=%s.\n", __func__, ha->host_no,
+	    eiter->a.orom_version));
+
+	/* Firmware version */
+	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
+	ha->isp_ops.fw_version_str(ha, eiter->a.fw_version);
+	alen = strlen(eiter->a.fw_version);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): FIRMWAREVER=%s.\n", __func__, ha->host_no,
+	    eiter->a.fw_version));
+
+	/* Update MS request size. */
+	qla2x00_update_ms_fdmi_iocb(ha, size + 16);
+
+	DEBUG13(printk("%s(%ld): RHBA identifier="
+	    "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
+	    ha->host_no, ct_req->req.rhba.hba_identifier[0],
+	    ct_req->req.rhba.hba_identifier[1],
+	    ct_req->req.rhba.hba_identifier[2],
+	    ct_req->req.rhba.hba_identifier[3],
+	    ct_req->req.rhba.hba_identifier[4],
+	    ct_req->req.rhba.hba_identifier[5],
+	    ct_req->req.rhba.hba_identifier[6],
+	    ct_req->req.rhba.hba_identifier[7], size));
+	DEBUG13(qla2x00_dump_buffer(entries, size));
+
+	/* Execute MS IOCB */
+	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+	    sizeof(ms_iocb_entry_t));
+	if (rval != QLA_SUCCESS) {
+		/*EMPTY*/
+		DEBUG2_3(printk("scsi(%ld): RHBA issue IOCB failed (%d).\n",
+		    ha->host_no, rval));
+	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RHBA") !=
+	    QLA_SUCCESS) {
+		rval = QLA_FUNCTION_FAILED;
+		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
+		    ct_rsp->header.explanation_code ==
+		    CT_EXPL_ALREADY_REGISTERED) {
+			DEBUG2_13(printk("%s(%ld): HBA already registered.\n",
+			    __func__, ha->host_no));
+			rval = QLA_ALREADY_REGISTERED;
+		}
+	} else {
+		DEBUG2(printk("scsi(%ld): RHBA exiting normally.\n",
+		    ha->host_no));
+	}
+
+	return rval;
+}
+
+/**
+ * qla2x00_fdmi_dhba() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_dhba(scsi_qla_host_t *ha)
+{
+	int rval;
+
+	ms_iocb_entry_t *ms_pkt;
+	struct ct_sns_req *ct_req;
+	struct ct_sns_rsp *ct_rsp;
+
+	/* Issue RPA */
+	/* Prepare common MS IOCB */
+	ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE,
+	    DHBA_RSP_SIZE);
+
+	/* Prepare CT request */
+	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
+	    DHBA_RSP_SIZE);
+	ct_rsp = &ha->ct_sns->p.rsp;
+
+	/* Prepare FDMI command arguments -- portname. */
+	memcpy(ct_req->req.dhba.port_name, ha->port_name, WWN_SIZE);
+
+	DEBUG13(printk("%s(%ld): DHBA portname="
+	    "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, ha->host_no,
+	    ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
+	    ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
+	    ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
+	    ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]));
+
+	/* Execute MS IOCB */
+	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+	    sizeof(ms_iocb_entry_t));
+	if (rval != QLA_SUCCESS) {
+		/*EMPTY*/
+		DEBUG2_3(printk("scsi(%ld): DHBA issue IOCB failed (%d).\n",
+		    ha->host_no, rval));
+	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "DHBA") !=
+	    QLA_SUCCESS) {
+		rval = QLA_FUNCTION_FAILED;
+	} else {
+		DEBUG2(printk("scsi(%ld): DHBA exiting normally.\n",
+		    ha->host_no));
+	}
+
+	return rval;
+}
+
+/**
+ * qla2x00_fdmi_rpa() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
+{
+	int rval, alen;
+	uint32_t size, max_frame_size;
+
+	ms_iocb_entry_t *ms_pkt;
+	struct ct_sns_req *ct_req;
+	struct ct_sns_rsp *ct_rsp;
+	uint8_t *entries;
+	struct ct_fdmi_port_attr *eiter;
+	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
+
+	/* Issue RPA */
+	/* Prepare common MS IOCB */
+	/*   Request size adjusted after CT preparation */
+	ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE);
+
+	/* Prepare CT request */
+	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
+	    RPA_RSP_SIZE);
+	ct_rsp = &ha->ct_sns->p.rsp;
+
+	/* Prepare FDMI command arguments -- attribute block, attributes. */
+	memcpy(ct_req->req.rpa.port_name, ha->port_name, WWN_SIZE);
+	size = WWN_SIZE + 4;
+
+	/* Attributes */
+	ct_req->req.rpa.attrs.count =
+	    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
+	entries = ct_req->req.rpa.port_name;
+
+	/* FC4 types. */
+	eiter = (struct ct_fdmi_port_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
+	eiter->len = __constant_cpu_to_be16(4 + 32);
+	eiter->a.fc4_types[2] = 0x01;
+	size += 4 + 32;
+
+	DEBUG13(printk("%s(%ld): FC4_TYPES=%02x %02x.\n", __func__, ha->host_no,
+	    eiter->a.fc4_types[2], eiter->a.fc4_types[1]));
+
+	/* Supported speed. */
+	eiter = (struct ct_fdmi_port_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
+	eiter->len = __constant_cpu_to_be16(4 + 4);
+	if (IS_QLA25XX(ha))
+		eiter->a.sup_speed = __constant_cpu_to_be32(4);
+	else if (IS_QLA24XX(ha))
+		eiter->a.sup_speed = __constant_cpu_to_be32(8);
+	else if (IS_QLA23XX(ha))
+		eiter->a.sup_speed = __constant_cpu_to_be32(2);
+	else
+		eiter->a.sup_speed = __constant_cpu_to_be32(1);
+	size += 4 + 4;
+
+	DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no,
+	    eiter->a.sup_speed));
+
+	/* Current speed. */
+	eiter = (struct ct_fdmi_port_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
+	eiter->len = __constant_cpu_to_be16(4 + 4);
+	switch (ha->link_data_rate) {
+	case 0:
+		eiter->a.cur_speed = __constant_cpu_to_be32(1);
+		break;
+	case 1:
+		eiter->a.cur_speed = __constant_cpu_to_be32(2);
+		break;
+	case 3:
+		eiter->a.cur_speed = __constant_cpu_to_be32(8);
+		break;
+	case 4:
+		eiter->a.cur_speed = __constant_cpu_to_be32(4);
+		break;
+	}
+	size += 4 + 4;
+
+	DEBUG13(printk("%s(%ld): CURRENT_SPEED=%x.\n", __func__, ha->host_no,
+	    eiter->a.cur_speed));
+
+	/* Max frame size. */
+	eiter = (struct ct_fdmi_port_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
+	eiter->len = __constant_cpu_to_be16(4 + 4);
+	max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ?
+		(uint32_t) icb24->frame_payload_size:
+		(uint32_t) ha->init_cb->frame_payload_size;
+	eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
+	size += 4 + 4;
+
+	DEBUG13(printk("%s(%ld): MAX_FRAME_SIZE=%x.\n", __func__, ha->host_no,
+	    eiter->a.max_frame_size));
+
+	/* OS device name. */
+	eiter = (struct ct_fdmi_port_attr *) (entries + size);
+	eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
+	sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no);
+	alen = strlen(eiter->a.os_dev_name);
+	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+	eiter->len = cpu_to_be16(4 + alen);
+	size += 4 + alen;
+
+	DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, ha->host_no,
+	    eiter->a.os_dev_name));
+
+	/* Update MS request size. */
+	qla2x00_update_ms_fdmi_iocb(ha, size + 16);
+
+	DEBUG13(printk("%s(%ld): RPA portname="
+	    "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
+	    ha->host_no, ct_req->req.rpa.port_name[0],
+	    ct_req->req.rpa.port_name[1], ct_req->req.rpa.port_name[2],
+	    ct_req->req.rpa.port_name[3], ct_req->req.rpa.port_name[4],
+	    ct_req->req.rpa.port_name[5], ct_req->req.rpa.port_name[6],
+	    ct_req->req.rpa.port_name[7], size));
+	DEBUG13(qla2x00_dump_buffer(entries, size));
+
+	/* Execute MS IOCB */
+	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+	    sizeof(ms_iocb_entry_t));
+	if (rval != QLA_SUCCESS) {
+		/*EMPTY*/
+		DEBUG2_3(printk("scsi(%ld): RPA issue IOCB failed (%d).\n",
+		    ha->host_no, rval));
+	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RPA") !=
+	    QLA_SUCCESS) {
+		rval = QLA_FUNCTION_FAILED;
+	} else {
+		DEBUG2(printk("scsi(%ld): RPA exiting normally.\n",
+		    ha->host_no));
+	}
+
+	return rval;
+}
+
+/**
+ * qla2x00_fdmi_register() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+int
+qla2x00_fdmi_register(scsi_qla_host_t *ha)
+{
+	int rval;
+
+	rval = qla2x00_mgmt_svr_login(ha);
+	if (rval)
+		return rval;
+
+	rval = qla2x00_fdmi_rhba(ha);
+	if (rval) {
+		if (rval != QLA_ALREADY_REGISTERED)
+			return rval;
+
+		rval = qla2x00_fdmi_dhba(ha);
+		if (rval)
+			return rval;
+
+		rval = qla2x00_fdmi_rhba(ha);
+		if (rval)
+			return rval;
+	}
+	rval = qla2x00_fdmi_rpa(ha);
+
+	return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -88,6 +88,7 @@ qla2x00_initialize_adapter(scsi_qla_host
 	ha->mbx_flags = 0;
 	ha->isp_abort_cnt = 0;
 	ha->beacon_blink_led = 0;
+	set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 
 	qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
 	rval = ha->isp_ops.pci_config(ha);
@@ -1563,7 +1564,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha
 	ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0);
 	ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
 	ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
-	ha->flags.enable_led_scheme = ((nv->efi_parameters & BIT_3) ? 1 : 0);
+	ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
 
 	ha->operating_mode =
 	    (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
@@ -1697,6 +1698,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha
 	fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
 	atomic_set(&fcport->state, FCS_UNCONFIGURED);
 	fcport->flags = FCF_RLC_SUPPORT;
+	fcport->supported_classes = FC_COS_UNSPECIFIED;
 
 	return (fcport);
 }
@@ -1898,7 +1900,8 @@ qla2x00_configure_local_loop(scsi_qla_ho
 			continue;
 
 		/* Bypass if not same domain and area of adapter. */
-		if (area != ha->d_id.b.area || domain != ha->d_id.b.domain)
+		if (area && domain &&
+		    (area != ha->d_id.b.area || domain != ha->d_id.b.domain))
 			continue;
 
 		/* Bypass invalid local loop ID. */
@@ -2075,6 +2078,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t 
 		return;
 	}
 	rport->dd_data = fcport;
+	rport->supported_classes = fcport->supported_classes;
 
 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
 	if (fcport->port_type == FCT_INITIATOR)
@@ -2130,6 +2134,11 @@ qla2x00_configure_fabric(scsi_qla_host_t
 		return (QLA_SUCCESS);
 	}
 	do {
+		/* FDMI support. */
+		if (ql2xfdmienable &&
+		    test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags))
+			qla2x00_fdmi_register(ha);
+
 		/* Ensure we are logged into the SNS. */
 		if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
 			loop_id = NPH_SNS;
@@ -2392,6 +2401,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho
 		if (new_fcport->d_id.b24 == ha->d_id.b24)
 			continue;
 
+		/* Bypass if same domain and area of adapter. */
+		if (((new_fcport->d_id.b24 & 0xffff00) ==
+		    (ha->d_id.b24 & 0xffff00)) && ha->current_topology ==
+			ISP_CFG_FL)
+			    continue;
+
 		/* Bypass reserved domain fields. */
 		if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0)
 			continue;
@@ -2794,6 +2809,11 @@ qla2x00_fabric_login(scsi_qla_host_t *ha
 				}
 			}
 
+			if (mb[10] & BIT_0)
+				fcport->supported_classes |= FC_COS_CLASS2;
+			if (mb[10] & BIT_1)
+				fcport->supported_classes |= FC_COS_CLASS3;
+
 			rval = QLA_SUCCESS;
 			break;
 		} else if (mb[0] == MBS_LOOP_ID_USED) {
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -810,12 +810,8 @@ qla24xx_start_scsi(srb_t *sp)
 			ha->req_q_cnt = ha->request_q_length -
 				(ha->req_ring_index - cnt);
 	}
-	if (ha->req_q_cnt < (req_cnt + 2)) {
-		if  (cmd->use_sg)
-			pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
-					cmd->sc_data_direction);
+	if (ha->req_q_cnt < (req_cnt + 2))
 		goto queuing_error;
-	}
 
 	/* Build command packet. */
 	ha->current_outstanding_cmd = handle;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -451,6 +451,8 @@ qla2x00_async_event(scsi_qla_host_t *ha,
 
 		ha->flags.management_server_logged_in = 0;
 		ha->link_data_rate = 0;
+		if (ql2xfdmienable)
+			set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 
 		/* Update AEN queue. */
 		qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -19,6 +19,7 @@
 #include "qla_def.h"
 
 #include <linux/delay.h>
+#include <scsi/scsi_transport_fc.h>
 
 static void
 qla2x00_mbx_sem_timeout(unsigned long data)
@@ -251,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t 
 			mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
 			ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
 		} else {
-			mb0 = RD_MAILBOX_REG(ha, reg->isp, 0);
+			mb0 = RD_MAILBOX_REG(ha, &reg->isp, 0);
 			ictrl = RD_REG_WORD(&reg->isp.ictrl);
 		}
 		printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n",
@@ -983,58 +984,6 @@ qla2x00_abort_target(fc_port_t *fcport)
 #endif
 
 /*
- * qla2x00_target_reset
- *	Issue target reset mailbox command.
- *
- * Input:
- *	ha = adapter block pointer.
- *	TARGET_QUEUE_LOCK must be released.
- *	ADAPTER_STATE_LOCK must be released.
- *
- * Returns:
- *	qla2x00 local function return status code.
- *
- * Context:
- *	Kernel context.
- */
-int
-qla2x00_target_reset(scsi_qla_host_t *ha, struct fc_port *fcport)
-{
-	int rval;
-	mbx_cmd_t mc;
-	mbx_cmd_t *mcp = &mc;
-
-	DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);)
-
-	if (atomic_read(&fcport->state) != FCS_ONLINE)
-		return 0;
-
-	mcp->mb[0] = MBC_TARGET_RESET;
-	if (HAS_EXTENDED_IDS(ha))
-		mcp->mb[1] = fcport->loop_id;
-	else
-		mcp->mb[1] = fcport->loop_id << 8;
-	mcp->mb[2] = ha->loop_reset_delay;
-	mcp->out_mb = MBX_2|MBX_1|MBX_0;
-	mcp->in_mb = MBX_0;
-	mcp->tov = 30;
-	mcp->flags = 0;
-	rval = qla2x00_mailbox_command(ha, mcp);
-
-	if (rval != QLA_SUCCESS) {
-		/*EMPTY*/
-		DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n",
-		    ha->host_no, rval);)
-	} else {
-		/*EMPTY*/
-		DEBUG11(printk("qla2x00_target_reset(%ld): done.\n",
-		    ha->host_no);)
-	}
-
-	return rval;
-}
-
-/*
  * qla2x00_get_adapter_id
  *	Get adapter ID and topology.
  *
@@ -1326,6 +1275,10 @@ qla2x00_get_port_database(scsi_qla_host_
 			fcport->port_type = FCT_INITIATOR;
 		else
 			fcport->port_type = FCT_TARGET;
+
+		/* Passback COS information. */
+		fcport->supported_classes = (pd->options & BIT_4) ?
+		    FC_COS_CLASS2: FC_COS_CLASS3;
 	}
 
 gpd_error_out:
@@ -1661,6 +1614,13 @@ qla24xx_login_fabric(scsi_qla_host_t *ha
 				mb[1] |= BIT_1;
 		} else
 			mb[1] = BIT_0;
+
+		/* Passback COS information. */
+		mb[10] = 0;
+		if (lg->io_parameter[7] || lg->io_parameter[8])
+			mb[10] |= BIT_0;	/* Class 2. */
+		if (lg->io_parameter[9] || lg->io_parameter[10])
+			mb[10] |= BIT_1;	/* Class 3. */
 	}
 
 	dma_pool_free(ha->s_dma_pool, lg, lg_dma);
@@ -1723,6 +1683,8 @@ qla2x00_login_fabric(scsi_qla_host_t *ha
 		mb[2] = mcp->mb[2];
 		mb[6] = mcp->mb[6];
 		mb[7] = mcp->mb[7];
+		/* COS retrieved from Get-Port-Database mailbox command. */
+		mb[10] = 0;
 	}
 
 	if (rval != QLA_SUCCESS) {
@@ -2465,3 +2427,32 @@ qla2x00_set_serdes_params(scsi_qla_host_
 
 	return rval;
 }
+
+int
+qla2x00_stop_firmware(scsi_qla_host_t *ha)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
+		return QLA_FUNCTION_FAILED;
+
+	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+	mcp->mb[0] = MBC_STOP_FIRMWARE;
+	mcp->out_mb = MBX_0;
+	mcp->in_mb = MBX_0;
+	mcp->tov = 5;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(ha, mcp);
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+		    ha->host_no, rval));
+	} else {
+		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+	}
+
+	return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -79,7 +79,7 @@ module_param(ql2xloginretrycount, int, S
 MODULE_PARM_DESC(ql2xloginretrycount,
 		"Specify an alternate value for the NVRAM login retry count.");
 
-int ql2xfwloadbin;
+int ql2xfwloadbin=1;
 module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xfwloadbin,
 		"Load ISP2xxx firmware image via hotplug.");
@@ -88,6 +88,12 @@ static void qla2x00_free_device(scsi_qla
 
 static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
 
+int ql2xfdmienable;
+module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfdmienable,
+		"Enables FDMI registratons "
+		"Default is 0 - no FDMI. 1 - perfom FDMI.");
+
 /*
  * SCSI host template entry points
  */
@@ -105,6 +111,9 @@ static int qla2xxx_eh_host_reset(struct 
 static int qla2x00_loop_reset(scsi_qla_host_t *ha);
 static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
 
+static int qla2x00_change_queue_depth(struct scsi_device *, int);
+static int qla2x00_change_queue_type(struct scsi_device *, int);
+
 static struct scsi_host_template qla2x00_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "qla2xxx",
@@ -119,6 +128,8 @@ static struct scsi_host_template qla2x00
 
 	.slave_alloc		= qla2xxx_slave_alloc,
 	.slave_destroy		= qla2xxx_slave_destroy,
+	.change_queue_depth	= qla2x00_change_queue_depth,
+	.change_queue_type	= qla2x00_change_queue_type,
 	.this_id		= -1,
 	.cmd_per_lun		= 3,
 	.use_clustering		= ENABLE_CLUSTERING,
@@ -129,6 +140,7 @@ static struct scsi_host_template qla2x00
 	 * which equates to 0x800000 sectors.
 	 */
 	.max_sectors		= 0xFFFF,
+	.shost_attrs		= qla2x00_host_attrs,
 };
 
 static struct scsi_host_template qla24xx_driver_template = {
@@ -145,12 +157,15 @@ static struct scsi_host_template qla24xx
 
 	.slave_alloc		= qla2xxx_slave_alloc,
 	.slave_destroy		= qla2xxx_slave_destroy,
+	.change_queue_depth	= qla2x00_change_queue_depth,
+	.change_queue_type	= qla2x00_change_queue_type,
 	.this_id		= -1,
 	.cmd_per_lun		= 3,
 	.use_clustering		= ENABLE_CLUSTERING,
 	.sg_tablesize		= SG_ALL,
 
 	.max_sectors		= 0xFFFF,
+	.shost_attrs		= qla2x00_host_attrs,
 };
 
 static struct scsi_transport_template *qla2xxx_transport_template = NULL;
@@ -487,14 +502,13 @@ qc24_fail_command:
 static int
 qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
 {
-#define ABORT_POLLING_PERIOD	HZ
-#define ABORT_WAIT_ITER		((10 * HZ) / (ABORT_POLLING_PERIOD))
+#define ABORT_POLLING_PERIOD	1000
+#define ABORT_WAIT_ITER		((10 * 1000) / (ABORT_POLLING_PERIOD))
 	unsigned long wait_iter = ABORT_WAIT_ITER;
 	int ret = QLA_SUCCESS;
 
 	while (CMD_SP(cmd)) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(ABORT_POLLING_PERIOD);
+		msleep(ABORT_POLLING_PERIOD);
 
 		if (--wait_iter)
 			break;
@@ -1016,7 +1030,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
 			if (fcport->port_type != FCT_TARGET)
 				continue;
 
-			status = qla2x00_target_reset(ha, fcport);
+			status = qla2x00_device_reset(ha, fcport);
 			if (status != QLA_SUCCESS)
 				break;
 		}
@@ -1103,6 +1117,28 @@ qla2xxx_slave_destroy(struct scsi_device
 	sdev->hostdata = NULL;
 }
 
+static int
+qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+	return sdev->queue_depth;
+}
+
+static int
+qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type)
+{
+	if (sdev->tagged_supported) {
+		scsi_set_tag_type(sdev, tag_type);
+		if (tag_type)
+			scsi_activate_tcq(sdev, sdev->queue_depth);
+		else
+			scsi_deactivate_tcq(sdev, sdev->queue_depth);
+	} else
+		tag_type = 0;
+
+	return tag_type;
+}
+
 /**
  * qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
  * @ha: HA context
@@ -1113,36 +1149,23 @@ qla2xxx_slave_destroy(struct scsi_device
 static void
 qla2x00_config_dma_addressing(scsi_qla_host_t *ha)
 {
-	/* Assume 32bit DMA address */
+	/* Assume a 32bit DMA mask. */
 	ha->flags.enable_64bit_addressing = 0;
 
-	/*
-	 * Given the two variants pci_set_dma_mask(), allow the compiler to
-	 * assist in setting the proper dma mask.
-	 */
-	if (sizeof(dma_addr_t) > 4) {
-		if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) {
+	if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) {
+		/* Any upper-dword bits set? */
+		if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
+		    !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) {
+			/* Ok, a 64bit DMA mask is applicable. */
 			ha->flags.enable_64bit_addressing = 1;
 			ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64;
 			ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64;
-
-			if (pci_set_consistent_dma_mask(ha->pdev,
-			    DMA_64BIT_MASK)) {
-				qla_printk(KERN_DEBUG, ha,
-				    "Failed to set 64 bit PCI consistent mask; "
-				    "using 32 bit.\n");
-				pci_set_consistent_dma_mask(ha->pdev,
-				    DMA_32BIT_MASK);
-			}
-		} else {
-			qla_printk(KERN_DEBUG, ha,
-			    "Failed to set 64 bit PCI DMA mask, falling back "
-			    "to 32 bit MASK.\n");
-			pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
+			return;
 		}
-	} else {
-		pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
 	}
+
+	dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK);
+	pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK);
 }
 
 static int
@@ -1316,6 +1339,7 @@ int qla2x00_probe_one(struct pci_dev *pd
 	ha->prev_topology = 0;
 	ha->ports = MAX_BUSES;
 	ha->init_cb_size = sizeof(init_cb_t);
+	ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
 
 	/* Assign ISP specific operations. */
 	ha->isp_ops.pci_config		= qla2100_pci_config;
@@ -1338,6 +1362,7 @@ int qla2x00_probe_one(struct pci_dev *pd
 	ha->isp_ops.calc_req_entries	= qla2x00_calc_iocbs_32;
 	ha->isp_ops.build_iocbs		= qla2x00_build_scsi_iocbs_32;
 	ha->isp_ops.prep_ms_iocb	= qla2x00_prep_ms_iocb;
+	ha->isp_ops.prep_ms_fdmi_iocb	= qla2x00_prep_ms_fdmi_iocb;
 	ha->isp_ops.read_nvram		= qla2x00_read_nvram_data;
 	ha->isp_ops.write_nvram		= qla2x00_write_nvram_data;
 	ha->isp_ops.fw_dump		= qla2100_fw_dump;
@@ -1375,6 +1400,7 @@ int qla2x00_probe_one(struct pci_dev *pd
 		ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
 		ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
 		ha->init_cb_size = sizeof(struct init_cb_24xx);
+		ha->mgmt_svr_loop_id = 10;
 		ha->isp_ops.pci_config = qla24xx_pci_config;
 		ha->isp_ops.reset_chip = qla24xx_reset_chip;
 		ha->isp_ops.chip_diag = qla24xx_chip_diag;
@@ -1395,6 +1421,7 @@ int qla2x00_probe_one(struct pci_dev *pd
 		ha->isp_ops.fabric_login = qla24xx_login_fabric;
 		ha->isp_ops.fabric_logout = qla24xx_fabric_logout;
 		ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb;
+		ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb;
 		ha->isp_ops.read_nvram = qla24xx_read_nvram_data;
 		ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
 		ha->isp_ops.fw_dump = qla24xx_fw_dump;
@@ -1558,8 +1585,6 @@ int qla2x00_probe_one(struct pci_dev *pd
 	return 0;
 
 probe_failed:
-	fc_remove_host(ha->host);
-
 	qla2x00_free_device(ha);
 
 	scsi_host_put(host);
@@ -1601,10 +1626,6 @@ qla2x00_free_device(scsi_qla_host_t *ha)
 	if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
 		qla2x00_cancel_io_descriptors(ha);
 
-	/* turn-off interrupts on the card */
-	if (ha->interrupts_on)
-		ha->isp_ops.disable_intrs(ha);
-
 	/* Disable timer */
 	if (ha->timer_active)
 		qla2x00_stop_timer(ha);
@@ -1624,8 +1645,14 @@ qla2x00_free_device(scsi_qla_host_t *ha)
 		}
 	}
 
-	qla2x00_mem_free(ha);
+	/* Stop currently executing firmware. */
+	qla2x00_stop_firmware(ha);
+
+	/* turn-off interrupts on the card */
+	if (ha->interrupts_on)
+		ha->isp_ops.disable_intrs(ha);
 
+	qla2x00_mem_free(ha);
 
 	ha->flags.online = 0;
 
@@ -1934,7 +1961,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
 {
 	struct list_head	*fcpl, *fcptemp;
 	fc_port_t	*fcport;
-	unsigned long	wtime;/* max wait time if mbx cmd is busy. */
+	unsigned int	wtime;/* max wait time if mbx cmd is busy. */
 
 	if (ha == NULL) {
 		/* error */
@@ -1943,11 +1970,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
 	}
 
 	/* Make sure all other threads are stopped. */
-	wtime = 60 * HZ;
-	while (ha->dpc_wait && wtime) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		wtime = schedule_timeout(wtime);
-	}
+	wtime = 60 * 1000;
+	while (ha->dpc_wait && wtime)
+		wtime = msleep_interruptible(wtime);
 
 	/* free ioctl memory */
 	qla2x00_free_ioctl_mem(ha);
@@ -2478,15 +2503,15 @@ qla2x00_timer(scsi_qla_host_t *ha)
 int
 qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
 {
-	const unsigned int step = HZ/10;
+	const unsigned int step = 100; /* msecs */
+	unsigned int iterations = jiffies_to_msecs(timeout)/100;
 
 	do {
 		if (!down_trylock(sema))
 			return 0;
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (schedule_timeout(step))
+		if (msleep_interruptible(step))
 			break;
-	} while ((timeout -= step) > 0);
+	} while (--iterations >= 0);
 
 	return -ETIMEDOUT;
 }
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -468,21 +468,12 @@ qla24xx_read_flash_data(scsi_qla_host_t 
     uint32_t dwords)
 {
 	uint32_t i;
-	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-
-	/* Pause RISC. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);		/* PCI Posting. */
 
 	/* Dword reads to flash. */
 	for (i = 0; i < dwords; i++, faddr++)
 		dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
 		    flash_data_to_access_addr(faddr)));
 
-	/* Release RISC pause. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);		/* PCI Posting. */
-
 	return dwptr;
 }
 
@@ -532,10 +523,6 @@ qla24xx_write_flash_data(scsi_qla_host_t
 
 	ret = QLA_SUCCESS;
 
-	/* Pause RISC. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);		/* PCI Posting. */
-
 	qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
 	DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
 	    ha->host_no, man_id, flash_id));
@@ -599,10 +586,6 @@ qla24xx_write_flash_data(scsi_qla_host_t
 	    RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
 	RD_REG_DWORD(&reg->ctrl_status);	/* PCI Posting. */
 
-	/* Release RISC pause. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);		/* PCI Posting. */
-
 	return ret;
 }
 
@@ -630,11 +613,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t 
 {
 	uint32_t i;
 	uint32_t *dwptr;
-	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-
-	/* Pause RISC. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);	/* PCI Posting. */
 
 	/* Dword reads to flash. */
 	dwptr = (uint32_t *)buf;
@@ -642,10 +620,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t 
 		dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
 		    nvram_data_to_access_addr(naddr)));
 
-	/* Release RISC pause. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);	/* PCI Posting. */
-
 	return buf;
 }
 
@@ -690,10 +664,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t
 
 	ret = QLA_SUCCESS;
 
-	/* Pause RISC. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);		/* PCI Posting. */
-
 	/* Enable flash write. */
 	WRT_REG_DWORD(&reg->ctrl_status,
 	    RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -728,9 +698,5 @@ qla24xx_write_nvram_data(scsi_qla_host_t
 	    RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
 	RD_REG_DWORD(&reg->ctrl_status);	/* PCI Posting. */
 
-	/* Release RISC pause. */
-	WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
-	RD_REG_DWORD(&reg->hccr);		/* PCI Posting. */
-
 	return ret;
 }
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -19,9 +19,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.00b5-k"
+#define QLA2XXX_VERSION      "8.01.00-k"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
 #define QLA_DRIVER_PATCH_VER	0
-#define QLA_DRIVER_BETA_VER	5
+#define QLA_DRIVER_BETA_VER	0
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
new file mode 100644
--- /dev/null
+++ b/drivers/scsi/raid_class.c
@@ -0,0 +1,250 @@
+/*
+ * RAID Attributes
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/raid_class.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#define RAID_NUM_ATTRS	3
+
+struct raid_internal {
+	struct raid_template r;
+	struct raid_function_template *f;
+	/* The actual attributes */
+	struct class_device_attribute private_attrs[RAID_NUM_ATTRS];
+	/* The array of null terminated pointers to attributes 
+	 * needed by scsi_sysfs.c */
+	struct class_device_attribute *attrs[RAID_NUM_ATTRS + 1];
+};
+
+struct raid_component {
+	struct list_head node;
+	struct device *dev;
+	int num;
+};
+
+#define to_raid_internal(tmpl)	container_of(tmpl, struct raid_internal, r)
+
+#define tc_to_raid_internal(tcont) ({					\
+	struct raid_template *r =					\
+		container_of(tcont, struct raid_template, raid_attrs);	\
+	to_raid_internal(r);						\
+})
+
+#define ac_to_raid_internal(acont) ({					\
+	struct transport_container *tc =				\
+		container_of(acont, struct transport_container, ac);	\
+	tc_to_raid_internal(tc);					\
+})
+
+#define class_device_to_raid_internal(cdev) ({				\
+	struct attribute_container *ac =				\
+		attribute_container_classdev_to_container(cdev);	\
+	ac_to_raid_internal(ac);					\
+})
+	
+
+static int raid_match(struct attribute_container *cont, struct device *dev)
+{
+	/* We have to look for every subsystem that could house
+	 * emulated RAID devices, so start with SCSI */
+	struct raid_internal *i = ac_to_raid_internal(cont);
+
+	if (scsi_is_sdev_device(dev)) {
+		struct scsi_device *sdev = to_scsi_device(dev);
+
+		if (i->f->cookie != sdev->host->hostt)
+			return 0;
+
+		return i->f->is_raid(dev);
+	}
+	/* FIXME: look at other subsystems too */
+	return 0;
+}
+
+static int raid_setup(struct transport_container *tc, struct device *dev,
+		       struct class_device *cdev)
+{
+	struct raid_data *rd;
+
+	BUG_ON(class_get_devdata(cdev));
+
+	rd = kmalloc(sizeof(*rd), GFP_KERNEL);
+	if (!rd)
+		return -ENOMEM;
+
+	memset(rd, 0, sizeof(*rd));
+	INIT_LIST_HEAD(&rd->component_list);
+	class_set_devdata(cdev, rd);
+		
+	return 0;
+}
+
+static int raid_remove(struct transport_container *tc, struct device *dev,
+		       struct class_device *cdev)
+{
+	struct raid_data *rd = class_get_devdata(cdev);
+	struct raid_component *rc, *next;
+	class_set_devdata(cdev, NULL);
+	list_for_each_entry_safe(rc, next, &rd->component_list, node) {
+		char buf[40];
+		snprintf(buf, sizeof(buf), "component-%d", rc->num);
+		list_del(&rc->node);
+		sysfs_remove_link(&cdev->kobj, buf);
+		kfree(rc);
+	}
+	kfree(class_get_devdata(cdev));
+	return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(raid_class,
+			       "raid_devices",
+			       raid_setup,
+			       raid_remove,
+			       NULL);
+
+static struct {
+	enum raid_state	value;
+	char		*name;
+} raid_states[] = {
+	{ RAID_ACTIVE, "active" },
+	{ RAID_DEGRADED, "degraded" },
+	{ RAID_RESYNCING, "resyncing" },
+	{ RAID_OFFLINE, "offline" },
+};
+
+static const char *raid_state_name(enum raid_state state)
+{
+	int i;
+	char *name = NULL;
+
+	for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) {
+		if (raid_states[i].value == state) {
+			name = raid_states[i].name;
+			break;
+		}
+	}
+	return name;
+}
+
+
+#define raid_attr_show_internal(attr, fmt, var, code)			\
+static ssize_t raid_show_##attr(struct class_device *cdev, char *buf)	\
+{									\
+	struct raid_data *rd = class_get_devdata(cdev);			\
+	code								\
+	return snprintf(buf, 20, #fmt "\n", var);			\
+}
+
+#define raid_attr_ro_states(attr, states, code)				\
+raid_attr_show_internal(attr, %s, name,					\
+	const char *name;						\
+	code								\
+	name = raid_##states##_name(rd->attr);				\
+)									\
+static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+
+#define raid_attr_ro_internal(attr, code)				\
+raid_attr_show_internal(attr, %d, rd->attr, code)			\
+static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+#define ATTR_CODE(attr)							\
+	struct raid_internal *i = class_device_to_raid_internal(cdev);	\
+	if (i->f->get_##attr)						\
+		i->f->get_##attr(cdev->dev);
+
+#define raid_attr_ro(attr)	raid_attr_ro_internal(attr, )
+#define raid_attr_ro_fn(attr)	raid_attr_ro_internal(attr, ATTR_CODE(attr))
+#define raid_attr_ro_state(attr)	raid_attr_ro_states(attr, attr, ATTR_CODE(attr))
+
+raid_attr_ro(level);
+raid_attr_ro_fn(resync);
+raid_attr_ro_state(state);
+
+void raid_component_add(struct raid_template *r,struct device *raid_dev,
+			struct device *component_dev)
+{
+	struct class_device *cdev =
+		attribute_container_find_class_device(&r->raid_attrs.ac,
+						      raid_dev);
+	struct raid_component *rc;
+	struct raid_data *rd = class_get_devdata(cdev);
+	char buf[40];
+
+	rc = kmalloc(sizeof(*rc), GFP_KERNEL);
+	if (!rc)
+		return;
+
+	INIT_LIST_HEAD(&rc->node);
+	rc->dev = component_dev;
+	rc->num = rd->component_count++;
+
+	snprintf(buf, sizeof(buf), "component-%d", rc->num);
+	list_add_tail(&rc->node, &rd->component_list);
+	sysfs_create_link(&cdev->kobj, &component_dev->kobj, buf);
+}
+EXPORT_SYMBOL(raid_component_add);
+
+struct raid_template *
+raid_class_attach(struct raid_function_template *ft)
+{
+	struct raid_internal *i = kmalloc(sizeof(struct raid_internal),
+					  GFP_KERNEL);
+	int count = 0;
+
+	if (unlikely(!i))
+		return NULL;
+
+	memset(i, 0, sizeof(*i));
+
+	i->f = ft;
+
+	i->r.raid_attrs.ac.class = &raid_class.class;
+	i->r.raid_attrs.ac.match = raid_match;
+	i->r.raid_attrs.ac.attrs = &i->attrs[0];
+
+	attribute_container_register(&i->r.raid_attrs.ac);
+
+	i->attrs[count++] = &class_device_attr_level;
+	i->attrs[count++] = &class_device_attr_resync;
+	i->attrs[count++] = &class_device_attr_state;
+
+	i->attrs[count] = NULL;
+	BUG_ON(count > RAID_NUM_ATTRS);
+
+	return &i->r;
+}
+EXPORT_SYMBOL(raid_class_attach);
+
+void
+raid_class_release(struct raid_template *r)
+{
+	struct raid_internal *i = to_raid_internal(r);
+
+	attribute_container_unregister(&i->r.raid_attrs.ac);
+
+	kfree(i);
+}
+EXPORT_SYMBOL(raid_class_release);
+
+static __init int raid_init(void)
+{
+	return transport_class_register(&raid_class);
+}
+
+static __exit void raid_exit(void)
+{
+	transport_class_unregister(&raid_class);
+}
+
+MODULE_AUTHOR("James Bottomley");
+MODULE_DESCRIPTION("RAID device class");
+MODULE_LICENSE("GPL");
+
+module_init(raid_init);
+module_exit(raid_exit);
+
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -268,6 +268,7 @@ struct scsi_cmnd *scsi_get_command(struc
 	} else
 		put_device(&dev->sdev_gendev);
 
+	cmd->jiffies_at_alloc = jiffies;
 	return cmd;
 }				
 EXPORT_SYMBOL(scsi_get_command);
@@ -627,7 +628,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 	spin_lock_irqsave(host->host_lock, flags);
 	scsi_cmd_get_serial(host, cmd); 
 
-	if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
+	if (unlikely(host->shost_state == SHOST_DEL)) {
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
 	} else {
@@ -798,9 +799,23 @@ static void scsi_softirq(struct softirq_
 	while (!list_empty(&local_q)) {
 		struct scsi_cmnd *cmd = list_entry(local_q.next,
 						   struct scsi_cmnd, eh_entry);
+		/* The longest time any command should be outstanding is the
+		 * per command timeout multiplied by the number of retries.
+		 *
+		 * For a typical command, this is 2.5 minutes */
+		unsigned long wait_for 
+			= cmd->allowed * cmd->timeout_per_command;
 		list_del_init(&cmd->eh_entry);
 
 		disposition = scsi_decide_disposition(cmd);
+		if (disposition != SUCCESS &&
+		    time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+			dev_printk(KERN_ERR, &cmd->device->sdev_gendev, 
+				   "timing out command, waited %lus\n",
+				   wait_for/HZ);
+			disposition = SUCCESS;
+		}
+			
 		scsi_log_completion(cmd, disposition);
 		switch (disposition) {
 		case SUCCESS:
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -114,6 +114,7 @@ static struct {
 	{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN},	/* locks up */
 	{"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN},	/* locks up */
 	{"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN},	/* locks up */
+	{"", "Scanner", "1.80", BLIST_NOLUN},	/* responds to all lun */
 
 	/*
 	 * Other types of devices that have special flags.
@@ -135,7 +136,7 @@ static struct {
 	{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
 	{"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
 	{"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
-	{"DEC", "HSG80", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
+	{"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
 	{"DELL", "PV660F", NULL, BLIST_SPARSELUN},
 	{"DELL", "PV660F   PSEUDO", NULL, BLIST_SPARSELUN},
 	{"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN},	/* Dell PV 530F */
@@ -191,6 +192,7 @@ static struct {
 	{"SGI", "RAID5", "*", BLIST_SPARSELUN},
 	{"SGI", "TP9100", "*", BLIST_REPORTLUN2},
 	{"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+	{"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
 	{"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
 	{"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
 	{"SONY", "TSL", NULL, BLIST_FORCELUN},		/* DDS3 & DDS4 autoloaders */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/kthread.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
@@ -75,7 +76,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *s
 
 	scmd->eh_eflags |= eh_flag;
 	list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
-	set_bit(SHOST_RECOVERY, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_RECOVERY);
 	shost->host_failed++;
 	scsi_eh_wakeup(shost);
 	spin_unlock_irqrestore(shost->host_lock, flags);
@@ -115,7 +116,6 @@ void scsi_add_timer(struct scsi_cmnd *sc
 
 	add_timer(&scmd->eh_timeout);
 }
-EXPORT_SYMBOL(scsi_add_timer);
 
 /**
  * scsi_delete_timer - Delete/cancel timer for a given function.
@@ -143,7 +143,6 @@ int scsi_delete_timer(struct scsi_cmnd *
 
 	return rtn;
 }
-EXPORT_SYMBOL(scsi_delete_timer);
 
 /**
  * scsi_times_out - Timeout function for normal scsi commands.
@@ -197,7 +196,8 @@ int scsi_block_when_processing_errors(st
 {
 	int online;
 
-	wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state)));
+	wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
+					   SHOST_RECOVERY));
 
 	online = scsi_device_online(sdev);
 
@@ -775,9 +775,11 @@ retry_tur:
 		__FUNCTION__, scmd, rtn));
 	if (rtn == SUCCESS)
 		return 0;
-	else if (rtn == NEEDS_RETRY)
+	else if (rtn == NEEDS_RETRY) {
 		if (retry_cnt--)
 			goto retry_tur;
+		return 0;
+	}
 	return 1;
 }
 
@@ -1458,7 +1460,7 @@ static void scsi_restart_operations(stru
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
 					  __FUNCTION__));
 
-	clear_bit(SHOST_RECOVERY, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_RUNNING);
 
 	wake_up(&shost->host_wait);
 
@@ -1582,16 +1584,8 @@ int scsi_error_handler(void *data)
 	int rtn;
 	DECLARE_MUTEX_LOCKED(sem);
 
-	/*
-	 *    Flush resources
-	 */
-
-	daemonize("scsi_eh_%d", shost->host_no);
-
 	current->flags |= PF_NOFREEZE;
-
 	shost->eh_wait = &sem;
-	shost->ehandler = current;
 
 	/*
 	 * Wake up the thread that created us.
@@ -1599,8 +1593,6 @@ int scsi_error_handler(void *data)
 	SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of"
 					  " scsi_eh_%d\n",shost->host_no));
 
-	complete(shost->eh_notify);
-
 	while (1) {
 		/*
 		 * If we get a signal, it means we are supposed to go
@@ -1621,7 +1613,7 @@ int scsi_error_handler(void *data)
 		 * semaphores isn't unreasonable.
 		 */
 		down_interruptible(&sem);
-		if (shost->eh_kill)
+		if (kthread_should_stop())
 			break;
 
 		SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
@@ -1660,22 +1652,6 @@ int scsi_error_handler(void *data)
 	 * Make sure that nobody tries to wake us up again.
 	 */
 	shost->eh_wait = NULL;
-
-	/*
-	 * Knock this down too.  From this point on, the host is flying
-	 * without a pilot.  If this is because the module is being unloaded,
-	 * that's fine.  If the user sent a signal to this thing, we are
-	 * potentially in real danger.
-	 */
-	shost->eh_active = 0;
-	shost->ehandler = NULL;
-
-	/*
-	 * If anyone is waiting for us to exit (i.e. someone trying to unload
-	 * a driver), then wake up that process to let them know we are on
-	 * the way out the door.
-	 */
-	complete_and_exit(shost->eh_notify, 0);
 	return 0;
 }
 
@@ -1846,12 +1822,16 @@ EXPORT_SYMBOL(scsi_reset_provider);
 int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
                          struct scsi_sense_hdr *sshdr)
 {
-	if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70)
+	if (!sense_buffer || !sb_len)
 		return 0;
 
 	memset(sshdr, 0, sizeof(struct scsi_sense_hdr));
 
 	sshdr->response_code = (sense_buffer[0] & 0x7f);
+
+	if (!scsi_sense_valid(sshdr))
+		return 0;
+
 	if (sshdr->response_code >= 0x72) {
 		/*
 		 * descriptor format
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -30,20 +30,20 @@
 
 #define MAX_BUF PAGE_SIZE
 
-/*
- * If we are told to probe a host, we will return 0 if  the host is not
- * present, 1 if the host is present, and will return an identifying
- * string at *arg, if arg is non null, filling to the length stored at
- * (int *) arg
+/**
+ * ioctl_probe  --  return host identification
+ * @host:	host to identify
+ * @buffer:	userspace buffer for identification
+ *
+ * Return an identifying string at @buffer, if @buffer is non-NULL, filling
+ * to the length stored at * (int *) @buffer.
  */
-
 static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
 {
 	unsigned int len, slen;
 	const char *string;
-	int temp = host->hostt->present;
 
-	if (temp && buffer) {
+	if (buffer) {
 		if (get_user(len, (unsigned int __user *) buffer))
 			return -EFAULT;
 
@@ -59,7 +59,7 @@ static int ioctl_probe(struct Scsi_Host 
 				return -EFAULT;
 		}
 	}
-	return temp;
+	return 1;
 }
 
 /*
@@ -88,25 +88,18 @@ static int ioctl_probe(struct Scsi_Host 
 static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
 				  int timeout, int retries)
 {
-	struct scsi_request *sreq;
 	int result;
 	struct scsi_sense_hdr sshdr;
 
 	SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd));
 
-	sreq = scsi_allocate_request(sdev, GFP_KERNEL);
-	if (!sreq) {
-		printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n");
-		return -ENOMEM;
-	}
-
-	sreq->sr_data_direction = DMA_NONE;
-        scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+	result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0,
+				  &sshdr, timeout, retries);
 
-	SCSI_LOG_IOCTL(2, printk("Ioctl returned  0x%x\n", sreq->sr_result));
+	SCSI_LOG_IOCTL(2, printk("Ioctl returned  0x%x\n", result));
 
-	if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
-	    (scsi_request_normalize_sense(sreq, &sshdr))) {
+	if ((driver_byte(result) & DRIVER_SENSE) &&
+	    (scsi_sense_valid(&sshdr))) {
 		switch (sshdr.sense_key) {
 		case ILLEGAL_REQUEST:
 			if (cmd[0] == ALLOW_MEDIUM_REMOVAL)
@@ -125,7 +118,7 @@ static int ioctl_internal_command(struct
 		case UNIT_ATTENTION:
 			if (sdev->removable) {
 				sdev->changed = 1;
-				sreq->sr_result = 0;	/* This is no longer considered an error */
+				result = 0;	/* This is no longer considered an error */
 				break;
 			}
 		default:	/* Fall through for non-removable media */
@@ -135,15 +128,13 @@ static int ioctl_internal_command(struct
 			       sdev->channel,
 			       sdev->id,
 			       sdev->lun,
-			       sreq->sr_result);
-			scsi_print_req_sense("   ", sreq);
+			       result);
+			scsi_print_sense_hdr("   ", &sshdr);
 			break;
 		}
 	}
 
-	result = sreq->sr_result;
 	SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n"));
-	scsi_release_request(sreq);
 	return result;
 }
 
@@ -208,8 +199,8 @@ int scsi_ioctl_send_command(struct scsi_
 {
 	char *buf;
 	unsigned char cmd[MAX_COMMAND_SIZE];
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
 	char __user *cmd_in;
-	struct scsi_request *sreq;
 	unsigned char opcode;
 	unsigned int inlen, outlen, cmdlen;
 	unsigned int needed, buf_needed;
@@ -321,31 +312,23 @@ int scsi_ioctl_send_command(struct scsi_
 		break;
 	}
 
-	sreq = scsi_allocate_request(sdev, GFP_KERNEL);
-        if (!sreq) {
-                result = -EINTR;
-                goto error;
-        }
-
-	sreq->sr_data_direction = data_direction;
-        scsi_wait_req(sreq, cmd, buf, needed, timeout, retries);
+	result = scsi_execute(sdev, cmd, data_direction, buf, needed,
+			      sense, timeout, retries, 0);
 
 	/* 
 	 * If there was an error condition, pass the info back to the user. 
 	 */
-	result = sreq->sr_result;
 	if (result) {
-		int sb_len = sizeof(sreq->sr_sense_buffer);
+		int sb_len = sizeof(*sense);
 
 		sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
-		if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len))
+		if (copy_to_user(cmd_in, sense, sb_len))
 			result = -EFAULT;
 	} else {
 		if (copy_to_user(cmd_in, buf, outlen))
 			result = -EFAULT;
 	}	
 
-	scsi_release_request(sreq);
 error:
 	kfree(buf);
 	return result;
@@ -475,8 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_
 	 * error processing, as long as the device was opened
 	 * non-blocking */
 	if (filp && filp->f_flags & O_NONBLOCK) {
-		if (test_bit(SHOST_RECOVERY,
-			     &sdev->host->shost_state))
+		if (sdev->host->shost_state == SHOST_RECOVERY)
 			return -ENODEV;
 	} else if (!scsi_block_when_processing_errors(sdev))
 		return -ENODEV;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -232,23 +232,6 @@ void scsi_do_req(struct scsi_request *sr
 }
 EXPORT_SYMBOL(scsi_do_req);
 
-static void scsi_wait_done(struct scsi_cmnd *cmd)
-{
-	struct request *req = cmd->request;
-	struct request_queue *q = cmd->device->request_queue;
-	unsigned long flags;
-
-	req->rq_status = RQ_SCSI_DONE;	/* Busy, but indicate request done */
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	if (blk_rq_tagged(req))
-		blk_queue_end_tag(q, req);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
-	if (req->waiting)
-		complete(req->waiting);
-}
-
 /* This is the end routine we get to if a command was never attached
  * to the request.  Simply complete the request without changing
  * rq_status; this will cause a DRIVER_ERROR. */
@@ -263,21 +246,114 @@ void scsi_wait_req(struct scsi_request *
 		   unsigned bufflen, int timeout, int retries)
 {
 	DECLARE_COMPLETION(wait);
-	
-	sreq->sr_request->waiting = &wait;
-	sreq->sr_request->rq_status = RQ_SCSI_BUSY;
-	sreq->sr_request->end_io = scsi_wait_req_end_io;
-	scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done,
-			timeout, retries);
+	int write = (sreq->sr_data_direction == DMA_TO_DEVICE);
+	struct request *req;
+
+	req = blk_get_request(sreq->sr_device->request_queue, write,
+			      __GFP_WAIT);
+	if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req,
+				       buffer, bufflen, __GFP_WAIT)) {
+		sreq->sr_result = DRIVER_ERROR << 24;
+		blk_put_request(req);
+		return;
+	}
+
+	req->flags |= REQ_NOMERGE;
+	req->waiting = &wait;
+	req->end_io = scsi_wait_req_end_io;
+	req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]);
+	req->sense = sreq->sr_sense_buffer;
+	req->sense_len = 0;
+	memcpy(req->cmd, cmnd, req->cmd_len);
+	req->timeout = timeout;
+	req->flags |= REQ_BLOCK_PC;
+	req->rq_disk = NULL;
+	blk_insert_request(sreq->sr_device->request_queue, req,
+			   sreq->sr_data_direction == DMA_TO_DEVICE, NULL);
 	wait_for_completion(&wait);
 	sreq->sr_request->waiting = NULL;
-	if (sreq->sr_request->rq_status != RQ_SCSI_DONE)
+	sreq->sr_result = req->errors;
+	if (req->errors)
 		sreq->sr_result |= (DRIVER_ERROR << 24);
 
-	__scsi_release_request(sreq);
+	blk_put_request(req);
 }
+
 EXPORT_SYMBOL(scsi_wait_req);
 
+/**
+ * scsi_execute - insert request and wait for the result
+ * @sdev:	scsi device
+ * @cmd:	scsi command
+ * @data_direction: data direction
+ * @buffer:	data buffer
+ * @bufflen:	len of buffer
+ * @sense:	optional sense buffer
+ * @timeout:	request timeout in seconds
+ * @retries:	number of times to retry request
+ * @flags:	or into request flags;
+ *
+ * returns the req->errors value which is the the scsi_cmnd result
+ * field.
+ **/
+int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+		 int data_direction, void *buffer, unsigned bufflen,
+		 unsigned char *sense, int timeout, int retries, int flags)
+{
+	struct request *req;
+	int write = (data_direction == DMA_TO_DEVICE);
+	int ret = DRIVER_ERROR << 24;
+
+	req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
+
+	if (bufflen &&	blk_rq_map_kern(sdev->request_queue, req,
+					buffer, bufflen, __GFP_WAIT))
+		goto out;
+
+	req->cmd_len = COMMAND_SIZE(cmd[0]);
+	memcpy(req->cmd, cmd, req->cmd_len);
+	req->sense = sense;
+	req->sense_len = 0;
+	req->timeout = timeout;
+	req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
+
+	/*
+	 * head injection *required* here otherwise quiesce won't work
+	 */
+	blk_execute_rq(req->q, NULL, req, 1);
+
+	ret = req->errors;
+ out:
+	blk_put_request(req);
+
+	return ret;
+}
+EXPORT_SYMBOL(scsi_execute);
+
+
+int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+		     int data_direction, void *buffer, unsigned bufflen,
+		     struct scsi_sense_hdr *sshdr, int timeout, int retries)
+{
+	char *sense = NULL;
+	int result;
+	
+	if (sshdr) {
+		sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+		if (!sense)
+			return DRIVER_ERROR << 24;
+		memset(sense, 0, SCSI_SENSE_BUFFERSIZE);
+	}
+	result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
+				  sense, timeout, retries, 0);
+	if (sshdr)
+		scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
+
+	kfree(sense);
+	return result;
+}
+EXPORT_SYMBOL(scsi_execute_req);
+
 /*
  * Function:    scsi_init_cmd_errh()
  *
@@ -348,7 +424,7 @@ void scsi_device_unbusy(struct scsi_devi
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	shost->host_busy--;
-	if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) &&
+	if (unlikely((shost->shost_state == SHOST_RECOVERY) &&
 		     shost->host_failed))
 		scsi_eh_wakeup(shost);
 	spin_unlock(shost->host_lock);
@@ -851,17 +927,20 @@ void scsi_io_completion(struct scsi_cmnd
 				scsi_requeue_command(q, cmd);
 				return;
 			}
-			printk(KERN_INFO "Device %s not ready.\n",
-			       req->rq_disk ? req->rq_disk->disk_name : "");
+			if (!(req->flags & REQ_QUIET))
+				dev_printk(KERN_INFO,
+					   &cmd->device->sdev_gendev,
+					   "Device not ready.\n");
 			cmd = scsi_end_request(cmd, 0, this_count, 1);
 			return;
 		case VOLUME_OVERFLOW:
-			printk(KERN_INFO "Volume overflow <%d %d %d %d> CDB: ",
-			       cmd->device->host->host_no,
-			       (int)cmd->device->channel,
-			       (int)cmd->device->id, (int)cmd->device->lun);
-			__scsi_print_command(cmd->data_cmnd);
-			scsi_print_sense("", cmd);
+			if (!(req->flags & REQ_QUIET)) {
+				dev_printk(KERN_INFO,
+					   &cmd->device->sdev_gendev,
+					   "Volume overflow, CDB: ");
+				__scsi_print_command(cmd->data_cmnd);
+				scsi_print_sense("", cmd);
+			}
 			cmd = scsi_end_request(cmd, 0, block_bytes, 1);
 			return;
 		default:
@@ -878,14 +957,13 @@ void scsi_io_completion(struct scsi_cmnd
 		return;
 	}
 	if (result) {
-		printk(KERN_INFO "SCSI error : <%d %d %d %d> return code "
-		       "= 0x%x\n", cmd->device->host->host_no,
-		       cmd->device->channel,
-		       cmd->device->id,
-		       cmd->device->lun, result);
+		if (!(req->flags & REQ_QUIET)) {
+			dev_printk(KERN_INFO, &cmd->device->sdev_gendev,
+				   "SCSI error: return code = 0x%x\n", result);
 
-		if (driver_byte(result) & DRIVER_SENSE)
-			scsi_print_sense("", cmd);
+			if (driver_byte(result) & DRIVER_SENSE)
+				scsi_print_sense("", cmd);
+		}
 		/*
 		 * Mark a single buffer as not uptodate.  Queue the remainder.
 		 * We sometimes get this cruft in the event that a medium error
@@ -1020,6 +1098,12 @@ static int scsi_issue_flush_fn(request_q
 	return -EOPNOTSUPP;
 }
 
+static void scsi_generic_done(struct scsi_cmnd *cmd)
+{
+	BUG_ON(!blk_pc_request(cmd->request));
+	scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0);
+}
+
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
 	struct scsi_device *sdev = q->queuedata;
@@ -1061,7 +1145,7 @@ static int scsi_prep_fn(struct request_q
 	 * these two cases differently.  We differentiate by looking
 	 * at request->cmd, as this tells us the real story.
 	 */
-	if (req->flags & REQ_SPECIAL) {
+	if (req->flags & REQ_SPECIAL && req->special) {
 		struct scsi_request *sreq = req->special;
 
 		if (sreq->sr_magic == SCSI_REQ_MAGIC) {
@@ -1073,7 +1157,7 @@ static int scsi_prep_fn(struct request_q
 			cmd = req->special;
 	} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
 
-		if(unlikely(specials_only)) {
+		if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
 			if(specials_only == SDEV_QUIESCE ||
 					specials_only == SDEV_BLOCK)
 				return BLKPREP_DEFER;
@@ -1142,11 +1226,26 @@ static int scsi_prep_fn(struct request_q
 		/*
 		 * Initialize the actual SCSI command for this request.
 		 */
-		drv = *(struct scsi_driver **)req->rq_disk->private_data;
-		if (unlikely(!drv->init_command(cmd))) {
-			scsi_release_buffers(cmd);
-			scsi_put_command(cmd);
-			return BLKPREP_KILL;
+		if (req->rq_disk) {
+			drv = *(struct scsi_driver **)req->rq_disk->private_data;
+			if (unlikely(!drv->init_command(cmd))) {
+				scsi_release_buffers(cmd);
+				scsi_put_command(cmd);
+				return BLKPREP_KILL;
+			}
+		} else {
+			memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
+			if (rq_data_dir(req) == WRITE)
+				cmd->sc_data_direction = DMA_TO_DEVICE;
+			else if (req->data_len)
+				cmd->sc_data_direction = DMA_FROM_DEVICE;
+			else
+				cmd->sc_data_direction = DMA_NONE;
+			
+			cmd->transfersize = req->data_len;
+			cmd->allowed = 3;
+			cmd->timeout_per_command = req->timeout;
+			cmd->done = scsi_generic_done;
 		}
 	}
 
@@ -1207,7 +1306,7 @@ static inline int scsi_host_queue_ready(
 				   struct Scsi_Host *shost,
 				   struct scsi_device *sdev)
 {
-	if (test_bit(SHOST_RECOVERY, &shost->shost_state))
+	if (shost->shost_state == SHOST_RECOVERY)
 		return 0;
 	if (shost->host_busy == 0 && shost->host_blocked) {
 		/*
@@ -1539,9 +1638,9 @@ void scsi_exit_queue(void)
 	}
 }
 /**
- *	__scsi_mode_sense - issue a mode sense, falling back from 10 to 
+ *	scsi_mode_sense - issue a mode sense, falling back from 10 to 
  *		six bytes if necessary.
- *	@sreq:	SCSI request to fill in with the MODE_SENSE
+ *	@sdev:	SCSI device to be queried
  *	@dbd:	set if mode sense will allow block descriptors to be returned
  *	@modepage: mode page being requested
  *	@buffer: request buffer (may not be smaller than eight bytes)
@@ -1549,26 +1648,34 @@ void scsi_exit_queue(void)
  *	@timeout: command timeout
  *	@retries: number of retries before failing
  *	@data: returns a structure abstracting the mode header data
+ *	@sense: place to put sense data (or NULL if no sense to be collected).
+ *		must be SCSI_SENSE_BUFFERSIZE big.
  *
  *	Returns zero if unsuccessful, or the header offset (either 4
  *	or 8 depending on whether a six or ten byte command was
  *	issued) if successful.
  **/
 int
-__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
+scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
 		  unsigned char *buffer, int len, int timeout, int retries,
-		  struct scsi_mode_data *data) {
+		  struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) {
 	unsigned char cmd[12];
 	int use_10_for_ms;
 	int header_length;
+	int result;
+	struct scsi_sense_hdr my_sshdr;
 
 	memset(data, 0, sizeof(*data));
 	memset(&cmd[0], 0, 12);
 	cmd[1] = dbd & 0x18;	/* allows DBD and LLBA bits */
 	cmd[2] = modepage;
 
+	/* caller might not be interested in sense, but we need it */
+	if (!sshdr)
+		sshdr = &my_sshdr;
+
  retry:
-	use_10_for_ms = sreq->sr_device->use_10_for_ms;
+	use_10_for_ms = sdev->use_10_for_ms;
 
 	if (use_10_for_ms) {
 		if (len < 8)
@@ -1586,36 +1693,31 @@ __scsi_mode_sense(struct scsi_request *s
 		header_length = 4;
 	}
 
-	sreq->sr_cmd_len = 0;
-	memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer));
-	sreq->sr_data_direction = DMA_FROM_DEVICE;
-
 	memset(buffer, 0, len);
 
-	scsi_wait_req(sreq, cmd, buffer, len, timeout, retries);
+	result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+				  sshdr, timeout, retries);
 
 	/* This code looks awful: what it's doing is making sure an
 	 * ILLEGAL REQUEST sense return identifies the actual command
 	 * byte as the problem.  MODE_SENSE commands can return
 	 * ILLEGAL REQUEST if the code page isn't supported */
 
-	if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) &&
-	    (driver_byte(sreq->sr_result) & DRIVER_SENSE)) {
-		struct scsi_sense_hdr sshdr;
-
-		if (scsi_request_normalize_sense(sreq, &sshdr)) {
-			if ((sshdr.sense_key == ILLEGAL_REQUEST) &&
-			    (sshdr.asc == 0x20) && (sshdr.ascq == 0)) {
+	if (use_10_for_ms && !scsi_status_is_good(result) &&
+	    (driver_byte(result) & DRIVER_SENSE)) {
+		if (scsi_sense_valid(sshdr)) {
+			if ((sshdr->sense_key == ILLEGAL_REQUEST) &&
+			    (sshdr->asc == 0x20) && (sshdr->ascq == 0)) {
 				/* 
 				 * Invalid command operation code
 				 */
-				sreq->sr_device->use_10_for_ms = 0;
+				sdev->use_10_for_ms = 0;
 				goto retry;
 			}
 		}
 	}
 
-	if(scsi_status_is_good(sreq->sr_result)) {
+	if(scsi_status_is_good(result)) {
 		data->header_length = header_length;
 		if(use_10_for_ms) {
 			data->length = buffer[0]*256 + buffer[1] + 2;
@@ -1632,73 +1734,31 @@ __scsi_mode_sense(struct scsi_request *s
 		}
 	}
 
-	return sreq->sr_result;
-}
-EXPORT_SYMBOL(__scsi_mode_sense);
-
-/**
- *	scsi_mode_sense - issue a mode sense, falling back from 10 to 
- *		six bytes if necessary.
- *	@sdev:	scsi device to send command to.
- *	@dbd:	set if mode sense will disable block descriptors in the return
- *	@modepage: mode page being requested
- *	@buffer: request buffer (may not be smaller than eight bytes)
- *	@len:	length of request buffer.
- *	@timeout: command timeout
- *	@retries: number of retries before failing
- *
- *	Returns zero if unsuccessful, or the header offset (either 4
- *	or 8 depending on whether a six or ten byte command was
- *	issued) if successful.
- **/
-int
-scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
-		unsigned char *buffer, int len, int timeout, int retries,
-		struct scsi_mode_data *data)
-{
-	struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
-	int ret;
-
-	if (!sreq)
-		return -1;
-
-	ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len,
-				timeout, retries, data);
-
-	scsi_release_request(sreq);
-
-	return ret;
+	return result;
 }
 EXPORT_SYMBOL(scsi_mode_sense);
 
 int
 scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
 {
-	struct scsi_request *sreq;
 	char cmd[] = {
 		TEST_UNIT_READY, 0, 0, 0, 0, 0,
 	};
+	struct scsi_sense_hdr sshdr;
 	int result;
 	
-	sreq = scsi_allocate_request(sdev, GFP_KERNEL);
-	if (!sreq)
-		return -ENOMEM;
-
-	sreq->sr_data_direction = DMA_NONE;
-	scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+	result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr,
+				  timeout, retries);
 
-	if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) {
-		struct scsi_sense_hdr sshdr;
+	if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) {
 
-		if ((scsi_request_normalize_sense(sreq, &sshdr)) &&
+		if ((scsi_sense_valid(&sshdr)) &&
 		    ((sshdr.sense_key == UNIT_ATTENTION) ||
 		     (sshdr.sense_key == NOT_READY))) {
 			sdev->changed = 1;
-			sreq->sr_result = 0;
+			result = 0;
 		}
 	}
-	result = sreq->sr_result;
-	scsi_release_request(sreq);
 	return result;
 }
 EXPORT_SYMBOL(scsi_test_unit_ready);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -63,6 +63,9 @@ extern int __init scsi_init_devinfo(void
 extern void scsi_exit_devinfo(void);
 
 /* scsi_error.c */
+extern void scsi_add_timer(struct scsi_cmnd *, int,
+		void (*)(struct scsi_cmnd *));
+extern int scsi_delete_timer(struct scsi_cmnd *);
 extern void scsi_times_out(struct scsi_cmnd *cmd);
 extern int scsi_error_handler(void *host);
 extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -111,15 +111,14 @@ MODULE_PARM_DESC(inq_timeout, 
 
 /**
  * scsi_unlock_floptical - unlock device via a special MODE SENSE command
- * @sreq:	used to send the command
+ * @sdev:	scsi device to send command to
  * @result:	area to store the result of the MODE SENSE
  *
  * Description:
- *     Send a vendor specific MODE SENSE (not a MODE SELECT) command using
- *     @sreq to unlock a device, storing the (unused) results into result.
+ *     Send a vendor specific MODE SENSE (not a MODE SELECT) command.
  *     Called for BLIST_KEY devices.
  **/
-static void scsi_unlock_floptical(struct scsi_request *sreq,
+static void scsi_unlock_floptical(struct scsi_device *sdev,
 				  unsigned char *result)
 {
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
@@ -129,11 +128,10 @@ static void scsi_unlock_floptical(struct
 	scsi_cmd[1] = 0;
 	scsi_cmd[2] = 0x2e;
 	scsi_cmd[3] = 0;
-	scsi_cmd[4] = 0x2a;	/* size */
+	scsi_cmd[4] = 0x2a;     /* size */
 	scsi_cmd[5] = 0;
-	sreq->sr_cmd_len = 0;
-	sreq->sr_data_direction = DMA_FROM_DEVICE;
-	scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3);
+	scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL,
+			 SCSI_TIMEOUT, 3);
 }
 
 /**
@@ -433,26 +431,25 @@ void scsi_target_reap(struct scsi_target
 
 /**
  * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
- * @sreq:	used to send the INQUIRY
+ * @sdev:	scsi_device to probe
  * @inq_result:	area to store the INQUIRY result
+ * @result_len: len of inq_result
  * @bflags:	store any bflags found here
  *
  * Description:
- *     Probe the lun associated with @sreq using a standard SCSI INQUIRY;
+ *     Probe the lun associated with @req using a standard SCSI INQUIRY;
  *
- *     If the INQUIRY is successful, sreq->sr_result is zero and: the
+ *     If the INQUIRY is successful, zero is returned and the
  *     INQUIRY data is in @inq_result; the scsi_level and INQUIRY length
- *     are copied to the Scsi_Device at @sreq->sr_device (sdev);
- *     any flags value is stored in *@bflags.
+ *     are copied to the Scsi_Device any flags value is stored in *@bflags.
  **/
-static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
-			   int *bflags)
+static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
+			  int result_len, int *bflags)
 {
-	struct scsi_device *sdev = sreq->sr_device;	/* a bit ugly */
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
 	int first_inquiry_len, try_inquiry_len, next_inquiry_len;
 	int response_len = 0;
-	int pass, count;
+	int pass, count, result;
 	struct scsi_sense_hdr sshdr;
 
 	*bflags = 0;
@@ -475,28 +472,26 @@ static void scsi_probe_lun(struct scsi_r
 		memset(scsi_cmd, 0, 6);
 		scsi_cmd[0] = INQUIRY;
 		scsi_cmd[4] = (unsigned char) try_inquiry_len;
-		sreq->sr_cmd_len = 0;
-		sreq->sr_data_direction = DMA_FROM_DEVICE;
 
 		memset(inq_result, 0, try_inquiry_len);
-		scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result,
-				try_inquiry_len,
-				HZ/2 + HZ*scsi_inq_timeout, 3);
+
+		result = scsi_execute_req(sdev,  scsi_cmd, DMA_FROM_DEVICE,
+					  inq_result, try_inquiry_len, &sshdr,
+					  HZ / 2 + HZ * scsi_inq_timeout, 3);
 
 		SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s "
 				"with code 0x%x\n",
-				sreq->sr_result ? "failed" : "successful",
-				sreq->sr_result));
+				result ? "failed" : "successful", result));
 
-		if (sreq->sr_result) {
+		if (result) {
 			/*
 			 * not-ready to ready transition [asc/ascq=0x28/0x0]
 			 * or power-on, reset [asc/ascq=0x29/0x0], continue.
 			 * INQUIRY should not yield UNIT_ATTENTION
 			 * but many buggy devices do so anyway. 
 			 */
-			if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
-			    scsi_request_normalize_sense(sreq, &sshdr)) {
+			if ((driver_byte(result) & DRIVER_SENSE) &&
+			    scsi_sense_valid(&sshdr)) {
 				if ((sshdr.sense_key == UNIT_ATTENTION) &&
 				    ((sshdr.asc == 0x28) ||
 				     (sshdr.asc == 0x29)) &&
@@ -507,7 +502,7 @@ static void scsi_probe_lun(struct scsi_r
 		break;
 	}
 
-	if (sreq->sr_result == 0) {
+	if (result == 0) {
 		response_len = (unsigned char) inq_result[4] + 5;
 		if (response_len > 255)
 			response_len = first_inquiry_len;	/* sanity */
@@ -556,8 +551,8 @@ static void scsi_probe_lun(struct scsi_r
 
 	/* If the last transfer attempt got an error, assume the
 	 * peripheral doesn't exist or is dead. */
-	if (sreq->sr_result)
-		return;
+	if (result)
+		return -EIO;
 
 	/* Don't report any more data than the device says is valid */
 	sdev->inquiry_len = min(try_inquiry_len, response_len);
@@ -593,7 +588,7 @@ static void scsi_probe_lun(struct scsi_r
 	    (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1))
 		sdev->scsi_level++;
 
-	return;
+	return 0;
 }
 
 /**
@@ -800,9 +795,8 @@ static int scsi_probe_and_add_lun(struct
 				  void *hostdata)
 {
 	struct scsi_device *sdev;
-	struct scsi_request *sreq;
 	unsigned char *result;
-	int bflags, res = SCSI_SCAN_NO_RESPONSE;
+	int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256;
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 
 	/*
@@ -831,16 +825,13 @@ static int scsi_probe_and_add_lun(struct
 	sdev = scsi_alloc_sdev(starget, lun, hostdata);
 	if (!sdev)
 		goto out;
-	sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
-	if (!sreq)
-		goto out_free_sdev;
-	result = kmalloc(256, GFP_ATOMIC |
+
+	result = kmalloc(result_len, GFP_ATOMIC |
 			((shost->unchecked_isa_dma) ? __GFP_DMA : 0));
 	if (!result)
-		goto out_free_sreq;
+		goto out_free_sdev;
 
-	scsi_probe_lun(sreq, result, &bflags);
-	if (sreq->sr_result)
+	if (scsi_probe_lun(sdev, result, result_len, &bflags))
 		goto out_free_result;
 
 	/*
@@ -868,7 +859,7 @@ static int scsi_probe_and_add_lun(struct
 	if (res == SCSI_SCAN_LUN_PRESENT) {
 		if (bflags & BLIST_KEY) {
 			sdev->lockable = 0;
-			scsi_unlock_floptical(sreq, result);
+			scsi_unlock_floptical(sdev, result);
 		}
 		if (bflagsp)
 			*bflagsp = bflags;
@@ -876,8 +867,6 @@ static int scsi_probe_and_add_lun(struct
 
  out_free_result:
 	kfree(result);
- out_free_sreq:
-	scsi_release_request(sreq);
  out_free_sdev:
 	if (res == SCSI_SCAN_LUN_PRESENT) {
 		if (sdevp) {
@@ -1070,8 +1059,8 @@ static int scsi_report_lun_scan(struct s
 	unsigned int lun;
 	unsigned int num_luns;
 	unsigned int retries;
+	int result;
 	struct scsi_lun *lunp, *lun_data;
-	struct scsi_request *sreq;
 	u8 *data;
 	struct scsi_sense_hdr sshdr;
 	struct scsi_target *starget = scsi_target(sdev);
@@ -1089,10 +1078,6 @@ static int scsi_report_lun_scan(struct s
 	if (bflags & BLIST_NOLUN)
 		return 0;
 
-	sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
-	if (!sreq)
-		goto out;
-
 	sprintf(devname, "host %d channel %d id %d",
 		sdev->host->host_no, sdev->channel, sdev->id);
 
@@ -1110,7 +1095,7 @@ static int scsi_report_lun_scan(struct s
 	lun_data = kmalloc(length, GFP_ATOMIC |
 			   (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0));
 	if (!lun_data)
-		goto out_release_request;
+		goto out;
 
 	scsi_cmd[0] = REPORT_LUNS;
 
@@ -1129,8 +1114,6 @@ static int scsi_report_lun_scan(struct s
 
 	scsi_cmd[10] = 0;	/* reserved */
 	scsi_cmd[11] = 0;	/* control */
-	sreq->sr_cmd_len = 0;
-	sreq->sr_data_direction = DMA_FROM_DEVICE;
 
 	/*
 	 * We can get a UNIT ATTENTION, for example a power on/reset, so
@@ -1146,29 +1129,29 @@ static int scsi_report_lun_scan(struct s
 		SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending"
 				" REPORT LUNS to %s (try %d)\n", devname,
 				retries));
-		scsi_wait_req(sreq, scsi_cmd, lun_data, length,
-				SCSI_TIMEOUT + 4*HZ, 3);
+
+		result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
+					  lun_data, length, &sshdr,
+					  SCSI_TIMEOUT + 4 * HZ, 3);
+
 		SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS"
-				" %s (try %d) result 0x%x\n", sreq->sr_result
-				?  "failed" : "successful", retries,
-				sreq->sr_result));
-		if (sreq->sr_result == 0)
+				" %s (try %d) result 0x%x\n", result
+				?  "failed" : "successful", retries, result));
+		if (result == 0)
 			break;
-		else if (scsi_request_normalize_sense(sreq, &sshdr)) {
+		else if (scsi_sense_valid(&sshdr)) {
 			if (sshdr.sense_key != UNIT_ATTENTION)
 				break;
 		}
 	}
 
-	if (sreq->sr_result) {
+	if (result) {
 		/*
 		 * The device probably does not support a REPORT LUN command
 		 */
 		kfree(lun_data);
-		scsi_release_request(sreq);
 		return 1;
 	}
-	scsi_release_request(sreq);
 
 	/*
 	 * Get the length from the first four bytes of lun_data.
@@ -1242,8 +1225,6 @@ static int scsi_report_lun_scan(struct s
 	kfree(lun_data);
 	return 0;
 
- out_release_request:
-	scsi_release_request(sreq);
  out:
 	/*
 	 * We are out of memory, don't try scanning any further.
@@ -1265,9 +1246,12 @@ struct scsi_device *__scsi_add_device(st
 
 	get_device(&starget->dev);
 	down(&shost->scan_mutex);
-	res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
-	if (res != SCSI_SCAN_LUN_PRESENT)
-		sdev = ERR_PTR(-ENODEV);
+	if (scsi_host_scan_allowed(shost)) {
+		res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
+					     hostdata);
+		if (res != SCSI_SCAN_LUN_PRESENT)
+			sdev = ERR_PTR(-ENODEV);
+	}
 	up(&shost->scan_mutex);
 	scsi_target_reap(starget);
 	put_device(&starget->dev);
@@ -1417,11 +1401,15 @@ int scsi_scan_host_selected(struct Scsi_
 		return -EINVAL;
 
 	down(&shost->scan_mutex);
-	if (channel == SCAN_WILD_CARD) 
-		for (channel = 0; channel <= shost->max_channel; channel++)
+	if (scsi_host_scan_allowed(shost)) {
+		if (channel == SCAN_WILD_CARD)
+			for (channel = 0; channel <= shost->max_channel;
+			     channel++)
+				scsi_scan_channel(shost, channel, id, lun,
+						  rescan);
+		else
 			scsi_scan_channel(shost, channel, id, lun, rescan);
-	else
-		scsi_scan_channel(shost, channel, id, lun, rescan);
+	}
 	up(&shost->scan_mutex);
 
 	return 0;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -48,6 +48,30 @@ const char *scsi_device_state_name(enum 
 	return name;
 }
 
+static struct {
+	enum scsi_host_state	value;
+	char			*name;
+} shost_states[] = {
+	{ SHOST_CREATED, "created" },
+	{ SHOST_RUNNING, "running" },
+	{ SHOST_CANCEL, "cancel" },
+	{ SHOST_DEL, "deleted" },
+	{ SHOST_RECOVERY, "recovery" },
+};
+const char *scsi_host_state_name(enum scsi_host_state state)
+{
+	int i;
+	char *name = NULL;
+
+	for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+		if (shost_states[i].value == state) {
+			name = shost_states[i].name;
+			break;
+		}
+	}
+	return name;
+}
+
 static int check_set(unsigned int *val, char *src)
 {
 	char *last;
@@ -124,6 +148,43 @@ static ssize_t store_scan(struct class_d
 };
 static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
 
+static ssize_t
+store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
+{
+	int i;
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	enum scsi_host_state state = 0;
+
+	for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+		const int len = strlen(shost_states[i].name);
+		if (strncmp(shost_states[i].name, buf, len) == 0 &&
+		   buf[len] == '\n') {
+			state = shost_states[i].value;
+			break;
+		}
+	}
+	if (!state)
+		return -EINVAL;
+
+	if (scsi_host_set_state(shost, state))
+		return -EINVAL;
+	return count;
+}
+
+static ssize_t
+show_shost_state(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	const char *name = scsi_host_state_name(shost->shost_state);
+
+	if (!name)
+		return -EINVAL;
+
+	return snprintf(buf, 20, "%s\n", name);
+}
+
+static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
+
 shost_rd_attr(unique_id, "%u\n");
 shost_rd_attr(host_busy, "%hu\n");
 shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -139,6 +200,7 @@ static struct class_device_attribute *sc
 	&class_device_attr_unchecked_isa_dma,
 	&class_device_attr_proc_name,
 	&class_device_attr_scan,
+	&class_device_attr_state,
 	NULL
 };
 
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -252,7 +252,8 @@ struct fc_internal {
 
 #define to_fc_internal(tmpl)	container_of(tmpl, struct fc_internal, t)
 
-static int fc_target_setup(struct device *dev)
+static int fc_target_setup(struct transport_container *tc, struct device *dev,
+			   struct class_device *cdev)
 {
 	struct scsi_target *starget = to_scsi_target(dev);
 	struct fc_rport *rport = starget_to_rport(starget);
@@ -281,7 +282,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transp
 			       NULL,
 			       NULL);
 
-static int fc_host_setup(struct device *dev)
+static int fc_host_setup(struct transport_container *tc, struct device *dev,
+			 struct class_device *cdev)
 {
 	struct Scsi_Host *shost = dev_to_shost(dev);
 
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -28,14 +28,14 @@
 #include "scsi_priv.h"
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
 
 #define SPI_PRINTK(x, l, f, a...)	dev_printk(l, &(x)->dev, f , ##a)
 
-#define SPI_NUM_ATTRS 13	/* increase this if you add attributes */
+#define SPI_NUM_ATTRS 14	/* increase this if you add attributes */
 #define SPI_OTHER_ATTRS 1	/* Increase this if you add "always
 				 * on" attributes */
 #define SPI_HOST_ATTRS	1
@@ -106,27 +106,31 @@ static int sprint_frac(char *dest, int v
 	return result;
 }
 
-/* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions
- * resulting from (likely) bus and device resets */
-static void spi_wait_req(struct scsi_request *sreq, const void *cmd,
-			 void *buffer, unsigned bufflen)
+static int spi_execute(struct scsi_device *sdev, const void *cmd,
+		       enum dma_data_direction dir,
+		       void *buffer, unsigned bufflen,
+		       struct scsi_sense_hdr *sshdr)
 {
-	int i;
+	int i, result;
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
 
 	for(i = 0; i < DV_RETRIES; i++) {
-		sreq->sr_request->flags |= REQ_FAILFAST;
-
-		scsi_wait_req(sreq, cmd, buffer, bufflen,
-			      DV_TIMEOUT, /* retries */ 1);
-		if (sreq->sr_result & DRIVER_SENSE) {
-			struct scsi_sense_hdr sshdr;
-
-			if (scsi_request_normalize_sense(sreq, &sshdr)
-			    && sshdr.sense_key == UNIT_ATTENTION)
+		result = scsi_execute(sdev, cmd, dir, buffer, bufflen,
+				      sense, DV_TIMEOUT, /* retries */ 1,
+				      REQ_FAILFAST);
+		if (result & DRIVER_SENSE) {
+			struct scsi_sense_hdr sshdr_tmp;
+			if (!sshdr)
+				sshdr = &sshdr_tmp;
+
+			if (scsi_normalize_sense(sense, sizeof(*sense),
+						 sshdr)
+			    && sshdr->sense_key == UNIT_ATTENTION)
 				continue;
 		}
 		break;
 	}
+	return result;
 }
 
 static struct {
@@ -162,7 +166,8 @@ static inline enum spi_signal_type spi_s
 	return SPI_SIGNAL_UNKNOWN;
 }
 
-static int spi_host_setup(struct device *dev)
+static int spi_host_setup(struct transport_container *tc, struct device *dev,
+			  struct class_device *cdev)
 {
 	struct Scsi_Host *shost = dev_to_shost(dev);
 
@@ -196,7 +201,9 @@ static int spi_host_match(struct attribu
 	return &i->t.host_attrs.ac == cont;
 }
 
-static int spi_device_configure(struct device *dev)
+static int spi_device_configure(struct transport_container *tc,
+				struct device *dev,
+				struct class_device *cdev)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	struct scsi_target *starget = sdev->sdev_target;
@@ -214,7 +221,9 @@ static int spi_device_configure(struct d
 	return 0;
 }
 
-static int spi_setup_transport_attrs(struct device *dev)
+static int spi_setup_transport_attrs(struct transport_container *tc,
+				     struct device *dev,
+				     struct class_device *cdev)
 {
 	struct scsi_target *starget = to_scsi_target(dev);
 
@@ -231,6 +240,7 @@ static int spi_setup_transport_attrs(str
 	spi_rd_strm(starget) = 0;
 	spi_rti(starget) = 0;
 	spi_pcomp_en(starget) = 0;
+	spi_hold_mcs(starget) = 0;
 	spi_dv_pending(starget) = 0;
 	spi_initial_dv(starget) = 0;
 	init_MUTEX(&spi_dv_sem(starget));
@@ -347,6 +357,7 @@ spi_transport_rd_attr(wr_flow, "%d\n");
 spi_transport_rd_attr(rd_strm, "%d\n");
 spi_transport_rd_attr(rti, "%d\n");
 spi_transport_rd_attr(pcomp_en, "%d\n");
+spi_transport_rd_attr(hold_mcs, "%d\n");
 
 /* we only care about the first child device so we return 1 */
 static int child_iter(struct device *dev, void *data)
@@ -539,13 +550,13 @@ enum spi_compare_returns {
 /* This is for read/write Domain Validation:  If the device supports
  * an echo buffer, we do read/write tests to it */
 static enum spi_compare_returns
-spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
+spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
 			  u8 *ptr, const int retries)
 {
-	struct scsi_device *sdev = sreq->sr_device;
 	int len = ptr - buffer;
-	int j, k, r;
+	int j, k, r, result;
 	unsigned int pattern = 0x0000ffff;
+	struct scsi_sense_hdr sshdr;
 
 	const char spi_write_buffer[] = {
 		WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0
@@ -590,14 +601,12 @@ spi_dv_device_echo_buffer(struct scsi_re
 	}
 
 	for (r = 0; r < retries; r++) {
-		sreq->sr_cmd_len = 0;	/* wait_req to fill in */
-		sreq->sr_data_direction = DMA_TO_DEVICE;
-		spi_wait_req(sreq, spi_write_buffer, buffer, len);
-		if(sreq->sr_result || !scsi_device_online(sdev)) {
-			struct scsi_sense_hdr sshdr;
+		result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE,
+				     buffer, len, &sshdr);
+		if(result || !scsi_device_online(sdev)) {
 
 			scsi_device_set_state(sdev, SDEV_QUIESCE);
-			if (scsi_request_normalize_sense(sreq, &sshdr)
+			if (scsi_sense_valid(&sshdr)
 			    && sshdr.sense_key == ILLEGAL_REQUEST
 			    /* INVALID FIELD IN CDB */
 			    && sshdr.asc == 0x24 && sshdr.ascq == 0x00)
@@ -609,14 +618,13 @@ spi_dv_device_echo_buffer(struct scsi_re
 				return SPI_COMPARE_SKIP_TEST;
 
 
-			SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
+			SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result);
 			return SPI_COMPARE_FAILURE;
 		}
 
 		memset(ptr, 0, len);
-		sreq->sr_cmd_len = 0;	/* wait_req to fill in */
-		sreq->sr_data_direction = DMA_FROM_DEVICE;
-		spi_wait_req(sreq, spi_read_buffer, ptr, len);
+		spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE,
+			    ptr, len, NULL);
 		scsi_device_set_state(sdev, SDEV_QUIESCE);
 
 		if (memcmp(buffer, ptr, len) != 0)
@@ -628,25 +636,22 @@ spi_dv_device_echo_buffer(struct scsi_re
 /* This is for the simplest form of Domain Validation: a read test
  * on the inquiry data from the device */
 static enum spi_compare_returns
-spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
+spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer,
 			      u8 *ptr, const int retries)
 {
-	int r;
-	const int len = sreq->sr_device->inquiry_len;
-	struct scsi_device *sdev = sreq->sr_device;
+	int r, result;
+	const int len = sdev->inquiry_len;
 	const char spi_inquiry[] = {
 		INQUIRY, 0, 0, 0, len, 0
 	};
 
 	for (r = 0; r < retries; r++) {
-		sreq->sr_cmd_len = 0;	/* wait_req to fill in */
-		sreq->sr_data_direction = DMA_FROM_DEVICE;
-
 		memset(ptr, 0, len);
 
-		spi_wait_req(sreq, spi_inquiry, ptr, len);
+		result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE,
+				     ptr, len, NULL);
 		
-		if(sreq->sr_result || !scsi_device_online(sdev)) {
+		if(result || !scsi_device_online(sdev)) {
 			scsi_device_set_state(sdev, SDEV_QUIESCE);
 			return SPI_COMPARE_FAILURE;
 		}
@@ -667,12 +672,11 @@ spi_dv_device_compare_inquiry(struct scs
 }
 
 static enum spi_compare_returns
-spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
+spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr,
 	       enum spi_compare_returns 
-	       (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
+	       (*compare_fn)(struct scsi_device *, u8 *, u8 *, int))
 {
-	struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
-	struct scsi_device *sdev = sreq->sr_device;
+	struct spi_internal *i = to_spi_internal(sdev->host->transportt);
 	struct scsi_target *starget = sdev->sdev_target;
 	int period = 0, prevperiod = 0; 
 	enum spi_compare_returns retval;
@@ -680,7 +684,7 @@ spi_dv_retrain(struct scsi_request *sreq
 
 	for (;;) {
 		int newperiod;
-		retval = compare_fn(sreq, buffer, ptr, DV_LOOPS);
+		retval = compare_fn(sdev, buffer, ptr, DV_LOOPS);
 
 		if (retval == SPI_COMPARE_SUCCESS
 		    || retval == SPI_COMPARE_SKIP_TEST)
@@ -726,9 +730,9 @@ spi_dv_retrain(struct scsi_request *sreq
 }
 
 static int
-spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
+spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer)
 {
-	int l;
+	int l, result;
 
 	/* first off do a test unit ready.  This can error out 
 	 * because of reservations or some other reason.  If it
@@ -744,18 +748,16 @@ spi_dv_device_get_echo_buffer(struct scs
 	};
 
 	
-	sreq->sr_cmd_len = 0;
-	sreq->sr_data_direction = DMA_NONE;
-
 	/* We send a set of three TURs to clear any outstanding 
 	 * unit attention conditions if they exist (Otherwise the
 	 * buffer tests won't be happy).  If the TUR still fails
 	 * (reservation conflict, device not ready, etc) just
 	 * skip the write tests */
 	for (l = 0; ; l++) {
-		spi_wait_req(sreq, spi_test_unit_ready, NULL, 0);
+		result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE, 
+				     NULL, 0, NULL);
 
-		if(sreq->sr_result) {
+		if(result) {
 			if(l >= 3)
 				return 0;
 		} else {
@@ -764,12 +766,10 @@ spi_dv_device_get_echo_buffer(struct scs
 		}
 	}
 
-	sreq->sr_cmd_len = 0;
-	sreq->sr_data_direction = DMA_FROM_DEVICE;
-
-	spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4);
+	result = spi_execute(sdev, spi_read_buffer_descriptor, 
+			     DMA_FROM_DEVICE, buffer, 4, NULL);
 
-	if (sreq->sr_result)
+	if (result)
 		/* Device has no echo buffer */
 		return 0;
 
@@ -777,17 +777,16 @@ spi_dv_device_get_echo_buffer(struct scs
 }
 
 static void
-spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
+spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
 {
-	struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
-	struct scsi_device *sdev = sreq->sr_device;
+	struct spi_internal *i = to_spi_internal(sdev->host->transportt);
 	struct scsi_target *starget = sdev->sdev_target;
 	int len = sdev->inquiry_len;
 	/* first set us up for narrow async */
 	DV_SET(offset, 0);
 	DV_SET(width, 0);
 	
-	if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
+	if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS)
 	    != SPI_COMPARE_SUCCESS) {
 		SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
 		/* FIXME: should probably offline the device here? */
@@ -799,7 +798,7 @@ spi_dv_device_internal(struct scsi_reque
 	    scsi_device_wide(sdev)) {
 		i->f->set_width(starget, 1);
 
-		if (spi_dv_device_compare_inquiry(sreq, buffer,
+		if (spi_dv_device_compare_inquiry(sdev, buffer,
 						   buffer + len,
 						   DV_LOOPS)
 		    != SPI_COMPARE_SUCCESS) {
@@ -820,7 +819,7 @@ spi_dv_device_internal(struct scsi_reque
 
 	len = 0;
 	if (scsi_device_dt(sdev))
-		len = spi_dv_device_get_echo_buffer(sreq, buffer);
+		len = spi_dv_device_get_echo_buffer(sdev, buffer);
 
  retry:
 
@@ -846,7 +845,7 @@ spi_dv_device_internal(struct scsi_reque
 
 	if (len == 0) {
 		SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n");
-		spi_dv_retrain(sreq, buffer, buffer + len,
+		spi_dv_retrain(sdev, buffer, buffer + len,
 			       spi_dv_device_compare_inquiry);
 		return;
 	}
@@ -856,7 +855,7 @@ spi_dv_device_internal(struct scsi_reque
 		len = SPI_MAX_ECHO_BUFFER_SIZE;
 	}
 
-	if (spi_dv_retrain(sreq, buffer, buffer + len,
+	if (spi_dv_retrain(sdev, buffer, buffer + len,
 			   spi_dv_device_echo_buffer)
 	    == SPI_COMPARE_SKIP_TEST) {
 		/* OK, the stupid drive can't do a write echo buffer
@@ -879,16 +878,12 @@ spi_dv_device_internal(struct scsi_reque
 void
 spi_dv_device(struct scsi_device *sdev)
 {
-	struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
 	struct scsi_target *starget = sdev->sdev_target;
 	u8 *buffer;
 	const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
 
-	if (unlikely(!sreq))
-		return;
-
 	if (unlikely(scsi_device_get(sdev)))
-		goto out_free_req;
+		return;
 
 	buffer = kmalloc(len, GFP_KERNEL);
 
@@ -909,7 +904,7 @@ spi_dv_device(struct scsi_device *sdev)
 
 	SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n");
 
-	spi_dv_device_internal(sreq, buffer);
+	spi_dv_device_internal(sdev, buffer);
 
 	SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n");
 
@@ -924,8 +919,6 @@ spi_dv_device(struct scsi_device *sdev)
 	kfree(buffer);
  out_put:
 	scsi_device_put(sdev);
- out_free_req:
-	scsi_release_request(sreq);
 }
 EXPORT_SYMBOL(spi_dv_device);
 
@@ -1028,10 +1021,17 @@ void spi_display_xfer_agreement(struct s
 		sprint_frac(tmp, picosec, 1000);
 
 		dev_info(&starget->dev,
-			"%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n",
-			scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
-			tp->dt ? "DT" : "ST", tp->iu ? " IU" : "",
-			tp->qas  ? " QAS" : "", tmp, tp->offset);
+			 "%s %sSCSI %d.%d MB/s %s%s%s%s%s%s%s%s (%s ns, offset %d)\n",
+			 scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
+			 tp->dt ? "DT" : "ST",
+			 tp->iu ? " IU" : "",
+			 tp->qas  ? " QAS" : "",
+			 tp->rd_strm ? " RDSTRM" : "",
+			 tp->rti ? " RTI" : "",
+			 tp->wr_flow ? " WRFLOW" : "",
+			 tp->pcomp_en ? " PCOMP" : "",
+			 tp->hold_mcs ? " HMCS" : "",
+			 tmp, tp->offset);
 	} else {
 		dev_info(&starget->dev, "%sasynchronous.\n",
 				tp->width ? "wide " : "");
@@ -1073,6 +1073,7 @@ static int spi_device_match(struct attri
 {
 	struct scsi_device *sdev;
 	struct Scsi_Host *shost;
+	struct spi_internal *i;
 
 	if (!scsi_is_sdev_device(dev))
 		return 0;
@@ -1085,6 +1086,9 @@ static int spi_device_match(struct attri
 	/* Note: this class has no device attributes, so it has
 	 * no per-HBA allocation and thus we don't need to distinguish
 	 * the attribute containers for the device */
+	i = to_spi_internal(shost->transportt);
+	if (i->f->deny_binding && i->f->deny_binding(sdev->sdev_target))
+		return 0;
 	return 1;
 }
 
@@ -1092,6 +1096,7 @@ static int spi_target_match(struct attri
 			    struct device *dev)
 {
 	struct Scsi_Host *shost;
+	struct scsi_target *starget;
 	struct spi_internal *i;
 
 	if (!scsi_is_target_device(dev))
@@ -1103,7 +1108,11 @@ static int spi_target_match(struct attri
 		return 0;
 
 	i = to_spi_internal(shost->transportt);
-	
+	starget = to_scsi_target(dev);
+
+	if (i->f->deny_binding && i->f->deny_binding(starget))
+		return 0;
+
 	return &i->t.target_attrs.ac == cont;
 }
 
@@ -1154,6 +1163,7 @@ spi_attach_transport(struct spi_function
 	SETUP_ATTRIBUTE(rd_strm);
 	SETUP_ATTRIBUTE(rti);
 	SETUP_ATTRIBUTE(pcomp_en);
+	SETUP_ATTRIBUTE(hold_mcs);
 
 	/* if you add an attribute but forget to increase SPI_NUM_ATTRS
 	 * this bug will trigger */
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -59,7 +59,6 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
 #include <scsi/scsicam.h>
 
 #include "scsi_logging.h"
@@ -125,7 +124,7 @@ static int sd_issue_flush(struct device 
 static void sd_end_flush(request_queue_t *, struct request *);
 static int sd_prepare_flush(request_queue_t *, struct request *);
 static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
-		 struct scsi_request *SRpnt, unsigned char *buffer);
+			     unsigned char *buffer);
 
 static struct scsi_driver sd_template = {
 	.owner			= THIS_MODULE,
@@ -682,19 +681,13 @@ not_present:
 
 static int sd_sync_cache(struct scsi_device *sdp)
 {
-	struct scsi_request *sreq;
 	int retries, res;
+	struct scsi_sense_hdr sshdr;
 
 	if (!scsi_device_online(sdp))
 		return -ENODEV;
 
-	sreq = scsi_allocate_request(sdp, GFP_KERNEL);
-	if (!sreq) {
-		printk("FAILED\n  No memory for request\n");
-		return -ENOMEM;
-	}
 
-	sreq->sr_data_direction = DMA_NONE;
 	for (retries = 3; retries > 0; --retries) {
 		unsigned char cmd[10] = { 0 };
 
@@ -703,22 +696,20 @@ static int sd_sync_cache(struct scsi_dev
 		 * Leave the rest of the command zero to indicate
 		 * flush everything.
 		 */
-		scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
-		if (sreq->sr_result == 0)
+		res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+				       SD_TIMEOUT, SD_MAX_RETRIES);
+		if (res == 0)
 			break;
 	}
 
-	res = sreq->sr_result;
-	if (res) {
-		printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
+	if (res) {		printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
 				    "host = %d, driver = %02x\n  ",
 				    status_byte(res), msg_byte(res),
 				    host_byte(res), driver_byte(res));
 			if (driver_byte(res) & DRIVER_SENSE)
-				scsi_print_req_sense("sd", sreq);
+				scsi_print_sense_hdr("sd", &sshdr);
 	}
 
-	scsi_release_request(sreq);
 	return res;
 }
 
@@ -957,22 +948,19 @@ static void sd_rw_intr(struct scsi_cmnd 
 	scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
 }
 
-static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp)
+static int media_not_present(struct scsi_disk *sdkp,
+			     struct scsi_sense_hdr *sshdr)
 {
-	struct scsi_sense_hdr sshdr;
 
-	if (!srp->sr_result)
-		return 0;
-	if (!(driver_byte(srp->sr_result) & DRIVER_SENSE))
+	if (!scsi_sense_valid(sshdr))
 		return 0;
 	/* not invoked for commands that could return deferred errors */
-	if (scsi_request_normalize_sense(srp, &sshdr)) {
-		if (sshdr.sense_key != NOT_READY &&
-		    sshdr.sense_key != UNIT_ATTENTION)
-			return 0;
-		if (sshdr.asc != 0x3A) /* medium not present */
-			return 0;
-	}
+	if (sshdr->sense_key != NOT_READY &&
+	    sshdr->sense_key != UNIT_ATTENTION)
+		return 0;
+	if (sshdr->asc != 0x3A) /* medium not present */
+		return 0;
+
 	set_media_not_present(sdkp);
 	return 1;
 }
@@ -981,10 +969,10 @@ static int media_not_present(struct scsi
  * spinup disk - called only in sd_revalidate_disk()
  */
 static void
-sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
-	       struct scsi_request *SRpnt, unsigned char *buffer) {
+sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+{
 	unsigned char cmd[10];
-	unsigned long spintime_value = 0;
+	unsigned long spintime_expire = 0;
 	int retries, spintime;
 	unsigned int the_result;
 	struct scsi_sense_hdr sshdr;
@@ -1001,18 +989,13 @@ sd_spinup_disk(struct scsi_disk *sdkp, c
 			cmd[0] = TEST_UNIT_READY;
 			memset((void *) &cmd[1], 0, 9);
 
-			SRpnt->sr_cmd_len = 0;
-			memset(SRpnt->sr_sense_buffer, 0,
-			       SCSI_SENSE_BUFFERSIZE);
-			SRpnt->sr_data_direction = DMA_NONE;
+			the_result = scsi_execute_req(sdkp->device, cmd,
+						      DMA_NONE, NULL, 0,
+						      &sshdr, SD_TIMEOUT,
+						      SD_MAX_RETRIES);
 
-			scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer,
-				       0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES);
-
-			the_result = SRpnt->sr_result;
 			if (the_result)
-				sense_valid = scsi_request_normalize_sense(
-							SRpnt, &sshdr);
+				sense_valid = scsi_sense_valid(&sshdr);
 			retries++;
 		} while (retries < 3 && 
 			 (!scsi_status_is_good(the_result) ||
@@ -1024,7 +1007,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, c
 		 * any media in it, don't bother with any of the rest of
 		 * this crap.
 		 */
-		if (media_not_present(sdkp, SRpnt))
+		if (media_not_present(sdkp, &sshdr))
 			return;
 
 		if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
@@ -1063,33 +1046,42 @@ sd_spinup_disk(struct scsi_disk *sdkp, c
 				cmd[1] = 1;	/* Return immediately */
 				memset((void *) &cmd[2], 0, 8);
 				cmd[4] = 1;	/* Start spin cycle */
-				SRpnt->sr_cmd_len = 0;
-				memset(SRpnt->sr_sense_buffer, 0,
-					SCSI_SENSE_BUFFERSIZE);
-
-				SRpnt->sr_data_direction = DMA_NONE;
-				scsi_wait_req(SRpnt, (void *)cmd, 
-					      (void *) buffer, 0/*512*/, 
-					      SD_TIMEOUT, SD_MAX_RETRIES);
-				spintime_value = jiffies;
+				scsi_execute_req(sdkp->device, cmd, DMA_NONE,
+						 NULL, 0, &sshdr,
+						 SD_TIMEOUT, SD_MAX_RETRIES);
+				spintime_expire = jiffies + 100 * HZ;
+				spintime = 1;
 			}
-			spintime = 1;
 			/* Wait 1 second for next try */
 			msleep(1000);
 			printk(".");
+
+		/*
+		 * Wait for USB flash devices with slow firmware.
+		 * Yes, this sense key/ASC combination shouldn't
+		 * occur here.  It's characteristic of these devices.
+		 */
+		} else if (sense_valid &&
+				sshdr.sense_key == UNIT_ATTENTION &&
+				sshdr.asc == 0x28) {
+			if (!spintime) {
+				spintime_expire = jiffies + 5 * HZ;
+				spintime = 1;
+			}
+			/* Wait 1 second for next try */
+			msleep(1000);
 		} else {
 			/* we don't understand the sense code, so it's
 			 * probably pointless to loop */
 			if(!spintime) {
 				printk(KERN_NOTICE "%s: Unit Not Ready, "
 					"sense:\n", diskname);
-				scsi_print_req_sense("", SRpnt);
+				scsi_print_sense_hdr("", &sshdr);
 			}
 			break;
 		}
 				
-	} while (spintime &&
-		 time_after(spintime_value + 100 * HZ, jiffies));
+	} while (spintime && time_before_eq(jiffies, spintime_expire));
 
 	if (spintime) {
 		if (scsi_status_is_good(the_result))
@@ -1104,14 +1096,15 @@ sd_spinup_disk(struct scsi_disk *sdkp, c
  */
 static void
 sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
-		 struct scsi_request *SRpnt, unsigned char *buffer) {
+		 unsigned char *buffer)
+{
 	unsigned char cmd[16];
-	struct scsi_device *sdp = sdkp->device;
 	int the_result, retries;
 	int sector_size = 0;
 	int longrc = 0;
 	struct scsi_sense_hdr sshdr;
 	int sense_valid = 0;
+	struct scsi_device *sdp = sdkp->device;
 
 repeat:
 	retries = 3;
@@ -1128,20 +1121,15 @@ repeat:
 			memset((void *) buffer, 0, 8);
 		}
 		
-		SRpnt->sr_cmd_len = 0;
-		memset(SRpnt->sr_sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-		SRpnt->sr_data_direction = DMA_FROM_DEVICE;
-
-		scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
-			      longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES);
+		the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+					      buffer, longrc ? 12 : 8, &sshdr,
+					      SD_TIMEOUT, SD_MAX_RETRIES);
 
-		if (media_not_present(sdkp, SRpnt))
+		if (media_not_present(sdkp, &sshdr))
 			return;
 
-		the_result = SRpnt->sr_result;
 		if (the_result)
-			sense_valid = scsi_request_normalize_sense(SRpnt,
-								   &sshdr);
+			sense_valid = scsi_sense_valid(&sshdr);
 		retries--;
 
 	} while (the_result && retries);
@@ -1156,7 +1144,7 @@ repeat:
 		       driver_byte(the_result));
 
 		if (driver_byte(the_result) & DRIVER_SENSE)
-			scsi_print_req_sense("sd", SRpnt);
+			scsi_print_sense_hdr("sd", &sshdr);
 		else
 			printk("%s : sense not available. \n", diskname);
 
@@ -1296,11 +1284,13 @@ got_data:
 
 /* called with buffer of length 512 */
 static inline int
-sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage,
-		 unsigned char *buffer, int len, struct scsi_mode_data *data)
-{
-	return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len,
-				 SD_TIMEOUT, SD_MAX_RETRIES, data);
+sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage,
+		 unsigned char *buffer, int len, struct scsi_mode_data *data,
+		 struct scsi_sense_hdr *sshdr)
+{
+	return scsi_mode_sense(sdp, dbd, modepage, buffer, len,
+			       SD_TIMEOUT, SD_MAX_RETRIES, data,
+			       sshdr);
 }
 
 /*
@@ -1309,25 +1299,27 @@ sd_do_mode_sense(struct scsi_request *SR
  */
 static void
 sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
-		   struct scsi_request *SRpnt, unsigned char *buffer) {
+			   unsigned char *buffer)
+{
 	int res;
+	struct scsi_device *sdp = sdkp->device;
 	struct scsi_mode_data data;
 
 	set_disk_ro(sdkp->disk, 0);
-	if (sdkp->device->skip_ms_page_3f) {
+	if (sdp->skip_ms_page_3f) {
 		printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname);
 		return;
 	}
 
-	if (sdkp->device->use_192_bytes_for_3f) {
-		res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 192, &data);
+	if (sdp->use_192_bytes_for_3f) {
+		res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL);
 	} else {
 		/*
 		 * First attempt: ask for all pages (0x3F), but only 4 bytes.
 		 * We have to start carefully: some devices hang if we ask
 		 * for more than is available.
 		 */
-		res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4, &data);
+		res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL);
 
 		/*
 		 * Second attempt: ask for page 0 When only page 0 is
@@ -1336,14 +1328,14 @@ sd_read_write_protect_flag(struct scsi_d
 		 * CDB.
 		 */
 		if (!scsi_status_is_good(res))
-			res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4, &data);
+			res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL);
 
 		/*
 		 * Third attempt: ask 255 bytes, as we did earlier.
 		 */
 		if (!scsi_status_is_good(res))
-			res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255,
-					       &data);
+			res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255,
+					       &data, NULL);
 	}
 
 	if (!scsi_status_is_good(res)) {
@@ -1365,19 +1357,20 @@ sd_read_write_protect_flag(struct scsi_d
  */
 static void
 sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
-		   struct scsi_request *SRpnt, unsigned char *buffer)
+		   unsigned char *buffer)
 {
 	int len = 0, res;
+	struct scsi_device *sdp = sdkp->device;
 
 	int dbd;
 	int modepage;
 	struct scsi_mode_data data;
 	struct scsi_sense_hdr sshdr;
 
-	if (sdkp->device->skip_ms_page_8)
+	if (sdp->skip_ms_page_8)
 		goto defaults;
 
-	if (sdkp->device->type == TYPE_RBC) {
+	if (sdp->type == TYPE_RBC) {
 		modepage = 6;
 		dbd = 8;
 	} else {
@@ -1386,7 +1379,7 @@ sd_read_cache_type(struct scsi_disk *sdk
 	}
 
 	/* cautiously ask */
-	res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data);
+	res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr);
 
 	if (!scsi_status_is_good(res))
 		goto bad_sense;
@@ -1407,7 +1400,7 @@ sd_read_cache_type(struct scsi_disk *sdk
 	len += data.header_length + data.block_descriptor_length;
 
 	/* Get the data */
-	res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data);
+	res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
 
 	if (scsi_status_is_good(res)) {
 		const char *types[] = {
@@ -1439,7 +1432,7 @@ sd_read_cache_type(struct scsi_disk *sdk
 	}
 
 bad_sense:
-	if (scsi_request_normalize_sense(SRpnt, &sshdr) &&
+	if (scsi_sense_valid(&sshdr) &&
 	    sshdr.sense_key == ILLEGAL_REQUEST &&
 	    sshdr.asc == 0x24 && sshdr.ascq == 0x0)
 		printk(KERN_NOTICE "%s: cache data unavailable\n",
@@ -1464,7 +1457,6 @@ static int sd_revalidate_disk(struct gen
 {
 	struct scsi_disk *sdkp = scsi_disk(disk);
 	struct scsi_device *sdp = sdkp->device;
-	struct scsi_request *sreq;
 	unsigned char *buffer;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
@@ -1476,18 +1468,11 @@ static int sd_revalidate_disk(struct gen
 	if (!scsi_device_online(sdp))
 		goto out;
 
-	sreq = scsi_allocate_request(sdp, GFP_KERNEL);
-	if (!sreq) {
-		printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation "
-		       "failure.\n");
-		goto out;
-	}
-
 	buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA);
 	if (!buffer) {
 		printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "
 		       "failure.\n");
-		goto out_release_request;
+		goto out;
 	}
 
 	/* defaults, until the device tells us otherwise */
@@ -1498,25 +1483,23 @@ static int sd_revalidate_disk(struct gen
 	sdkp->WCE = 0;
 	sdkp->RCD = 0;
 
-	sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer);
+	sd_spinup_disk(sdkp, disk->disk_name);
 
 	/*
 	 * Without media there is no reason to ask; moreover, some devices
 	 * react badly if we do.
 	 */
 	if (sdkp->media_present) {
-		sd_read_capacity(sdkp, disk->disk_name, sreq, buffer);
+		sd_read_capacity(sdkp, disk->disk_name, buffer);
 		if (sdp->removable)
 			sd_read_write_protect_flag(sdkp, disk->disk_name,
-					sreq, buffer);
-		sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer);
+						   buffer);
+		sd_read_cache_type(sdkp, disk->disk_name, buffer);
 	}
 		
 	set_capacity(disk, sdkp->capacity);
 	kfree(buffer);
 
- out_release_request: 
-	scsi_release_request(sreq);
  out:
 	return 0;
 }
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -61,7 +61,7 @@ static int sg_version_num = 30533;	/* 2 
 
 #ifdef CONFIG_SCSI_PROC_FS
 #include <linux/proc_fs.h>
-static char *sg_version_date = "20050328";
+static char *sg_version_date = "20050901";
 
 static int sg_proc_init(void);
 static void sg_proc_cleanup(void);
@@ -1027,8 +1027,7 @@ sg_ioctl(struct inode *inode, struct fil
 		if (sdp->detached)
 			return -ENODEV;
 		if (filp->f_flags & O_NONBLOCK) {
-			if (test_bit(SHOST_RECOVERY,
-				     &sdp->device->host->shost_state))
+			if (sdp->device->host->shost_state == SHOST_RECOVERY)
 				return -EBUSY;
 		} else if (!scsi_block_when_processing_errors(sdp->device))
 			return -EBUSY;
@@ -1795,12 +1794,12 @@ st_map_user_pages(struct scatterlist *sg
 	          unsigned long uaddr, size_t count, int rw,
 	          unsigned long max_pfn)
 {
+	unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	unsigned long start = uaddr >> PAGE_SHIFT;
+	const int nr_pages = end - start;
 	int res, i, j;
-	unsigned int nr_pages;
 	struct page **pages;
 
-	nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
-
 	/* User attempted Overflow! */
 	if ((uaddr + count) < uaddr)
 		return -EINVAL;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -50,10 +50,10 @@
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_driver.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>	/* For the door lock/unlock commands */
-#include <scsi/scsi_request.h>
 
 #include "scsi_logging.h"
 #include "sr.h"
@@ -199,15 +199,7 @@ int sr_media_change(struct cdrom_device_
 		/* check multisession offset etc */
 		sr_cd_check(cdi);
 
-		/* 
-		 * If the disk changed, the capacity will now be different,
-		 * so we force a re-read of this information 
-		 * Force 2048 for the sector size so that filesystems won't
-		 * be trying to use something that is too small if the disc
-		 * has changed.
-		 */
-		cd->needs_sector_size = 1;
-		cd->device->sector_size = 2048;
+		get_sectorsize(cd);
 	}
 	return retval;
 }
@@ -538,13 +530,6 @@ static int sr_open(struct cdrom_device_i
 	if (!scsi_block_when_processing_errors(sdev))
 		goto error_out;
 
-	/*
-	 * If this device did not have media in the drive at boot time, then
-	 * we would have been unable to get the sector size.  Check to see if
-	 * this is the case, and try again.
-	 */
-	if (cd->needs_sector_size)
-		get_sectorsize(cd);
 	return 0;
 
 error_out:
@@ -604,7 +589,6 @@ static int sr_probe(struct device *dev)
 	cd->driver = &sr_template;
 	cd->disk = disk;
 	cd->capacity = 0x1fffff;
-	cd->needs_sector_size = 1;
 	cd->device->changed = 1;	/* force recheck CD type */
 	cd->use = 1;
 	cd->readcd_known = 0;
@@ -658,43 +642,30 @@ static void get_sectorsize(struct scsi_c
 	unsigned char *buffer;
 	int the_result, retries = 3;
 	int sector_size;
-	struct scsi_request *SRpnt = NULL;
 	request_queue_t *queue;
 
 	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		goto Enomem;
-	SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
-	if (!SRpnt)
-		goto Enomem;
 
 	do {
 		cmd[0] = READ_CAPACITY;
 		memset((void *) &cmd[1], 0, 9);
-		/* Mark as really busy */
-		SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
-		SRpnt->sr_cmd_len = 0;
-
 		memset(buffer, 0, 8);
 
 		/* Do the command and wait.. */
-		SRpnt->sr_data_direction = DMA_FROM_DEVICE;
-		scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
-			      8, SR_TIMEOUT, MAX_RETRIES);
+		the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE,
+					      buffer, 8, NULL, SR_TIMEOUT,
+					      MAX_RETRIES);
 
-		the_result = SRpnt->sr_result;
 		retries--;
 
 	} while (the_result && retries);
 
 
-	scsi_release_request(SRpnt);
-	SRpnt = NULL;
-
 	if (the_result) {
 		cd->capacity = 0x1fffff;
 		sector_size = 2048;	/* A guess, just in case */
-		cd->needs_sector_size = 1;
 	} else {
 #if 0
 		if (cdrom_get_last_written(&cd->cdi,
@@ -727,7 +698,6 @@ static void get_sectorsize(struct scsi_c
 			printk("%s: unsupported sector size %d.\n",
 			       cd->cdi.name, sector_size);
 			cd->capacity = 0;
-			cd->needs_sector_size = 1;
 		}
 
 		cd->device->sector_size = sector_size;
@@ -736,7 +706,6 @@ static void get_sectorsize(struct scsi_c
 		 * Add this so that we have the ability to correctly gauge
 		 * what the device is capable of.
 		 */
-		cd->needs_sector_size = 0;
 		set_capacity(cd->disk, cd->capacity);
 	}
 
@@ -748,10 +717,7 @@ out:
 
 Enomem:
 	cd->capacity = 0x1fffff;
-	sector_size = 2048;	/* A guess, just in case */
-	cd->needs_sector_size = 1;
-	if (SRpnt)
-		scsi_release_request(SRpnt);
+	cd->device->sector_size = 2048;	/* A guess, just in case */
 	goto out;
 }
 
@@ -759,8 +725,8 @@ static void get_capabilities(struct scsi
 {
 	unsigned char *buffer;
 	struct scsi_mode_data data;
-	struct scsi_request *SRpnt;
 	unsigned char cmd[MAX_COMMAND_SIZE];
+	struct scsi_sense_hdr sshdr;
 	unsigned int the_result;
 	int retries, rc, n;
 
@@ -776,19 +742,11 @@ static void get_capabilities(struct scsi
 		""
 	};
 
-	/* allocate a request for the TEST_UNIT_READY */
-	SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
-	if (!SRpnt) {
-		printk(KERN_WARNING "(get_capabilities:) Request allocation "
-		       "failure.\n");
-		return;
-	}
 
 	/* allocate transfer buffer */
 	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
 		printk(KERN_ERR "sr: out of memory.\n");
-		scsi_release_request(SRpnt);
 		return;
 	}
 
@@ -800,24 +758,19 @@ static void get_capabilities(struct scsi
 		memset((void *)cmd, 0, MAX_COMMAND_SIZE);
 		cmd[0] = TEST_UNIT_READY;
 
-		SRpnt->sr_cmd_len = 0;
-		SRpnt->sr_sense_buffer[0] = 0;
-		SRpnt->sr_sense_buffer[2] = 0;
-		SRpnt->sr_data_direction = DMA_NONE;
-
-		scsi_wait_req (SRpnt, (void *) cmd, buffer,
-			       0, SR_TIMEOUT, MAX_RETRIES);
+		the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL,
+					       0, &sshdr, SR_TIMEOUT,
+					       MAX_RETRIES);
 
-		the_result = SRpnt->sr_result;
 		retries++;
 	} while (retries < 5 && 
 		 (!scsi_status_is_good(the_result) ||
-		  ((driver_byte(the_result) & DRIVER_SENSE) &&
-		   SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)));
+		  (scsi_sense_valid(&sshdr) &&
+		   sshdr.sense_key == UNIT_ATTENTION)));
 
 	/* ask for mode page 0x2a */
 	rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
-			     SR_TIMEOUT, 3, &data);
+			     SR_TIMEOUT, 3, &data, NULL);
 
 	if (!scsi_status_is_good(rc)) {
 		/* failed, drive doesn't have capabilities mode page */
@@ -825,7 +778,6 @@ static void get_capabilities(struct scsi
 		cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
 					 CDC_DVD | CDC_DVD_RAM |
 					 CDC_SELECT_DISC | CDC_SELECT_SPEED);
-		scsi_release_request(SRpnt);
 		kfree(buffer);
 		printk("%s: scsi-1 drive\n", cd->cdi.name);
 		return;
@@ -885,7 +837,6 @@ static void get_capabilities(struct scsi
 		cd->device->writeable = 1;
 	}
 
-	scsi_release_request(SRpnt);
 	kfree(buffer);
 }
 
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -33,7 +33,6 @@ typedef struct scsi_cd {
 	struct scsi_device *device;
 	unsigned int vendor;	/* vendor code, see sr_vendor.c         */
 	unsigned long ms_offset;	/* for reading multisession-CD's        */
-	unsigned needs_sector_size:1;	/* needs to get sector size */
 	unsigned use:1;		/* is this device still supportable     */
 	unsigned xa_flag:1;	/* CD has XA sectors ? */
 	unsigned readcd_known:1;	/* drive supports READ_CD (0xbe) */
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -17,7 +17,7 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_cmnd.h>
 
 #include "sr.h"
 
@@ -84,41 +84,37 @@ static int sr_fake_playtrkind(struct cdr
 
 int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
 {
-	struct scsi_request *SRpnt;
 	struct scsi_device *SDev;
-        struct request *req;
+	struct scsi_sense_hdr sshdr;
 	int result, err = 0, retries = 0;
+	struct request_sense *sense = cgc->sense;
 
 	SDev = cd->device;
-	SRpnt = scsi_allocate_request(SDev, GFP_KERNEL);
-        if (!SRpnt) {
-                printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl");
-		err = -ENOMEM;
-		goto out;
-        }
-	SRpnt->sr_data_direction = cgc->data_direction;
+
+	if (!sense) {
+		sense = kmalloc(sizeof(*sense), GFP_KERNEL);
+		if (!sense) {
+			err = -ENOMEM;
+			goto out;
+		}
+	}
 
       retry:
 	if (!scsi_block_when_processing_errors(SDev)) {
 		err = -ENODEV;
-		goto out_free;
+		goto out;
 	}
 
-	scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen,
-		      cgc->timeout, IOCTL_RETRIES);
-
-	req = SRpnt->sr_request;
-	if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) {
-		memcpy(req->buffer, SRpnt->sr_buffer, SRpnt->sr_bufflen);
-		kfree(SRpnt->sr_buffer);
-		SRpnt->sr_buffer = req->buffer;
-        }
+	memset(sense, 0, sizeof(*sense));
+	result = scsi_execute(SDev, cgc->cmd, cgc->data_direction,
+			      cgc->buffer, cgc->buflen, (char *)sense,
+			      cgc->timeout, IOCTL_RETRIES, 0);
 
-	result = SRpnt->sr_result;
+	scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr);
 
 	/* Minimal error checking.  Ignore cases we know about, and report the rest. */
 	if (driver_byte(result) != 0) {
-		switch (SRpnt->sr_sense_buffer[2] & 0xf) {
+		switch (sshdr.sense_key) {
 		case UNIT_ATTENTION:
 			SDev->changed = 1;
 			if (!cgc->quiet)
@@ -128,8 +124,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct pack
 			err = -ENOMEDIUM;
 			break;
 		case NOT_READY:	/* This happens if there is no disc in drive */
-			if (SRpnt->sr_sense_buffer[12] == 0x04 &&
-			    SRpnt->sr_sense_buffer[13] == 0x01) {
+			if (sshdr.asc == 0x04 &&
+			    sshdr.ascq == 0x01) {
 				/* sense: Logical unit is in process of becoming ready */
 				if (!cgc->quiet)
 					printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
@@ -146,37 +142,33 @@ int sr_do_ioctl(Scsi_CD *cd, struct pack
 			if (!cgc->quiet)
 				printk(KERN_INFO "%s: CDROM not ready.  Make sure there is a disc in the drive.\n", cd->cdi.name);
 #ifdef DEBUG
-			scsi_print_req_sense("sr", SRpnt);
+			scsi_print_sense_hdr("sr", &sshdr);
 #endif
 			err = -ENOMEDIUM;
 			break;
 		case ILLEGAL_REQUEST:
 			err = -EIO;
-			if (SRpnt->sr_sense_buffer[12] == 0x20 &&
-			    SRpnt->sr_sense_buffer[13] == 0x00)
+			if (sshdr.asc == 0x20 &&
+			    sshdr.ascq == 0x00)
 				/* sense: Invalid command operation code */
 				err = -EDRIVE_CANT_DO_THIS;
 #ifdef DEBUG
 			__scsi_print_command(cgc->cmd);
-			scsi_print_req_sense("sr", SRpnt);
+			scsi_print_sense_hdr("sr", &sshdr);
 #endif
 			break;
 		default:
 			printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name);
 			__scsi_print_command(cgc->cmd);
-			scsi_print_req_sense("sr", SRpnt);
+			scsi_print_sense_hdr("sr", &sshdr);
 			err = -EIO;
 		}
 	}
 
-	if (cgc->sense)
-		memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense));
-
 	/* Wake up a process waiting for device */
-      out_free:
-	scsi_release_request(SRpnt);
-	SRpnt = NULL;
       out:
+	if (!cgc->sense)
+		kfree(sense);
 	cgc->stat = err;
 	return err;
 }
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static char *verstr = "20050501";
+static char *verstr = "20050830";
 
 #include <linux/module.h>
 
@@ -219,6 +219,12 @@ static int switch_partition(struct scsi_
 
 static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
 
+static void scsi_tape_release(struct kref *);
+
+#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
+
+static DECLARE_MUTEX(st_ref_sem);
+
 
 #include "osst_detect.h"
 #ifndef SIGS_FROM_OSST
@@ -230,6 +236,46 @@ static int st_int_ioctl(struct scsi_tape
 	{"OnStream", "FW-", "", "osst"}
 #endif
 
+static struct scsi_tape *scsi_tape_get(int dev)
+{
+	struct scsi_tape *STp = NULL;
+
+	down(&st_ref_sem);
+	write_lock(&st_dev_arr_lock);
+
+	if (dev < st_dev_max && scsi_tapes != NULL)
+		STp = scsi_tapes[dev];
+	if (!STp) goto out;
+
+	kref_get(&STp->kref);
+
+	if (!STp->device)
+		goto out_put;
+
+	if (scsi_device_get(STp->device))
+		goto out_put;
+
+	goto out;
+
+out_put:
+	kref_put(&STp->kref, scsi_tape_release);
+	STp = NULL;
+out:
+	write_unlock(&st_dev_arr_lock);
+	up(&st_ref_sem);
+	return STp;
+}
+
+static void scsi_tape_put(struct scsi_tape *STp)
+{
+	struct scsi_device *sdev = STp->device;
+
+	down(&st_ref_sem);
+	kref_put(&STp->kref, scsi_tape_release);
+	scsi_device_put(sdev);
+	up(&st_ref_sem);
+}
+
 struct st_reject_data {
 	char *vendor;
 	char *model;
@@ -311,7 +357,7 @@ static int st_chk_result(struct scsi_tap
 		return 0;
 
 	cmdstatp = &STp->buffer->cmdstat;
-	st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp);
+	st_analyze_sense(SRpnt, cmdstatp);
 
 	if (cmdstatp->have_sense)
 		scode = STp->buffer->cmdstat.sense_hdr.sense_key;
@@ -399,10 +445,10 @@ static void st_sleep_done(struct scsi_cm
 
 	(STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
 	SCpnt->request->rq_status = RQ_SCSI_DONE;
-	(STp->buffer)->last_SRpnt = SCpnt->sc_request;
 	DEB( STp->write_pending = 0; )
 
-	complete(SCpnt->request->waiting);
+	if (SCpnt->request->waiting)
+		complete(SCpnt->request->waiting);
 }
 
 /* Do the scsi command. Waits until command performed if do_wait is true.
@@ -412,8 +458,20 @@ static struct scsi_request *
 st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
 	   int bytes, int direction, int timeout, int retries, int do_wait)
 {
+	struct completion *waiting;
 	unsigned char *bp;
 
+	/* if async, make sure there's no command outstanding */
+	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
+		printk(KERN_ERR "%s: Async command already active.\n",
+		       tape_name(STp));
+		if (signal_pending(current))
+			(STp->buffer)->syscall_result = (-EINTR);
+		else
+			(STp->buffer)->syscall_result = (-EBUSY);
+		return NULL;
+	}
+
 	if (SRpnt == NULL) {
 		SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
 		if (SRpnt == NULL) {
@@ -427,7 +485,13 @@ st_do_scsi(struct scsi_request * SRpnt, 
 		}
 	}
 
-	init_completion(&STp->wait);
+	/* If async IO, set last_SRpnt. This ptr tells write_behind_check
+	   which IO is outstanding. It's nulled out when the IO completes. */
+	if (!do_wait)
+		(STp->buffer)->last_SRpnt = SRpnt;
+
+	waiting = &STp->wait;
+	init_completion(waiting);
 	SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
 	if (SRpnt->sr_use_sg) {
 		if (!STp->buffer->do_dio)
@@ -438,17 +502,20 @@ st_do_scsi(struct scsi_request * SRpnt, 
 		bp = (STp->buffer)->b_data;
 	SRpnt->sr_data_direction = direction;
 	SRpnt->sr_cmd_len = 0;
-	SRpnt->sr_request->waiting = &(STp->wait);
+	SRpnt->sr_request->waiting = waiting;
 	SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
 	SRpnt->sr_request->rq_disk = STp->disk;
+	SRpnt->sr_request->end_io = blk_end_sync_rq;
 	STp->buffer->cmdstat.have_sense = 0;
 
 	scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
 		    st_sleep_done, timeout, retries);
 
 	if (do_wait) {
-		wait_for_completion(SRpnt->sr_request->waiting);
+		wait_for_completion(waiting);
 		SRpnt->sr_request->waiting = NULL;
+		if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+			SRpnt->sr_result |= (DRIVER_ERROR << 24);
 		(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
 	}
 	return SRpnt;
@@ -465,6 +532,7 @@ static int write_behind_check(struct scs
 	struct st_buffer *STbuffer;
 	struct st_partstat *STps;
 	struct st_cmdstatus *cmdstatp;
+	struct scsi_request *SRpnt;
 
 	STbuffer = STp->buffer;
 	if (!STbuffer->writing)
@@ -478,10 +546,14 @@ static int write_behind_check(struct scs
         ) /* end DEB */
 
 	wait_for_completion(&(STp->wait));
-	(STp->buffer)->last_SRpnt->sr_request->waiting = NULL;
+	SRpnt = STbuffer->last_SRpnt;
+	STbuffer->last_SRpnt = NULL;
+	SRpnt->sr_request->waiting = NULL;
+	if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+		SRpnt->sr_result |= (DRIVER_ERROR << 24);
 
-	(STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt);
-	scsi_release_request((STp->buffer)->last_SRpnt);
+	(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
+	scsi_release_request(SRpnt);
 
 	STbuffer->buffer_bytes -= STbuffer->writing;
 	STps = &(STp->ps[STp->partition]);
@@ -1055,25 +1127,20 @@ static int st_open(struct inode *inode, 
 	 */
 	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
 
+	if (!(STp = scsi_tape_get(dev)))
+		return -ENXIO;
+
 	write_lock(&st_dev_arr_lock);
-	if (dev >= st_dev_max || scsi_tapes == NULL ||
-	    ((STp = scsi_tapes[dev]) == NULL)) {
-		write_unlock(&st_dev_arr_lock);
-		return (-ENXIO);
-	}
 	filp->private_data = STp;
 	name = tape_name(STp);
 
 	if (STp->in_use) {
 		write_unlock(&st_dev_arr_lock);
+		scsi_tape_put(STp);
 		DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
 		return (-EBUSY);
 	}
 
-	if(scsi_device_get(STp->device)) {
-		write_unlock(&st_dev_arr_lock);
-		return (-ENXIO);
-	}
 	STp->in_use = 1;
 	write_unlock(&st_dev_arr_lock);
 	STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
@@ -1118,7 +1185,7 @@ static int st_open(struct inode *inode, 
  err_out:
 	normalize_buffer(STp->buffer);
 	STp->in_use = 0;
-	scsi_device_put(STp->device);
+	scsi_tape_put(STp);
 	return retval;
 
 }
@@ -1250,7 +1317,7 @@ static int st_release(struct inode *inod
 	write_lock(&st_dev_arr_lock);
 	STp->in_use = 0;
 	write_unlock(&st_dev_arr_lock);
-	scsi_device_put(STp->device);
+	scsi_tape_put(STp);
 
 	return result;
 }
@@ -3887,6 +3954,7 @@ static int st_probe(struct device *dev)
 		goto out_put_disk;
 	}
 	memset(tpnt, 0, sizeof(struct scsi_tape));
+	kref_init(&tpnt->kref);
 	tpnt->disk = disk;
 	sprintf(disk->disk_name, "st%d", i);
 	disk->private_data = &tpnt->driver;
@@ -3902,6 +3970,7 @@ static int st_probe(struct device *dev)
 		tpnt->tape_type = MT_ISSCSI2;
 
 	tpnt->buffer = buffer;
+	tpnt->buffer->last_SRpnt = NULL;
 
 	tpnt->inited = 0;
 	tpnt->dirty = 0;
@@ -4076,15 +4145,10 @@ static int st_remove(struct device *dev)
 					tpnt->modes[mode].cdevs[j] = NULL;
 				}
 			}
-			tpnt->device = NULL;
 
-			if (tpnt->buffer) {
-				tpnt->buffer->orig_frp_segs = 0;
-				normalize_buffer(tpnt->buffer);
-				kfree(tpnt->buffer);
-			}
-			put_disk(tpnt->disk);
-			kfree(tpnt);
+			down(&st_ref_sem);
+			kref_put(&tpnt->kref, scsi_tape_release);
+			up(&st_ref_sem);
 			return 0;
 		}
 	}
@@ -4093,6 +4157,34 @@ static int st_remove(struct device *dev)
 	return 0;
 }
 
+/**
+ *      scsi_tape_release - Called to free the Scsi_Tape structure
+ *      @kref: pointer to embedded kref
+ *
+ *      st_ref_sem must be held entering this routine.  Because it is
+ *      called on last put, you should always use the scsi_tape_get()
+ *      scsi_tape_put() helpers which manipulate the semaphore directly
+ *      and never do a direct kref_put().
+ **/
+static void scsi_tape_release(struct kref *kref)
+{
+	struct scsi_tape *tpnt = to_scsi_tape(kref);
+	struct gendisk *disk = tpnt->disk;
+
+	tpnt->device = NULL;
+
+	if (tpnt->buffer) {
+		tpnt->buffer->orig_frp_segs = 0;
+		normalize_buffer(tpnt->buffer);
+		kfree(tpnt->buffer);
+	}
+
+	disk->private_data = NULL;
+	put_disk(disk);
+	kfree(tpnt);
+	return;
+}
+
 static void st_intr(struct scsi_cmnd *SCpnt)
 {
 	scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
@@ -4348,12 +4440,12 @@ static int st_map_user_pages(struct scat
 static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 
 			      unsigned long uaddr, size_t count, int rw)
 {
+	unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	unsigned long start = uaddr >> PAGE_SHIFT;
+	const int nr_pages = end - start;
 	int res, i, j;
-	unsigned int nr_pages;
 	struct page **pages;
 
-	nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
-
 	/* User attempted Overflow! */
 	if ((uaddr + count) < uaddr)
 		return -EINVAL;
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -3,7 +3,7 @@
 #define _ST_H
 
 #include <linux/completion.h>
-
+#include <linux/kref.h>
 
 /* Descriptor for analyzed sense data */
 struct st_cmdstatus {
@@ -156,6 +156,7 @@ struct scsi_tape {
 	unsigned char last_sense[16];
 #endif
 	struct gendisk *disk;
+	struct kref     kref;
 };
 
 /* Bit masks for use_pf */
diff --git a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/mempool.h>
 #include <linux/workqueue.h>
+#include <scsi/sg.h>		/* for struct sg_iovec */
 
 #define BIO_POOL_SIZE 256
 
@@ -546,22 +547,34 @@ out_bmd:
 	return ERR_PTR(ret);
 }
 
-static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
-				  unsigned long uaddr, unsigned int len,
-				  int write_to_vm)
+static struct bio *__bio_map_user_iov(request_queue_t *q,
+				      struct block_device *bdev,
+				      struct sg_iovec *iov, int iov_count,
+				      int write_to_vm)
 {
-	unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	unsigned long start = uaddr >> PAGE_SHIFT;
-	const int nr_pages = end - start;
-	int ret, offset, i;
+	int i, j;
+	int nr_pages = 0;
 	struct page **pages;
 	struct bio *bio;
+	int cur_page = 0;
+	int ret, offset;
 
-	/*
-	 * transfer and buffer must be aligned to at least hardsector
-	 * size for now, in the future we can relax this restriction
-	 */
-	if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+	for (i = 0; i < iov_count; i++) {
+		unsigned long uaddr = (unsigned long)iov[i].iov_base;
+		unsigned long len = iov[i].iov_len;
+		unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		unsigned long start = uaddr >> PAGE_SHIFT;
+
+		nr_pages += end - start;
+		/*
+		 * transfer and buffer must be aligned to at least hardsector
+		 * size for now, in the future we can relax this restriction
+		 */
+		if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+			return ERR_PTR(-EINVAL);
+	}
+
+	if (!nr_pages)
 		return ERR_PTR(-EINVAL);
 
 	bio = bio_alloc(GFP_KERNEL, nr_pages);
@@ -573,42 +586,54 @@ static struct bio *__bio_map_user(reques
 	if (!pages)
 		goto out;
 
-	down_read(&current->mm->mmap_sem);
-	ret = get_user_pages(current, current->mm, uaddr, nr_pages,
-						write_to_vm, 0, pages, NULL);
-	up_read(&current->mm->mmap_sem);
-
-	if (ret < nr_pages)
-		goto out;
-
-	bio->bi_bdev = bdev;
+	memset(pages, 0, nr_pages * sizeof(struct page *));
 
-	offset = uaddr & ~PAGE_MASK;
-	for (i = 0; i < nr_pages; i++) {
-		unsigned int bytes = PAGE_SIZE - offset;
+	for (i = 0; i < iov_count; i++) {
+		unsigned long uaddr = (unsigned long)iov[i].iov_base;
+		unsigned long len = iov[i].iov_len;
+		unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		unsigned long start = uaddr >> PAGE_SHIFT;
+		const int local_nr_pages = end - start;
+		const int page_limit = cur_page + local_nr_pages;
+		
+		down_read(&current->mm->mmap_sem);
+		ret = get_user_pages(current, current->mm, uaddr,
+				     local_nr_pages,
+				     write_to_vm, 0, &pages[cur_page], NULL);
+		up_read(&current->mm->mmap_sem);
+
+		if (ret < local_nr_pages)
+			goto out_unmap;
+
+
+		offset = uaddr & ~PAGE_MASK;
+		for (j = cur_page; j < page_limit; j++) {
+			unsigned int bytes = PAGE_SIZE - offset;
+
+			if (len <= 0)
+				break;
+			
+			if (bytes > len)
+				bytes = len;
+
+			/*
+			 * sorry...
+			 */
+			if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes)
+				break;
 
-		if (len <= 0)
-			break;
-
-		if (bytes > len)
-			bytes = len;
+			len -= bytes;
+			offset = 0;
+		}
 
+		cur_page = j;
 		/*
-		 * sorry...
+		 * release the pages we didn't map into the bio, if any
 		 */
-		if (__bio_add_page(q, bio, pages[i], bytes, offset) < bytes)
-			break;
-
-		len -= bytes;
-		offset = 0;
+		while (j < page_limit)
+			page_cache_release(pages[j++]);
 	}
 
-	/*
-	 * release the pages we didn't map into the bio, if any
-	 */
-	while (i < nr_pages)
-		page_cache_release(pages[i++]);
-
 	kfree(pages);
 
 	/*
@@ -617,9 +642,17 @@ static struct bio *__bio_map_user(reques
 	if (!write_to_vm)
 		bio->bi_rw |= (1 << BIO_RW);
 
+	bio->bi_bdev = bdev;
 	bio->bi_flags |= (1 << BIO_USER_MAPPED);
 	return bio;
-out:
+
+ out_unmap:
+	for (i = 0; i < nr_pages; i++) {
+		if(!pages[i])
+			break;
+		page_cache_release(pages[i]);
+	}
+ out:
 	kfree(pages);
 	bio_put(bio);
 	return ERR_PTR(ret);
@@ -639,9 +672,33 @@ out:
 struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev,
 			 unsigned long uaddr, unsigned int len, int write_to_vm)
 {
+	struct sg_iovec iov;
+
+	iov.iov_base = (__user void *)uaddr;
+	iov.iov_len = len;
+
+	return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm);
+}
+
+/**
+ *	bio_map_user_iov - map user sg_iovec table into bio
+ *	@q: the request_queue_t for the bio
+ *	@bdev: destination block device
+ *	@iov:	the iovec.
+ *	@iov_count: number of elements in the iovec
+ *	@write_to_vm: bool indicating writing to pages or not
+ *
+ *	Map the user space address into a bio suitable for io to a block
+ *	device. Returns an error pointer in case of error.
+ */
+struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev,
+			     struct sg_iovec *iov, int iov_count,
+			     int write_to_vm)
+{
 	struct bio *bio;
+	int len = 0, i;
 
-	bio = __bio_map_user(q, bdev, uaddr, len, write_to_vm);
+	bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm);
 
 	if (IS_ERR(bio))
 		return bio;
@@ -654,6 +711,9 @@ struct bio *bio_map_user(request_queue_t
 	 */
 	bio_get(bio);
 
+	for (i = 0; i < iov_count; i++)
+		len += iov[i].iov_len;
+
 	if (bio->bi_size == len)
 		return bio;
 
@@ -698,6 +758,82 @@ void bio_unmap_user(struct bio *bio)
 	bio_put(bio);
 }
 
+static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err)
+{
+	if (bio->bi_size)
+		return 1;
+
+	bio_put(bio);
+	return 0;
+}
+
+
+static struct bio *__bio_map_kern(request_queue_t *q, void *data,
+				  unsigned int len, unsigned int gfp_mask)
+{
+	unsigned long kaddr = (unsigned long)data;
+	unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	unsigned long start = kaddr >> PAGE_SHIFT;
+	const int nr_pages = end - start;
+	int offset, i;
+	struct bio *bio;
+
+	bio = bio_alloc(gfp_mask, nr_pages);
+	if (!bio)
+		return ERR_PTR(-ENOMEM);
+
+	offset = offset_in_page(kaddr);
+	for (i = 0; i < nr_pages; i++) {
+		unsigned int bytes = PAGE_SIZE - offset;
+
+		if (len <= 0)
+			break;
+
+		if (bytes > len)
+			bytes = len;
+
+		if (__bio_add_page(q, bio, virt_to_page(data), bytes,
+				   offset) < bytes)
+			break;
+
+		data += bytes;
+		len -= bytes;
+		offset = 0;
+	}
+
+	bio->bi_end_io = bio_map_kern_endio;
+	return bio;
+}
+
+/**
+ *	bio_map_kern	-	map kernel address into bio
+ *	@q: the request_queue_t for the bio
+ *	@data: pointer to buffer to map
+ *	@len: length in bytes
+ *	@gfp_mask: allocation flags for bio allocation
+ *
+ *	Map the kernel address into a bio suitable for io to a block
+ *	device. Returns an error pointer in case of error.
+ */
+struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len,
+			 unsigned int gfp_mask)
+{
+	struct bio *bio;
+
+	bio = __bio_map_kern(q, data, len, gfp_mask);
+	if (IS_ERR(bio))
+		return bio;
+
+	if (bio->bi_size == len)
+		return bio;
+
+	/*
+	 * Don't support partial mappings.
+	 */
+	bio_put(bio);
+	return ERR_PTR(-EINVAL);
+}
+
 /*
  * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions
  * for performing direct-IO in BIOs.
@@ -1085,6 +1221,7 @@ EXPORT_SYMBOL(bio_add_page);
 EXPORT_SYMBOL(bio_get_nr_vecs);
 EXPORT_SYMBOL(bio_map_user);
 EXPORT_SYMBOL(bio_unmap_user);
+EXPORT_SYMBOL(bio_map_kern);
 EXPORT_SYMBOL(bio_pair_release);
 EXPORT_SYMBOL(bio_split);
 EXPORT_SYMBOL(bio_split_pool);
diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
--- a/include/linux/attribute_container.h
+++ b/include/linux/attribute_container.h
@@ -11,10 +11,12 @@
 
 #include <linux/device.h>
 #include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
 
 struct attribute_container {
 	struct list_head	node;
-	struct list_head	containers;
+	struct klist		containers;
 	struct class		*class;
 	struct class_device_attribute **attrs;
 	int (*match)(struct attribute_container *, struct device *);
@@ -62,12 +64,8 @@ int attribute_container_add_class_device
 						 struct class_device *classdev);
 void attribute_container_remove_attrs(struct class_device *classdev);
 void attribute_container_class_device_del(struct class_device *classdev);
-
-
-
-
-
-
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
 struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
 
 #endif
diff --git a/include/linux/bio.h b/include/linux/bio.h
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -295,7 +295,13 @@ extern int bio_add_page(struct bio *, st
 extern int bio_get_nr_vecs(struct block_device *);
 extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
 				unsigned long, unsigned int, int);
+struct sg_iovec;
+extern struct bio *bio_map_user_iov(struct request_queue *,
+				    struct block_device *,
+				    struct sg_iovec *, int, int);
 extern void bio_unmap_user(struct bio *);
+extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
+				unsigned int);
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
 extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -563,10 +563,12 @@ extern void blk_sync_queue(struct reques
 extern void __blk_stop_queue(request_queue_t *q);
 extern void blk_run_queue(request_queue_t *);
 extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
-extern struct request *blk_rq_map_user(request_queue_t *, int, void __user *, unsigned int);
-extern int blk_rq_unmap_user(struct request *, struct bio *, unsigned int);
-extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *);
-
+extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
+extern int blk_rq_unmap_user(struct bio *, unsigned int);
+extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, unsigned int);
+extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
+extern int blk_execute_rq(request_queue_t *, struct gendisk *,
+			  struct request *, int);
 static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
 {
 	return bdev->bd_disk->queue;
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
new file mode 100644
--- /dev/null
+++ b/include/linux/raid_class.h
@@ -0,0 +1,59 @@
+/*
+ */
+#include <linux/transport_class.h>
+
+struct raid_template {
+	struct transport_container raid_attrs;
+};
+
+struct raid_function_template {
+	void *cookie;
+	int (*is_raid)(struct device *);
+	void (*get_resync)(struct device *);
+	void (*get_state)(struct device *);
+};
+
+enum raid_state {
+	RAID_ACTIVE = 1,
+	RAID_DEGRADED,
+	RAID_RESYNCING,
+	RAID_OFFLINE,
+};
+
+struct raid_data {
+	struct list_head component_list;
+	int component_count;
+	int level;
+	enum raid_state state;
+	int resync;
+};
+
+#define DEFINE_RAID_ATTRIBUTE(type, attr)				      \
+static inline void							      \
+raid_set_##attr(struct raid_template *r, struct device *dev, type value) {    \
+	struct class_device *cdev =					      \
+		attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+	struct raid_data *rd;						      \
+	BUG_ON(!cdev);							      \
+	rd = class_get_devdata(cdev);					      \
+	rd->attr = value;						      \
+}									      \
+static inline type							      \
+raid_get_##attr(struct raid_template *r, struct device *dev) {		      \
+	struct class_device *cdev =					      \
+		attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+	struct raid_data *rd;						      \
+	BUG_ON(!cdev);							      \
+	rd = class_get_devdata(cdev);					      \
+	return rd->attr;						      \
+}
+
+DEFINE_RAID_ATTRIBUTE(int, level)
+DEFINE_RAID_ATTRIBUTE(int, resync)
+DEFINE_RAID_ATTRIBUTE(enum raid_state, state)
+	
+struct raid_template *raid_class_attach(struct raid_function_template *);
+void raid_class_release(struct raid_template *);
+
+void raid_component_add(struct raid_template *, struct device *,
+			struct device *);
diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
--- a/include/linux/transport_class.h
+++ b/include/linux/transport_class.h
@@ -12,11 +12,16 @@
 #include <linux/device.h>
 #include <linux/attribute_container.h>
 
+struct transport_container;
+
 struct transport_class {
 	struct class class;
-	int (*setup)(struct device *);
-	int (*configure)(struct device *);
-	int (*remove)(struct device *);
+	int (*setup)(struct transport_container *, struct device *,
+		     struct class_device *);
+	int (*configure)(struct transport_container *, struct device *,
+			 struct class_device *);
+	int (*remove)(struct transport_container *, struct device *,
+		      struct class_device *);
 };
 
 #define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg)			\
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -51,12 +51,16 @@ struct scsi_cmnd {
 	 * printk's to use ->pid, so that we can kill this field.
 	 */
 	unsigned long serial_number;
+	/*
+	 * This is set to jiffies as it was when the command was first
+	 * allocated.  It is used to time how long the command has
+	 * been outstanding
+	 */
+	unsigned long jiffies_at_alloc;
 
 	int retries;
 	int allowed;
 	int timeout_per_command;
-	int timeout_total;
-	int timeout;
 
 	unsigned char cmd_len;
 	unsigned char old_cmd_len;
diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -3,8 +3,10 @@
 
 struct scsi_cmnd;
 struct scsi_request;
+struct scsi_sense_hdr;
 
 extern void scsi_print_command(struct scsi_cmnd *);
+extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
 extern void __scsi_print_command(unsigned char *);
 extern void scsi_print_sense(const char *, struct scsi_cmnd *);
 extern void scsi_print_req_sense(const char *, struct scsi_request *);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -8,8 +8,17 @@
 
 struct request_queue;
 struct scsi_cmnd;
-struct scsi_mode_data;
 struct scsi_lun;
+struct scsi_sense_hdr;
+
+struct scsi_mode_data {
+	__u32	length;
+	__u16	block_descriptor_length;
+	__u8	medium_type;
+	__u8	device_specific;
+	__u8	header_length;
+	__u8	longlba:1;
+};
 
 /*
  * sdev state: If you alter this, you also need to alter scsi_sysfs.c
@@ -228,7 +237,8 @@ extern int scsi_set_medium_removal(struc
 
 extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
 			   unsigned char *buffer, int len, int timeout,
-			   int retries, struct scsi_mode_data *data);
+			   int retries, struct scsi_mode_data *data,
+			   struct scsi_sense_hdr *);
 extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
 				int retries);
 extern int scsi_device_set_state(struct scsi_device *sdev,
@@ -247,6 +257,14 @@ extern void int_to_scsilun(unsigned int,
 extern const char *scsi_device_state_name(enum scsi_device_state);
 extern int scsi_is_sdev_device(const struct device *);
 extern int scsi_is_target_device(const struct device *);
+extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+			int data_direction, void *buffer, unsigned bufflen,
+			unsigned char *sense, int timeout, int retries,
+			int flag);
+extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+			    int data_direction, void *buffer, unsigned bufflen,
+			    struct scsi_sense_hdr *, int timeout, int retries);
+
 static inline int scsi_device_online(struct scsi_device *sdev)
 {
 	return sdev->sdev_state != SDEV_OFFLINE;
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -26,10 +26,15 @@ struct scsi_sense_hdr {		/* See SPC-3 se
 	u8 additional_length;	/* always 0 for fixed sense format */
 };
 
+static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr)
+{
+	if (!sshdr)
+		return 0;
+
+	return (sshdr->response_code & 0x70) == 0x70;
+}
+
 
-extern void scsi_add_timer(struct scsi_cmnd *, int,
-		void (*)(struct scsi_cmnd *));
-extern int scsi_delete_timer(struct scsi_cmnd *);
 extern void scsi_report_bus_reset(struct Scsi_Host *, int);
 extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
 extern int scsi_block_when_processing_errors(struct scsi_device *);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -429,12 +429,15 @@ struct scsi_host_template {
 };
 
 /*
- * shost states
+ * shost state: If you alter this, you also need to alter scsi_sysfs.c
+ * (for the ascii descriptions) and the state model enforcer:
+ * scsi_host_set_state()
  */
-enum {
-	SHOST_ADD,
-	SHOST_DEL,
+enum scsi_host_state {
+	SHOST_CREATED = 1,
+	SHOST_RUNNING,
 	SHOST_CANCEL,
+	SHOST_DEL,
 	SHOST_RECOVERY,
 };
 
@@ -464,12 +467,10 @@ struct Scsi_Host {
 	struct task_struct    * ehandler;  /* Error recovery thread. */
 	struct semaphore      * eh_wait;   /* The error recovery thread waits
 					      on this. */
-	struct completion     * eh_notify; /* wait for eh to begin or end */
 	struct semaphore      * eh_action; /* Wait for specific actions on the
                                           host. */
 	unsigned int            eh_active:1; /* Indicates the eh thread is awake and active if
                                           this is true. */
-	unsigned int            eh_kill:1; /* set when killing the eh thread */
 	wait_queue_head_t       host_wait;
 	struct scsi_host_template *hostt;
 	struct scsi_transport_template *transportt;
@@ -575,7 +576,7 @@ struct Scsi_Host {
 	unsigned int  irq;
 	
 
-	unsigned long shost_state;
+	enum scsi_host_state shost_state;
 
 	/* ldm bits */
 	struct device		shost_gendev;
@@ -633,6 +634,7 @@ extern void scsi_remove_host(struct Scsi
 extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
 extern void scsi_host_put(struct Scsi_Host *t);
 extern struct Scsi_Host *scsi_host_lookup(unsigned short);
+extern const char *scsi_host_state_name(enum scsi_host_state);
 
 extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
 
@@ -646,6 +648,15 @@ static inline struct device *scsi_get_de
         return shost->shost_gendev.parent;
 }
 
+/**
+ * scsi_host_scan_allowed - Is scanning of this host allowed
+ * @shost:	Pointer to Scsi_Host.
+ **/
+static inline int scsi_host_scan_allowed(struct Scsi_Host *shost)
+{
+	return shost->shost_state == SHOST_RUNNING;
+}
+
 extern void scsi_unblock_requests(struct Scsi_Host *);
 extern void scsi_block_requests(struct Scsi_Host *);
 
@@ -663,5 +674,6 @@ extern struct scsi_device *scsi_get_host
 /* legacy interfaces */
 extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
 extern void scsi_unregister(struct Scsi_Host *);
+extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
 
 #endif /* _SCSI_SCSI_HOST_H */
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -54,20 +54,4 @@ extern void scsi_do_req(struct scsi_requ
 			void *buffer, unsigned bufflen,
 			void (*done) (struct scsi_cmnd *),
 			int timeout, int retries);
-
-struct scsi_mode_data {
-	__u32	length;
-	__u16	block_descriptor_length;
-	__u8	medium_type;
-	__u8	device_specific;
-	__u8	header_length;
-	__u8	longlba:1;
-};
-
-extern int __scsi_mode_sense(struct scsi_request *SRpnt, int dbd,
-			     int modepage, unsigned char *buffer, int len,
-			     int timeout, int retries,
-			     struct scsi_mode_data *data);
-
-
 #endif /* _SCSI_SCSI_REQUEST_H */
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -39,6 +39,7 @@ struct spi_transport_attrs {
 	unsigned int rd_strm:1;	/* Read streaming enabled */
 	unsigned int rti:1;	/* Retain Training Information */
 	unsigned int pcomp_en:1;/* Precompensation enabled */
+	unsigned int hold_mcs:1;/* Hold Margin Control Settings */
 	unsigned int initial_dv:1; /* DV done to this target yet  */
 	unsigned long flags;	/* flags field for drivers to use */
 	/* Device Properties fields */
@@ -78,6 +79,7 @@ struct spi_host_attrs {
 #define spi_rd_strm(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->rd_strm)
 #define spi_rti(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->rti)
 #define spi_pcomp_en(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en)
+#define spi_hold_mcs(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs)
 #define spi_initial_dv(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv)
 
 #define spi_support_sync(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_sync)
@@ -114,8 +116,11 @@ struct spi_function_template {
 	void	(*set_rti)(struct scsi_target *, int);
 	void	(*get_pcomp_en)(struct scsi_target *);
 	void	(*set_pcomp_en)(struct scsi_target *, int);
+	void	(*get_hold_mcs)(struct scsi_target *);
+	void	(*set_hold_mcs)(struct scsi_target *, int);
 	void	(*get_signalling)(struct Scsi_Host *);
 	void	(*set_signalling)(struct Scsi_Host *, enum spi_signal_type);
+	int	(*deny_binding)(struct scsi_target *);
 	/* The driver sets these to tell the transport class it
 	 * wants the attributes displayed in sysfs.  If the show_ flag
 	 * is not set, the attribute will be private to the transport
@@ -130,6 +135,7 @@ struct spi_function_template {
 	unsigned long	show_rd_strm:1;
 	unsigned long	show_rti:1;
 	unsigned long	show_pcomp_en:1;
+	unsigned long	show_hold_mcs:1;
 };
 
 struct scsi_transport_template *spi_attach_transport(struct spi_function_template *);