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/scsi/scsi.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 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993-1989 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        scsi.c,v $
   29  * Revision 2.22  93/11/17  18:45:33  dbg
   30  *      Added include of kern/time_out.h.
   31  *      [93/05/21            dbg]
   32  * 
   33  * Revision 2.21  93/08/03  12:34:16  mrt
   34  *      Moved zero_ior() here.
   35  *      [93/07/29  23:37:16  af]
   36  * 
   37  * Revision 2.20  93/05/15  19:43:07  mrt
   38  *      machparam.h -> machspl.h
   39  * 
   40  * Revision 2.19  93/05/10  21:22:49  rvb
   41  *      Make CDROMs readonly.
   42  *      [93/05/06  10:07:01  af]
   43  * 
   44  * Revision 2.18  93/03/09  10:57:52  danner
   45  *      By default, do not require any enquiry-time operations to
   46  *      be done on devices.  The only case so far was a tape drive
   47  *      from <unnamed> who required a receive_diagnostics() at powerup.
   48  *      [93/03/06            af]
   49  * 
   50  *      Changes to make SCSI_MEMORY (optical direct access media) work.
   51  *      [93/02/17            jeffreyh]
   52  * 
   53  *      In scsi_bus_was_reset().  Fixed second loop to touch all
   54  *      targets for which we have a descriptor.  The problem is
   55  *      with dynamic probe and spinup of disks, assuming the disk
   56  *      takes a loooong time we endup resetting the bus while
   57  *      the scsi_inquiry() routine is spinning on tgt->done.
   58  *      [93/02/06            af]
   59  * 
   60  * Revision 2.17  93/01/14  17:55:45  danner
   61  *      Use SCSI_{OPEN,CLOSE,OPTIMIZE}_NULL
   62  *      [93/01/14            danner]
   63  * 
   64  *      Added initializers for up to 5 scsi busses. Proper spl typing.
   65  *      [92/12/01            af]
   66  * 
   67  * Revision 2.16  92/08/03  17:54:24  jfriedl
   68  *      removed silly prototypes
   69  *      [92/08/02            jfriedl]
   70  * 
   71  * Revision 2.15  92/05/21  17:24:02  jfriedl
   72  *      Cleanup to quiet gcc warnings.
   73  *      [92/05/16            jfriedl]
   74  * 
   75  * Revision 2.14  92/05/05  10:47:14  danner
   76  *      Reduced reset delay; knows about not probing itself;
   77  *      do not clear synch params on reset.
   78  *      [92/05/04  17:17:45  af]
   79  * 
   80  * Revision 2.13  92/02/23  22:44:40  elf
   81  *      Changed the interface of a number of functions not to
   82  *      require the scsi_softc pointer any longer.  It was
   83  *      mostly unused, now it can be found via tgt->masterno.
   84  *      [92/02/22  19:30:58  af]
   85  * 
   86  * Revision 2.12  91/08/24  12:28:21  af
   87  *      Spls defs, corrected scsi_master_alloc() to allocate
   88  *      as expected, support for processor devices, 
   89  *      made it possible to avoid sync neg at all (for rb's sake),
   90  *      no start unit on processor devices, understand our
   91  *      own descriptor.
   92  *      [91/08/02  04:01:50  af]
   93  * 
   94  * Revision 2.11  91/07/09  23:22:46  danner
   95  *      Added gross luna88k ifdef to use <sd.h> instead of <scsi.h>. Will be
   96  *      fixed when I understand how to use the configuration tools.
   97  *      [91/07/09  11:08:15  danner]
   98  * 
   99  * Revision 2.10  91/06/25  20:56:48  rpd
  100  *      Tweaks to make gcc happy.
  101  * 
  102  * Revision 2.9  91/06/19  11:57:17  rvb
  103  *      mips->DECSTATION; vax->VAXSTATION
  104  *      [91/06/12  14:02:21  rvb]
  105  * 
  106  *      File moved here from mips/PMAX since it is now "MI" code, also
  107  *      used by Vax3100 and soon -- the omron luna88k.
  108  *      [91/06/04            rvb]
  109  * 
  110  *      Printing of 'unsupported..' in scsi_slave was screwed cuz
  111  *      ui->mi and ui->unit could be bogus at that point in time.
  112  *      [91/05/30            af]
  113  * 
  114  * Revision 2.8  91/05/14  17:28:00  mrt
  115  *      Correcting copyright
  116  * 
  117  * Revision 2.7  91/05/13  06:04:45  af
  118  *      Added flags to control use of disconnect-reconnect mode.
  119  *      Added device-specific close routine (for tapes).
  120  *      Wait for start_unit to complete properly and tell the user
  121  *      what we are waiting for.
  122  *      [91/03/29  16:59:15  af]
  123  * 
  124  * Revision 2.6  91/02/05  17:44:35  mrt
  125  *      Added author notices
  126  *      [91/02/04  11:18:01  mrt]
  127  * 
  128  *      Changed to use new Mach copyright
  129  *      [91/02/02  12:16:40  mrt]
  130  * 
  131  * Revision 2.5  90/12/05  23:34:36  af
  132  *      Cleanups, still awaits SCSI-2 fixes.
  133  *      [90/12/03  23:38:14  af]
  134  * 
  135  * Revision 2.3.1.1  90/11/01  03:38:17  af
  136  *      Created.
  137  *      [90/09/03            af]
  138  */
  139 /*
  140  *      File: scsi.c
  141  *      Author: Alessandro Forin, Carnegie Mellon University
  142  *      Date:   9/90
  143  *
  144  *      Middle layer of the SCSI driver: chip independent functions
  145  *      This file contains Controller and Device-independent functions
  146  */
  147 
  148 #include <scsi.h>
  149 
  150 #if     NSCSI > 0
  151 #include <platforms.h>
  152 
  153 #include <machine/machspl.h>            /* spl definitions */
  154 #include <kern/time_out.h>              /* hz, timeout, untimeout */
  155 
  156 #include <mach/std_types.h>
  157 #include <sys/types.h>
  158 #include <scsi/compat_30.h>
  159 
  160 #include <chips/busses.h>
  161 #include <scsi/scsi.h>
  162 #include <scsi/scsi2.h>
  163 #include <scsi/scsi_defs.h>
  164 
  165 
  166 #ifdef  VAXSTATION
  167 /* We run some of this code on the interrupt stack */
  168 #undef  spl0
  169 #define spl0()  spl1()
  170 #endif  /*VAXSTATION*/
  171 
  172 /*
  173  *      Overall driver state
  174  */
  175 
  176 target_info_t   scsi_target_data[NSCSI*8];      /* per target state */
  177 scsi_softc_t    scsi_softc_data[NSCSI];         /* per HBA state */
  178 scsi_softc_t    *scsi_softc[NSCSI];             /* quick access&checking */
  179 
  180 /*
  181  * If a specific target should NOT be asked to go synchronous
  182  * then its bit in this bitmap should be set. Each SCSI controller
  183  * (Host Bus Adapter) can hold at most 8 targets --> use one
  184  * byte per controller.  A bit set to one means NO synchronous.
  185  * Patch with adb if necessary.
  186  */
  187 unsigned char   scsi_no_synchronous_xfer[NSCSI];
  188 
  189 /*
  190  * For certain targets it is wise to use the long form of the
  191  * read/write commands even if their capacity would not necessitate
  192  * it.  Same as above for usage.
  193  */
  194 unsigned char   scsi_use_long_form[NSCSI];
  195 
  196 
  197 /*
  198  * Control over disconnect-reconnect mode.
  199  */
  200 unsigned char   scsi_might_disconnect[NSCSI] =  /* do it if deemed appropriate */
  201                 { 0xff, 0xff, 0xff, 0xff, 0xff};/* Fix by hand viz NSCSI */
  202 unsigned char   scsi_should_disconnect[NSCSI] = /* just do it */
  203                 { 0,};
  204 unsigned char   scsi_initiator_id[NSCSI] =      /* our id on the bus(ses) */
  205                 { 7, 7, 7, 7, 7};
  206 
  207 /*
  208  * Miscellaneus config
  209  */
  210 boolean_t       scsi_exabyte_filemarks = FALSE; /* use short filemarks */
  211 int             scsi_watchdog_period = 10;      /* but exabyte needs >=30 for bspace */
  212 int             scsi_delay_after_reset = 1000000;/* microseconds */
  213 boolean_t       scsi_no_automatic_bbr = FALSE;  /* revector bad blocks automatically */
  214 
  215 #ifdef  MACH_KERNEL
  216 #else
  217 /* This covers Exabyte's max record size */
  218 unsigned int    scsi_per_target_virtual = 256*1024;
  219 #endif  MACH_KERNEL
  220 
  221 
  222 /*
  223  * Device-specific operations are switched off this table
  224  */
  225 
  226 extern char
  227                 *scdisk_name(), *sctape_name(), *scprt_name(),
  228                 *sccpu_name(), *scworm_name(), *sccdrom_name(),
  229                 *scscn_name(), *scmem_name(), *scjb_name(), *sccomm_name();
  230 extern void
  231                 sctape_optimize();
  232 extern scsi_ret_t
  233                 scdisk_open(), sctape_open(), sctape_close(),
  234                 sccomm_open(), sccomm_close();
  235 extern int
  236                 scdisk_strategy(), sctape_strategy(), sccpu_strategy(),
  237                 sccomm_strategy();
  238 extern void
  239                 scdisk_start(), sctape_start(), sccpu_start(), sccomm_start();
  240 
  241 extern io_return_t
  242                 scdisk_set_status(), scdisk_get_status(),
  243                 sctape_set_status(), sctape_get_status(),
  244                 sccomm_set_status(), sccomm_get_status();
  245 
  246 scsi_devsw_t    scsi_devsw[] = {
  247 
  248 /* SCSI_DISK */         { scdisk_name, SCSI_OPTIMIZE_NULL,
  249                           scdisk_open, SCSI_CLOSE_NULL,
  250                           scdisk_strategy, scdisk_start,
  251                           scdisk_get_status, scdisk_set_status },
  252 
  253 /* SCSI_TAPE */         { sctape_name, sctape_optimize,
  254                           sctape_open, sctape_close,
  255                           sctape_strategy, sctape_start,
  256                           sctape_get_status, sctape_set_status },
  257 
  258 /* SCSI_PRINTER */      { scprt_name, SCSI_OPTIMIZE_NULL, /*XXX*/},
  259 
  260 /* SCSI_CPU */          { sccpu_name, SCSI_OPTIMIZE_NULL,
  261                           SCSI_OPEN_NULL, SCSI_CLOSE_NULL,
  262                           sccpu_strategy, sccpu_start,},
  263 
  264 /* SCSI_WORM */         { scworm_name, SCSI_OPTIMIZE_NULL,
  265                           scdisk_open, SCSI_CLOSE_NULL,
  266                           scdisk_strategy, scdisk_start,
  267                           scdisk_get_status, scdisk_set_status },
  268 
  269 /* SCSI_CDROM */        { sccdrom_name, SCSI_OPTIMIZE_NULL,
  270                           scdisk_open, SCSI_CLOSE_NULL,
  271                           scdisk_strategy, scdisk_start,
  272                           scdisk_get_status, scdisk_set_status },
  273 /* scsi2 */
  274 /* SCSI_SCANNER */      { scscn_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
  275 
  276 /* SCSI_MEMORY */       { scmem_name, SCSI_OPTIMIZE_NULL,
  277                           scdisk_open, SCSI_CLOSE_NULL,
  278                           scdisk_strategy, scdisk_start,
  279                           scdisk_get_status, scdisk_set_status },
  280 
  281 /* SCSI_J_BOX */        { scjb_name, SCSI_OPTIMIZE_NULL, /*XXX*/ },
  282 
  283 /* SCSI_COMM */         { sccomm_name, SCSI_OPTIMIZE_NULL,
  284 #if     (NCENDATA>0)
  285                           sccomm_open, sccomm_close,
  286                           sccomm_strategy, sccomm_start,
  287                           sccomm_get_status, sccomm_set_status
  288 #endif
  289                         },
  290                         0
  291 };
  292 
  293 /*
  294  * Allocation routines for state structures
  295  */
  296 scsi_softc_t *
  297 scsi_master_alloc(unit, hw)
  298         unsigned unit;
  299         char    *hw;
  300 {
  301         scsi_softc_t    *sc;
  302 
  303         if (unit < NSCSI) {
  304                 sc = &scsi_softc_data[unit];
  305                 scsi_softc[unit] = sc;
  306                 sc->masterno = unit;
  307                 sc->hw_state = hw;
  308                 return sc;
  309         }
  310         return 0;
  311 }
  312 
  313 target_info_t *
  314 scsi_slave_alloc(unit, slave, hw)
  315         unsigned unit, slave;
  316         char    *hw;
  317 {
  318         target_info_t   *tgt;
  319 
  320         tgt = &scsi_target_data[(unit<<3) + slave];
  321         tgt->hw_state = hw;
  322         tgt->dev_ops = 0;       /* later */
  323         tgt->target_id = slave;
  324         tgt->masterno = unit;
  325         tgt->block_size = 1;    /* default */
  326         tgt->flags = TGT_ALIVE;
  327         tgt->sync_period = 0;
  328         tgt->sync_offset = 0;
  329         simple_lock_init(&tgt->target_lock);
  330 
  331         scsi_softc[unit]->target[slave] = tgt;
  332         return tgt;
  333 }
  334 
  335 void
  336 zero_ior(
  337         io_req_t        ior )
  338 {
  339         ior->io_next = ior->io_prev = 0;
  340         ior->io_count = 0;
  341         ior->io_op = IO_INTERNAL;
  342         ior->io_error = 0;
  343 }
  344 
  345 /*
  346  * Slave routine:
  347  *      See if the slave description (controller, unit, ..)
  348  *      matches one of the slaves found during probe
  349  *
  350  * Implementation:
  351  *      Send out an INQUIRY command to see what sort of device
  352  *      the slave is.
  353  * Notes:
  354  *      At this time the driver is fully functional and works
  355  *      off interrupts.
  356  * TODO:
  357  *      The SCSI2 spec says what exactly must happen: see F.2.3
  358  */
  359 int scsi_slave( ui, reg)
  360         struct bus_device       *ui;
  361         unsigned                reg;
  362 {
  363         scsi_softc_t            *sc = scsi_softc[(unsigned char)ui->ctlr];
  364         target_info_t           *tgt = sc->target[(unsigned char)ui->slave];
  365         scsi2_inquiry_data_t    *inq;
  366         int                     scsi_std;
  367         int                     ptype, s;
  368 
  369         if (!tgt || !(tgt->flags & TGT_ALIVE))
  370                 return 0;
  371 
  372         /* Might have scanned already */
  373         if (tgt->dev_ops)
  374                 goto out;
  375 
  376 #ifdef  SCSI2
  377         This is what should happen:
  378         - for all LUNs 
  379                 INQUIRY
  380                 scsi_verify_state (see)
  381                 scsi_initialize (see)
  382 #endif  SCSI2
  383 
  384         tgt->unit_no = ui->slave;       /* incorrect, but needed early */
  385 
  386         s = spl0();     /* we need interrupts */
  387 
  388         if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
  389                 tgt->flags |= TGT_DID_SYNCH;
  390 
  391         /*
  392          * Ok, it is time to see what type of device this is,
  393          * send an INQUIRY cmd and wait till done.
  394          * Possibly do the synch negotiation here.
  395          */
  396         scsi_inquiry(tgt, SCSI_INQ_STD_DATA);
  397 
  398         inq = (scsi2_inquiry_data_t*)tgt->cmd_ptr;
  399         ptype = inq->periph_type;
  400 
  401         switch (ptype) {
  402         case SCSI_CDROM :
  403                 tgt->flags |= TGT_READONLY;
  404                 /* fall through */
  405         case SCSI_DISK :
  406         case SCSI_TAPE :
  407         case SCSI_PRINTER :
  408         case SCSI_CPU :
  409         case SCSI_WORM :
  410         case SCSI_SCANNER :
  411         case SCSI_MEMORY :
  412         case SCSI_J_BOX :
  413         case SCSI_COMM :
  414 /*      case SCSI_PREPRESS1 : reserved, really
  415         case SCSI_PREPRESS2 :   */
  416                 tgt->dev_ops = &scsi_devsw[ptype];
  417                 break;
  418         default:
  419                 printf("scsi%d: %s %d (x%x). ", ui->ctlr,
  420                        "Unsupported device type at SCSI id", ui->slave,
  421                         inq->periph_type);
  422                 scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
  423                         SCSI_INQ_STD_DATA, 0);
  424                 tgt->flags = 0;
  425                 splx(s);
  426                 return 0;
  427         }
  428 
  429         if (inq->rmb)
  430                 tgt->flags |= TGT_REMOVABLE_MEDIA;
  431 
  432         /*
  433          * Tell the user we know this target, then see if we
  434          * can be a bit smart about it.
  435          */
  436         scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
  437                 SCSI_INQ_STD_DATA, tgt->tgt_name);
  438         if (scsi_debug)
  439                 scsi_print_inquiry((scsi2_inquiry_data_t*)inq,
  440                         SCSI_INQ_STD_DATA, 0);
  441 
  442         /*
  443          * The above says if it currently behaves as a scsi2,
  444          * however scsi1 might just be the default setting.
  445          * The spec say that even if in scsi1 mode the target
  446          * should answer to the full scsi2 inquiry spec.
  447          */
  448         scsi_std = (inq->ansi == 2 || inq->response_fmt == 2) ? 2 : 1;
  449 #if nosey
  450         if (scsi_std == 2) {
  451                 unsigned char   supp_pages[256], i;
  452                 scsi2_impl_opdef_page_t *impl;
  453 
  454                 scsi_inquiry(tgt, SCSI_INQ_SUPP_PAGES);
  455                 impl = (scsi2_impl_opdef_page_t *)inq;
  456                 npages = impl->page_len - 2;
  457                 bcopy(impl->supp_opdef, supp_pages, npages);
  458 
  459                 for (i = 0; i < npages; i++) {
  460                         scsi_inquiry(tgt, supp_pages[i]);
  461                         scsi_print_inquiry(inq, supp_pages[i], 0);
  462                 }
  463         }
  464 
  465         if (scsi_std == 2) {
  466                 scsi2_impl_opdef_page_t *impl;
  467                 int i;
  468 
  469                 scsi_inquiry(tgt, SCSI_INQ_IMPL_OPDEF);
  470                 impl = (scsi2_impl_opdef_page_t *)inq;
  471                 for (i = 0; i < impl->page_len - 2; i++)
  472                         if (impl->supp_opdef[i] == SCSI2_OPDEF) {
  473                                 scsi_change_definition(tgt, SCSI2_OPDEF);
  474                                 /* if success .. */
  475                                         tgt->flags |= TGT_SCSI_2_MODE;
  476                                 break;
  477                         }
  478         }
  479 #endif  nosey
  480 
  481         splx(s);
  482 out:
  483         return (strcmp(ui->name, (*tgt->dev_ops->driver_name)(TRUE)) == 0);
  484 }
  485 
  486 #ifdef  SCSI2
  487 scsi_verify_state(...)
  488 {
  489 verify_state: send test_unit_ready up to 3 times, each time it fails
  490 (with check condition) send a requeste_sense. It is ok to get UNIT ATTENTION 
  491 the first time only, NOT READY the second, only GOOD the last time.
  492 If you get BUSY or RESERVATION CONFLICT retry.
  493 }
  494 
  495 scsi_initialize(...)
  496 {
  497 
  498 initialize: send start_unit with immed=0 (->disconnect), if fails
  499 with check condition send requeste_sense and if "illegal request"
  500 proceed anyways. Retry on BUSY.
  501 Do a verify_state, then
  502 disks:
  503         - mode_sense (current) if ANSI2 or needed by vendor (!!!!)
  504           and if check-condition&illegal-request goto capacity
  505         - mode_sense (changeable)
  506         - if needed do a mode_select (yes, 512)
  507         - read_capacity
  508 tapes:
  509 
  510 }
  511 #endif  SCSI2
  512 
  513 /*
  514  * Attach routine:
  515  *      Fill in all the relevant per-slave data and make
  516  *      the slave operational.
  517  *
  518  * Implementation:
  519  *      Get target's status, start the unit and then
  520  *      switch off to device-specific functions to gather
  521  *      as much info as possible about the slave.
  522  */
  523 void scsi_attach(ui)
  524         register struct bus_device *ui;
  525 {
  526         scsi_softc_t            *sc = scsi_softc[ui->mi->unit];
  527         target_info_t           *tgt = sc->target[(unsigned char)ui->slave];
  528         int                     i;
  529         spl_t                   s;
  530 
  531         printf(" (%s %s) ", (*tgt->dev_ops->driver_name)(FALSE),tgt->tgt_name);
  532 
  533         if (tgt->flags & TGT_US) {
  534                 printf(" [this cpu]");
  535                 return;
  536         }
  537 
  538         s = spl0();
  539 
  540         /* sense return from inquiry */
  541         scsi_request_sense(tgt, 0, 0);
  542 
  543         /*
  544          * Do this twice, certain targets need it
  545          */
  546         if (tgt->dev_ops != &scsi_devsw[SCSI_CPU]) {
  547                 (void) scsi_start_unit(tgt, SCSI_CMD_SS_START, 0);
  548                 i = 0;
  549                 while (scsi_start_unit(tgt, SCSI_CMD_SS_START, 0) == SCSI_RET_RETRY) {
  550                         if (i++ == 5)
  551                                 printf(".. not yet online ..");
  552                         delay(1000000);
  553                         if (i == 60) {
  554                                 printf(" seems hopeless.");
  555                                 break;
  556                         }
  557                 }
  558         }
  559 
  560         /*
  561          * See if it is up and about
  562          */
  563         scsi_test_unit_ready(tgt, 0);
  564 
  565         if (tgt->dev_ops->optimize != SCSI_OPTIMIZE_NULL)
  566                 (*tgt->dev_ops->optimize)(tgt);
  567 
  568         tgt->flags |= TGT_FULLY_PROBED;
  569 
  570         splx(s);
  571 }
  572 
  573 /*
  574  * Probe routine:
  575  *      See if a device answers.  Used AFTER autoconf.
  576  *
  577  * Implementation:
  578  *      First ask the HBA to see if anyone is there at all, then
  579  *      call the scsi_slave and scsi_attach routines with a fake ui.
  580  */
  581 boolean_t
  582 scsi_probe( sc, tgt_ptr, target_id, ior)
  583         scsi_softc_t            *sc;
  584         target_info_t           **tgt_ptr;
  585         int                     target_id;
  586         io_req_t                ior;
  587 {
  588         struct bus_device       ui;
  589         target_info_t           *tgt;
  590 
  591         if (!sc->probe || target_id > 7 || target_id == sc->initiator_id)
  592                 return FALSE;   /* sanity */
  593 
  594         if (sc->target[target_id] == 0)
  595                 scsi_slave_alloc( sc->masterno, target_id, sc->hw_state);
  596         tgt = sc->target[target_id];
  597         tgt->flags = 0;/* we donno yet */
  598         tgt->dev_ops = 0;
  599 
  600         /* mildly enquire */
  601         if (!(sc->probe)(tgt, ior))
  602                 goto fail;
  603 
  604         /* There is something there, see what it is */
  605         bzero(&ui, sizeof(ui));
  606         ui.ctlr = sc->masterno;
  607         ui.unit =
  608         ui.slave = target_id;
  609         ui.name = "";
  610 
  611         /* this fails on the name for sure */
  612         (void) scsi_slave( &ui, 0 /* brrrr */);
  613         if ((tgt->flags & TGT_ALIVE) == 0)
  614                 goto fail;
  615 
  616         {
  617                 struct bus_ctlr mi;
  618 
  619                 mi.unit = sc->masterno;
  620                 ui.mi = &mi;
  621                 printf("%s at slave %d ",
  622                         (*tgt->dev_ops->driver_name)(TRUE), target_id);
  623                 scsi_attach(&ui);
  624         }
  625 
  626         *tgt_ptr = tgt;
  627         return TRUE;
  628 fail:
  629         tgt->flags = 0;
  630         return FALSE;
  631 }
  632 
  633 
  634 /*
  635  * Watchdog routine:
  636  *      Issue a SCSI bus reset if a target holds up the
  637  *      bus for too long.
  638  *
  639  * Implementation:
  640  *      Each HBA that wants to use this should have a
  641  *      watchdog_t structure at the head of its hardware
  642  *      descriptor.  This variable is set by this periodic
  643  *      routine and reset on bus activity. If it is not reset on
  644  *      time (say some ten seconds or so) we reset the
  645  *      SCSI bus.
  646  * NOTE:
  647  *      An HBA must be ready to accept bus reset interrupts
  648  *      properly in order to use this.
  649  */
  650 void scsi_watchdog(hw)
  651         watchdog_t      *hw;
  652 {
  653         spl_t           s = splbio();
  654 
  655         switch (hw->watchdog_state) {
  656         case SCSI_WD_EXPIRED:
  657 
  658                 /* double check first */
  659                 if (hw->nactive == 0) {
  660                         hw->watchdog_state = SCSI_WD_INACTIVE;
  661                         break;
  662                 }
  663                 if (scsi_debug)
  664                         printf("SCSI Watchdog expired\n");
  665                 hw->watchdog_state = SCSI_WD_INACTIVE;
  666                 (*hw->reset)(hw);
  667                 break;
  668 
  669         case SCSI_WD_ACTIVE:
  670 
  671                 hw->watchdog_state = SCSI_WD_EXPIRED;
  672                 break;
  673 
  674         case SCSI_WD_INACTIVE:
  675 
  676                 break;
  677         }
  678 
  679         /* do this here, fends against powered down devices */
  680         if (scsi_watchdog_period != 0)
  681             timeout(scsi_watchdog, hw, scsi_watchdog_period * hz);
  682 
  683         splx(s);
  684 }
  685 
  686 
  687 /*
  688  * BusReset Notification:
  689  *      Called when the HBA sees a BusReset interrupt
  690  *
  691  * Implementation:
  692  *      Go through the list of targets, redo the synch
  693  *      negotiation, and restart whatever operation was
  694  *      in progress for that target.
  695  */
  696 void scsi_bus_was_reset(sc)
  697         scsi_softc_t    *sc;
  698 {
  699         register target_info_t  *tgt;
  700         int                     i;
  701         /*
  702          * Redo the synch negotiation
  703          */
  704         for (i = 0; i < 8; i++) {
  705                 io_req_t        ior;
  706                 spl_t           s;
  707 
  708                 if (i == sc->initiator_id)
  709                         continue;
  710                 tgt = sc->target[i];
  711                 if (!tgt || !(tgt->flags & TGT_ALIVE))
  712                         continue;
  713 
  714                 tgt->flags &= ~(TGT_DID_SYNCH|TGT_DISCONNECTED);
  715 #if 0
  716                 /* the standard does *not* imply this gets reset too */
  717                 tgt->sync_period = 0;
  718                 tgt->sync_offset = 0;
  719 #endif
  720 
  721                 /*
  722                  * retry the synch negotiation
  723                  */
  724                 ior = tgt->ior;
  725                 tgt->ior = 0;
  726                 printf(".. tgt %d ", tgt->target_id);
  727                 if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id))
  728                         tgt->flags |= TGT_DID_SYNCH;
  729                 else {
  730                         s = spl0();
  731                         scsi_test_unit_ready(tgt, 0);
  732                         splx(s);
  733                 }
  734                 tgt->ior = ior;
  735         }
  736 
  737         /*
  738          * Notify each target of the accident
  739          */
  740         for (i = 0; i < 8; i++) {
  741                 if (i == sc->initiator_id)
  742                         continue;
  743                 tgt = sc->target[i];
  744                 if (!tgt)
  745                         continue;
  746                 tgt->done = SCSI_RET_ABORTED|SCSI_RET_RETRY;
  747                 if (tgt->ior)
  748                         (*tgt->dev_ops->restart)( tgt, TRUE);
  749         }
  750 
  751         printf("%s", " reset complete\n");
  752 }
  753 
  754 #endif  NSCSI > 0

Cache object: 745d87a0d328561c9f3e9ab9fdbbf83b


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