Index: drivers/scsi/sym53c8xx_2/sym_glue.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/scsi/sym53c8xx_2/sym_glue.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -p -r1.61 -r1.62
--- drivers/scsi/sym53c8xx_2/sym_glue.c 17 Sep 2004 17:54:29 -0000      1.61
+++ drivers/scsi/sym53c8xx_2/sym_glue.c 20 Sep 2004 02:32:26 -0000      1.62
@@ -1109,7 +1109,7 @@ static void sym_exec_user_command (struc
                               if (uc->data <= 9 && np->minsync_dt) {
                                       if (uc->data < np->minsync_dt)
                                               uc->data = np->minsync_dt;
-                                       tp->tinfo.goal.options = PPR_OPT_DT;
+                                       tp->tinfo.goal.options = PPR_OPT_MASK;
                                       tp->tinfo.goal.width   = 1;
                                       tp->tinfo.goal.period = uc->data;
                                       tp->tinfo.goal.offset = np->maxoffs_dt;
@@ -2292,9 +2292,10 @@ static void sym2_set_width(struct scsi_d
       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
       struct sym_tcb *tp = &np->target[sdev->id];

-       /* It is illegal to have DT set on narrow transfers */
+       /* It is illegal to have DT set on narrow transfers.  If DT is
+        * clear, we must also clear IU and QAS.  */
       if (width == 0)
-               tp->tinfo.goal.options &= ~PPR_OPT_DT;
+               tp->tinfo.goal.options &= ~PPR_OPT_MASK;

       tp->tinfo.goal.width = width;
}
@@ -2312,12 +2313,51 @@ static void sym2_set_dt(struct scsi_devi
       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
       struct sym_tcb *tp = &np->target[sdev->id];

+       /* We must clear QAS and IU if DT is clear */
       if (dt)
               tp->tinfo.goal.options |= PPR_OPT_DT;
       else
-               tp->tinfo.goal.options &= ~PPR_OPT_DT;
+               tp->tinfo.goal.options &= ~PPR_OPT_MASK;
}
-
+
+static void sym2_get_iu(struct scsi_device *sdev)
+{
+       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+       struct sym_tcb *tp = &np->target[sdev->id];
+
+       spi_iu(sdev) = (tp->tinfo.curr.options & PPR_OPT_IU) ? 1 : 0;
+}
+
+static void sym2_set_iu(struct scsi_device *sdev, int iu)
+{
+       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+       struct sym_tcb *tp = &np->target[sdev->id];
+
+       if (iu)
+               tp->tinfo.goal.options |= PPR_OPT_IU | PPR_OPT_DT;
+       else
+               tp->tinfo.goal.options &= ~PPR_OPT_IU;
+}
+
+static void sym2_get_qas(struct scsi_device *sdev)
+{
+       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+       struct sym_tcb *tp = &np->target[sdev->id];
+
+       spi_qas(sdev) = (tp->tinfo.curr.options & PPR_OPT_QAS) ? 1 : 0;
+}
+
+static void sym2_set_qas(struct scsi_device *sdev, int qas)
+{
+       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+       struct sym_tcb *tp = &np->target[sdev->id];
+
+       if (qas)
+               tp->tinfo.goal.options |= PPR_OPT_QAS | PPR_OPT_DT;
+       else
+               tp->tinfo.goal.options &= ~PPR_OPT_QAS;
+}
+

static struct spi_function_template sym2_transport_functions = {
       .set_offset     = sym2_set_offset,
@@ -2332,6 +2372,12 @@ static struct spi_function_template sym2
       .get_dt         = sym2_get_dt,
       .set_dt         = sym2_set_dt,
       .show_dt        = 1,
+       .get_iu         = sym2_get_iu,
+       .set_iu         = sym2_set_iu,
+       .show_iu        = 1,
+       .get_qas        = sym2_get_qas,
+       .set_qas        = sym2_set_qas,
+       .show_qas       = 1,
};

static struct pci_device_id sym2_id_table[] __devinitdata = {
Index: drivers/scsi/sym53c8xx_2/sym_hipd.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/scsi/sym53c8xx_2/sym_hipd.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -p -r1.32 -r1.33
--- drivers/scsi/sym53c8xx_2/sym_hipd.c 13 Sep 2004 15:23:29 -0000      1.32
+++ drivers/scsi/sym53c8xx_2/sym_hipd.c 20 Sep 2004 02:32:26 -0000      1.33
@@ -1503,6 +1503,7 @@ static void sym_check_goals(struct scsi_
               if (st->period > np->maxsync_dt)
                       st->period = np->maxsync_dt;
       } else {
+               st->options &= ~PPR_OPT_MASK;
               if (st->offset > np->maxoffs)
                       st->offset = np->maxoffs;
               if (st->period < np->minsync)
@@ -1575,7 +1576,7 @@ static int sym_prepare_nego(hcb_p np, cc
               msgptr[msglen++] = 0;
               msgptr[msglen++] = tp->tinfo.goal.offset;
               msgptr[msglen++] = tp->tinfo.goal.width;
-               msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_DT;
+               msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_MASK;
               break;
       };

@@ -2009,7 +2010,7 @@ void sym_start_up (hcb_p np, int reason)
/*
 *  Switch trans mode for current job and it's target.
 */
-static void sym_settrans(hcb_p np, int target, u_char dt, u_char ofs,
+static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs,
                        u_char per, u_char wide, u_char div, u_char fak)
{
       SYM_QUEHEAD *qp;
@@ -2060,7 +2061,7 @@ static void sym_settrans(hcb_p np, int t
        */
       if (np->features & FE_C10) {
               uval = uval & ~(U3EN|AIPCKEN);
-               if (dt) {
+               if (opts)       {
                       assert(np->features & FE_U3EN);
                       uval |= U3EN;
               }
@@ -2163,17 +2164,17 @@ sym_setsync(hcb_p np, int target,
 *  Let everything be aware of the changes.
 */
static void
-sym_setpprot(hcb_p np, int target, u_char dt, u_char ofs,
+sym_setpprot(hcb_p np, int target, u_char opts, u_char ofs,
             u_char per, u_char wide, u_char div, u_char fak)
{
       tcb_p tp = &np->target[target];

-       sym_settrans(np, target, dt, ofs, per, wide, div, fak);
+       sym_settrans(np, target, opts, ofs, per, wide, div, fak);

       tp->tinfo.goal.width    = tp->tinfo.curr.width  = wide;
       tp->tinfo.goal.period   = tp->tinfo.curr.period = per;
       tp->tinfo.goal.offset   = tp->tinfo.curr.offset = ofs;
-       tp->tinfo.goal.options  = tp->tinfo.curr.options = dt;
+       tp->tinfo.goal.options  = tp->tinfo.curr.options = opts;

       sym_xpt_async_nego_ppr(np, target);
}
@@ -4139,20 +4140,17 @@ static int
sym_ppr_nego_check(hcb_p np, int req, int target)
{
       tcb_p tp = &np->target[target];
-       u_char  chg, ofs, per, fak, dt, div, wide;
+       unsigned char fak, div;
+       int dt, chg = 0;
+
+       unsigned char per = np->msgin[3];
+       unsigned char ofs = np->msgin[5];
+       unsigned char wide = np->msgin[6];
+       unsigned char opts = np->msgin[7] & PPR_OPT_MASK;

       if (DEBUG_FLAGS & DEBUG_NEGO) {
               sym_print_nego_msg(np, target, "ppr msgin", np->msgin);
-       };
-
-       /*
-        *  Get requested values.
-        */
-       chg  = 0;
-       per  = np->msgin[3];
-       ofs  = np->msgin[5];
-       wide = np->msgin[6];
-       dt   = np->msgin[7] & PPR_OPT_DT;
+       }

       /*
        *  Check values against our limits.
@@ -4162,29 +4160,30 @@ sym_ppr_nego_check(hcb_p np, int req, in
               wide = np->maxwide;
       }
       if (!wide || !(np->features & FE_ULTRA3))
-               dt &= ~PPR_OPT_DT;
+               opts = 0;

       if (!(np->features & FE_U3EN))  /* Broken U3EN bit not supported */
-               dt &= ~PPR_OPT_DT;
+               opts = 0;
+
+       if (opts != (np->msgin[7] & PPR_OPT_MASK))
+               chg = 1;

-       if (dt != (np->msgin[7] & PPR_OPT_MASK)) chg = 1;
+       dt = opts & PPR_OPT_DT;

       if (ofs) {
-               if (dt) {
-                       if (ofs > np->maxoffs_dt)
-                               {chg = 1; ofs = np->maxoffs_dt;}
+               unsigned char maxoffs = dt ? np->maxoffs_dt : np->maxoffs;
+               if (ofs > maxoffs) {
+                       chg = 1;
+                       ofs = maxoffs;
               }
-               else if (ofs > np->maxoffs)
-                       {chg = 1; ofs = np->maxoffs;}
       }

       if (ofs) {
-               if (dt) {
-                       if (per < np->minsync_dt)
-                               {chg = 1; per = np->minsync_dt;}
+               unsigned char minsync = dt ? np->minsync_dt : np->minsync;
+               if (per < np->minsync_dt) {
+                       chg = 1;
+                       per = minsync;
               }
-               else if (per < np->minsync)
-                       {chg = 1; per = np->minsync;}
       }

       /*
@@ -4204,7 +4203,7 @@ sym_ppr_nego_check(hcb_p np, int req, in
       /*
        *  Apply new values.
        */
-       sym_setpprot (np, target, dt, ofs, per, wide, div, fak);
+       sym_setpprot(np, target, opts, ofs, per, wide, div, fak);

       /*
        *  It was an answer. We are done.
@@ -4222,7 +4221,7 @@ sym_ppr_nego_check(hcb_p np, int req, in
       np->msgout[4] = 0;
       np->msgout[5] = ofs;
       np->msgout[6] = wide;
-       np->msgout[7] = dt;
+       np->msgout[7] = opts;

       if (DEBUG_FLAGS & DEBUG_NEGO) {
               sym_print_nego_msg(np, target, "ppr msgout", np->msgout);
@@ -4238,7 +4237,7 @@ reject_it:
        *  If it is a device response that should result in
        *  ST, we may want to try a legacy negotiation later.
        */
-       if (!req && !dt) {
+       if (!req && !opts) {
               tp->tinfo.goal.options = 0;
               tp->tinfo.goal.width   = wide;
               tp->tinfo.goal.period  = per;
Index: drivers/scsi/sym53c8xx_2/sym_misc.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/scsi/sym53c8xx_2/sym_misc.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -p -r1.7 -r1.8
--- drivers/scsi/sym53c8xx_2/sym_misc.c 13 Sep 2004 15:23:29 -0000      1.7
+++ drivers/scsi/sym53c8xx_2/sym_misc.c 20 Sep 2004 02:32:26 -0000      1.8
@@ -190,10 +190,12 @@ void sym_announce_transfer_rate(hcb_p np
                       mb10 = (f10 + period/2) / period;
               }
               printf_info (
-                   "%s:%d: %s %sSCSI %d.%d MB/s %s (%d.%d ns, offset %d)\n",
+                   "%s:%d: %s %sSCSI %d.%d MB/s %s%s%s (%d.%d ns, offset %d)\n",
                   sym_name(np), target, scsi, __tcurr.width? "WIDE " : "",
                   mb10/10, mb10%10,
                   (__tcurr.options & PPR_OPT_DT) ? "DT" : "ST",
+                   (__tcurr.options & PPR_OPT_IU) ? " IU" : "",
+                   (__tcurr.options & PPR_OPT_QAS) ? " QAS" : "",
                   period/10, period%10, __tcurr.offset);
       }
       else