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/rz_disk.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,1992,1991,1990 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:        rz_disk.c,v $
   29  * Revision 2.26  93/11/17  18:43:33  dbg
   30  *      Added include of kern/time_out.h.
   31  *      [93/05/21            dbg]
   32  * 
   33  * Revision 2.25  93/08/10  15:19:44  mrt
   34  *      Fix DIOCxxx ioctls to deal with MAXPARTITION or MAXPARTITION+1
   35  *      partitions.  We'll do this better next release.
   36  *      [93/08/09            rvb]
   37  * 
   38  * Revision 2.24  93/08/03  12:34:06  mrt
   39  *      No default spl protection for start routine.
   40  *      [93/07/29  23:31:54  af]
   41  * 
   42  * Revision 2.23  93/05/15  19:42:50  mrt
   43  *      machparam.h -> machspl.h
   44  * 
   45  * Revision 2.22  93/05/10  21:22:28  rvb
   46  *      Removed depends on DEV_BSIZE.
   47  *      Do not assume read_capacity will work (violations of standard..)
   48  *      Try to set the logical block size to the default U*X wants,
   49  *      but take whatever the drive wants if not.  For CDROMs.
   50  *      Write back the label where we found it.
   51  *      [93/05/06  10:13:33  af]
   52  * 
   53  * Revision 2.21  93/03/09  11:18:27  danner
   54  *      If there is no recognizable label, we must set p_size of the
   55  *      MAXPARTITION slice.  We use MAXPARTITION to do ABSOLUTE reads.
   56  *      [93/02/23            rvb]
   57  * 
   58  * Revision 2.20  93/03/09  10:57:38  danner
   59  *      Merge botch in scdisk_writelabel(), was still setting tgt->ior
   60  *      before grab_it().
   61  *      To accomodate a weird "feature" in some Adaptec microcode and
   62  *      slowpoke <unnamed> disk.. retry if the unit is not yet ready
   63  *      when we come to read it.
   64  *      [93/02/23            af]
   65  * 
   66  * Revision 2.19  93/01/14  17:55:21  danner
   67  *      Made all stack-allocated buffers aligned.
   68  *      [92/08/02            af]
   69  * 
   70  * Revision 2.18  92/08/03  17:53:30  jfriedl
   71  *      removed silly prototypes
   72  *      [92/08/02            jfriedl]
   73  * 
   74  * Revision 2.17  92/05/21  17:23:32  jfriedl
   75  *      Fixed return-value types (most now void).
   76  *      Cleanup to quiet gcc warnings.
   77  *      [92/05/16            jfriedl]
   78  * 
   79  * Revision 2.16  92/04/06  23:23:01  rpd
   80  *      On bad errors, be loquacious and decode all sense data.
   81  *      Do not retry IO_INTERNAL operations, cuz we donno what it is.
   82  *      [92/04/06            af]
   83  * 
   84  * Revision 2.15  92/04/03  12:17:54  rpd
   85  *      With af, fixed berkeley label processing not to trash tgt->ior.
   86  *      Use PARTITION_ABSOLUTE to read absolute sectors from the 
   87  *      disk, by reading/writing on the absolute partition.
   88  *      [92/04/01            rvb]
   89  *      Merged bernadat's change to mainline.  Made conditional
   90  *      on i386 vs AT386.
   91  *      [92/03/16            rvb]
   92  *      Call machine dependant set_status/get_status
   93  *      if flavor is not a known one.
   94  *      [92/03/04            bernadat]
   95  * 
   96  * Revision 2.14  92/02/23  22:44:21  elf
   97  *      Changed the interface of a number of functions not to
   98  *      require the scsi_softc pointer any longer.  It was
   99  *      mostly unused, now it can be found via tgt->masterno.
  100  *      Added DEV_GET_SIZE flavor for get status.
  101  *      Disabled PERF code.
  102  *      [92/02/22  19:06:12  af]
  103  * 
  104  * Revision 2.13  91/10/09  16:17:00  af
  105  *      Do not tolerate a negative io_count (sanity).
  106  *      [91/10/05  10:21:09  af]
  107  * 
  108  * Revision 2.12.1.1  91/09/01  17:18:33  af
  109  *      Fixed blooper in setdisklabel(), now disk labels work on 3.0.
  110  *      Zero io_error before using the ior.
  111  * 
  112  * Revision 2.12  91/08/24  12:27:52  af
  113  *      Spl defs.  Search for label. MultiP locks.
  114  *      [91/08/02  03:53:45  af]
  115  * 
  116  *      Bcopy casts.
  117  * 
  118  * Revision 2.11  91/07/09  23:22:28  danner
  119  *      Upgraded to support new label technology.
  120  *      [91/07/09  11:15:50  danner]
  121  * 
  122  * Revision 2.10  91/06/25  20:56:16  rpd
  123  *      Tweaks to make gcc happy.
  124  * 
  125  * Revision 2.9  91/06/19  11:57:01  rvb
  126  *      File moved here from mips/PMAX since it is now "MI" code, also
  127  *      used by Vax3100 and soon -- the omron luna88k.
  128  *      [91/06/04            rvb]
  129  * 
  130  * Revision 2.8  91/05/14  17:26:29  mrt
  131  *      Correcting copyright
  132  * 
  133  * Revision 2.7  91/05/13  06:04:25  af
  134  *      Fixed a type declaration, now an HBA with unlimited DMA
  135  *      capability sez so by setting the max_dma_size to -1.
  136  *      [91/04/05  13:08:43  af]
  137  * 
  138  *      Use long forms of read/write commands on disks bigger than 1Gb,
  139  *      which we automatically recognize from the read_capacity.
  140  *      Allocate io_req_t records properly.
  141  *      Check for transactions that aborted due to scsi bus resets.
  142  *      Issue a request_sense on bad transactions, log soft errors
  143  *      and only make fail bad errors.
  144  *      [91/03/29  17:03:03  af]
  145  * 
  146  * Revision 2.6  91/02/14  14:35:22  mrt
  147  *      Added (optional and disabled) code for checksumming.
  148  *      [91/02/12  12:58:27  af]
  149  * 
  150  *      Bug in strategy routine: for xfers larger than
  151  *      max_dma was not setting the io_count right at
  152  *      the end of the transfer.  Now new fsck works.
  153  *      [90/12/10  17:26:47  af]
  154  * 
  155  * Revision 2.5  91/02/05  17:43:47  mrt
  156  *      Added author notices
  157  *      [91/02/04  11:16:50  mrt]
  158  * 
  159  *      Changed to use new Mach copyright
  160  *      [91/02/02  12:15:37  mrt]
  161  * 
  162  * Revision 2.4  90/12/20  17:01:09  jeffreyh
  163  *      Bug in strategy routine: for xfers larger than
  164  *      max_dma was not setting the io_count right at
  165  *      the end of the transfer.  Now new fsck works.
  166  *      [90/12/10  17:26:47  af]
  167  * 
  168  * Revision 2.3  90/12/05  23:33:57  af
  169  *      Use and prefer BSD/OSF labels.
  170  *      [90/12/03  23:33:43  af]
  171  * 
  172  * Revision 2.1.1.1  90/11/01  03:43:47  af
  173  *      Created.
  174  *      [90/10/21            af]
  175  */
  176 /*
  177  *      File: rz_disk.c
  178  *      Author: Alessandro Forin, Carnegie Mellon University
  179  *      Date:   10/90
  180  *
  181  *      Top layer of the SCSI driver: interface with the MI.
  182  *      This file contains operations specific to disk-like devices.
  183  */
  184 
  185 #include <machine/machspl.h>            /* spl definitions */
  186 #include <mach/std_types.h>
  187 #include <scsi/compat_30.h>
  188 
  189 #ifdef  MACH_KERNEL
  190 #include <kern/time_out.h>      /* for hz, timeout, untimeout */
  191 #else   /*MACH_KERNEL*/
  192 #include <sys/kernel.h>         /* for hz */
  193 #endif  /*MACH_KERNEL*/
  194 
  195 #include <scsi/scsi.h>
  196 #include <scsi/scsi_defs.h>
  197 #include <scsi/rz.h>
  198 #include <scsi/rz_labels.h>
  199 
  200 extern void     scdisk_read(), scdisk_write(),
  201                 scsi_long_read(), scsi_long_write();
  202 
  203 void scdisk_start(); /* forwards */
  204 void scdisk_start_rw();
  205 unsigned dkcksum();
  206 
  207 /*
  208  * Label used if the disk does not have one
  209  */
  210 struct disklabel scsi_default_label =
  211 {
  212         DISKMAGIC, DTYPE_SCSI, 0,
  213         "SCSI", "",
  214         DEV_BSIZE, 1, 1, 1, 1, 1, 0, 0, 0,
  215         3600, 1, 1, 1, 0, 0, 0,
  216         {0,}, {0,},
  217         DISKMAGIC, 0,
  218         8, 8192, 8192,
  219         {{ -1, 0, 1024, FS_BSDFFS, 8, 3 },
  220          { -1, 0, 1024, FS_BSDFFS, 8, 3 },
  221          { -1, 0, 1024, FS_BSDFFS, 8, 3 },
  222          { -1, 0, 1024, FS_BSDFFS, 8, 3 },
  223          { -1, 0, 1024, FS_BSDFFS, 8, 3 },
  224          { -1, 0, 1024, FS_BSDFFS, 8, 3 },
  225          { -1, 0, 1024, FS_BSDFFS, 8, 3 },
  226          { -1, 0, 1024, FS_BSDFFS, 8, 3 }}
  227 };
  228 
  229 
  230 /*
  231  * Specialized side of the open routine for disks
  232  */
  233 scsi_ret_t scdisk_open(
  234         target_info_t           *tgt,
  235         io_req_t                req)
  236 {
  237         register int            i, dev_bsize;
  238         scsi_ret_t              ret = SCSI_RET_SUCCESS;
  239         unsigned int            disk_size, secs_per_cyl, sector_size;
  240         scsi_rcap_data_t        *cap;
  241         struct disklabel        *label;
  242         io_req_t                ior;
  243         void                    (*readfun)() = scdisk_read;
  244         char                    *data = (char *)0;
  245 
  246         if (tgt->flags & TGT_ONLINE)
  247                 return SCSI_RET_SUCCESS;
  248 
  249         /*
  250          * Dummy ior for proper sync purposes
  251          */
  252         io_req_alloc(ior,0);
  253         ior->io_next = 0;
  254         ior->io_count = 0;
  255 
  256         /*
  257          * Set the LBN to DEV_BSIZE with a MODE SELECT.
  258          * If this fails we try a couple other tricks.
  259          */
  260         dev_bsize = 0;
  261         for (i = 0; i < 5; i++) {
  262                 ior->io_op = IO_INTERNAL;
  263                 ior->io_error = 0;
  264                 ret = scdisk_mode_select(tgt, DEV_BSIZE, ior, 0, 0, 0);
  265                 if (ret == SCSI_RET_SUCCESS) {
  266                         dev_bsize = DEV_BSIZE;
  267                         break;
  268                 }
  269                 if (ret == SCSI_RET_RETRY) {
  270                         timeout(wakeup, tgt, 2*hz);
  271                         await(tgt);
  272                 }
  273                 if (ret == SCSI_RET_DEVICE_DOWN)
  274                         goto done;
  275         }
  276 #if 0
  277         if (ret != SCSI_RET_SUCCESS) {
  278                 scsi_error( tgt, SCSI_ERR_MSEL, ret, 0);
  279                 ret = D_INVALID_SIZE;
  280                 goto done;
  281         }
  282 #endif
  283         /*
  284          * Do a READ CAPACITY to get max size. Check LBN too.
  285          */
  286         for (i = 0; i < 5; i++) {
  287                 ior->io_op = IO_INTERNAL;
  288                 ior->io_error = 0;
  289                 ret = scsi_read_capacity(tgt, 0, ior);
  290                 if (ret == SCSI_RET_SUCCESS)
  291                         break;
  292         }
  293         if (ret == SCSI_RET_SUCCESS) {
  294                 int                     val;
  295 
  296                 cap = (scsi_rcap_data_t*) tgt->cmd_ptr;
  297                 disk_size = (cap->lba1<<24) |
  298                             (cap->lba2<<16) |
  299                             (cap->lba3<< 8) |
  300                              cap->lba4;
  301                 if (scsi_debug)
  302                         printf("rz%d holds %d blocks\n", tgt->unit_no, disk_size);
  303                 val = (cap->blen1<<24) |
  304                       (cap->blen2<<16) |
  305                       (cap->blen3<<8 ) |
  306                        cap->blen4;
  307                 if (dev_bsize == 0)
  308                         dev_bsize = val;
  309                 else
  310                 if (val != dev_bsize) panic("read capacity bad");
  311 
  312                 if (disk_size > SCSI_CMD_READ_MAX_LBA)
  313                         tgt->flags |= TGT_BIG;
  314 
  315         } else {
  316                 printf("Unknown disk capacity??\n");
  317                 disk_size = -1;
  318         }
  319         /*
  320          * Mandatory long-form commands ?
  321          */
  322         if (BGET(scsi_use_long_form,(unsigned char)tgt->masterno,tgt->target_id))
  323                 tgt->flags |= TGT_BIG;
  324         if (tgt->flags & TGT_BIG)
  325                 readfun = scsi_long_read;
  326 
  327         /*
  328          * Some CDROMS truly dislike 512 as LBN.
  329          * Use a MODE_SENSE to cover for this case.
  330          */
  331         if (dev_bsize == 0) {
  332                 scsi_mode_sense_data_t *m;
  333 
  334                 ior->io_op = IO_INTERNAL;
  335                 ior->io_error = 0;
  336                 ret = scsi_mode_sense(tgt, 0/*pagecode*/, 32/*?*/, ior);
  337                 if (ret == SCSI_RET_SUCCESS) {
  338                         m = (scsi_mode_sense_data_t *) tgt->cmd_ptr;
  339                         dev_bsize =
  340                                 m->bdesc[0].blen_msb << 16 |
  341                                 m->bdesc[0].blen <<  8 |
  342                                 m->bdesc[0].blen_lsb;
  343                 }
  344         }
  345 
  346         /*
  347          * Find out about the phys disk geometry
  348          */
  349 
  350         ior->io_op = IO_INTERNAL;
  351         ior->io_error = 0;
  352         ret = scsi_read_capacity( tgt, 1, ior);
  353         if (ret == SCSI_RET_SUCCESS) {
  354                 cap = (scsi_rcap_data_t*) tgt->cmd_ptr;
  355                 secs_per_cyl =  (cap->lba1<<24) | (cap->lba2<<16) |
  356                                 (cap->lba3<< 8) |  cap->lba4;
  357                 secs_per_cyl += 1;
  358                 sector_size =   (cap->blen1<<24) | (cap->blen2<<16) |
  359                                 (cap->blen3<<8 ) |  cap->blen4;
  360         } else {
  361                 sector_size = dev_bsize ? dev_bsize : DEV_BSIZE;
  362                 secs_per_cyl = disk_size;
  363         }
  364         if (dev_bsize == 0)
  365                 dev_bsize = sector_size;
  366 
  367         if (scsi_debug)
  368         printf("rz%d: %d sect/cyl %d bytes/sec\n", tgt->unit_no,
  369                 secs_per_cyl, sector_size);
  370 
  371         /*
  372          * At this point, one way or other, we are committed to
  373          * a given disk capacity and sector size.
  374          */
  375         tgt->block_size = dev_bsize;
  376 
  377         /*
  378          * Get partition table off pack
  379          */
  380 
  381         /* first look for a BSD label */        
  382 #ifdef  MACH_KERNEL
  383         data = (char *)kalloc(dev_bsize);
  384 #else   /*MACH_KERNEL*/
  385         data = (char *)ior->io_data;
  386 #endif  /*MACH_KERNEL*/
  387 
  388         ior->io_data = data;
  389         ior->io_count = dev_bsize;
  390         ior->io_op = IO_READ;
  391         ior->io_error = 0;
  392         tgt->ior = ior;
  393         (*readfun)( tgt, LABELSECTOR, ior);
  394         iowait(ior);
  395 
  396         {
  397                 /* Search for BSD label, might be a bit further along */
  398                 register int    j;
  399                 boolean_t       found;
  400 
  401                 for (j = LABELOFFSET, found = FALSE;
  402                      j < (dev_bsize-sizeof(struct disklabel));
  403                      j += sizeof(int)) {
  404                         label = (struct disklabel *) &data[j];
  405                         if (label->d_magic  == DISKMAGIC &&
  406                             label->d_magic2 == DISKMAGIC) {
  407                                 found = TRUE;
  408                                 break;
  409                         }
  410                 }
  411                 if (found)
  412                         tgt->dev_info.disk.labeloffset = j;
  413                 else {
  414                         tgt->dev_info.disk.labeloffset = LABELOFFSET;
  415                         label = 0;
  416                 }
  417                 tgt->dev_info.disk.labelsector = LABELSECTOR;
  418         }
  419 
  420         if (label) {
  421                 if (scsi_debug)
  422                         printf("{Using BSD label}");
  423                 tgt->dev_info.disk.l = *label;
  424         } else {
  425                 /* then look for a vendor's label, but first
  426                    fill in defaults and what we found */
  427 
  428                 label = &tgt->dev_info.disk.l;
  429                 *label = scsi_default_label;
  430                 label->d_secsize = sector_size;
  431                 label->d_secpercyl = secs_per_cyl;
  432                 label->d_secperunit = disk_size;
  433 
  434                 ior->io_data = data;
  435                 if (!rz_vendor_label(tgt, label, ior)) {
  436 
  437                         printf("rz%d: %s\n", tgt->unit_no,
  438                                 "No valid disk label, using defaults");
  439                         /* Validate partitions a and c for initialization */
  440                         tgt->dev_info.disk.l.d_partitions[0].p_offset = 0;
  441                         tgt->dev_info.disk.l.d_partitions[0].p_size   = disk_size;
  442                         tgt->dev_info.disk.l.d_partitions[2].p_offset = 0;
  443                         tgt->dev_info.disk.l.d_partitions[2].p_size   = disk_size;
  444                         tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_offset = 0;
  445                         tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_size   = -1;
  446                 }
  447                 label->d_checksum = 0;
  448                 label->d_checksum = dkcksum(label);
  449         }
  450 
  451         ret = SCSI_RET_SUCCESS;
  452 done:
  453 #ifdef  MACH_KERNEL
  454         if (data) kfree((vm_offset_t) data, dev_bsize);
  455 #endif  /*MACH_KERNEL*/
  456 
  457         io_req_free(ior);
  458         return ret;
  459 }
  460 
  461 /*
  462  * Disk strategy routine
  463  */
  464 io_return_t
  465 scdisk_strategy(
  466         register io_req_t       ior)
  467 {
  468         target_info_t  *tgt;
  469         register scsi_softc_t   *sc;
  470         register int    i = ior->io_unit, part;
  471         register unsigned rec, max;
  472         spl_t           s;
  473 
  474         sc = scsi_softc[rzcontroller(i)];
  475         tgt = sc->target[rzslave(i)];
  476         part = rzpartition(i);
  477 
  478         /*
  479          * Validate request 
  480          */
  481 
  482         /* readonly ? */
  483         if ((tgt->flags & TGT_READONLY) &&
  484             (ior->io_op & (IO_READ|IO_INTERNAL) == 0)) {
  485                 ior->io_error = D_READ_ONLY;
  486                 ior->io_op |= IO_ERROR;
  487                 ior->io_residual = ior->io_count;
  488                 iodone(ior);
  489                 return ior->io_error;
  490         }
  491 
  492         rec = ior->io_recnum;
  493         max = tgt->dev_info.disk.l.d_partitions[part].p_size;
  494         if (max == -1)
  495                 max = tgt->dev_info.disk.l.d_secperunit -
  496                         tgt->dev_info.disk.l.d_partitions[part].p_offset;
  497         i = (ior->io_count + tgt->block_size - 1) / tgt->block_size;
  498         if (((rec + i) > max) || (ior->io_count < 0) ||
  499 #if later
  500             ((rec <= LABELSECTOR) && ((tgt->flags & TGT_WRITE_LABEL) == 0))
  501 #else
  502             FALSE
  503 #endif
  504             ) {
  505                 ior->io_error = D_INVALID_SIZE;
  506                 ior->io_op |= IO_ERROR;
  507                 ior->io_residual = ior->io_count;
  508                 iodone(ior);
  509                 return ior->io_error;
  510         }
  511         /*
  512          * Find location on disk: secno and cyl (for disksort) 
  513          */
  514         rec += tgt->dev_info.disk.l.d_partitions[part].p_offset;
  515         ior->io_residual = rec / tgt->dev_info.disk.l.d_secpercyl;
  516 
  517         /*
  518          * Enqueue operation 
  519          */
  520         s = splbio();
  521         simple_lock(&tgt->target_lock);
  522         if (tgt->ior) {
  523                 disksort(tgt->ior, ior);
  524                 simple_unlock(&tgt->target_lock);
  525                 splx(s);
  526         } else {
  527                 ior->io_next = 0;
  528                 tgt->ior = ior;
  529                 simple_unlock(&tgt->target_lock);
  530                 splx(s);
  531 
  532                 scdisk_start(tgt,FALSE);
  533         }
  534 
  535         return D_SUCCESS;
  536 }
  537 
  538 /*#define CHECKSUM*/
  539 #ifdef  CHECKSUM
  540 int max_checksum_size = 0x2000;
  541 #endif  /*CHECKSUM*/
  542 
  543 /*
  544  * Start/completion routine for disks
  545  */
  546 void scdisk_start(
  547         target_info_t   *tgt,
  548         boolean_t       done)
  549 {
  550         register io_req_t       ior = tgt->ior;
  551         register unsigned       part;
  552 #ifdef  CHECKSUM
  553         register unsigned       secno;
  554 #endif
  555         if (ior == 0)
  556                 return;
  557 
  558         if (tgt->flags & TGT_BBR_ACTIVE)
  559         {
  560                 scdisk_bbr_start(tgt, done);
  561                 return;
  562         }
  563 
  564         if (done) {
  565                 register unsigned int   xferred;
  566                 unsigned int            max_dma_data;
  567 
  568                 max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
  569                 /* see if we must retry */
  570                 if ((tgt->done == SCSI_RET_RETRY) &&
  571                     ((ior->io_op & IO_INTERNAL) == 0)) {
  572                         delay(1000000);/*XXX*/
  573                         goto start;
  574                 } else
  575                 /* got a bus reset ? pifff.. */
  576                 if ((tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) &&
  577                     ((ior->io_op & IO_INTERNAL) == 0)) {
  578                         if ((xferred = ior->io_residual) != 0) {
  579                                 ior->io_data -= xferred;
  580                                 ior->io_count += xferred;
  581                                 ior->io_recnum -= xferred / tgt->block_size;
  582                                 ior->io_residual = 0;
  583                         }
  584                         goto start;
  585                 } else
  586                 /*
  587                  * Quickly check for errors: if anything goes wrong
  588                  * we do a request sense, see if that is what we did.
  589                  */
  590                 if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) {
  591                         scsi_sense_data_t       *sns;
  592                         unsigned int            blockno;
  593                         char                    *outcome;
  594 
  595                         ior->io_op = ior->io_temporary;
  596 
  597                         sns = (scsi_sense_data_t *)tgt->cmd_ptr;
  598                         if (sns->addr_valid)
  599                                 blockno = sns->u.xtended.info0 << 24 |
  600                                           sns->u.xtended.info1 << 16 |
  601                                           sns->u.xtended.info2 <<  8 |
  602                                           sns->u.xtended.info3;
  603                         else {
  604                                 part     = rzpartition(ior->io_unit);
  605                                 blockno  = tgt->dev_info.disk.l.d_partitions[part].p_offset;
  606                                 blockno += ior->io_recnum;
  607                         }
  608 
  609                         if (scsi_check_sense_data(tgt, sns)) {
  610                                 ior->io_error = 0;
  611                                 if ((tgt->done == SCSI_RET_RETRY) &&
  612                                     ((ior->io_op & IO_INTERNAL) == 0)) {
  613                                         delay(1000000);/*XXX*/
  614                                         goto start;
  615                                 }
  616                                 outcome = "Recovered";
  617                         } else {
  618                                 outcome = "Unrecoverable";
  619                                 ior->io_error = D_IO_ERROR;
  620                                 ior->io_op |= IO_ERROR;
  621                         }
  622                         if ((tgt->flags & TGT_OPTIONAL_CMD) == 0) {
  623                             printf("%s Error, rz%d: %s%s%d\n", outcome,
  624                                 tgt->target_id + (tgt->masterno * 8),
  625                                 (ior->io_op & IO_READ) ? "Read" :
  626                                  ((ior->io_op & IO_INTERNAL) ? "(command)" : "Write"),
  627                                 " disk error, phys block no. ", blockno);
  628 
  629                             scsi_print_sense_data(sns);
  630 
  631                             /*
  632                              * On fatal read/write errors try replacing the bad block
  633                              * The bbr routine will return TRUE iff it took control
  634                              * over the target for all subsequent operations. In this
  635                              * event, the queue of requests is effectively frozen.
  636                              */
  637                             if (ior->io_error && 
  638                                 ((sns->error_class == SCSI_SNS_XTENDED_SENSE_DATA) &&
  639                                  ((sns->u.xtended.sense_key == SCSI_SNS_HW_ERR) ||
  640                                   (sns->u.xtended.sense_key == SCSI_SNS_MEDIUM_ERR))) &&
  641                                 scdisk_bad_block_repl(tgt, blockno))
  642                                     return;
  643                         }
  644                 }
  645 
  646                 /*
  647                  * See if we had errors
  648                  */
  649                 else if (tgt->done != SCSI_RET_SUCCESS) {
  650 
  651                         if (tgt->done == SCSI_RET_NEED_SENSE) {
  652 
  653                                 ior->io_temporary = ior->io_op;
  654                                 ior->io_op = IO_INTERNAL;
  655                                 scsi_request_sense(tgt, ior, 0);
  656                                 return;
  657 
  658                         } else if (tgt->done == SCSI_RET_DEVICE_DOWN) {
  659                                 ior->io_error = D_DEVICE_DOWN;
  660                                 ior->io_op |= IO_ERROR;
  661                         } else {
  662                                 printf("%s%x\n", "?rz_disk Disk error, ret=x", tgt->done);
  663                                 ior->io_error = D_IO_ERROR;
  664                                 ior->io_op |= IO_ERROR;
  665                         }
  666                 }
  667                 /*
  668                  * No errors.
  669                  * See if we requested more than the max
  670                  * (We use io_residual in a flip-side way here)
  671                  */
  672                 else if (ior->io_count > (xferred = max_dma_data)) {
  673                         ior->io_residual += xferred;
  674                         ior->io_count -= xferred;
  675                         ior->io_data += xferred;
  676                         ior->io_recnum += xferred / tgt->block_size;
  677                         goto start;
  678                 }
  679                 else if (xferred = ior->io_residual) {
  680                         ior->io_data -= xferred;
  681                         ior->io_count += xferred;
  682                         ior->io_recnum -= xferred / tgt->block_size;
  683                         ior->io_residual = 0;
  684                 } /* that's it */
  685 
  686 #ifdef  CHECKSUM
  687                 if ((ior->io_op & IO_READ) && (ior->io_count < max_checksum_size)) {
  688                         part = rzpartition(ior->io_unit);
  689                         secno = ior->io_recnum + tgt->dev_info.disk.l.d_partitions[part].p_offset;
  690                         scdisk_bcheck(secno, ior->io_data, ior->io_count);
  691                 }
  692 #endif  /*CHECKSUM*/
  693 
  694                 /* dequeue next one */
  695                 {
  696                         io_req_t        next;
  697 
  698                         simple_lock(&tgt->target_lock);
  699                         next = ior->io_next;
  700                         tgt->ior = next;
  701                         simple_unlock(&tgt->target_lock);
  702 
  703                         iodone(ior);
  704                         if (next == 0)
  705                                 return;
  706 
  707                         ior = next;
  708                 }
  709 
  710 #ifdef  CHECKSUM
  711                 if (((ior->io_op & IO_READ) == 0) && (ior->io_count < max_checksum_size)) {
  712                         part = rzpartition(ior->io_unit);
  713                         secno = ior->io_recnum + tgt->dev_info.disk.l.d_partitions[part].p_offset;
  714                         scdisk_checksum(secno, ior->io_data, ior->io_count);
  715                 }
  716 #endif  /*CHECKSUM*/
  717         }
  718         ior->io_residual = 0;
  719 start:
  720         scdisk_start_rw( tgt, ior);
  721 }
  722 
  723 void scdisk_start_rw(
  724         target_info_t   *tgt,
  725         register io_req_t       ior)
  726 {
  727         unsigned int    part, secno;
  728         register boolean_t      long_form;
  729 
  730         part = rzpartition(ior->io_unit);
  731         secno = ior->io_recnum + tgt->dev_info.disk.l.d_partitions[part].p_offset;
  732 
  733         /* Use long form if either big block addresses or
  734            the size is more than we can fit in one byte */
  735         long_form = (tgt->flags & TGT_BIG) ||
  736                     (ior->io_count > (256 * tgt->block_size));
  737         if (ior->io_op & IO_READ)
  738                 (long_form ? scsi_long_read : scdisk_read)(tgt, secno, ior);
  739         else if ((ior->io_op & IO_INTERNAL) == 0)
  740                 (long_form ? scsi_long_write : scdisk_write)(tgt, secno, ior);
  741 }
  742 
  743 #include <sys/ioctl.h>
  744 #ifdef  ULTRIX_COMPAT
  745 #include <mips/PMAX/rzdisk.h>
  746 #endif  /*ULTRIX_COMPAT*/
  747 
  748 io_return_t
  749 scdisk_get_status(
  750         int             dev,
  751         target_info_t   *tgt,
  752         dev_flavor_t    flavor,
  753         dev_status_t    status,
  754         natural_t       *status_count)
  755 {
  756         struct disklabel *lp;
  757 
  758         lp = &tgt->dev_info.disk.l;
  759 
  760         switch (flavor) {
  761 #ifdef  MACH_KERNEL
  762         case DEV_GET_SIZE:
  763                 
  764                 status[DEV_GET_SIZE_DEVICE_SIZE] = lp->d_partitions[rzpartition(dev)].p_size * lp->d_secsize;
  765                 status[DEV_GET_SIZE_RECORD_SIZE] = tgt->block_size;
  766                 *status_count = DEV_GET_SIZE_COUNT;
  767                 break;
  768 #endif
  769 
  770         case DIOCGDINFO:
  771                 *(struct disklabel *)status = *lp;
  772 #ifdef  MACH_KERNEL
  773                 *status_count = sizeof(struct disklabel)/sizeof(int);
  774 #endif  /*MACH_KERNEL*/
  775                 break;
  776 
  777         case DIOCGDINFO - (0x10<<16):
  778                 *(struct disklabel *)status = *lp;
  779 #ifdef  MACH_KERNEL
  780                 *status_count = sizeof(struct disklabel)/sizeof(int) - 4;
  781 #endif  MACH_KERNEL
  782                 break;
  783 
  784 #ifdef  MACH_KERNEL
  785 #else   /*MACH_KERNEL*/
  786 #if     ULTRIX_COMPAT
  787         case SCSI_MODE_SENSE:           /*_IOWR(p, 9, struct mode_sel_sns_params) */
  788                 break;
  789         case DIOCGETPT:                 /*_IOR(p, 1, struct pt) */
  790         case SCSI_GET_SENSE:            /*_IOR(p, 10, struct extended_sense) */
  791                 return ul_disk_ioctl(tgt, flavor, status, status_count);
  792 #endif  /*ULTRIX_COMPAT*/
  793 #endif  /*!MACH_KERNEL*/
  794 
  795 #if 0
  796         case DIOCRFORMAT:
  797                 break;
  798 #endif
  799         default:
  800 #ifdef  i386
  801                 return scsi_i386_get_status(dev, tgt, flavor, status, status_count);
  802 #else   /*i386*/
  803                 return D_INVALID_OPERATION;
  804 #endif  /*i386*/
  805         }
  806         return D_SUCCESS;
  807 }
  808 
  809 io_return_t
  810 scdisk_set_status(
  811         int             dev,
  812         target_info_t   *tgt,
  813         dev_flavor_t    flavor,
  814         dev_status_t    status,
  815         natural_t       status_count)
  816 {
  817         io_return_t error = D_SUCCESS;
  818         struct disklabel *lp;
  819 
  820         lp = &tgt->dev_info.disk.l;
  821 
  822 
  823         switch (flavor) {
  824         case DIOCSRETRIES:
  825 #ifdef  MACH_KERNEL
  826                 if (status_count != sizeof(int))
  827                         return D_INVALID_SIZE;
  828 #endif  /* MACH_KERNEL */
  829                 scsi_bbr_retries = *(int *)status;
  830                 break;
  831 
  832         case DIOCWLABEL:
  833         case DIOCWLABEL - (0x10<<16):
  834                 if (*(int*)status)
  835                         tgt->flags |= TGT_WRITE_LABEL;
  836                 else
  837                         tgt->flags &= ~TGT_WRITE_LABEL;
  838                 break;
  839         case DIOCSDINFO:
  840         case DIOCSDINFO - (0x10<<16):
  841         case DIOCWDINFO:
  842         case DIOCWDINFO - (0x10<<16):
  843 #ifdef  MACH_KERNEL
  844                 if (status_count != sizeof(struct disklabel) / sizeof(int))
  845                         return D_INVALID_SIZE;
  846 #endif  /* MACH_KERNEL */
  847                 error = setdisklabel(lp, (struct disklabel*) status);
  848                 if (error || (flavor == DIOCSDINFO) || (flavor == DIOCSDINFO - (0x10<<16)))
  849                         return error;
  850                 error = scdisk_writelabel(tgt);
  851                 break;
  852 
  853 #ifdef  MACH_KERNEL
  854 #else   /*MACH_KERNEL*/
  855 #if     ULTRIX_COMPAT
  856         case SCSI_FORMAT_UNIT:          /*_IOW(p, 4, struct format_params) */
  857         case SCSI_REASSIGN_BLOCK:       /*_IOW(p, 5, struct reassign_params) */
  858         case SCSI_READ_DEFECT_DATA:     /*_IOW(p, 6, struct read_defect_params) */
  859         case SCSI_VERIFY_DATA:          /*_IOW(p, 7, struct verify_params) */
  860         case SCSI_MODE_SELECT:          /*_IOW(p, 8, struct mode_sel_sns_params) */
  861         case SCSI_MODE_SENSE:           /*_IOW(p, 9, struct mode_sel_sns_params) */
  862         case SCSI_GET_INQUIRY_DATA:     /*_IOW(p, 11, struct inquiry_info) */
  863                 return ul_disk_ioctl(tgt, flavor, status, status_count);
  864 #endif  /*ULTRIX_COMPAT*/
  865 #endif  /*!MACH_KERNEL*/
  866 
  867 #if notyet
  868         case DIOCWFORMAT:
  869         case DIOCSBAD:  /* ?? how ? */
  870 #endif
  871         default:
  872 #ifdef  i386
  873                 error = scsi_i386_set_status(dev, tgt, flavor, status, status_count);
  874 #else   /*i386*/
  875                 error = D_INVALID_OPERATION;
  876 #endif  /*i386*/
  877         }
  878         return error;
  879 }
  880 
  881 static io_return_t
  882 grab_it(
  883         target_info_t   *tgt,
  884         io_req_t        ior)
  885 {
  886         spl_t   s;
  887 
  888         s = splbio();
  889         simple_lock(&tgt->target_lock);
  890         if (!tgt->ior)
  891                 tgt->ior = ior;
  892         simple_unlock(&tgt->target_lock);
  893         splx(s);
  894 
  895         if (tgt->ior != ior)
  896                 return D_ALREADY_OPEN;
  897         return D_SUCCESS;
  898 }
  899 
  900 /* Write back a label to the disk */
  901 io_return_t
  902 scdisk_writelabel(
  903         target_info_t   *tgt)
  904 {
  905         io_req_t        ior;
  906         char            *data = (char *)0;
  907         struct disklabel *label;
  908         io_return_t     error;
  909         int             dev_bsize = tgt->block_size;
  910 
  911         io_req_alloc(ior,0);
  912 #ifdef  MACH_KERNEL
  913         data = (char *)kalloc(dev_bsize);
  914 #else   /*MACH_KERNEL*/
  915         data = (char *)ior->io_data;
  916 #endif  /*MACH_KERNEL*/
  917         ior->io_next = 0;
  918         ior->io_prev = 0;
  919         ior->io_data = data;
  920         ior->io_count = dev_bsize;
  921         ior->io_op = IO_READ;
  922         ior->io_error = 0;
  923 
  924         if (grab_it(tgt, ior) != D_SUCCESS) {
  925                 error = D_ALREADY_OPEN;
  926                 goto ret;
  927         }
  928 
  929         scdisk_read( tgt, tgt->dev_info.disk.labelsector, ior);
  930         iowait(ior);
  931         if (error = ior->io_error)
  932                 goto ret;
  933 
  934         label = (struct disklabel *) &data[tgt->dev_info.disk.labeloffset];
  935         *label = tgt->dev_info.disk.l;
  936 
  937         ior->io_next = 0;
  938         ior->io_prev = 0;
  939         ior->io_data = data;
  940         ior->io_count = dev_bsize;
  941         ior->io_op = IO_WRITE;
  942 
  943         while (grab_it(tgt, ior) != D_SUCCESS)  ;       /* ahem */
  944 
  945         scdisk_write( tgt, tgt->dev_info.disk.labelsector, ior);
  946         iowait(ior);
  947 
  948         error = ior->io_error;
  949 ret:
  950 #ifdef  MACH_KERNEL
  951         if (data) kfree((vm_offset_t) data, dev_bsize);
  952 #endif  /*MACH_KERNEL*/
  953         io_req_free(ior);
  954         return error;
  955 }
  956 
  957 #ifdef  MACH_KERNEL
  958 #else   /*MACH_KERNEL*/
  959 #if     ULTRIX_COMPAT
  960 
  961 io_return_t ul_disk_ioctl(tgt, flavor, status, status_count)
  962         target_info_t   *tgt;
  963         dev_flavor_t    flavor;
  964         dev_status_t    status;
  965         natural_t       status_count;
  966 {
  967         io_return_t     ret;
  968         scsi_ret_t      err = SCSI_RET_ABORTED;/*xxx*/
  969         io_req_t        ior;
  970 
  971         if (!suser())
  972                 return EACCES;
  973 
  974         ior = geteblk(sizeof(struct defect_descriptors));
  975         ior->io_next = 0;
  976         ior->io_count = 0;
  977         ior->io_op = IO_INTERNAL;
  978         ior->io_error = 0;
  979         ior->io_recnum = 0;
  980         ior->io_residual = 0;
  981 
  982         switch (flavor) {
  983 
  984         case DIOCGETPT: {                       /*_IOR(p, 1, struct pt) */
  985                 scsi_dec_label_t        *p;
  986                 struct disklabel        *lp;
  987                 int                     i;
  988 
  989                 lp = &tgt->dev_info.disk.l;
  990                 p = (scsi_dec_label_t *)status;
  991 
  992                 p->magic = DEC_PARTITION_MAGIC;
  993                 p->in_use = 1;
  994                 for (i = 0; i < 8; i++) {
  995                         p->partitions[i].n_sectors = lp->d_partitions[i].p_size;
  996                         p->partitions[i].offset = lp->d_partitions[i].p_offset;
  997                 }
  998                 err = SCSI_RET_SUCCESS;
  999             }
 1000             break;
 1001 
 1002         case SCSI_GET_SENSE: {          /*_IOR(p, 10, struct extended_sense) */
 1003                 scsi_sense_data_t       *s;
 1004 
 1005                 s = (scsi_sense_data_t*)tgt->cmd_ptr;
 1006                 bcopy(s, status, sizeof(*s) + s->u.xtended.add_len - 1);
 1007                 err = SCSI_RET_SUCCESS;
 1008                 /* only once */
 1009                 bzero(tgt->cmd_ptr, sizeof(scsi_sense_data_t));
 1010             }
 1011             break;
 1012 
 1013         case SCSI_GET_INQUIRY_DATA: {   /*_IOR(p, 11, struct inquiry_info) */
 1014                 struct mode_sel_sns_params *ms;
 1015 
 1016                 ms = (struct mode_sel_sns_params*)status;
 1017                 err = scsi_inquiry( tgt, SCSI_INQ_STD_DATA);
 1018                 if (copyout(tgt->cmd_ptr, ms->msp_addr, sizeof(struct inquiry_info))){
 1019                         ret = EFAULT;
 1020                         goto out;
 1021                 }
 1022             }
 1023             break;
 1024 
 1025         case SCSI_FORMAT_UNIT: {        /*_IOW(p, 4, struct format_params) */
 1026                 struct format_params *fp;
 1027                 struct defect_descriptors *df;
 1028                 unsigned char   mode;
 1029                 unsigned int    old_timeout;
 1030 
 1031                 fp = (struct format_params *)status;
 1032                 df = (struct defect_descriptors*)ior->io_data;
 1033                 if (fp->fp_length != 0) {
 1034                         if (copyin(fp->fp_addr, df, sizeof(*df))) {
 1035                                 ret = EFAULT;
 1036                                 goto out;
 1037                         }
 1038                         ior->io_count = sizeof(*df);
 1039                 } else
 1040                         ior->io_count = 0;
 1041                 mode = fp->fp_format & SCSI_CMD_FMT_LIST_TYPE;
 1042                 switch (fp->fp_defects) {
 1043                 case VENDOR_DEFECTS:
 1044                         mode |= SCSI_CMD_FMT_FMTDATA|SCSI_CMD_FMT_CMPLIST;
 1045                         break;
 1046                 case KNOWN_DEFECTS:
 1047                         mode |= SCSI_CMD_FMT_FMTDATA;
 1048                         break;
 1049                 case NO_DEFECTS:
 1050                 default:
 1051                         break;
 1052                 }
 1053                 old_timeout = scsi_watchdog_period;
 1054                 scsi_watchdog_period = 60*60;   /* 1 hour should be enough, I hope */
 1055                 err = scsi_format_unit( tgt, mode, fp->fp_pattern,
 1056                                         fp->fp_interleave, ior);
 1057                 scsi_watchdog_period = old_timeout;
 1058                 /* Make sure we re-read all info afresh */
 1059                 tgt->flags = TGT_ALIVE |
 1060                              (tgt->flags & (TGT_REMOVABLE_MEDIA|TGT_FULLY_PROBED));
 1061             }
 1062             break;
 1063 
 1064         case SCSI_REASSIGN_BLOCK: {     /*_IOW(p, 5, struct reassign_params) */
 1065                 struct reassign_params  *r;
 1066                 int                     ndef;
 1067 
 1068                 r = (struct reassign_params*) status;
 1069                 ndef = r->rp_header.defect_len0 | (r->rp_header.defect_len1 >> 8);
 1070                 ndef >>= 2;
 1071                 tgt->ior = ior;
 1072                 (void) scsi_reassign_blocks( tgt, &r->rp_lbn3, ndef, ior);
 1073                 iowait(ior);
 1074                 err = tgt->done;
 1075             }
 1076             break;
 1077 
 1078         case SCSI_READ_DEFECT_DATA: {   /*_IOW(p, 6, struct read_defect_params) */
 1079                 struct read_defect_params *dp;
 1080 
 1081                 dp = (struct read_defect_params *)status;
 1082                 ior->io_count = ior->io_alloc_size;
 1083                 if (dp->rdp_alclen > ior->io_count)
 1084                         dp->rdp_alclen = ior->io_count;
 1085                 else
 1086                         ior->io_count = dp->rdp_alclen;
 1087                 ior->io_op |= IO_READ;
 1088                 tgt->ior = ior;
 1089                 err = scsi_read_defect(tgt, dp->rdp_format|0x18, ior);
 1090                 if (copyout(ior->io_data, dp->rdp_addr, dp->rdp_alclen)) {
 1091                         ret = EFAULT;
 1092                         goto out;
 1093                 }
 1094             }
 1095             break;
 1096 
 1097         case SCSI_VERIFY_DATA: {        /*_IOW(p, 7, struct verify_params) */
 1098                 struct verify_params    *v;
 1099                 unsigned int    old_timeout;
 1100 
 1101                 old_timeout = scsi_watchdog_period;
 1102                 scsi_watchdog_period = 5*60;    /* 5 mins enough, I hope */
 1103                 v = (struct verify_params *)status;
 1104                 ior->io_count = 0;
 1105                 err = scdisk_verify( tgt, v->vp_lbn, v->vp_length, ior);
 1106                 scsi_watchdog_period = old_timeout;
 1107             }
 1108             break;
 1109 
 1110         case SCSI_MODE_SELECT: {        /*_IOW(p, 8, struct mode_sel_sns_params) */
 1111                 struct mode_sel_sns_params *ms;
 1112 
 1113                 ms = (struct mode_sel_sns_params*)status;
 1114                 if(copyin(ms->msp_addr, ior->io_data, ms->msp_length)) {
 1115                         ret = EFAULT;
 1116                         goto out;
 1117                 }
 1118                 err = scdisk_mode_select( tgt, DEV_BSIZE, ior, ior->io_data,
 1119                                           ms->msp_length, ms->msp_setps);
 1120             }
 1121             break;
 1122 
 1123         case SCSI_MODE_SENSE: {         /*_IOWR(p, 9, struct mode_sel_sns_params) */
 1124                 struct mode_sel_sns_params *ms;
 1125                 unsigned char           pagecode;
 1126 
 1127                 ms = (struct mode_sel_sns_params*)status;
 1128                 pagecode = (ms->msp_pgcode & 0x3f) | (ms->msp_pgctrl << 6);
 1129                 err = scsi_mode_sense( tgt, pagecode, ms->msp_length, ior);
 1130                 if (copyout(tgt->cmd_ptr, ms->msp_addr, ms->msp_length)){
 1131                         ret = EFAULT;
 1132                         goto out;
 1133                 }
 1134             }
 1135             break;
 1136         }
 1137 
 1138         ret = (err == SCSI_RET_SUCCESS) ? D_SUCCESS : D_IO_ERROR;
 1139         if (ior->io_op & IO_ERROR)
 1140                 ret = D_IO_ERROR;
 1141 out:
 1142         brelse(ior);
 1143         return ret;
 1144 }
 1145 #endif  /*ULTRIX_COMPAT*/
 1146 #endif  /*!MACH_KERNEL*/
 1147 
 1148 #ifdef  CHECKSUM
 1149 
 1150 #define SUMSIZE 0x10000
 1151 #define SUMHASH(b)      (((b)>>1) & (SUMSIZE - 1))
 1152 struct {
 1153         long blockno;
 1154         long sum;
 1155 } scdisk_checksums[SUMSIZE];
 1156 
 1157 void scdisk_checksum(
 1158         long    bno,
 1159         register unsigned int *addr,
 1160         int     size)
 1161 {
 1162         register int i = size/sizeof(int);
 1163         register unsigned int sum = -1;
 1164 
 1165         while (i-- > 0)
 1166                 sum ^= *addr++;
 1167         scdisk_checksums[SUMHASH(bno)].blockno = bno;
 1168         scdisk_checksums[SUMHASH(bno)].sum = sum;
 1169 }
 1170 
 1171 void scdisk_bcheck(
 1172         long    bno,
 1173         register unsigned int *addr,
 1174         int     size)
 1175 {
 1176         register int i = size/sizeof(int);
 1177         register unsigned int sum = -1;
 1178         unsigned int *start = addr;
 1179 
 1180         if (scdisk_checksums[SUMHASH(bno)].blockno != bno) {
 1181 if (scsi_debug) printf("No checksum for block x%x\n", bno);
 1182                 return;
 1183         }
 1184 
 1185         while (i-- > 0)
 1186                 sum ^= *addr++;
 1187 
 1188         if (scdisk_checksums[SUMHASH(bno)].sum != sum) {
 1189                 printf("Bad checksum (x%x != x%x), bno x%x size x%x at x%x\n",
 1190                         sum,
 1191                         scdisk_checksums[bno & (SUMSIZE - 1)].sum,
 1192                         bno, size, start);
 1193                 gimmeabreak();
 1194                 scdisk_checksums[SUMHASH(bno)].sum = sum;
 1195         }
 1196 }
 1197 
 1198 
 1199 #endif  /*CHECKSUM*/
 1200 
 1201 /*#define PERF */
 1202 #ifdef  PERF
 1203 int test_read_size = 512;
 1204 int test_read_skew = 12;
 1205 int test_read_skew_min = 0;
 1206 int test_read_nreads = 1000;
 1207 int test_read_bdev = 0;
 1208 
 1209 #include <sys/time.h>
 1210 
 1211 void test_read(int max)
 1212 {
 1213         int i, ssk, usecs;
 1214         struct timeval start, stop;
 1215 
 1216         if (max == 0)
 1217                 max = test_read_skew + 1;
 1218         ssk = test_read_skew;
 1219         for (i = test_read_skew_min; i < max; i++){
 1220                 test_read_skew = i;
 1221 
 1222                 start = time;
 1223                 read_test();
 1224                 stop = time;
 1225 
 1226                 usecs = stop.tv_usec - start.tv_usec;
 1227                 if (usecs < 0) {
 1228                         stop.tv_sec -= 1;
 1229                         usecs += 1000000;
 1230                 }
 1231                 printf("Skew %3d size %d count %d time %3d sec %d us\n",
 1232                         i, test_read_size, test_read_nreads,
 1233                         stop.tv_sec - start.tv_sec, usecs);
 1234         }
 1235         test_read_skew = ssk;
 1236 }
 1237 
 1238 void read_test(void)
 1239 {
 1240         static int      buffer[(8192*2)/sizeof(int)];
 1241         struct io_req   io;
 1242         register int    i, rec;
 1243 
 1244         bzero(&io, sizeof(io));
 1245         io.io_unit = test_read_bdev;
 1246         io.io_op = IO_READ;
 1247         io.io_count = test_read_size;
 1248         io.io_data = (char*) buffer;
 1249 
 1250         for (rec = 0, i = 0; i < test_read_nreads; i++) {
 1251                 io.io_op = IO_READ;
 1252                 io.io_recnum = rec;
 1253                 scdisk_strategy(&io);
 1254                 rec += test_read_skew;
 1255                 iowait(&io);
 1256         }
 1257 }
 1258 
 1259 void tur_test(void)
 1260 {
 1261         struct io_req   io;
 1262         register int    i;
 1263         char            *a, *b;
 1264         struct timeval start, stop;
 1265 
 1266         bzero(&io, sizeof(io));
 1267         io.io_unit = test_read_bdev;
 1268         io.io_data = (char*)&io;/*unused but kernel space*/
 1269 
 1270         start = time;
 1271         for (i = 0; i < test_read_nreads; i++) {
 1272                 io.io_op = IO_INTERNAL;
 1273                 rz_check(io.io_unit, &a, &b);
 1274                 scsi_test_unit_ready(b,&io);
 1275         }
 1276         stop = time;
 1277         i = stop.tv_usec - start.tv_usec;
 1278         if (i < 0) {
 1279                 stop.tv_sec -= 1;
 1280                 i += 1000000;
 1281         }
 1282         printf("%d test-unit-ready took %3d sec %d us\n",
 1283                         test_read_nreads,
 1284                         stop.tv_sec - start.tv_sec, i);
 1285 }
 1286 
 1287 #endif  /*PERF*/
 1288 
 1289 /*#define WDEBUG*/
 1290 #ifdef  WDEBUG
 1291 
 1292 int buggo_write_size = 8192;
 1293 int buggo_dev = 1; /* rz0b */
 1294 int     buggo_out_buffer[8192/2];
 1295 int     buggo_in_buffer[8192/2];
 1296 
 1297 int buggotest(n, pattern, verbose)
 1298 {
 1299         struct io_req   io;
 1300         register int    i, rec;
 1301 
 1302         if (n <= 0)
 1303                 n = 1;
 1304 
 1305         if(pattern)
 1306                 for (i = 0; i < buggo_write_size/4; i++)
 1307                         buggo_out_buffer[i] = i + pattern;
 1308 
 1309         for (i = 0; i < n; i++) {
 1310                 register int j;
 1311 
 1312                 buggo_out_buffer[0] = i + pattern;
 1313                 buggo_out_buffer[(buggo_write_size/4)-1] = i + pattern;
 1314                 bzero(&io, sizeof(io));
 1315                 io.io_unit = buggo_dev;
 1316                 io.io_data = (char*)buggo_out_buffer;
 1317                 io.io_op = IO_WRITE;
 1318                 io.io_count = buggo_write_size;
 1319                 io.io_recnum = i % 1024;
 1320                 scdisk_strategy(&io);
 1321 
 1322                 bzero(buggo_in_buffer, sizeof(buggo_in_buffer));
 1323                 iowait(&io);
 1324 
 1325                 if (verbose)
 1326                         printf("Done write with %x", io.io_error);
 1327 
 1328                 bzero(&io, sizeof(io));
 1329                 io.io_unit = buggo_dev;
 1330                 io.io_data = (char*)buggo_in_buffer;
 1331                 io.io_op = IO_READ;
 1332                 io.io_count = buggo_write_size;
 1333                 io.io_recnum = i % 1024;
 1334                 scdisk_strategy(&io);
 1335                 iowait(&io);
 1336 
 1337                 if (verbose)
 1338                         printf("Done read with %x", io.io_error);
 1339 
 1340                 for  (j = 0; j < buggo_write_size/4; j++)
 1341                         if (buggo_out_buffer[j] != buggo_in_buffer[j]){
 1342                                 printf("Difference at %d-th word: %x %x\n",
 1343                                         buggo_out_buffer[j], buggo_in_buffer[j]);
 1344                                 return i;
 1345                         }
 1346         }
 1347         printf("Test ok\n");
 1348         return n;
 1349 }
 1350 #endif  /*WDEBUG*/

Cache object: f05443a97123606c821bb524464e485c


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