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

Cache object: f441a69c529a1ef432b43cf542980f84


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