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

Cache object: 8a5c33d213725f2ab2ccffae67ff5efb


[ 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.