The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/bs/bsfunc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NecBSD: bsfunc.c,v 1.2 1997/10/31 17:43:37 honda Exp $ */
    2 /*      $NetBSD$        */
    3 /* $FreeBSD: releng/5.1/sys/i386/isa/bs/bsfunc.c 92765 2002-03-20 07:51:46Z alfred $ */
    4 /*
    5  * [NetBSD for NEC PC98 series]
    6  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
    7  *  All rights reserved.
    8  * 
    9  *  Redistribution and use in source and binary forms, with or without
   10  *  modification, are permitted provided that the following conditions
   11  *  are met:
   12  *  1. Redistributions of source code must retain the above copyright
   13  *     notice, this list of conditions and the following disclaimer.
   14  *  2. Redistributions in binary form must reproduce the above copyright
   15  *     notice, this list of conditions and the following disclaimer in the
   16  *     documentation and/or other materials provided with the distribution.
   17  *  3. The name of the author may not be used to endorse or promote products
   18  *     derived from this software without specific prior written permission.
   19  * 
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   23  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 /*
   33  * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved.
   34  */
   35 
   36 #ifdef  __NetBSD__
   37 #include <i386/Cbus/dev/bs/bsif.h>
   38 #endif
   39 #ifdef  __FreeBSD__
   40 #include <i386/isa/bs/bsif.h>
   41 #endif
   42 
   43 #ifdef  BS_STATICS
   44 struct bs_statics bs_statics[NTARGETS];
   45 u_int bs_linkcmd_count[NTARGETS];
   46 u_int bs_bounce_used[NTARGETS];
   47 #endif  /* BS_STATICS */
   48 
   49 #ifdef  BS_DEBUG
   50 int bs_debug_flag = 0;
   51 #endif  /* BS_DEBUG */
   52 
   53 static void bs_print_syncmsg(struct targ_info *, char*);
   54 static void bs_timeout_target(struct targ_info *);
   55 static void bs_kill_msg(struct bsccb *cb);
   56 
   57 static int bs_start_target(struct targ_info *);
   58 static int bs_check_target(struct targ_info *);
   59 
   60 /*************************************************************
   61  * CCB
   62  ************************************************************/
   63 GENERIC_CCB_STATIC_ALLOC(bs, bsccb)
   64 GENERIC_CCB(bs, bsccb, ccb_chain)
   65 
   66 /*************************************************************
   67  * TIMEOUT
   68  ************************************************************/
   69 static void
   70 bs_timeout_target(ti)
   71         struct targ_info *ti;
   72 {
   73         struct bs_softc *bsc = ti->ti_bsc;
   74 
   75         ti->ti_error |= BSTIMEOUT;
   76         bsc->sc_flags |= BSRESET;
   77 
   78         if (ti->ti_herrcnt ++ >= HARDRETRIES)
   79         {
   80                 bs_printf(ti, "timeout", "async transfer!");
   81                 ti->ti_syncmax.period = ti->ti_syncmax.offset = 0;
   82         }
   83 }
   84 
   85 void
   86 bstimeout(arg)
   87         void *arg;
   88 {
   89         struct bs_softc *bsc = (struct bs_softc *) arg;
   90         struct targ_info *ti;
   91         struct bsccb *cb;
   92         int s;
   93 
   94         s = splcam();
   95         bsc->sc_flags &= ~BSSTARTTIMEOUT;
   96 
   97         /* check */
   98         if ((ti = bsc->sc_nexus) && (cb = TAILQ_FIRST(&ti->ti_ctab)))
   99         {
  100                 if ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0)
  101                         bs_timeout_target(ti);
  102         }
  103         else TAILQ_FOREACH(ti, &bsc->sc_titab, ti_tchain)
  104         {
  105                 if (bsc->sc_dtgnum && ti->ti_phase < DISCONNECTED)
  106                         continue;
  107 
  108                 cb = TAILQ_FIRST(&ti->ti_ctab);
  109                 if (cb && ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0))
  110                         bs_timeout_target(ti);
  111         }
  112 
  113         /* try to recover */
  114         if (bsc->sc_flags & BSRESET)
  115         {
  116                 bs_debug_print_all(bsc);
  117                 bs_printf(ti, "timeout", "bus hang up");
  118                 bs_reset_nexus(bsc);
  119         }
  120 
  121         bs_start_timeout(bsc);
  122         splx(s);
  123 }
  124 
  125 /**************************************************
  126  * MAKE CCB & MSG CCB
  127  *************************************************/
  128 static u_int8_t cmd_unit_ready[6];
  129 
  130 struct bsccb *
  131 bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout)
  132         struct targ_info *ti;
  133         u_int lun;
  134         u_int8_t *cmd;
  135         u_int cmdlen;
  136         u_int8_t *data;
  137         u_int datalen;
  138         u_int flags;
  139         int timeout;
  140 {
  141         struct bsccb *cb;
  142 
  143         if ((cb = bs_get_ccb()) == NULL)
  144                 bs_panic(ti->ti_bsc, "can not get ccb mem");
  145 
  146         cb->ccb = NULL;
  147         cb->lun = lun;
  148         cb->cmd = (cmd ? cmd : cmd_unit_ready);
  149         cb->cmdlen = (cmd ? cmdlen : sizeof(cmd_unit_ready));
  150         cb->data = data;
  151         cb->datalen = (data ? datalen : 0);
  152         cb->msgoutlen = 0;
  153         cb->bsccb_flags = flags & BSCFLAGSMASK;
  154         bs_targ_flags(ti, cb);
  155         cb->rcnt = 0;
  156         cb->tcmax = (timeout > BS_DEFAULT_TIMEOUT_SECOND ? timeout :
  157                                 BS_DEFAULT_TIMEOUT_SECOND);
  158 
  159         TAILQ_INSERT_HEAD(&ti->ti_ctab, cb, ccb_chain);
  160 
  161         return cb;
  162 }
  163 
  164 struct bsccb *
  165 bs_make_msg_ccb(ti, lun, cb, msg, timex)
  166         struct targ_info *ti;
  167         u_int lun;
  168         struct bsccb *cb;
  169         struct msgbase *msg;
  170         u_int timex;
  171 {
  172         u_int flags;
  173 
  174         flags = BSFORCEIOPOLL | msg->flag;
  175         if (cb == NULL)
  176                 cb = bs_make_internal_ccb(ti, lun, NULL, 0, NULL, 0,
  177                                            flags, timex);
  178         else
  179                 cb->bsccb_flags |= flags & BSCFLAGSMASK;
  180 
  181         cb->msgoutlen = msg->msglen;
  182         bcopy(msg->msg, cb->msgout, msg->msglen);
  183         return cb;
  184 }
  185 
  186 int
  187 bs_send_msg(ti, lun, msg, timex)
  188         struct targ_info *ti;
  189         u_int lun;
  190         struct msgbase *msg;
  191         int timex;
  192 {
  193         struct bsccb *cb;
  194 
  195         cb = bs_make_msg_ccb(ti, lun, NULL, msg, timex);
  196         bscmdstart(ti, BSCMDSTART);
  197         return bs_scsi_cmd_poll(ti, cb);
  198 }
  199 
  200 static void
  201 bs_kill_msg(cb)
  202         struct bsccb *cb;
  203 {
  204         cb->msgoutlen = 0;
  205 }
  206 
  207 /**************************************************
  208  * MAKE SENSE CCB
  209  **************************************************/
  210 struct bsccb *
  211 bs_request_sense(ti)
  212         struct targ_info *ti;
  213 {
  214         struct bsccb *cb;
  215 
  216         bzero(ti->scsi_cmd, sizeof(struct scsi_sense));
  217         bzero(&ti->sense, sizeof(struct scsi_sense_data));
  218         ti->scsi_cmd[0] = REQUEST_SENSE;
  219         ti->scsi_cmd[1] = (ti->ti_lun << 5);
  220         ti->scsi_cmd[4] = sizeof(struct scsi_sense_data);
  221         cb = bs_make_internal_ccb(ti, ti->ti_lun, ti->scsi_cmd,
  222                                      sizeof(struct scsi_sense),
  223                                      (u_int8_t *) & ti->sense,
  224                                      sizeof(struct scsi_sense_data),
  225                                      BSFORCEIOPOLL,
  226                                      BS_DEFAULT_TIMEOUT_SECOND);
  227         cb->bsccb_flags |= BSSENSECCB;
  228         return cb;
  229 }
  230 
  231 /**************************************************
  232  * SYNC MSG
  233  *************************************************/
  234 /* sync neg */
  235 int
  236 bs_start_syncmsg(ti, cb, flag)
  237         struct targ_info *ti;
  238         struct bsccb *cb;
  239         int flag;
  240 {
  241         struct syncdata *negp, *maxp;
  242         struct msgbase msg;
  243         u_int lun;
  244 
  245         negp = &ti->ti_syncnow;
  246         maxp = &ti->ti_syncmax;
  247 
  248         ti->ti_state = BS_TARG_SYNCH;
  249 
  250         if (flag == BS_SYNCMSG_REQUESTED)
  251         {
  252                 if (negp->offset > maxp->offset)
  253                         negp->offset = maxp->offset;
  254                 if (negp->offset != 0 && negp->period < maxp->period)
  255                         negp->period = maxp->period;
  256 
  257                 msg.flag = 0;
  258                 lun = ti->ti_lun;
  259                 if (cb == NULL)
  260                         cb = TAILQ_FIRST(&ti->ti_ctab);
  261         }
  262         else if (ti->ti_cfgflags & BS_SCSI_SYNC)
  263         {
  264                 negp->offset = maxp->offset;
  265                 negp->period = maxp->period;
  266 
  267                 msg.flag = BSERROROK;
  268                 lun = 0;
  269         }
  270         else
  271         {
  272                 ti->ti_state = BS_TARG_RDY;
  273                 return COMPLETE;
  274         }
  275 
  276         BS_SETUP_SYNCSTATE(flag);
  277         msg.msg[0] = MSG_EXTEND;
  278         msg.msg[1] = MSG_EXTEND_SYNCHLEN;
  279         msg.msg[2] = MSG_EXTEND_SYNCHCODE;
  280         msg.msg[3] = negp->period;
  281         msg.msg[4] = negp->offset;
  282         msg.msglen = MSG_EXTEND_SYNCHLEN + 2;
  283 
  284         bs_make_msg_ccb(ti, lun, cb, &msg, BS_SYNC_TIMEOUT);
  285         return COMPLETE;
  286 }
  287 
  288 static void
  289 bs_print_syncmsg(ti, s)
  290         struct targ_info *ti;
  291         char *s;
  292 {
  293         struct bs_softc *bsc = ti->ti_bsc;
  294         struct syncdata *negp;
  295         u_int speed;
  296 
  297         negp = &ti->ti_syncnow;
  298         speed = (negp->offset && negp->period) ?
  299                 (2500 / ((u_int) negp->period)) : 0;
  300 
  301         printf("%s(%d:%d): <%s> ", bsc->sc_dvname, ti->ti_id, ti->ti_lun, s);
  302         printf("period 0x%x offset %d chip (0x%x)", negp->period, negp->offset,
  303                 ti->ti_sync);
  304         if (speed)
  305                 printf(" %d.%d M/s", speed / 10, speed % 10);
  306         printf("\n");
  307 }
  308 
  309 int
  310 bs_analyze_syncmsg(ti, cb)
  311         struct targ_info *ti;
  312         struct bsccb *cb;
  313 {
  314         struct bs_softc *bsc = ti->ti_bsc;
  315         u_int8_t ans = ti->ti_syncnow.state;
  316         struct syncdata *negp, *maxp;
  317         struct syncdata bdata;
  318         char *s = NULL;
  319         u_int8_t period;
  320 
  321         negp = &ti->ti_syncnow;
  322         bdata = *negp;
  323         maxp = &ti->ti_syncmax;
  324 
  325         switch(ans)
  326         {
  327         case BS_SYNCMSG_REJECT:
  328                 period = 0;
  329                 s = "msg reject";
  330                 break;
  331 
  332         case BS_SYNCMSG_ASSERT:
  333                 period = 0;
  334                 s = "no msg";
  335                 break;
  336 
  337         default:
  338                 if (negp->offset != 0 && negp->period < maxp->period)
  339                 {
  340                         period = 0xff;
  341                         s = "illegal(period)";
  342                 }
  343                 else if (negp->offset > maxp->offset)
  344                 {
  345                         period = 0xff;
  346                         s = "illegal(offset)";
  347                 }
  348                 else
  349                         period = negp->offset ? negp->period : 0;
  350                 break;
  351         }
  352 
  353         if (s == NULL)
  354         {
  355                 bshw_adj_syncdata(negp);
  356                 *maxp = *negp;
  357 
  358                 if (ans == BS_SYNCMSG_REQUESTED)
  359                         s = "requested";
  360                 else
  361                         s = negp->offset ? "synchronous" : "async";
  362         }
  363         else
  364         {
  365                 negp->offset = maxp->offset = 0;
  366                 bshw_adj_syncdata(negp);
  367                 bshw_adj_syncdata(maxp);
  368         }
  369 
  370         /* really setup hardware */
  371         bshw_set_synchronous(bsc, ti);
  372         if (cb == NULL || (period >= negp->period && period <= negp->period + 2))
  373         {
  374                 bs_print_syncmsg(ti, s);
  375                 BS_SETUP_TARGSTATE(BS_TARG_RDY);
  376                 BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
  377                 if (cb)
  378                         bs_kill_msg(cb);
  379 
  380                 return 0;
  381         }
  382         else
  383         {
  384                 bs_printf(ti, "bs_analyze_syncmsg",
  385                           "sync(period) mismatch, retry neg...");
  386                 printf("expect(%d:0x%x) => reply(%d:0x%x)\n",
  387                         bdata.offset, bdata.period, negp->offset, negp->period);
  388 
  389                 bs_start_syncmsg(ti, cb, BS_SYNCMSG_ASSERT);
  390                 return EINVAL;
  391         }
  392 }
  393 
  394 /**************************************************
  395  * ABORT AND RESET MSG
  396  **************************************************/
  397 /* send device reset msg and wait */
  398 void
  399 bs_reset_device(ti)
  400         struct targ_info *ti;
  401 {
  402         struct msgbase msg;
  403 
  404         msg.msglen = 1;
  405         msg.msg[0] = MSG_RESET;
  406         msg.flag = 0;
  407 
  408         bs_send_msg(ti, 0, &msg, 0);
  409 
  410         delay(ti->ti_bsc->sc_RSTdelay);
  411         bs_check_target(ti);
  412 }
  413 
  414 /* send abort msg */
  415 struct bsccb *
  416 bs_force_abort(ti)
  417         struct targ_info *ti;
  418 {
  419         struct bs_softc *bsc = ti->ti_bsc;
  420         struct msgbase msg;
  421         struct bsccb *cb = TAILQ_FIRST(&ti->ti_ctab);
  422         u_int lun;
  423 
  424         if (cb)
  425         {
  426                 lun = cb->lun;
  427                 cb->rcnt++;
  428         }
  429         else
  430                 lun = 0;
  431 
  432         msg.msglen = 1;
  433         msg.msg[0] = MSG_ABORT;
  434         msg.flag = 0;
  435 
  436         cb = bs_make_msg_ccb(ti, lun, NULL, &msg, 0);
  437         bscmdstart(ti, BSCMDSTART);
  438 
  439         if (bsc->sc_nexus == ti)
  440                 BS_LOAD_SDP
  441 
  442         return cb;
  443 }
  444 
  445 /**************************************************
  446  * COMPLETE SCSI BUS RESET
  447  *************************************************/
  448 /*
  449  * XXX:
  450  * 1) reset scsi bus (ie. all target reseted).
  451  * 2) chip reset.
  452  * 3) check target status.
  453  * 4) sync neg with all targets.
  454  * 5) setup sync reg in host.
  455  * 6) recover previous nexus.
  456  */
  457 void
  458 bs_scsibus_start(bsc)
  459         struct bs_softc *bsc;
  460 {
  461         struct targ_info *ti, *nextti = NULL;
  462         int error = HASERROR;
  463         u_int querm, bits, skip = 0;
  464 
  465         querm = (bsc->sc_hstate == BSC_BOOTUP);
  466         bsc->sc_hstate = BSC_TARG_CHECK;
  467 
  468         /* target check */
  469         do
  470         {
  471                 if (error != COMPLETE)
  472                 {
  473                         printf("%s: scsi bus reset and try to restart ...",
  474                                bsc->sc_dvname);
  475                         bshw_smitabort(bsc);
  476                         bshw_dmaabort(bsc, NULL);
  477                         bshw_chip_reset(bsc);
  478                         bshw_bus_reset(bsc);
  479                         bshw_chip_reset(bsc);
  480                         printf(" done. scsi bus ready.\n");
  481                         nextti = TAILQ_FIRST(&bsc->sc_titab);
  482                         error = COMPLETE;
  483                 }
  484 
  485                 if ((ti = nextti) == NULL)
  486                         break;
  487                 nextti = TAILQ_NEXT(ti, ti_tchain);
  488 
  489                 bits = (1 << ti->ti_id);
  490                 if (skip & bits)
  491                         continue;
  492 
  493                 if ((error = bs_check_target(ti)) != COMPLETE)
  494                 {
  495                         if (querm)
  496                         {
  497                                 TAILQ_REMOVE(&bsc->sc_titab, ti, ti_tchain);
  498                                 bsc->sc_openf &= ~bits;
  499                         }
  500 
  501                         if (error == NOTARGET)
  502                                 error = COMPLETE;
  503 
  504                         skip |= bits;
  505                 }
  506         }
  507         while (1);
  508 
  509         /* ok now ready */
  510         bsc->sc_hstate = BSC_RDY;
  511 
  512         /* recover */
  513         TAILQ_FOREACH(ti, &bsc->sc_titab, ti_tchain)
  514         {
  515                 ti->ti_ctab = ti->ti_bctab;
  516                 TAILQ_INIT(&ti->ti_bctab);
  517                 if (TAILQ_FIRST(&ti->ti_ctab))
  518                         bscmdstart(ti, BSCMDSTART);
  519         }
  520 }
  521 
  522 void
  523 bs_reset_nexus(bsc)
  524         struct bs_softc *bsc;
  525 {
  526         struct targ_info *ti;
  527         struct bsccb *cb;
  528 
  529         bsc->sc_flags &= ~(BSRESET | BSUNDERRESET);
  530         if (bsc->sc_poll)
  531         {
  532                 bsc->sc_flags |= BSUNDERRESET;
  533                 return;
  534         }
  535 
  536         /* host state clear */
  537         BS_HOST_TERMINATE
  538         BS_SETUP_MSGPHASE(FREE)
  539         bsc->sc_dtgnum = 0;
  540 
  541         /* target state clear */
  542         TAILQ_FOREACH(ti, &bsc->sc_titab, ti_tchain)
  543         {
  544                 if (ti->ti_state == BS_TARG_SYNCH)
  545                         bs_analyze_syncmsg(ti, NULL);
  546                 if (ti->ti_state > BS_TARG_START)
  547                         BS_SETUP_TARGSTATE(BS_TARG_START);
  548 
  549                 BS_SETUP_PHASE(UNDEF)
  550                 bs_hostque_delete(bsc, ti);
  551                 if ((cb = TAILQ_FIRST(&ti->ti_ctab)) != NULL)
  552                 {
  553                         if (bsc->sc_hstate == BSC_TARG_CHECK)
  554                         {
  555                                 ti->ti_error |= BSFATALIO;
  556                                 bscmddone(ti);
  557                         }
  558                         else if (cb->rcnt >= bsc->sc_retry)
  559                         {
  560                                 ti->ti_error |= BSABNORMAL;
  561                                 bscmddone(ti);
  562                         }
  563                         else if (ti->ti_error)
  564                                 cb->rcnt++;
  565                 }
  566 
  567                 /* target state clear */
  568                 BS_SETUP_PHASE(FREE)
  569                 BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
  570                 ti->ti_flags &= ~BSCFLAGSMASK;
  571                 ti->ti_msgout = 0;
  572 #ifdef  BS_DIAG
  573                 ti->ti_flags &= ~BSNEXUS;
  574 #endif  /* BS_DIAG */
  575 
  576                 for ( ; cb; cb = TAILQ_NEXT(cb, ccb_chain))
  577                 {
  578                         bs_kill_msg(cb);
  579                         cb->bsccb_flags &= ~(BSITSDONE | BSCASTAT);
  580                         cb->error = 0;
  581                 }
  582 
  583                 if (bsc->sc_hstate != BSC_TARG_CHECK &&
  584                     TAILQ_FIRST(&ti->ti_bctab) == NULL)
  585                         ti->ti_bctab = ti->ti_ctab;
  586 
  587                 TAILQ_INIT(&ti->ti_ctab);
  588         }
  589 
  590         if (bsc->sc_hstate != BSC_TARG_CHECK)
  591                 bs_scsibus_start(bsc);
  592 }
  593 
  594 /**************************************************
  595  * CHECK TARGETS AND START TARGETS
  596  *************************************************/
  597 static int
  598 bs_start_target(ti)
  599         struct targ_info *ti;
  600 {
  601         struct bsccb *cb;
  602         struct scsi_start_stop_unit cmd;
  603 
  604         bzero(&cmd, sizeof(struct scsi_start_stop_unit));
  605         cmd.opcode = START_STOP;
  606         cmd.how = SSS_START;
  607         ti->ti_lun = 0;
  608         cb = bs_make_internal_ccb(ti, 0, (u_int8_t *) &cmd,
  609                                    sizeof(struct scsi_start_stop_unit),
  610                                    NULL, 0, BSFORCEIOPOLL, BS_MOTOR_TIMEOUT);
  611         bscmdstart(ti, BSCMDSTART);
  612         return bs_scsi_cmd_poll(ti, cb);
  613 }
  614 
  615 /* test unit ready and check ATN msgout response */
  616 static int
  617 bs_check_target(ti)
  618         struct targ_info *ti;
  619 {
  620         struct bs_softc *bsc = ti->ti_bsc;
  621         struct scsi_inquiry scsi_cmd;
  622         struct scsi_inquiry_data scsi_inquiry_data;
  623         struct bsccb *cb;
  624         int count, retry = bsc->sc_retry;
  625         int s, error = COMPLETE;
  626 
  627         ti->ti_lun = 0;
  628         bsc->sc_retry = 2;
  629         s = splcam();
  630 
  631         /* inquiry */
  632         bzero(&scsi_cmd, sizeof(scsi_cmd));
  633         scsi_cmd.opcode = INQUIRY;
  634         scsi_cmd.length = (u_int8_t) sizeof(struct scsi_inquiry_data);
  635         cb = bs_make_internal_ccb(ti, 0,
  636                                    (u_int8_t *) &scsi_cmd, sizeof(scsi_cmd),
  637                                    (u_int8_t *) &scsi_inquiry_data,
  638                                    sizeof(scsi_inquiry_data),
  639                                    BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
  640         bscmdstart(ti, BSCMDSTART);
  641         error = bs_scsi_cmd_poll(ti, cb);
  642         if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
  643                 goto done;
  644         ti->targ_type = scsi_inquiry_data.device;
  645         ti->targ_support = scsi_inquiry_data.flags;
  646 
  647         /* test unit ready twice */
  648         for (count = 0; count < 2; count++)
  649         {
  650                 cb = bs_make_internal_ccb(ti, 0, NULL, 0, NULL, 0,
  651                                          BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
  652                 bscmdstart(ti, BSCMDSTART);
  653                 error = bs_scsi_cmd_poll(ti, cb);
  654                 if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
  655                         goto done;
  656         }
  657 
  658         if (cb->bsccb_flags & BSCASTAT)
  659                 bs_printf(ti, "check", "could not clear CA state");
  660         ti->ti_error = 0;
  661 
  662 done:
  663         bsc->sc_retry = retry;
  664 
  665         if (ti->ti_error & BSSELTIMEOUT)
  666                 error = NOTARGET;
  667 
  668         if (error == COMPLETE)
  669                 error = bs_start_target(ti);
  670 
  671         splx(s);
  672         return error;
  673 }
  674 
  675 /**************************************************
  676  * TARGET CONTROL
  677  **************************************************/
  678 struct targ_info *
  679 bs_init_target_info(bsc, target)
  680         struct bs_softc *bsc;
  681         int target;
  682 {
  683         struct targ_info *ti;
  684 
  685         ti = malloc(sizeof(struct targ_info), M_DEVBUF, M_NOWAIT | M_ZERO);
  686         if (ti == NULL)
  687         {
  688                 bs_printf(NULL, "bs_init_targ_info", "no target info memory");
  689                 return ti;
  690         }
  691 
  692         ti->ti_bsc = bsc;
  693         ti->ti_id = target;
  694         ti->sm_offset = 0;
  695         ti->ti_cfgflags = BS_SCSI_NOPARITY | BS_SCSI_NOSAT;
  696         ti->ti_mflags = ~(BSSAT | BSDISC | BSSMIT | BSLINK);
  697         BS_SETUP_TARGSTATE(BS_TARG_CTRL);
  698 
  699         TAILQ_INIT(&ti->ti_ctab);
  700 
  701         bs_alloc_buf(ti);
  702         if (ti->bounce_addr == NULL)
  703         {
  704                 free(ti, M_DEVBUF);
  705                 return NULL;
  706         }
  707 
  708         TAILQ_INSERT_TAIL(&bsc->sc_titab, ti, ti_tchain);
  709         bsc->sc_ti[target] = ti;
  710         bsc->sc_openf |= (1 << target);
  711 
  712         return ti;
  713 }
  714 
  715 void
  716 bs_setup_ctrl(ti, quirks, flags)
  717         struct targ_info *ti;
  718         u_int quirks;
  719         u_int flags;
  720 {
  721         struct bs_softc *bsc = ti->ti_bsc;
  722         u_int offset, period, maxperiod;
  723 
  724         if (ti->ti_state == BS_TARG_CTRL)
  725         {
  726                 ti->ti_cfgflags = BS_SCSI_POSITIVE;
  727                 ti->ti_syncmax.offset = BSHW_MAX_OFFSET;
  728                 BS_SETUP_TARGSTATE(BS_TARG_START);
  729         }
  730         else
  731                 flags |= ti->ti_cfgflags & BS_SCSI_NEGATIVE;
  732 
  733 #ifdef  BS_TARG_SAFEMODE
  734         if (ti->targ_type != 0)
  735         {
  736                 flags &= ~(BS_SCSI_DISC | BS_SCSI_SYNC);
  737                 flags |= BS_SCSI_NOPARITY;
  738         }
  739 #endif
  740 
  741 #ifdef  SDEV_NODISC
  742         if (quirks & SDEV_NODISC)
  743                 flags &= ~BS_SCSI_DISC;
  744 #endif
  745 #ifdef  SDEV_NOPARITY
  746         if (quirks & SDEV_NOPARITY)
  747                 flags |= BS_SCSI_NOPARITY;
  748 #endif
  749 #ifdef  SDEV_NOCMDLNK
  750         if (quirks & SDEV_NOCMDLNK)
  751                 flags &= ~BS_SCSI_LINK;
  752 #endif
  753 #ifdef  SDEV_ASYNC
  754         if (quirks & SDEV_ASYNC)
  755                 flags &= ~BS_SCSI_SYNC;
  756 #endif
  757 #ifdef  SDEV_AUTOSAVE
  758         if (quirks & SDEV_AUTOSAVE)
  759                 flags |= BS_SCSI_SAVESP;
  760 #endif
  761 #ifdef  SD_Q_NO_SYNC
  762         if (quirks & SD_Q_NO_SYNC)
  763                 flags &= ~BS_SCSI_SYNC;
  764 #endif
  765 
  766         if ((flags & BS_SCSI_DISC) == 0 ||
  767             (ti->targ_support & SID_Linked) == 0)
  768                 flags &= ~BS_SCSI_LINK;
  769 
  770         ti->sm_offset = (flags & BS_SCSI_NOSMIT) ?  0 : bsc->sm_offset;
  771         if (ti->sm_offset == 0)
  772                 flags |= BS_SCSI_NOSMIT;
  773         else if (bsc->sc_cfgflags & BSC_SMITSAT_DISEN)
  774                 flags |= BS_SCSI_NOSAT;
  775 
  776         flags &= (ti->ti_cfgflags & BS_SCSI_POSITIVE) | (~BS_SCSI_POSITIVE);
  777         ti->ti_cfgflags = flags;
  778 
  779         /* calculate synch setup */
  780         period = BS_SCSI_PERIOD(flags);
  781         offset = (flags & BS_SCSI_SYNC) ? BS_SCSI_OFFSET(flags) : 0;
  782 
  783         maxperiod = (bsc->sc_cspeed & IDR_FS_16_20) ? 100 : 50;
  784         if (period > maxperiod)
  785                 period = maxperiod;
  786 
  787         if (period)
  788                 period = 2500 / period;
  789 
  790         if (ti->ti_syncmax.offset > offset)
  791                 ti->ti_syncmax.offset = offset;
  792         if (ti->ti_syncmax.period < period)
  793                 ti->ti_syncmax.period = period;
  794 
  795         bshw_adj_syncdata(&ti->ti_syncmax);
  796 
  797         /* finally report our info */
  798         printf("%s(%d:%d): {%d:0x%x:0x%x:%s} flags 0x%b\n",
  799                 bsc->sc_dvname, ti->ti_id, ti->ti_lun,
  800                (u_int) ti->targ_type,
  801                (u_int) ti->targ_support,
  802                (u_int) ti->bounce_size,
  803                (flags & BS_SCSI_NOSMIT) ? "dma" : "pdma",
  804                 flags, BS_SCSI_BITS);
  805 
  806         /* internal representation */
  807         ti->ti_mflags = ~0;
  808         if ((ti->ti_cfgflags & BS_SCSI_DISC) == 0)
  809                 ti->ti_mflags &= ~BSDISC;
  810         if ((ti->ti_cfgflags & BS_SCSI_LINK) == 0)
  811                 ti->ti_mflags &= ~BSLINK;
  812         if (ti->ti_cfgflags & BS_SCSI_NOSAT)
  813                 ti->ti_mflags &= ~BSSAT;
  814         if (ti->ti_cfgflags & BS_SCSI_NOSMIT)
  815                 ti->ti_mflags &= ~BSSMIT;
  816 }
  817 
  818 /**************************************************
  819  * MISC
  820  **************************************************/
  821 void
  822 bs_printf(ti, ph, c)
  823         struct targ_info *ti;
  824         char *ph;
  825         char *c;
  826 {
  827 
  828         if (ti)
  829                 printf("%s(%d:%d): <%s> %s\n",
  830                        ti->ti_bsc->sc_dvname, ti->ti_id, ti->ti_lun, ph, c);
  831         else
  832                 printf("bs*(*:*): <%s> %s\n", ph, c);
  833 }
  834 
  835 void
  836 bs_panic(bsc, c)
  837         struct bs_softc *bsc;
  838         u_char *c;
  839 {
  840 
  841         panic("%s %s\n", bsc->sc_dvname, c);
  842 }
  843 
  844 /**************************************************
  845  * DEBUG FUNC
  846  **************************************************/
  847 #ifdef  BS_DEBUG_ROUTINE
  848 u_int
  849 bsr(addr)
  850         u_int addr;
  851 {
  852 
  853         outb(0xcc0, addr);
  854         return inb(0xcc2);
  855 }
  856 
  857 u_int
  858 bsw(addr, data)
  859         u_int addr;
  860         int data;
  861 {
  862 
  863         outb(0xcc0, addr);
  864         outb(0xcc2, data);
  865         return 0;
  866 }
  867 #endif  /* BS_DEBUG_ROUTINE */
  868 
  869 void
  870 bs_debug_print_all(bsc)
  871         struct bs_softc *bsc;
  872 {
  873         struct targ_info *ti;
  874 
  875         TAILQ_FOREACH(ti, &bsc->sc_titab, ti_tchain)
  876                 bs_debug_print(bsc, ti);
  877 }
  878 
  879 static u_char *phase[] =
  880 {
  881         "FREE", "HOSTQUE", "DISC", "COMPMSG", "ATN", "DISCMSG", "SELECT",
  882         "SELECTED", "RESELECTED", "MSGIN", "MSGOUT", "STATIN", "CMDOUT",
  883         "DATA", "SATSEL", "SATRESEL", "SATSDP", "SATCOMPSEQ", "UNDEF",
  884 };
  885 
  886 void
  887 bs_debug_print(bsc, ti)
  888         struct bs_softc *bsc;
  889         struct targ_info *ti;
  890 {
  891         struct bsccb *cb;
  892 
  893         /* host stat */
  894         printf("%s <DEBUG INFO> nexus %lx bs %lx bus status %lx \n",
  895                bsc->sc_dvname, (u_long) ti, (u_long) bsc->sc_nexus, (u_long) bsc->sc_busstat);
  896 
  897         /* target stat */
  898         if (ti)
  899         {
  900                 struct sc_p *sp = &bsc->sc_p;
  901 
  902                 printf("%s(%d:%d) ph<%s> ", bsc->sc_dvname, ti->ti_id,
  903                        ti->ti_lun, phase[(int) ti->ti_phase]);
  904                 printf("msgptr %x msg[0] %x status %x tqh %lx fl %x\n",
  905                        (u_int) (ti->ti_msginptr), (u_int) (ti->ti_msgin[0]),
  906                        ti->ti_status, (u_long) (cb = TAILQ_FIRST(&ti->ti_ctab)),
  907                        ti->ti_flags);
  908                 if (cb)
  909                         printf("cmdlen %x cmdaddr %lx cmd[0] %x\n",
  910                                cb->cmdlen, (u_long) cb->cmd, (int) cb->cmd[0]);
  911                 printf("datalen %x dataaddr %lx seglen %x ",
  912                        sp->datalen, (u_long) sp->data, sp->seglen);
  913                 if (cb)
  914                         printf("odatalen %x flags %x\n",
  915                                 cb->datalen, cb->bsccb_flags);
  916                 else
  917                         printf("\n");
  918                 printf("error flags %b\n", ti->ti_error, BSERRORBITS);
  919         }
  920 }

Cache object: b54fc11295b5a305a502d5fa25966504


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.