vserver 1.9.3
[linux-2.6.git] / drivers / scsi / sym53c8xx_2 / sym_hipd.c
index c4f6c26..dddf88b 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-#define SYM_VERSION "2.1.18j"
-#define SYM_DRIVER_NAME        "sym-" SYM_VERSION
-
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
@@ -1042,28 +1038,11 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
        for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
                tcb_p tp = &np->target[i];
 
-               tp->tinfo.user.scsi_version = tp->tinfo.curr.scsi_version= 2;
-               tp->tinfo.user.spi_version  = tp->tinfo.curr.spi_version = 2;
-               tp->tinfo.user.period = np->minsync;
-               tp->tinfo.user.offset = np->maxoffs;
-               tp->tinfo.user.width  = np->maxwide ? BUS_16_BIT : BUS_8_BIT;
                tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
                tp->usrtags = SYM_SETUP_MAX_TAG;
 
                sym_nvram_setup_target (np, i, nvram);
 
-               /*
-                * Some single-ended devices may crash on receiving a
-                * PPR negotiation attempt.  Only try PPR if we're in
-                * LVD mode.
-                */
-               if (np->features & FE_ULTRA3) {
-                       tp->tinfo.user.options |= PPR_OPT_DT;
-                       tp->tinfo.user.period = np->minsync_dt;
-                       tp->tinfo.user.offset = np->maxoffs_dt;
-                       tp->tinfo.user.spi_version = 3;
-               }
-
                if (!tp->usrtags)
                        tp->usrflags &= ~SYM_TAGS_ENABLED;
        }
@@ -1302,7 +1281,7 @@ static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
        } else {
                script_ofs      = dsp;
                script_size     = 0;
-               script_base     = 0;
+               script_base     = NULL;
                script_name     = "mem";
        }
 
@@ -1440,7 +1419,7 @@ sym_lookup_pci_chip_table (u_short device_id, u_char revision)
                return chip;
        }
 
-       return 0;
+       return NULL;
 }
 
 #if SYM_CONF_DMA_ADDRESSING_MODE == 2
@@ -1497,6 +1476,55 @@ static void sym_update_dmap_regs(hcb_p np)
 }
 #endif
 
+static void sym_check_goals(struct scsi_device *sdev)
+{
+       struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+       struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
+
+       /* here we enforce all the fiddly SPI rules */
+
+       if (!scsi_device_wide(sdev))
+               st->width = 0;
+
+       if (!scsi_device_sync(sdev)) {
+               st->options = 0;
+               st->period = 0;
+               st->offset = 0;
+               return;
+       }
+               
+       if (scsi_device_dt(sdev)) {
+               if (scsi_device_dt_only(sdev))
+                       st->options |= PPR_OPT_DT;
+
+               if (st->offset == 0)
+                       st->options &= ~PPR_OPT_DT;
+       } else {
+               st->options &= ~PPR_OPT_DT;
+       }
+
+       if (!(np->features & FE_ULTRA3))
+               st->options &= ~PPR_OPT_DT;
+
+       if (st->options & PPR_OPT_DT) {
+               /* all DT transfers must be wide */
+               st->width = 1;
+               if (st->offset > np->maxoffs_dt)
+                       st->offset = np->maxoffs_dt;
+               if (st->period < np->minsync_dt)
+                       st->period = np->minsync_dt;
+               if (st->period > np->maxsync_dt)
+                       st->period = np->maxsync_dt;
+       } else {
+               if (st->offset > np->maxoffs)
+                       st->offset = np->maxoffs;
+               if (st->period < np->minsync)
+                       st->period = np->minsync;
+               if (st->period > np->maxsync)
+                       st->period = np->maxsync;
+       }
+}              
+
 /*
  *  Prepare the next negotiation message if needed.
  *
@@ -1508,6 +1536,10 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
 {
        tcb_p tp = &np->target[cp->target];
        int msglen = 0;
+       struct scsi_device *sdev = tp->sdev;
+
+       if (likely(sdev))
+               sym_check_goals(sdev);
 
        /*
         *  Early C1010 chips need a work-around for DT 
@@ -1518,19 +1550,21 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
        /*
         *  negotiate using PPR ?
         */
-       if (tp->tinfo.goal.options & PPR_OPT_MASK)
+       if (scsi_device_dt(sdev)) {
                nego = NS_PPR;
-       /*
-        *  negotiate wide transfers ?
-        */
-       else if (tp->tinfo.curr.width != tp->tinfo.goal.width)
-               nego = NS_WIDE;
-       /*
-        *  negotiate synchronous transfers?
-        */
-       else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
-                tp->tinfo.curr.offset != tp->tinfo.goal.offset)
-               nego = NS_SYNC;
+       } else {
+               /*
+                *  negotiate wide transfers ?
+                */
+               if (tp->tinfo.curr.width != tp->tinfo.goal.width)
+                       nego = NS_WIDE;
+               /*
+                *  negotiate synchronous transfers?
+                */
+               else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
+                        tp->tinfo.curr.offset != tp->tinfo.goal.offset)
+                       nego = NS_SYNC;
+       }
 
        switch (nego) {
        case NS_SYNC:
@@ -2490,7 +2524,7 @@ static void sym_int_ma (hcb_p np)
         *  try to find the interrupted script command,
         *  and the address at which to continue.
         */
-       vdsp    = 0;
+       vdsp    = NULL;
        nxtdsp  = 0;
        if      (dsp >  np->scripta_ba &&
                 dsp <= np->scripta_ba + np->scripta_sz) {
@@ -3400,7 +3434,7 @@ static void sym_sir_task_recovery(hcb_p np, int num)
                 *  we are not in race.
                 */
                i = 0;
-               cp = 0;
+               cp = NULL;
                FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
                        cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
                        if (cp->host_status != HS_BUSY &&
@@ -3516,7 +3550,7 @@ static void sym_sir_task_recovery(hcb_p np, int num)
                 *  abort for this target.
                 */
                i = 0;
-               cp = 0;
+               cp = NULL;
                FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
                        cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
                        if (cp->host_status != HS_DISCONNECT)
@@ -3698,7 +3732,7 @@ static int sym_evaluate_dp(hcb_p np, ccb_p cp, u32 scr, int *ofs)
        else if (dp_scr == SCRIPTA_BA (np, pm1_data))
                pm = &cp->phys.pm1;
        else
-               pm = 0;
+               pm = NULL;
 
        if (pm) {
                dp_scr  = scr_to_cpu(pm->ret);
@@ -3999,7 +4033,6 @@ int sym_compute_residual(hcb_p np, ccb_p cp)
 static int  
 sym_sync_nego_check(hcb_p np, int req, int target)
 {
-       tcb_p tp = &np->target[target];
        u_char  chg, ofs, per, fak, div;
 
        if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4019,19 +4052,11 @@ sym_sync_nego_check(hcb_p np, int req, int target)
        if (ofs) {
                if (ofs > np->maxoffs)
                        {chg = 1; ofs = np->maxoffs;}
-               if (req) {
-                       if (ofs > tp->tinfo.user.offset)
-                               {chg = 1; ofs = tp->tinfo.user.offset;}
-               }
        }
 
        if (ofs) {
                if (per < np->minsync)
                        {chg = 1; per = np->minsync;}
-               if (req) {
-                       if (per < tp->tinfo.user.period)
-                               {chg = 1; per = tp->tinfo.user.period;}
-               }
        }
 
        /*
@@ -4151,10 +4176,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
        }
        if (!wide || !(np->features & FE_ULTRA3))
                dt &= ~PPR_OPT_DT;
-       if (req) {
-               if (wide > tp->tinfo.user.width)
-                       {chg = 1; wide = tp->tinfo.user.width;}
-       }
 
        if (!(np->features & FE_U3EN))  /* Broken U3EN bit not supported */
                dt &= ~PPR_OPT_DT;
@@ -4168,10 +4189,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
                }
                else if (ofs > np->maxoffs)
                        {chg = 1; ofs = np->maxoffs;}
-               if (req) {
-                       if (ofs > tp->tinfo.user.offset)
-                               {chg = 1; ofs = tp->tinfo.user.offset;}
-               }
        }
 
        if (ofs) {
@@ -4181,10 +4198,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
                }
                else if (per < np->minsync)
                        {chg = 1; per = np->minsync;}
-               if (req) {
-                       if (per < tp->tinfo.user.period)
-                               {chg = 1; per = tp->tinfo.user.period;}
-               }
        }
 
        /*
@@ -4286,7 +4299,6 @@ reject_it:
 static int  
 sym_wide_nego_check(hcb_p np, int req, int target)
 {
-       tcb_p tp = &np->target[target];
        u_char  chg, wide;
 
        if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4306,10 +4318,6 @@ sym_wide_nego_check(hcb_p np, int req, int target)
                chg = 1;
                wide = np->maxwide;
        }
-       if (req) {
-               if (wide > tp->tinfo.user.width)
-                       {chg = 1; wide = tp->tinfo.user.width;}
-       }
 
        if (DEBUG_FLAGS & DEBUG_NEGO) {
                PRINT_TARGET(np, target);
@@ -4946,7 +4954,7 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
         *  used for negotiation, clear this info in the tcb.
         */
        if (cp == tp->nego_cp)
-               tp->nego_cp = 0;
+               tp->nego_cp = NULL;
 
 #ifdef SYM_CONF_IARB_SUPPORT
        /*
@@ -4965,7 +4973,7 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
        /*
         *  Make this CCB available.
         */
-       cp->cam_ccb = 0;
+       cp->cam_ccb = NULL;
        cp->host_status = HS_IDLE;
        sym_remque(&cp->link_ccbq);
        sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
@@ -4997,7 +5005,7 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
  */
 static ccb_p sym_alloc_ccb(hcb_p np)
 {
-       ccb_p cp = 0;
+       ccb_p cp = NULL;
        int hcode;
 
        /*
@@ -5005,7 +5013,7 @@ static ccb_p sym_alloc_ccb(hcb_p np)
         *  queue to the controller.
         */
        if (np->actccbs >= SYM_CONF_MAX_START)
-               return 0;
+               return NULL;
 
        /*
         *  Allocate memory for this CCB.
@@ -5076,7 +5084,7 @@ out_free:
                        sym_mfree_dma(cp->sns_bbuf,SYM_SNS_BBUF_LEN,"SNS_BBUF");
                sym_mfree_dma(cp, sizeof(*cp), "CCB");
        }
-       return 0;
+       return NULL;
 }
 
 /*
@@ -5134,7 +5142,7 @@ lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
         *  allocation for not probed LUNs.
         */
        if (!sym_is_bit(tp->lun_map, ln))
-               return 0;
+               return NULL;
 
        /*
         *  Initialize the target control block if not yet.
@@ -5242,7 +5250,7 @@ static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln)
        lp->cb_tags = sym_calloc(SYM_CONF_MAX_TASK, "CB_TAGS");
        if (!lp->cb_tags) {
                sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
-               lp->itlq_tbl = 0;
+               lp->itlq_tbl = NULL;
                goto fail;
        }
 
@@ -5471,7 +5479,7 @@ int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
        /*
         *  Look up our CCB control block.
         */
-       cp = 0;
+       cp = NULL;
        FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
                ccb_p cp2 = sym_que_entry(qp, struct sym_ccb, link_ccbq);
                if (cp2->cam_ccb == ccb) {