Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 8 Sep 2005 00:31:27 +0000 (17:31 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 8 Sep 2005 00:31:27 +0000 (17:31 -0700)
119 files changed:
Documentation/scsi/aic7xxx.txt
Documentation/scsi/scsi_mid_low_api.txt
MAINTAINERS
drivers/base/attribute_container.c
drivers/base/transport_class.c
drivers/block/ll_rw_blk.c
drivers/block/scsi_ioctl.c
drivers/cdrom/cdrom.c
drivers/ide/ide-disk.c
drivers/message/fusion/lsi/mpi.h
drivers/message/fusion/lsi/mpi_cnfg.h
drivers/message/fusion/lsi/mpi_history.txt
drivers/message/fusion/lsi/mpi_init.h
drivers/message/fusion/lsi/mpi_ioc.h
drivers/message/fusion/lsi/mpi_targ.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/scsi/3w-xxxx.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commctrl.c
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/rkt.c
drivers/scsi/aacraid/rx.c
drivers/scsi/aacraid/sa.c
drivers/scsi/advansys.c
drivers/scsi/aic7xxx/Kconfig.aic79xx
drivers/scsi/aic7xxx/aic7770.c
drivers/scsi/aic7xxx/aic79xx.h
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic79xx_proc.c
drivers/scsi/aic7xxx/aic7xxx.h
drivers/scsi/aic7xxx/aic7xxx.reg
drivers/scsi/aic7xxx/aic7xxx.seq
drivers/scsi/aic7xxx/aic7xxx_93cx6.c
drivers/scsi/aic7xxx/aic7xxx_core.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_proc.c
drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
drivers/scsi/aic7xxx/aiclib.c
drivers/scsi/aic7xxx/aiclib.h
drivers/scsi/ch.c
drivers/scsi/constants.c
drivers/scsi/hosts.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvscsi.h
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_mem.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_scsi.h
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/qla1280.c
drivers/scsi/qla1280.h
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/raid_class.c [new file with mode: 0644]
drivers/scsi/scsi.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/sr.h
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
drivers/scsi/st.h
fs/bio.c
include/linux/attribute_container.h
include/linux/bio.h
include/linux/blkdev.h
include/linux/raid_class.h [new file with mode: 0644]
include/linux/transport_class.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_dbg.h
include/scsi/scsi_device.h
include/scsi/scsi_eh.h
include/scsi/scsi_host.h
include/scsi/scsi_request.h
include/scsi/scsi_transport_spi.h

index 160e735..47e74dd 100644 (file)
@@ -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 in this file:
       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
index 7536823..44df89c 100644 (file)
@@ -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)
@@ -457,27 +455,6 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
 int scsi_add_host(struct Scsi_Host *shost, struct device * dev)
 
 
-/**
- * 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
@@ -565,24 +542,6 @@ void scsi_block_requests(struct Scsi_Host * shost)
 void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
 
 
-/**
- * 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.
index 2af78e9..8e4e829 100644 (file)
@@ -822,6 +822,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
index ec615d8..373e7b7 100644 (file)
 /* 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 attribute_container *cont)
 {
        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 device *dev,
                        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 device *dev,
                        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 device *dev,
 
        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(struct device *dev,
 
        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(struct class_device *classdev)
 }
 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)
 {
index 6c2b447..f25e7c6 100644 (file)
@@ -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 transport_class *tclass)
 }
 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(struct attribute_container *cont,
                                    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 *dev)
 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 attribute_container *cont,
  */
 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(struct attribute_container *cont,
        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)
index b4b1795..483d71b 100644 (file)
@@ -284,6 +284,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
        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_queue_t *q, int rw, void __user *ubuf,
         */
        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_queue_t *q, int rw, void __user *ubuf,
 
                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, struct bio *bio, unsigned int ulen)
                        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, struct gendisk *bd_disk,
                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_device *bdev, sector_t *error_sector)
 
 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);
index 681871c..abb2df2 100644 (file)
@@ -216,7 +216,7 @@ static int sg_io(struct file *file, request_queue_t *q,
                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, request_queue_t *q,
        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 (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 (IS_ERR(rq))
-                       return PTR_ERR(rq);
-       } else
-               rq = blk_get_request(q, READ, __GFP_WAIT);
+       if (ret)
+               goto out;
 
        /*
         * fill in request structure
@@ -298,7 +308,7 @@ static int sg_io(struct file *file, request_queue_t *q,
         * (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, request_queue_t *q,
                        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 *file, request_queue_t *q,
        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, struct gendisk *bd_disk, unsigned int cmd,
                        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:
index beaa561..1539603 100644 (file)
@@ -2097,6 +2097,10 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
        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 cdrom_device_info *cdi, __u8 __user *ubuf,
 
                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 cdrom_device_info *cdi, __u8 __user *ubuf,
                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 cdrom_device_info *cdi, __u8 __user *ubuf,
                ubuf += len;
        }
 
+       blk_put_request(rq);
        return ret;
 }
 
index c9d3a00..234f5de 100644 (file)
@@ -754,7 +754,7 @@ static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
 
        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
index 9f98334..b61e3d1 100644 (file)
@@ -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.
  *  --------------------------------------------------------------------------
  */
 
 /* 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)
 #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)
 
@@ -680,6 +686,15 @@ typedef struct _MSG_DEFAULT_REPLY
 #define MPI_IOCSTATUS_SCSI_IOC_TERMINATED       (0x004B)
 #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                                                      */
 /****************************************************************************/
index 15b12b0..d833989 100644 (file)
@@ -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
  *  ---------------
  *                      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_VOL
 #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_DISK_0
 } 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_0
 } 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_0
 #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_1
 #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_1
 #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_2
 } 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_2
 #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_ENCLOSURE_0
 } 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_ENCLOSURE_0
 #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)
 
 
 /****************************************************************************
index c9edbee..1a30ef1 100644 (file)
@@ -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
 ----------  --------   --------   --------   --------   --------   --------
index aca0358..d5af75a 100644 (file)
@@ -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.
  *  --------------------------------------------------------------------------
  */
 
@@ -202,6 +204,197 @@ typedef struct _MSG_SCSI_IO_REPLY
 #define MPI_SCSI_TASKTAG_UNKNOWN                (0xFFFF)
 
 
+/****************************************************************************/
+/*  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)
index f91eb4e..93b70e2 100644 (file)
@@ -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_ERROR
 #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)
 
 
 /*****************************************************************************
index 623901f..3f46285 100644 (file)
@@ -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.
  *  --------------------------------------------------------------------------
  */
 
@@ -370,6 +371,77 @@ typedef struct _MSG_TARGET_ERROR_REPLY
   TargetErrorReply_t, MPI_POINTER pTargetErrorReply_t;
 
 
+/****************************************************************************/
+/* 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                                               */
 /****************************************************************************/
index ffbe6f4..f517d06 100644 (file)
@@ -218,8 +218,7 @@ pci_enable_io_access(struct pci_dev *pdev)
  *     (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, struct pt_regs *r)
                        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, struct pt_regs *r)
                        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, struct pt_regs *r)
  *     @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_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
        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_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                 *      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_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 
                                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_ADAPTER *ioc, MPT_FRAME_HDR *mf)
        }
 #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, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
 
        /* 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, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
                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_ADAPTER **iocpp)
                if (ioc->id == iocid) {
                        *iocpp =ioc;
                        return iocid;
-               } 
+               }
        }
-       
+
        *iocpp = NULL;
        return -1;
 }
@@ -1032,9 +1037,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 
        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 struct pci_device_id *id)
        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 struct pci_device_id *id)
        /* 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 struct pci_device_id *id)
                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, u32 reason, int sleepFlag)
                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, u32 reason, int sleepFlag)
        } 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, u32 reason, int sleepFlag)
 
        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, u32 reason, int sleepFlag)
 
                        /* 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, u32 reason, int sleepFlag)
                        }
 
                        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, struct pci_dev *pdev)
 
        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->memmap != NULL)
-                       iounmap(ioc->memmap);
+       if (ioc->pci_irq != -1) {
+               free_irq(ioc->pci_irq, ioc);
+               ioc->pci_irq = -1;
+       }
+
+       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, int sleepFlag)
        }
 
        /* 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, int sleepFlag)
         *      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, int sleepFlag)
                 * 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 sleepFlag, int reason)
        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 sleepFlag, int reason)
                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 sleepFlag, int reason)
                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 sleepFlag, int reason)
                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 sleepFlag, int reason)
                                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 sleepFlag)
 
        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 sleepFlag)
                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 sleepFlag)
 
        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 sleepFlag)
        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 sleepFlag)
                                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 sleepFlag)
                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 sleepFlag)
  *                       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 ignore, int sleepFlag)
                 *
                 */
                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_type, int sleepFlag)
        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 *ioc, int reqBytes, u32 *req,
                 */
                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, int howlong, int sleepFlag)
        }
 
        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 portnum)
        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, int portnum)
        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, int portnum)
                                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, int portnum)
 
                                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, int portnum)
                                        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, int portnum)
                                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, int portnum)
        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_ADAPTER *ioc, int portnum)
        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_ADAPTER *ioc, int portnum)
        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_ADAPTER *ioc, int portnum)
        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, u8 EvSwitch)
 
        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, EventNotificationReply_t *evnp)
        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 *pCfg)
        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 *pCfg)
        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, CONFIGPARMS *pCfg)
        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 *ioc, EventNotificationReply_t *pEventReply
         *  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 log_info)
        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 log_info)
        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 ioc_status, MPT_FRAME_HDR *mf)
                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;
index 848fb23..f4827d9 100644 (file)
@@ -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 */
index 05ea594..7577c24 100644 (file)
@@ -242,7 +242,7 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
                /* 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, unsigned int data_size)
        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, unsigned int data_size)
 
        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) {
index b9d4f78..4a003dc 100644 (file)
@@ -281,12 +281,12 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
                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_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                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_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                /* 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_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        } 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_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        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 *host, char *buffer, char **start, off_t off
        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 type, u8 channel, u8 target, u8 lun, in
         */
        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, u8 type, u8 channel, u8 target, u8 lun
        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, u8 type, u8 channel, u8 target, u8 lun
 
        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 *SCpnt)
 
        /*  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 *SCpnt)
                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 * hd)
                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_HOST * hd, ulong timeout )
                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_device *device)
        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, int bus_id, int target_id, u8 lun, char *
         * 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, int portnum, int target_id, int flags)
                /* 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, int target_id, int bus)
        /* 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 *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                 * 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 *hd, int portnum)
                                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 *hd, int portnum)
                        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_number, int id)
        /* 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_number, int id)
        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_number, int id)
 
                                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_number, int id)
                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_number, int id)
                                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_number, int id)
                                        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_number, int id)
                                                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_number, int id)
 
                        } 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_number, int id)
         * 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, DVPARAMETERS *dv,void *pPage)
                /* 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, DVPARAMETERS *dv,void *pPage)
                                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, DVPARAMETERS *dv,void *pPage)
                                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, DVPARAMETERS *dv,void *pPage)
                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",
index dfa8806..587d127 100644 (file)
@@ -162,15 +162,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        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) {
index 973c51f..ae9e020 100644 (file)
@@ -1499,22 +1499,43 @@ static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
        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_Device_Extension *tw_dev, int request_i
        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_Device_Extension *tw_dev, int reques
 {
        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(TW_Device_Extension *tw_dev, int reques
                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(TW_Device_Extension *tw_dev, int reques
                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_complete(TW_Device_Extension *tw_dev, int req
 {
        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_complete(TW_Device_Extension *tw_dev, int req
        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() */
 
index a261b9e..2d21265 100644 (file)
@@ -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---
index c662b8c..4b4fd94 100644 (file)
@@ -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
index ccdf440..a8e3dfc 100644 (file)
@@ -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 * scsicmd)
        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(void *context, struct fib * fibptr)
        /* 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* 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* 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, struct fib * fibptr)
        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, struct fib * fibptr)
                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, struct fib * fibptr)
        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 * scsicmd, int cid)
 
        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 * scsicmd, int cid)
                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 * scsicmd, int cid)
                          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 * scsicmd, int cid)
                          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 * scsicmd, int cid)
        }
        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 * scsicmd, int cid)
                          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 * scsicmd, int cid)
                          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 * scsicmd)
        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 * scsicmd)
                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 * scsicmd)
 
        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 * scsicmd)
        }
        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 * scsicmd)
                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_cmnd* scsicmd)
        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(struct scsi_cmnd* scsicmd, struct sgmap64* p
        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 {
index 4ab0786..e405281 100644 (file)
@@ -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* dev);
 int aac_send_shutdown(struct aac_dev *dev);
 extern int numacb;
 extern int acbsize;
+extern char aac_driver_version[];
index 8538709..71f1cad 100644 (file)
@@ -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 aac_dev * dev, void __user *arg)
 static int check_revision(struct aac_dev *dev, void __user *arg)
 {
        struct revision response;
-
-       response.compat = 1;
-       response.version = le32_to_cpu(dev->adapter_info.kernelrev);
-       response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
+       char *driver_version = aac_driver_version;
+       u32 version;
+
+       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;
index 43557bf..75abd04 100644 (file)
@@ -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)
 {
index 5322865..a1d303f 100644 (file)
@@ -254,6 +254,7 @@ static void fib_dealloc(struct fib * fibptr)
 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 * dev, u32 qid, struct aac_entry **entr
         */
 
        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)
index 562da90..4ff29d7 100644 (file)
  * 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>
 
 #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_drivers[] = {
        { 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_drivers[] = {
        { 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(struct pci_dev *pdev,
 
        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(struct pci_dev *pdev)
        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;
 }
 
index 7d68b78..557287a 100644 (file)
@@ -87,6 +87,16 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_NONE;
 }
 
+/**
+ *     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
@@ -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:
index 1ff25f4..a8459fa 100644 (file)
@@ -87,6 +87,16 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_NONE;
 }
 
+/**
+ *     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
@@ -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:
index 0680249..3900abc 100644 (file)
@@ -81,6 +81,16 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_NONE;
 }
 
+/**
+ *     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
@@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
  
 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:
index 0fb9336..37ec541 100644 (file)
@@ -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",
index c2523a3..69ed77f 100644 (file)
@@ -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.
index 00f3bd1..527efd3 100644 (file)
@@ -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;
index fd4b2f3..653fb0b 100644 (file)
@@ -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_softc *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,
index 137fb1a..4e8f00d 100644 (file)
@@ -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[] =
@@ -5179,74 +5177,6 @@ ahd_softc_init(struct ahd_softc *ahd)
        return (0);
 }
 
-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)
 {
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
 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 *ahd)
                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);
index 329cb23..6b6d4e2 100644 (file)
 #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.
  */
@@ -187,71 +169,6 @@ static adapter_tag_info_t aic79xx_tag_info[] =
        {AIC79XX_CONFIGED_TAG_COMMANDS}
 };
 
-/*
- * 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
@@ -374,13 +291,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:
@@ -412,7 +322,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
 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);
-}
+static int  aic79xx_setup(char *c);
 
-#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;
+static int ahd_linux_unit;
 
-       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 __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 __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 *ahd, struct scb *scb)
 #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) {
-
-               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);
+       if (ahd->platform_data->qfrozen != 0) {
+               printf("%s: queue frozen\n", ahd_name(ahd));
+
+               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);
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int
-ahd_linux_slave_alloc(Scsi_Device *device)
+static inline struct scsi_target **
+ahd_linux_target_in_softc(struct scsi_target *starget)
 {
-       struct  ahd_softc *ahd;
+       struct  ahd_softc *ahd =
+               *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
+       unsigned int target_offset;
 
-       ahd = *((struct ahd_softc **)device->host->hostdata);
-       if (bootverbose)
-               printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id);
-       return (0);
+       target_offset = starget->id;
+       if (starget->channel != 0)
+               target_offset += 8;
+
+       return &ahd->platform_data->starget[target_offset];
 }
 
 static int
-ahd_linux_slave_configure(Scsi_Device *device)
+ahd_linux_target_alloc(struct scsi_target *starget)
 {
-       struct  ahd_softc *ahd;
-       struct  ahd_linux_device *dev;
-       u_long  flags;
+       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 Configure %d\n", ahd_name(ahd), device->id);
-       ahd_midlayer_entrypoint_lock(ahd, &flags);
-       /*
-        * 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->flags |= AHD_DEV_SLAVE_CONFIGURED;
-               dev->scsi_device = device;
-               ahd_linux_device_queue_depth(ahd, dev);
-       }
-       ahd_midlayer_entrypoint_unlock(ahd, &flags);
-       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_slave_destroy(Scsi_Device *device)
+ahd_linux_target_destroy(struct scsi_target *starget)
 {
-       struct  ahd_softc *ahd;
-       struct  ahd_linux_device *dev;
-       u_long  flags;
+       struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
+
+       *ahd_targp = NULL;
+}
+
+static int
+ahd_linux_slave_alloc(struct scsi_device *sdev)
+{
+       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 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 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));
 
        /*
-        * 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.
+        * We start out life using untagged
+        * transactions of which we allow one.
         */
-       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);
+       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);
 }
-#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)
+
+static int
+ahd_linux_slave_configure(struct scsi_device *sdev)
 {
-       Scsi_Device *device;
-       Scsi_Device *ldev;
        struct  ahd_softc *ahd;
-       u_long  flags;
 
-       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 Configure %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;
+       ahd_linux_device_queue_depth(sdev);
 
-               if (device->host == host) {
-                       struct   ahd_linux_device *dev;
+       /* Initial Domain Validation */
+       if (!spi_initial_dv(sdev->sdev_target))
+               spi_dv_device(sdev);
+
+       return 0;
+}
+
+static void
+ahd_linux_slave_destroy(struct scsi_device *sdev)
+{
+       struct  ahd_softc *ahd;
+       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 **)sdev->host->hostdata);
+       if (bootverbose)
+               printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id);
+
+       BUG_ON(dev->active);
+
+       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 dev, int geom[])
 
        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 dev, int geom[])
  * 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;
+       bus_dma_segment_t stack_sg;
 
-       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;
-       }
+       stack_sg.ds_addr = map;
+       stack_sg.ds_len = dmat->maxsize;
+       cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
+       return (0);
+}
 
-       printf("%s: At time of recovery, card was %spaused\n",
-              ahd_name(ahd), was_paused ? "" : "not ");
-       ahd_dump_card_state(ahd);
+void
+ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+}
 
-       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;
-       }
+int
+ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+       /* Nothing to do */
+       return (0);
+}
 
-       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;
+/********************* 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;
 
-               bus_scb = ahd_lookup_scb(ahd, active_scbptr);
-               if (bus_scb == 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.
-        */
-       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));
-#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
-
-       if (oldstate == newstate)
-               targ->dv_state_retry++;
-       else
-               targ->dv_state_retry = 0;
-       targ->dv_state = newstate;
-}
-
-static void
-ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
-{
-       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);
+        * 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
-               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);
+       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 (ahd->platform_data->dv_scsi_dev != NULL) {
-               free(ahd->platform_data->dv_scsi_dev, M_DEVBUF);
-               ahd->platform_data->dv_scsi_dev = NULL;
-       }
+       /* 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);
 
-       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);
+       value = rahd->channel - lahd->channel;
+       return (value);
 }
 
-static __inline int
-ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+static void
+ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
 {
-       u_long s;
-       int retval;
 
-       ahd_lock(ahd, &s);
-       retval = ahd_linux_fallback(ahd, devinfo);
-       ahd_unlock(ahd, &s);
+       if ((instance >= 0)
+        && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) {
+               uint8_t *iocell_info;
 
-       return (retval);
+               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_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-                       struct ahd_devinfo *devinfo,
-                       struct ahd_linux_target *targ)
+ahd_linux_setup_tag_info_global(char *p)
 {
-       u_int32_t status;
-
-       status = aic_error_action(cmd, targ->inq_data,
-                                 ahd_cmd_get_transaction_status(cmd),
-                                 ahd_cmd_get_scsi_status(cmd));
-
-       
-#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);
-       }
-#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;
+       int tags, i, j;
 
-                       xportflags = targ->inq_data->flags;
-                       if ((xportflags & (SID_Sync|SID_WBus16)) == 0)
-                               break;
+       tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
+       printf("Setting Global Tags= %d\n", tags);
 
-                       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;
+       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;
                }
-               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;
+static void
+ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
+{
 
-                               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 ((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);
+       }
+}
 
-                       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;
+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'};
 
-       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);
+       /* 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 '}':
+                       if (targ != -1)
+                               targ = -1;
+                       else if (instance != -1)
+                               instance = -1;
+                       opt_arg++;
                        break;
-               case SS_START:
-                       AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU);
+               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;
+/*
+ * 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;
 
-                       AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
-                       echo_size = scsi_3btoul(&targ->dv_buffer[1]);
-                       echo_size &= 0x1FFF;
+       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("Echo buffer size= %d\n", echo_size);
-                       }
+               { "debug", &ahd_debug },
 #endif
-                       if (echo_size == 0) {
-                               AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-                               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 },
+       };
 
-                       /* 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;
-#ifdef AHD_DEBUG
-                       if (ahd_debug & AHD_SHOW_DV) {
-                               ahd_print_devinfo(ahd, devinfo);
-                               printf("DV REBD reties exhausted\n");
-                       }
-#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;
+       end = strchr(s, '\0');
 
-       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;
+       /*
+        * 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_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;
+       while ((p = strsep(&s, ",.")) != NULL) {
+               if (*p == '\0')
+                       continue;
+               for (i = 0; i < NUM_ELEMENTS(options); i++) {
 
-       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;
+                       n = strlen(options[i].name);
+                       if (strncmp(options[i].name, p, n) == 0)
+                               break;
                }
-               break;
+               if (i == NUM_ELEMENTS(options))
+                       continue;
 
-       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;
+               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;
                }
-               break;
-
-       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;
        }
+       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;
-}
+__setup("aic79xx=", aic79xx_setup);
 
-/*
- * 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)
+uint32_t aic79xx_verbose;
+
+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 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);
+       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);
+       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);
 
-       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);
+       host->transportt = ahd_linux_transport_template;
+
+       scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
+       scsi_scan_host(host);
+       return (0);
 }
 
-static void
-ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-                struct ahd_devinfo *devinfo)
+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 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;
+       si_meminfo(&si);
+       return ((uint64_t)si.totalram << PAGE_SHIFT);
 }
 
-#define AHD_REBD_LEN 4
-
+/*
+ * 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_rebd(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 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;
-}
+       target_id = 0;
+       numtarg = 0;
 
-static void
-ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-                struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
+       if (aic79xx_no_reset != 0)
+               ahd->flags &= ~AHD_RESET_BUS_A;
 
-#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;
-}
+       if ((ahd->flags & AHD_RESET_BUS_A) != 0)
+               ahd_reset_channel(ahd, 'A', /*initiate_reset*/TRUE);
+       else
+               numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
 
-static void
-ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-                struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
+       /*
+        * 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;
 
-#ifdef AHD_DEBUG
-       if (ahd_debug & AHD_SHOW_DV) {
-               ahd_print_devinfo(ahd, devinfo);
-               printf("Sending REB\n");
+               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_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;
 }
 
-static void
-ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-               struct ahd_devinfo *devinfo,
-               struct ahd_linux_target *targ)
+int
+ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
 {
-       u_int le;
-
-       le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0;
-
-#ifdef AHD_DEBUG
-       if (ahd_debug & AHD_SHOW_DV) {
-               ahd_print_devinfo(ahd, devinfo);
-               printf("Sending SU\n");
-       }
-#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;
+       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);
 }
 
-static int
-ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+void
+ahd_platform_free(struct ahd_softc *ahd)
 {
-       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;
-
-#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
+       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;
+               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);
                }
-       } 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;
+               free(ahd->platform_data, M_DEVBUF);
        }
-       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)
+void
+ahd_platform_init(struct ahd_softc *ahd)
 {
-       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.
+        * Lookup and commit any modified IO Cell options.
         */
-       if ((scb = (struct scb *)cmd->host_scribble) == NULL) {
-               ahd_unlock(ahd, &flags);
-               return;
+       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);
        }
 
-       /*
-        * Command has not completed.  Mark this
-        * SCB as having failing status prior to
-        * resetting the bus, so we get the correct
-        * error code.
-        */
-       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);
+}
 
-       /*
-        * 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);
+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);
 }
 
-static void
-ahd_linux_dv_complete(struct scsi_cmnd *cmd)
+void
+ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
+                     ahd_queue_alg alg)
 {
-       struct ahd_softc *ahd;
+       struct scsi_target *starget;
+       struct ahd_linux_target *targ;
+       struct ahd_linux_device *dev;
+       struct scsi_device *sdev;
+       int was_queuing;
+       int now_queuing;
 
-       ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
+       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;
 
-       /* Delete the DV timer before it goes off! */
-       scsi_delete_timer(cmd);
+       dev = scsi_transport_device_data(sdev);
 
-#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
+       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++;
+       }
 
-       /* Wake up the state machine */
-       up(&ahd->platform_data->dv_cmd_sem);
-}
+       dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);
+       if (now_queuing) {
+               u_int usertags;
 
-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) {
+               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 *ahd, struct ahd_devinfo *devinfo)
        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_softc *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_softc *ahd, struct ahd_linux_device *dev)
        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) {
-
-               /*
-                * 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) {
-
-                       TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
-                                         dev, links);
-                       dev->flags |= AHD_DEV_ON_RUN_LIST;
-                       return;
-               }
-
-               cmd = &acmd_scsi_cmd(acmd);
+       /*
+        * 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;
+       }
 
-               /*
-                * 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;
+       scb->io_ctx = cmd;
+       scb->platform_data->dev = dev;
+       hscb = scb->hscb;
+       cmd->host_scribble = (char *)scb;
 
-               /*
-                * 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);
+       /*
+        * 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->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 ((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) {
+               int     msg_bytes;
+               uint8_t tag_msgs[2];
 
-               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;
+               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);
-
-               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;
+       hscb->cdb_len = cmd->cmd_len;
+       memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
+
+       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;
-
-                       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);
-               }
+                       bus_size_t len;
 
-               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;
+                       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;
 
-               if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
-                       dev->commands_since_idle_or_otag++;
-               scb->flags |= SCB_ACTIVE;
-               ahd_queue_scb(ahd, scb);
+               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++;
+
+       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, struct pt_regs * regs)
        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, char channel,
        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, char channel,
                 * 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, char channel,
 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 scb *scb)
                        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 scb *scb)
        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_softc *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_softc *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_softc *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 */
@@ -4745,272 +1991,798 @@ no_fallback:
                ahd_cmd_set_transaction_status(cmd, new_status);
        }
 
-       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);
+       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;
+       }
+
+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;
-
-       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;
+       ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+                           starget->channel + 'A', ROLE_INITIATOR);
+
+       /* 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;
        }
-       /* 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);
+
+       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;
+#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;
        }
-       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);
+       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);
index 7823e52..052c661 100644 (file)
@@ -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>
 #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
 /************************* 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_int usec)
 /***************************** 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 port, uint8_t *array, int count)
 
 /**************************** 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_str *info,
                             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, unsigned long *flags)
        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 *ahd)
 }
 
 /**************************** 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_free(struct ahd_softc *ahd,
 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 scb *scb, uint32_t status)
 }
 
 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, uint32_t status)
 }
 
 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(struct scb *scb)
 }
 
 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 scb*);
 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
index 91daf0c..390b538 100644 (file)
@@ -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 *pdev, const struct pci_device_id *ent)
        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 *pdev, const struct pci_device_id *ent)
                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 *pdev, const struct pci_device_id *ent)
                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);
 }
 
index 703f6e4..2131db6 100644 (file)
@@ -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, struct ahd_pci_identity *entry)
         * 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;
 }
 
 /*
index e01cd61..39a2784 100644 (file)
@@ -49,10 +49,53 @@ static void ahd_dump_target_state(struct ahd_softc *ahd,
                                      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 *info, struct ahd_transinfo *tinfo)
         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 *ahd, struct info_str *info,
                      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 *ahd, struct info_str *info,
        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 *ahd, struct info_str *info,
 }
 
 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 *shost, char *buffer, char **start,
        }
        retval = info.pos > info.offset ? info.pos - info.offset : 0;
 done:
-       ahd_list_unlock(&l);
        return (retval);
 }
index 088cbc2..91d294c 100644 (file)
@@ -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
index 810ec70..e196d83 100644 (file)
@@ -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
        }
 
        /*
index d84b741..1519639 100644 (file)
@@ -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;
                        }
                }
index 468d612..3cb07e1 100644 (file)
@@ -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__
  * 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_descriptor *sd, uint16_t *buf,
        }
 
        /* Put the chip back into write-protect mode */
-       send_seeprom_cmd(sd, &seeprom_ewds);
+       send_seeprom_cmd(sd, ewds);
        reset_seeprom(sd);
 
        return (1);
index 7bc01e4..58ac461 100644 (file)
@@ -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, u_int intstat)
                                       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 *ahc, struct ahc_devinfo *devinfo,
                         /*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 reinit)
         * 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)
        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
index 687f19e..c932b3b 100644 (file)
 
 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 ahc_softc*,
                                 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 *sdev)
        
        targ->sdev[sdev->lun] = sdev;
 
+       spi_period(starget) = 0;
+
        return 0;
 }
 
@@ -918,6 +913,86 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
        }
 }
 
+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, char channel,
                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_softc *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);
index 0e47ac2..c529962 100644 (file)
@@ -265,7 +265,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
 /***************************** SMP support ************************************/
 #include <linux/spinlock.h>
 
-#define AIC7XXX_DRIVER_VERSION "6.2.36"
+#define AIC7XXX_DRIVER_VERSION "7.0"
 
 /*************************** Device Data Structures ***************************/
 /*
index 9d318ce..0d44a69 100644 (file)
@@ -149,6 +149,27 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
        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 *pdev, const struct pci_device_id *ent)
                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);
index 3802c91..04a3506 100644 (file)
@@ -54,6 +54,49 @@ static void  ahc_dump_device_state(struct info_str *info,
 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 *info, struct ahc_transinfo *tinfo)
         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);
index 7c1390e..2ce1feb 100644 (file)
@@ -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
index 9c71377..88bfd76 100644 (file)
@@ -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"
index cf41136..4cee085 100644 (file)
@@ -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)
index 7c5a6db..828ae3d 100644 (file)
  * $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);
-}
index bfe6f95..3bfbf0f 100644 (file)
 #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 heads, int sectors)
        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)
index 3900e28..bd0e1b6 100644 (file)
@@ -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 char *cmd,
           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 char *cmd,
                __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 char *cmd,
                        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--;
index ec16173..f6be2c1 100644 (file)
@@ -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, unsigned char ascq)
        }
 }
 
+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, const unsigned char *sense_buffer,
 {
        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, const unsigned char *sense_buffer,
                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];
index 5feb886..85503fa 100644 (file)
@@ -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_Host *shost, int recovery)
  **/
 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 *shost, struct device *dev)
        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 device *dev)
        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 scsi_host_template *sht, int privsize)
 {
        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 scsi_host_template *sht, int privsize)
 
        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 scsi_host_template *sht, int privsize)
        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;
index 2cb3c83..5b14934 100644 (file)
@@ -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 event_pool *pool,
                        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 event_pool *pool,
                               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 scsi_cmnd *cmd,
        } 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_cmd *cmd, struct device *dev)
                        (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_cmd *cmd, struct device *dev)
  * 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 *cmd,
                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_cmnd *cmd,
  * 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 scsi_cmnd *cmd,
        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(struct srp_event_struct *evt_struct,
                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(struct srp_event_struct *evt_struct,
        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_event_struct *evt_struct)
                               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 scsi_cmnd *cmnd,
 {
        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 scsi_cmnd *cmnd,
        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 scsi_cmnd *cmnd,
        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(struct scsi_cmnd *cmd)
        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(struct scsi_cmnd *cmd)
                }
        }
 
-       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(struct scsi_cmnd *cmd)
 
        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(struct scsi_cmnd *cmd)
         * 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(struct scsi_cmnd *cmd)
        }
 
        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(struct scsi_cmnd *cmd)
 
        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_handler(struct scsi_cmnd *cmd)
        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_handler(struct scsi_cmnd *cmd)
 
        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_handler(struct scsi_cmnd *cmd)
        /* 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_handler(struct scsi_cmnd *cmd)
                                tmp_evt->done(tmp_evt);
                }
        }
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
        return SUCCESS;
 }
 
@@ -1035,6 +1123,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata)
                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_template = {
        .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,
 };
index 1030b70..8bec043 100644 (file)
@@ -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 */
index 3bb82aa..adb9567 100644 (file)
@@ -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;
 };
 
 
index 3cea928..0e089a4 100644 (file)
@@ -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;
index 78adee4..1280f0e 100644 (file)
 #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"
index 2b1c957..63caf7f 100644 (file)
@@ -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>
index 233901e..0a8269d 100644 (file)
@@ -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, struct lpfc_nodelist * nlp, int list)
        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);
index 34d416d..6f3cb59 100644 (file)
@@ -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, const struct pci_device_id *pid)
        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;
index c27cf94..73eb89f 100644 (file)
 #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"
index a5cfb64..0aba13c 100644 (file)
 #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"
index 45dc021..9b35eaa 100644 (file)
@@ -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>
index 17e4974..b5ad187 100644 (file)
 #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 * phba, struct lpfc_scsi_buf * lpfc_cmd)
                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 * phba, struct lpfc_scsi_buf * lpfc_cmd)
 
        /*
         * 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 * phba, struct lpfc_scsi_buf * lpfc_cmd,
        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_hba *phba,
        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, void (*done) (struct scsi_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
index 0fd9ba1..acd64c4 100644 (file)
@@ -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 */
index 1775508..e74e224 100644 (file)
 #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"
index 47dea48..7e6747b 100644 (file)
@@ -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"
 
index b993652..637fb65 100644 (file)
@@ -996,7 +996,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
                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 *cmd, enum action action)
                        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 *cmd, enum action action)
                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 *cmd, enum action action)
 
        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_t dev, int geom[])
        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_id, struct pt_regs *regs)
        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_id, struct pt_regs *regs)
 
        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 scsi_qla_host *ha, int bus, int target)
        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 scsi_qla_host *ha, int bus, int target)
 
        /* 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_device *device)
        }
 
 #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_device *device)
        }
 
        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_Host *host, struct scsi_device *sdev_q)
  *
  * 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 * sts, struct scsi_cmnd *cp)
        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 * sts, struct scsi_cmnd *cp)
 
        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 * sts, struct scsi_cmnd *cp)
 /*                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_qla_host *ha)
        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_qla_host *ha)
        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_qla_host *ha)
                        "%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_host *ha)
        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_host *ha)
 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_qla_host *ha, int bus, int target)
 {
        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_host *ha)
        /* 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_host *ha)
         * 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_host *ha, int bus, int target)
        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_host *ha)
        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_host *ha)
                /* 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_host *ha)
 
                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_host *ha)
 
        /* 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_host *ha)
                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_host *ha, struct srb * sp)
        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_host *ha, struct srb * sp)
                                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_host *ha, struct srb * sp)
 
        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_host *ha, struct srb * sp)
        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_host *ha, struct srb * sp)
        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_cmnd *cmd, struct scsi_qla_host *ha)
        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_host *ha, struct response *pkt,
                /* 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, const struct pci_device_id *id)
        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, const struct pci_device_id *id)
 #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, const struct pci_device_id *id)
        }
 
        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, const struct pci_device_id *id)
 
 #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, const struct pci_device_id *id)
 #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);
 
index d245ae0..59915fb 100644 (file)
@@ -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];
 };
 
@@ -978,14 +966,6 @@ struct ctio_a64_ret_entry {
 #define CS_UNKNOWN          0x81       /* Driver defined */
 #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.
  */
@@ -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
index 659a5d6..fe0fce7 100644 (file)
@@ -211,6 +211,138 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
        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_transport_functions = {
 
        .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 *ha)
            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;
 }
index b8d90e9..9684e7a 100644 (file)
@@ -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
 
 #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)
index 1c6d366..b455c31 100644 (file)
  * 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
index 665c203..1ed32e7 100644 (file)
@@ -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 *);
 
@@ -146,9 +147,6 @@ extern int
 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_t *, uint16_t *, uint16_t *,
 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_t *);
 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_descriptors(scsi_qla_host_t *);
 /*
  * 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 *);
index 31ce4f6..e7b138c 100644 (file)
@@ -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;
+}
index a6d2559..c619583 100644 (file)
@@ -88,6 +88,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
        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, int flags)
        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_host_t *ha)
                        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 *ha, fc_port_t *fcport)
                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 *ha)
                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_host_t *ha, struct list_head *new_fcports)
                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, fc_port_t *fcport,
                                }
                        }
 
+                       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) {
index ebdc3c5..37f82e2 100644 (file)
@@ -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;
index f910de6..c255bb0 100644 (file)
@@ -451,6 +451,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                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);
index 409ea0a..13e1c90 100644 (file)
@@ -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 *ha, mbx_cmd_t *mcp)
                        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",
@@ -982,58 +983,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_t *ha, fc_port_t *fcport, uint8_t opt)
                        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, uint16_t loop_id, uint8_t domain,
                                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, uint16_t loop_id, uint8_t domain,
                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_t *ha, uint16_t sw_em_1g,
 
        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;
+}
index 9000659..8982978 100644 (file)
@@ -79,7 +79,7 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
 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_host_t *);
 
 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 scsi_cmnd *);
 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_driver_template = {
 
        .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_driver_template = {
         * 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_driver_template = {
 
        .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)
        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 *sdev)
 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 *pdev, struct qla_board_info *brd_info)
        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 *pdev, struct qla_board_info *brd_info)
        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 *pdev, struct qla_board_info *brd_info)
                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 *pdev, struct qla_board_info *brd_info)
                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 *pdev, struct qla_board_info *brd_info)
        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;
 }
index d7f5c60..c14abf7 100644 (file)
@@ -468,21 +468,12 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
     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 *ha, uint32_t *dwptr, uint32_t faddr,
 
        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 *ha, uint32_t *dwptr, uint32_t faddr,
            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 *ha, uint8_t *buf, uint32_t naddr,
 {
        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 *ha, uint8_t *buf, uint32_t naddr,
                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 *ha, uint8_t *buf, uint32_t naddr,
 
        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 *ha, uint8_t *buf, uint32_t naddr,
            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;
 }
index e3cd361..eae7d6e 100644 (file)
@@ -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 (file)
index 0000000..f1ea502
--- /dev/null
@@ -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);
+
index d14523d..a780546 100644 (file)
@@ -268,6 +268,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
        } 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 *cmd)
        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_action *h)
        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:
index 6121dc1..07b554a 100644 (file)
@@ -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 */
index 0fc8b48..895c945 100644 (file)
@@ -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 *scmd, int eh_flag)
 
        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 *scmd, int timeout,
 
        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 *scmd)
 
        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(struct scsi_device *sdev)
 {
        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(struct Scsi_Host *shost)
        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
index 7a6b530..b7fddac 100644 (file)
 
 #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 *host, void __user *buffer)
                                return -EFAULT;
                }
        }
-       return temp;
+       return 1;
 }
 
 /*
@@ -88,25 +88,18 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
 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 scsi_device *sdev, char *cmd,
                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 scsi_device *sdev, char *cmd,
                               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_device *sdev,
 {
        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_device *sdev,
                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_device *sdev, int cmd,
         * 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;
index 7a91ca3..77f2d44 100644 (file)
@@ -232,23 +232,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd,
 }
 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 *sreq, const void *cmnd, void *buffer,
                   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_device *sdev)
 
        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 *cmd, unsigned int good_bytes,
                                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 *cmd, unsigned int good_bytes,
                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 (driver_byte(result) & DRIVER_SENSE)
-                       scsi_print_sense("", cmd);
+               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);
+               }
                /*
                 * 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_queue_t *q, struct gendisk *disk,
        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_queue *q, struct request *req)
         * 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_queue *q, struct request *req)
                        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_queue *q, struct request *req)
                /*
                 * 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 request_queue *q,
                                   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 *sreq, int dbd, int modepage,
                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 *sreq, int dbd, int modepage,
                }
        }
 
-       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);
index d30d7f4..ee6de17 100644 (file)
@@ -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);
index 48edd67..19c9a23 100644 (file)
@@ -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_request *sreq,
        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 *starget)
 
 /**
  * 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_request *sreq, char *inq_result,
                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_request *sreq, char *inq_result,
                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_request *sreq, char *inq_result,
 
        /* 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_request *sreq, char *inq_result,
            (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 scsi_target *starget,
                                  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 scsi_target *starget,
        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 scsi_target *starget,
        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 scsi_target *starget,
 
  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 scsi_device *sdev, int bflags,
        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 scsi_device *sdev, int bflags,
        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 scsi_device *sdev, int bflags,
        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 scsi_device *sdev, int bflags,
 
        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 scsi_device *sdev, int bflags,
                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 scsi_device *sdev, int bflags,
        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(struct Scsi_Host *shost, uint channel,
 
        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_Host *shost, unsigned int channel,
                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;
index beed7fb..dae59d1 100644 (file)
@@ -48,6 +48,30 @@ const char *scsi_device_state_name(enum scsi_device_state state)
        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_device *class_dev, const char *buf,
 };
 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 *scsi_sysfs_shost_attrs[] = {
        &class_device_attr_unchecked_isa_dma,
        &class_device_attr_proc_name,
        &class_device_attr_scan,
+       &class_device_attr_state,
        NULL
 };
 
index e6412fc..2cab556 100644 (file)
@@ -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_transport_class,
                               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);
 
index 7670919..ef577c8 100644 (file)
 #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 value, int denom)
        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_signal_to_value(const char *name)
        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 attribute_container *cont,
        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 device *dev)
        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(struct device *dev)
        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_request *sreq, u8 *buffer,
        }
 
        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_request *sreq, u8 *buffer,
                                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_request *sreq, u8 *buffer,
 /* 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 scsi_request *sreq, u8 *buffer,
 }
 
 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, u8 *buffer, u8 *ptr,
 
        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, u8 *buffer, u8 *ptr,
 }
 
 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 scsi_request *sreq, u8 *buffer)
        };
 
        
-       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 scsi_request *sreq, u8 *buffer)
                }
        }
 
-       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 scsi_request *sreq, u8 *buffer)
 }
 
 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_request *sreq, u8 *buffer)
            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_request *sreq, u8 *buffer)
 
        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_request *sreq, u8 *buffer)
 
        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_request *sreq, u8 *buffer)
                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_request *sreq, u8 *buffer)
 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 scsi_target *starget)
                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 attribute_container *cont,
 {
        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 attribute_container *cont,
        /* 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 attribute_container *cont,
                            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 attribute_container *cont,
                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_template *ft)
        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 */
index 0410e1b..de564b3 100644 (file)
@@ -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 *, sector_t *);
 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_device *sdp)
                 * 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 * SCpnt)
        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_disk *sdkp, struct scsi_request *srp)
  * 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, char *diskname,
                        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, char *diskname,
                 * 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, char *diskname,
                                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, char *diskname,
  */
 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)
+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(SRpnt, dbd, modepage, buffer, len,
-                                SD_TIMEOUT, SD_MAX_RETRIES, data);
+       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 *SRpnt, int dbd, int modepage,
  */
 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_disk *sdkp, char *diskname,
                 * 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_disk *sdkp, char *diskname,
  */
 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 *sdkp, char *diskname,
        }
 
        /* 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 *sdkp, char *diskname,
        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 *sdkp, char *diskname,
        }
 
 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 gendisk *disk)
 {
        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 gendisk *disk)
        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 gendisk *disk)
        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;
 }
index e822ca0..b1b69d7 100644 (file)
@@ -61,7 +61,7 @@ static int sg_version_num = 30533;    /* 2 digits for each component */
 
 #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 file *filp,
                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 *sgl, const unsigned int max_pages,
                  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;
index 2f259f2..ce63fc8 100644 (file)
 #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_info *cdi, int slot)
                /* 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_info *cdi, int purpose)
        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_cd *cd)
        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_cd *cd)
                        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_cd *cd)
                 * 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_cd *cd)
 {
        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_cd *cd)
                ""
        };
 
-       /* 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_cd *cd)
                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 *cd)
                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 *cd)
                cd->device->writeable = 1;
        }
 
-       scsi_release_request(SRpnt);
        kfree(buffer);
 }
 
index 0b31780..d2bcd99 100644 (file)
@@ -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) */
index 82d68fd..6e45ac3 100644 (file)
@@ -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 cdrom_device_info *cdi, struct cdrom_ti *ti
 
 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 packet_command *cgc)
                        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 packet_command *cgc)
                        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;
 }
index 0a7839d..a93308a 100644 (file)
@@ -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_tape *);
 
 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);
+
 \f
 #include "osst_detect.h"
 #ifndef SIGS_FROM_OSST
@@ -230,6 +236,46 @@ static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
        {"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_tape *STp, struct scsi_request * SRpnt)
                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_cmnd * SCpnt)
 
        (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, struct scsi_tape * STp, unsigned char *c
                }
        }
 
-       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, struct scsi_tape * STp, unsigned char *c
                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 scsi_tape * STp)
        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 scsi_tape * STp)
         ) /* 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, struct file *filp)
         */
        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, struct file *filp)
  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 *inode, struct file *filp)
        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 scatterlist *sgl, const unsigned int max_pag
 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;
index 061da11..790acac 100644 (file)
@@ -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 */
index bf3ec9d..a7d4fd3 100644 (file)
--- 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
 
@@ -555,22 +556,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);
@@ -582,42 +595,54 @@ static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
        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;
-
-       offset = uaddr & ~PAGE_MASK;
-       for (i = 0; i < nr_pages; i++) {
-               unsigned int bytes = PAGE_SIZE - offset;
-
-               if (len <= 0)
-                       break;
-
-               if (bytes > len)
-                       bytes = len;
+       memset(pages, 0, nr_pages * sizeof(struct page *));
+
+       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;
+
+                       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);
 
        /*
@@ -626,9 +651,17 @@ static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
        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);
@@ -647,10 +680,34 @@ 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;
@@ -663,6 +720,9 @@ struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev,
         */
        bio_get(bio);
 
+       for (i = 0; i < iov_count; i++)
+               len += iov[i].iov_len;
+
        if (bio->bi_size == len)
                return bio;
 
@@ -707,6 +767,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.
@@ -1095,6 +1231,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);
index af1010b..93bfb0b 100644 (file)
 
 #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_adapter(struct attribute_container *con
                                                 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
index 69e0479..cdaf03a 100644 (file)
@@ -295,7 +295,13 @@ extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
 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);
index 19bd8e7..aefa26f 100644 (file)
@@ -563,10 +563,12 @@ extern void blk_sync_queue(struct request_queue *q);
 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 (file)
index 0000000..a71123c
--- /dev/null
@@ -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 *);
index 87d98d1..1d6cc22 100644 (file)
 #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)                  \
index 9957f16..bed4b7c 100644 (file)
@@ -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;
index 12e9093..b090a11 100644 (file)
@@ -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 *);
index 835af8e..da63722 100644 (file)
@@ -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(struct scsi_device *, char);
 
 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, struct scsi_lun *);
 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;
index 80557f8..fabd879 100644 (file)
@@ -26,10 +26,15 @@ struct scsi_sense_hdr {             /* See SPC-3 section 4.5 */
        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 *);
index 81d5234..916144b 100644 (file)
@@ -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_Host *);
 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_device(struct Scsi_Host *shost)
         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_dev(struct Scsi_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 */
index 9871940..6a14002 100644 (file)
@@ -54,20 +54,4 @@ extern void scsi_do_req(struct scsi_request *, const void *cmnd,
                        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 */
index a30d6cd..6bdc4af 100644 (file)
@@ -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 *);